Perl script for generating Win95 printer driver data for Samba

Rick Cochran rick at msc.cornell.edu
Wed Feb 18 20:11:43 GMT 1998


Here are two bits of Perl code which make my life easier.  The
documentation is barely existant.  If they help you, then fine.  If
you can't figure them out, I'm sorry but I don't have time for
answering questions.

You may want to remove the 'printcap.proto' processing.  We generate
printcap files for each host from a prototype file.

These scripts do not require AFS.  We just happen to use (and like) AFS.

These excerpts from our printcap file may help:

# '# sambadata=' lines are for creating the Samba printer share config files, an
d
# have the form:
# '# sambadata=<printer name>:<server1,server2,all>:<public>:<printer driver nam
e>'
# where:
# <server1,server2,all> designate which Samba servers should advertise
#   the printer
# <public> is 'yes' or 'no' for whether the 'nobody' user is allowed to print
# <printer driver name> is the official Windows printer name

# sambadata=mscqms:all:no:HP LaserJet IIISi PostScript
mscqms|mscqms|MSC, HP IIIsi, E17 Clark:\
        :lp=:rm=lynx.msc.cornell.edu:rp=mscqms:sd=/usr/spool/lpd/mscqms:mx#0:

-Rick

-- 
|Rick Cochran		  			      phone: 607-255-7223|
|Cornell Materials Science Center			FAX: 607-255-3957|
|E20 Clark Hall, Ithaca, N.Y. 14853	      email: rick at msc.cornell.edu|
| "The Founding Fathers did not establish the United States as a	 |
| democratic republic so that elected officials would decide trivia,	 |
| while all great questions would be decided by the judiciary."		 |
|					Judge Andrew Kleinfeld		 |


------------------------------ make_printer_dist ------------------------------
#!/usr/local/bin/perl
# Create printers.def file for Samba and list of printer driver files
# to go in the 'printer$' share.
# 2/4/98 rcc - original

$protofile = "/afs/.msc.cornell.edu/common/config/printcap.proto";
#$protofile = "printcap.proto";
$vendor_drivers_dir = '/afs/.msc.cornell.edu/i386_windows/drivers/printer';

# Create DOS batch file to extract driver files from Windows95 CD using
# "make_printerdef" output.
sub extract {
  open(F, 'printerfiles.tmp');
  $copy_seen = 0;
  while ( <F> ) {
    chop;
    if ( /^Found:(.*)$/ ) {
      $spd = $1;
      if ( $spd =~ /^([^.]+)\./ ) {
        $spd = $1;
      }
      else {
        print "$spd doesn't conform to 'XXXXXX.' format\n";
      }
  print "$spd\n";
      while ( <F> ) {
        last if /^Copy the following/;
      }
      while ( <F> ) {
        chop;
        last if /^$/;
        push(@msfiles, $_);
      }
    }
  }
  close(F);
}

# Extract Samba data from the printcap.proto file
open(F, 'sed -e \'s/^\\(#[ 	]\\)/+\\1/\' -e \'s/^#$/+#/\' -e \'s/\\\\$/>>/\' ' . $protofile . ' | /lib/cpp -P | sed -e \'s/^+#/#/\' -e \'s/>>$/\\\\/\' -e \'s/|=|/#/\' |') || die "unable to open printcap.proto\n";
while ( <F> ) {
  chop;
  # '# sambadata=<printer name>:<server1,server2,all>:<public>:<printer driver name>'
  if ( /^#\s+sambadata=(.*)$/ ) {
    ($n, $s, $p, $d) = split(/:/, $1, 4);
    push(@printernames, $d);
  }
}
close(F);

# Create list of vendor directories
opendir(D, $vendor_drivers_dir) || die "unable to open $vendor_drivers_dir\n";
@vdirs = readdir(D);
close(D);

# Move Microsoft directory to the end of the list
foreach $vdir ( @vdirs ) {
  next if $vdir eq 'mswin95';
  push(@vdirs2, $vdir);
}
push(@vdirs2, 'mswin95');

# Create list of vendor ".inf" files
foreach $vdir ( @vdirs2 ) {
  opendir(D, "$vendor_drivers_dir/$vdir") || next;
  @vfiles = readdir(D);
  close(D);
  foreach $f ( @vfiles ) {
    if ( $f =~ /\.inf$/i ) {
      push(@infs, "$vdir/$f");
    }
  }
}

# For each printer, extract data from vendor ".inf" files
# Also, create "printer-to-driverdirectory" database for make_printer_conf.
unlink('printers.def');
unlink('printerfiles.list');
open(G, '>printerfiles.db') || die "unable to create printerfiles.db\n";
$ld = '';
foreach $printername ( sort(@printernames) ) {
  next if $printername eq $ld;
  foreach $inf ( @infs ) {
    $rc = system("../samba/source/make_printerdef $vendor_drivers_dir/$inf '$printername' >>printers.def 2>printerfiles.tmp");
    if ( $rc == 0 ) {
print "$inf $printername\n";
      # Create batch file to extract printer files if from Microsoft
      &extract if $inf =~ m#^mswin95/#;
      system("cat printerfiles.tmp >>printerfiles.list");
      unlink('printerfiles.tmp');
      $inf =~ m#^([^/]+)/#;
      $dir = $1;
      print G "$printername:$dir\n";
      # Quit as soon as the command is successful
      last;
    }
  }
  if ( $rc != 0 ) {
    print "'$printername' not found\n";
  }
  $ld = $printername
}
close(G);

# Create list of Microsoft driver files which we already have.
opendir(D, "$vendor_drivers_dir/mswin95") || die "unable to open $vendor_drivers_dir/mswin95\n";
@mdirs = readdir(D);
close(D);
foreach $d ( @mdirs ) {
  $d =~ tr/A-Z/a-z/;
  $mdirs{$d} = 'T';
}

# Remove duplicate Microsoft file entries and create batch file.
# Maximum of six files per "extract" command!
open(G, '>getfiles.bat');
print G "mkdir c:\\tmp\\pdrivers\n";
$n = 0;
$lf = '';
$files = '';
foreach $f ( sort(@msfiles) ) {
  # "make_printerdef" has a bug which causes it to prepend "color\" to
  # file names sometimes:
  $f =~ s#^.*\\##;
  next if $f eq $lf;
  $lf = $f;
  # skip if we already have this file
  $lcf = $f;
  $lcf =~ tr/A-Z/a-z/;
  next if $mdirs{$lcf} ne '';
  $files .= " $f";
  if ( ++$n >= 6 ) {
    print G "extract /a /l c:\\tmp\\pdrivers d:\\win95\\win95_02.cab$files\n";
    $n = 0;
    $files = '';
  }
}
if ( $n > 0 ) {
  print G "extract /a /l c:\\tmp\\pdrivers d:\\win95\\win95_02.cab$files\n";
}
close(G);

exit(0);

------------------------------ make_printer_conf ------------------------------
#!/usr/local/bin/perl
# Create Samba configuration file entries for printers
# 2/4/98 rcc - original

$protofile = "/afs/.msc.cornell.edu/common/config/printcap.proto";
#$protofile = "printcap.proto";

print "This script uses 'printerfiles.db' which is produced by 'make_printer_dist'\n";

# Extract Samba data from the printcap.proto file
open(F, 'sed -e \'s/^\\(#[ 	]\\)/+\\1/\' -e \'s/^#$/+#/\' -e \'s/\\\\$/>>/\' ' . $protofile . ' | /lib/cpp -P | sed -e \'s/^+#/#/\' -e \'s/>>$/\\\\/\' -e \'s/|=|/#/\' |') || die "unable to open printcap.proto\n";
while ( <F> ) {
  chop;
  # '# sambadata=<printer name>:<server1,server2,all>:<public>:<printer driver name>'
  if ( /^#\s+sambadata=(.*)$/ ) {
    ($n, $s, $p, $d) = split(/:/, $1, 4);
    $servers{$n} = $s;
    $public{$n} = $p;
    $driver{$n} = $d;
  }
  next if /^#|^$|^\s/;
  @tmp = split(/\|/);
  $name = @tmp[0];
  next if $name eq 'lp';
  $d = @tmp[$#tmp];
  $d =~ s/\s*:\s*\\\s*//;
  $desc{$name} = $d;
}
close(F);

# Read in "printer-to-driverdirectory" database
open(F, 'printerfiles.db') || die "unable to open printerfiles.db\n";
while ( <F> ) {
  chop;
  ($name, $dir) = split(/:/);
  $driverdir{$name} = $dir;
}
close(F);

# Create Samba configuration file
open(F, '>printers_all.conf') || die "Unable to create 'printers_all.conf'\n";
print F "; printers_all.conf\n";
print F "; created using make_printer_conf\n";
foreach $printer ( sort(keys(%desc)) ) {
  # defaults:
  if ( ($de = $desc{$printer}) eq '' ) { $de = $printer; }
  if ( ($pu = $public{$printer}) eq '' ) { $pu = 'no'; }
  if ( ($dr = $driver{$printer}) eq '' ) {
    $dr = 'none';
  }
  else {
    if ( ($dir = $driverdir{$dr}) eq '' ) {
      print "No driver directory found for '$dr'\n";
    }
  }
  print F "\n[$printer]\n";
  print F "   printer = $printer\n";
  print F "   path = /usr/spool/samba\n";
  print F "   comment = $de\n";
  print F "   printer driver = $dr\n";
  print F "   printer driver location = \\\\%h\\PRINTER\$\\$dir\n";
  print F "   browseable = yes\n";
  print F "   printable = yes\n";
  print F "   public = $pu\n";
  print F "   writable = no\n";
  print F "   create mode = 0700\n";
}
close(F);

exit(0);


More information about the samba mailing list