2 # Functions for lprng-style printer management
5 # Returns a list of known printer names
9 foreach $l (&list_printcap()) {
10 $l->{'name'} =~ /^([^\|]+)/;
16 # get_printer(name, [nostatus])
19 local($l, %prn, @w, @n, $w, %cap, @jobs);
20 foreach $l (&list_printcap()) {
21 @n = split(/\|/, $l->{'name'});
23 # found the printer.. get info from printcap
25 if (@n > 1) { $prn{'alias'} =
26 [ grep { $_ ne $l->{'cm'} } @n[1..$#n] ]; }
27 $prn{'desc'} = $l->{'cm'} if ($l->{'cm'});
28 $prn{'iface'} = $l->{'if'};
29 $prn{'banner'} = !defined($l->{'sh'});
31 $prn{'rhost'} = $l->{'rm'};
32 $prn{'rqueue'} = $l->{'rp'};
34 elsif ($l->{'lp'} =~ /^(\S+)\%(\d+)$/) {
39 $prn{'dev'} = $l->{'lp'};
41 $prn{'msize'} = $l->{'mx'};
42 $prn{'comment'} = $l->{'comment'};
43 $prn{'ro'} = $l->{'file'} eq $config{'ro_printcap_file'} &&
44 $config{'printcap_file'} ne $config{'ro_printcap_file'};
47 # call lpc to get status
48 local $esc = quotemeta($prn{'name'});
49 $out = &backquote_command("lpc -P$esc status 2>&1", 1);
50 if ($out =~ /\n(\S+)\s+(\S+)\s+(\S+)/) {
51 $prn{'accepting'} = $3 eq 'enabled';
52 $prn{'enabled'} = $2 eq 'enabled';
66 local $esc = quotemeta($_[0]);
67 open(LPQ, "lpq -P$esc |");
70 if (/^\s+Rank\s+Owner/i) { $doneheader++; }
71 elsif ($doneheader && /^(\S+)\s+(\S+)\s+\S+\s+(\d+)\s+(.*\S)\s+(\d+)\s+(\S+)$/) {
73 next if ($1 eq "done");
79 $job{'printing'} = ($1 eq "active");
80 $job{'user'} =~ s/\+\d+$//g;
81 local $d = "$config{'spool_dir'}/$_[0]";
83 while($f = readdir(DIR)) {
84 if ($f =~ /df.(\d+)/ && $1 == $job{'id'}) {
89 $job{'printfile'} = @pq ? \@pq : undef;
92 elsif (/^(\S+):\s+(\S+)\s+\[job\s+(\d+)/) {
97 if (<LPQ> =~ /^\s+(.*\S)\s+(\d+)/) {
110 return $_[0] !~ /^(why|allow|default|ctype|sysv|ipp)$/;
114 # create_printer(&details)
115 # Create a new printer in /etc/printcap
119 if (!-d $config{'spool_dir'}) {
120 &lock_file($config{'spool_dir'});
121 mkdir($config{'spool_dir'}, 0755);
122 &unlock_file($config{'spool_dir'});
123 &system_logged("chown $config{'iface_owner'} $config{'spool_dir'}");
125 $cap{'sd'} = "$config{'spool_dir'}/$_[0]->{'name'}";
126 &lock_file($cap{'sd'});
127 mkdir($cap{'sd'}, 0755);
128 &unlock_file($cap{'sd'});
129 &open_lock_tempfile(TOUCH, ">$cap{'sd'}/control.$_[0]->{'name'}");
130 &close_tempfile(TOUCH);
131 &open_lock_tempfile(TOUCH, ">$cap{'sd'}/status.$_[0]->{'name'}");
132 &close_tempfile(TOUCH);
133 &open_lock_tempfile(TOUCH, ">$cap{'sd'}/unspooler.$_[0]->{'name'}");
134 &close_tempfile(TOUCH);
135 if ($config{'iface_owner'}) {
136 &system_logged("chown -R $config{'iface_owner'} $cap{'sd'}");
139 local @st = stat($config{'spool_dir'});
140 &system_logged("chown -R $st[4]:$st[5] $cap{'sd'}");
142 &system_logged("chmod 2700 $cap{'sd'}");
143 &system_logged("chmod 600 $cap{'sd'}/*");
144 &system_logged("chmod 700 $cap{'sd'}/printfilter")
145 if (-r "$cap{'sd'}/printfilter");
147 &lock_file($config{'printcap_file'});
148 local $lref = &read_file_lines($config{'printcap_file'});
149 push(@$lref, &make_printcap($_[0], \%cap));
150 &flush_file_lines($config{'printcap_file'});
151 &unlock_file($config{'printcap_file'});
153 &system_logged("lpc reread all >/dev/null 2>&1");
154 &apply_status($_[0]);
157 # modify_printer(&details)
160 local(@old, $o, $old, @cap);
161 &lock_file($config{'printcap_file'});
162 @old = &list_printcap();
164 $o->{'name'} =~ /^([^\|]+)/;
165 if ($1 eq $_[0]->{'name'}) {
166 # found current details
171 if (!$old) { &error("Printer '$_[0]->{'name'}' no longer exists"); }
173 &lock_file($config{'printcap_file'});
174 local $lref = &read_file_lines($config{'printcap_file'});
175 splice(@$lref, $old->{'line'}, $old->{'eline'} - $old->{'line'} + 1,
176 &make_printcap($_[0], $old));
177 &flush_file_lines($config{'printcap_file'});
178 &unlock_file($config{'printcap_file'});
180 &system_logged("lpc reread all >/dev/null 2>&1");
181 &apply_status($_[0]);
184 # delete_printer(name)
187 local(@old, $o, $old, @cap);
188 &lock_file($config{'printcap_file'});
189 @old = &list_printcap();
191 $o->{'name'} =~ /^([^\|]+)/;
193 # found current details
198 if (!$old) { &error("Printer '$_[0]' no longer exists"); }
200 &lock_file($config{'printcap_file'});
201 local $lref = &read_file_lines($config{'printcap_file'});
202 splice(@$lref, $old->{'line'}, $old->{'eline'} - $old->{'line'} + 1);
203 &flush_file_lines($config{'printcap_file'});
204 &unlock_file($config{'printcap_file'});
206 if ($old->{'sd'} =~ /$_[0]$/) {
207 &system_logged("rm -rf '$old->{'sd'}'");
209 &system_logged("lpc reread all >/dev/null 2>&1");
212 # cancel_job(printer, job)
213 # Calls lprm to remove some job
217 local $esc = quotemeta($_[0]);
218 local $iesc = quotemeta($_[1]);
219 $out = &backquote_logged("lprm -P$esc $iesc 2>&1");
220 if ($?) { &error("lprm failed : $out"); }
223 # make_printcap(&details, &old)
224 # Updates or creates a printcap line
227 local(%prn, %cap, $a, $rv, $c);
228 %prn = %{$_[0]}; %cap = %{$_[1]};
229 $cap{'if'} = $prn{'iface'} ? $prn{'iface'} : undef;
230 $cap{'sh'} = $prn{'banner'} ? undef : "";
231 $cap{'lp'} = $prn{'dhost'} ? "$prn{'dhost'}%$prn{'dport'}" :
232 $prn{'dev'} ? $prn{'dev'} : undef;
233 $cap{'rm'} = $prn{'rhost'} ? $prn{'rhost'} : undef;
234 $cap{'rp'} = $prn{'rqueue'} ? $prn{'rqueue'} : undef;
235 $cap{'mx'} = defined($prn{'msize'}) ? $prn{'msize'} : undef;
236 $cap{'cm'} = $prn{'desc'} ? $prn{'desc'} : undef;
237 $rv = $prn{'comment'}."\n" if ($prn{'comment'});
239 foreach $a (@{$prn{'alias'}}) { $rv .= "|$a"; }
240 $rv .= "|$prn{'desc'}" if ($prn{'desc'});
241 foreach $c (keys %cap) {
242 if ($c =~ /^([A-z0-9\-\_]+)(#?)$/ && defined($cap{$c}) &&
243 $1 ne 'eline' && $1 ne 'line' && $1 ne 'name' && $1 ne 'comment' &&
245 if ($cap{$c} eq "") { $rv .= ":$c"; }
246 elsif ($cap{$c} =~ /^\d+$/) { $rv .= ":$c#$cap{$c}"; }
247 else { $rv .= ":$c=$cap{$c}"; }
255 # Returns an array of associative arrays containing printcap fields
258 return @list_printcap_cache if (scalar(@list_printcap_cache));
259 local(@rv, @line, @comment, $line, $cont, $lnum, $i, %done, $capfile);
260 foreach $capfile ($config{'printcap_file'}, $config{'ro_printcap_file'}) {
261 next if (!$capfile || $done{$capfile}++);
264 while($line = <CAP>) {
265 $line =~ s/\s+$//g; # remove trailing spaces
266 if ($line =~ /^(##.*)/) {
267 # special commented line .. keep it
268 $comment[@line] = $line;
271 local $oline = $line;
272 $line =~ s/^#.*$//g; # remove comments
273 $line =~ s/^\s+//g; # remove leading spaces
275 $ncont = ($line =~ s/\\$//g);
276 if ($cont || $oline =~ /^\s+:/) {
277 $line[$#line] .= $line;
278 $eline[@line - 1] = $lnum;
283 $sline[@line - 1] = $lnum;
288 # only keep comments immediately before an entry
289 $comment[@line] = undef;
295 for($i=0; $i<@line; $i++) {
297 next if ($line[$i] =~ /^include\s+(\S+)/);
298 @w = split(/:+/, $line[$i]);
299 $cap{'name'} = $w[0];
300 next if ($done{$w[0]}++);
301 $cap{'line'} = $sline[$i] - ($comment[$i] ? 1 : 0);
302 $cap{'eline'} = $eline[$i];
303 $cap{'comment'} = $comment[$i];
304 $cap{'file'} = $capfile;
305 foreach $w (@w[1..$#w]) {
306 if ($w =~ /^([A-z0-9\-\_]+)[=#](.*)$/) { $cap{$1} = $2;}
307 elsif ($w =~ /^([A-z0-9\-\_]+)$/) { $cap{$w} = ""; }
312 @list_printcap_cache = @rv;
316 # apply_status(&details)
317 # Calls lpc to enable or disable a printer.
318 # Restarting lpd doesn't seem to be necessary?
322 local $esc = quotemeta($prn{'name'});
323 if ($prn{'enabled'}) {
324 $out = &backquote_logged("lpc -P$esc start 2>&1");
327 $out = &backquote_logged("lpc -P$esc stop 2>&1");
329 if ($prn{'accepting'}) {
330 $out = &backquote_logged("lpc -P$esc enable 2>&1");
333 $out = &backquote_logged("lpc -P$esc disable 2>&1");
338 # Returns the pid if lpsched is running, 0 if not, -1 if cannot be stopped
341 local $out = &backquote_command("lpc lpd all 2>&1", 1);
342 return $out =~ /pid\s+(\d+)/ ? $1 : 0;
349 local $out = &backquote_logged("lpd 2>&1");
350 if ($? || $out =~ /error/i) { &error("<tt>$out</tt>"); }
354 # Stop the running lpsched process
357 &kill_logged('INT', $_[0]) || &error(&text("estop", $!));
360 # print_command(printer, file)
361 # Returns the command to print some file on some printer
364 local $esc = quotemeta($_[0]);
365 local $fesc = quotemeta($_[1]);
366 return "lpr -P$esc $fesc";
369 # check_print_system()
370 sub check_print_system
372 &has_command("lpr") || return &text('lprng_ecmd', "<tt>lpr</tt>");
373 -d $config{'spool_dir'} || return &text('lprng_espool', "<tt>$config{'spool_dir'}</tt>");
378 @device_files = ("/dev/lp0", "/dev/lp1", "/dev/lp2", "/dev/lp3",
379 "/dev/ttyS0", "/dev/ttyS1", "/dev/null");
382 @device_files = ("/dev/lp1", "/dev/lp2", "/dev/lp2", "/dev/lp3",
383 "/dev/ttyS0", "/dev/ttyS1", "/dev/null");
385 if (-r "/dev/usblp0") {
386 push(@device_files, "/dev/usblp0", "/dev/usblp1",
387 "/dev/usblp2", "/dev/usblp3");
389 elsif (-r "/dev/usb/lp0") {
390 push(@device_files, "/dev/usb/lp0", "/dev/usb/lp1",
391 "/dev/usb/lp2", "/dev/usb/lp3");
393 @device_names = (&text('lprng_paralel', "1"), &text('lprng_paralel', "2"),
394 &text('lprng_paralel', "3"), &text('lprng_paralel', "4"),
395 &text('lprng_serial', "1"), &text('lprng_serial', "2"),
396 $text{'lprng_null'}, &text('linux_usb', 1),
397 &text('linux_usb', 2), &text('linux_usb', 3),
398 &text('linux_usb', 4));