Handle hostnames with upper-case letters
[webmin.git] / lpadmin / freebsd-lib.pl
1 # freebsd-lib.pl
2 # Functions for printcap-style printer management
3
4 # list_printers()
5 # Returns a list of known printer names
6 sub list_printers
7 {
8 local($l, @rv);
9 foreach $l (&list_printcap()) {
10         $l->{'name'} =~ /^([^\|]+)/;
11         push(@rv, $1);
12         }
13 return @rv;
14 }
15
16 # get_printer(name, [nostatus])
17 sub get_printer
18 {
19 local($l, %prn, @w, @n, $w, %cap, @jobs);
20 foreach $l (&list_printcap()) {
21         @n = split(/\|/, $l->{'name'});
22         if ($n[0] eq $_[0]) {
23                 # found the printer.. get info from printcap
24                 $prn{'name'} = $n[0];
25                 if (@n > 2) { $prn{'alias'} = [ @n[1..$#n-1] ]; }
26                 if (@n > 1) { $prn{'desc'} = $n[$#n]; }
27                 $prn{'iface'} = $l->{'if'};
28                 $prn{'banner'} = !defined($l->{'sh'});
29                 $prn{'dev'} = $l->{'lp'};
30                 $prn{'rhost'} = $l->{'rm'};
31                 $prn{'rqueue'} = $l->{'rp'};
32                 $prn{'msize'} = $l->{'mx'};
33                 $prn{'ro'} = $l->{'file'} eq $config{'ro_printcap_file'};
34
35                 if (!$_[1]) {
36                         # call lpc to get status
37                         local $esc = quotemeta($prn{'name'});
38                         $out = &backquote_command("lpc status $esc 2>&1", 1);
39                         $prn{'accepting'} = ($out =~ /queuing is enabled/);
40                         $prn{'enabled'} = ($out =~ /printing is enabled/);
41                         }
42
43                 return \%prn;
44                 }
45         }
46 return undef;
47 }
48
49 sub get_jobs
50 {
51 local @jobs;
52 local $esc = quotemeta($_[0]);
53 open(LPQ, "lpq -P$esc |");
54 while(<LPQ>) {
55         chop;
56         if (/^Rank\s+Owner\s+/) { $doneheader++; }
57         elsif ($doneheader && /^(\S+)\s+(\S+)\s+(\d+)\s+(.*\S)\s+(\d+)\s+(\S+)$/) {
58                 local(%job);
59                 $job{'id'} = $3;
60                 $job{'user'} = $2;
61                 $job{'size'} = $5;
62                 $job{'file'} = $4;
63                 $job{'printing'} = ($1 eq "active");
64                 push(@jobs, \%job);
65                 }
66         }
67 close(LPQ);
68 return @jobs;
69 }
70
71 sub printer_support
72 {
73 return $_[0] !~ /^(why|allow|default|ctype|riface|sysv|direct|rnoqueue|ipp)$/;
74 }
75
76
77 # create_printer(&details)
78 # Create a new printer in /etc/printcap
79 sub create_printer
80 {
81 local(%cap);
82 $cap{'sd'} = "$config{'spool_dir'}/$_[0]->{'name'}";
83 &lock_file($cap{'sd'});
84 mkdir($cap{'sd'}, 0755);
85 &unlock_file($cap{'sd'});
86
87 &lock_file($config{'printcap_file'});
88 local $lref = &read_file_lines($config{'printcap_file'});
89 push(@$lref, &make_printcap($_[0], \%cap));
90 &flush_file_lines($config{'printcap_file'});
91 &unlock_file($config{'printcap_file'});
92 &apply_status($_[0]);
93 }
94
95 # modify_printer(&details)
96 sub modify_printer
97 {
98 local(@old, $o, $old, @cap);
99 &lock_file($config{'printcap_file'});
100 @old = &list_printcap();
101 foreach $o (@old) {
102         $o->{'name'} =~ /^([^\|]+)/;
103         if ($1 eq $_[0]->{'name'}) {
104                 # found current details
105                 $old = $o;
106                 last;
107                 }
108         }
109 if (!$old) { &error("Printer '$_[0]->{'name'}' no longer exists"); }
110 local $lref = &read_file_lines($config{'printcap_file'});
111 splice(@$lref, $old->{'line'}, $old->{'eline'} - $old->{'line'} + 1,
112         &make_printcap($_[0], $old));
113 &flush_file_lines($config{'printcap_file'});
114 &unlock_file($config{'printcap_file'});
115 &apply_status($_[0]);
116 }
117
118 # delete_printer(name)
119 sub delete_printer
120 {
121 local(@old, $o, $old, @cap);
122 &lock_file($config{'printcap_file'});
123 @old = &list_printcap();
124 foreach $o (@old) {
125         $o->{'name'} =~ /^([^\|]+)/;
126         if ($1 eq $_[0]) {
127                 # found current details
128                 $old = $o;
129                 last;
130                 }
131         }
132 if (!$old) { &error("Printer '$_[0]' no longer exists"); }
133 local $lref = &read_file_lines($config{'printcap_file'});
134 splice(@$lref, $old->{'line'}, $old->{'eline'} - $old->{'line'} + 1);
135 &flush_file_lines($config{'printcap_file'});
136 &unlock_file($config{'printcap_file'});
137 }
138
139 # cancel_job(printer, job)
140 # Calls lprm to remove some job
141 sub cancel_job
142 {
143 local($out);
144 local $esc = quotemeta($_[0]);
145 local $iesc = quotemeta($_[1]);
146 $out = &backquote_logged("lprm -P$esc $iesc 2>&1");
147 if ($?) { &error("lprm failed : $out"); }
148 }
149
150 # make_printcap(&details, &old)
151 # Updates or creates a printcap line
152 sub make_printcap
153 {
154 local(%prn, %cap, $a, $rv, $c);
155 %prn = %{$_[0]}; %cap = %{$_[1]};
156 $cap{'if'} = $prn{'iface'} ? $prn{'iface'} : undef;
157 $cap{'sh'} = $prn{'banner'} ? undef : "";
158 $cap{'lp'} = $prn{'dev'} ? $prn{'dev'} : undef;
159 $cap{'rm'} = $prn{'rhost'} ? $prn{'rhost'} : undef;
160 $cap{'rp'} = $prn{'rqueue'} ? $prn{'rqueue'} : undef;
161 $cap{'mx'} = defined($prn{'msize'}) ? $prn{'msize'} : undef;
162 $rv = $prn{'name'};
163 foreach $a (@{$prn{'alias'}}) { $rv .= "|$a"; }
164 $rv .= "|$prn{'desc'}";
165 foreach $c (keys %cap) {
166         if (length($c) == 2 && defined($cap{$c})) {
167                 if ($cap{$c} eq "") { $rv .= ":$c"; }
168                 elsif ($cap{$c} =~ /^\d+$/) { $rv .= ":$c#$cap{$c}"; }
169                 else { $rv .= ":$c=$cap{$c}"; }
170                 }
171         }
172 $rv .= ":";
173 return $rv;
174 }
175
176 # list_printcap()
177 # Returns an array of associative arrays containing printcap fields
178 sub list_printcap
179 {
180 return @list_printcap_cache if (scalar(@list_printcap_cache));
181 local(@rv, @line, $line, $cont, $lnum, $i, %done, $capfile);
182 foreach $capfile ($config{'printcap_file'}, $config{'ro_printcap_file'}) {
183         next if (!$capfile || $done{$capfile}++);
184         open(CAP, $capfile);
185         $lnum = 0;
186         while($line = <CAP>) {
187                 $line =~ s/^#.*$//g;    # remove comments
188                 $line =~ s/\s+$//g;     # remove trailing spaces
189                 $line =~ s/^\s+//g;     # remove leading spaces
190                 if ($line =~ /\S/) {
191                         $ncont = ($line =~ s/\\$//g);
192                         if ($cont) {
193                                 $line[$#line] .= $line;
194                                 $eline[@line - 1] = $lnum;
195                                 }
196                         else {
197                                 push(@line, $line);
198                                 $eline[@line - 1] = $sline[@line - 1] = $lnum;
199                                 }
200                         $cont = $ncont;
201                         }
202                 $lnum++;
203                 }
204         close(CAP);
205         for($i=0; $i<@line; $i++) {
206                 local(%cap);
207                 @w = split(/:+/, $line[$i]);
208                 $cap{'name'} = $w[0];
209                 $cap{'line'} = $sline[$i];
210                 $cap{'eline'} = $eline[$i];
211                 $cap{'file'} = $capfile;
212                 foreach $w (@w[1..$#w]) {
213                         if ($w =~ /^([A-z0-9]+)[=#](.*)$/) { $cap{$1} = $2; }
214                         elsif ($w =~ /^([A-z0-9]+)$/) { $cap{$w} = ""; }
215                         }
216                 push(@rv, \%cap);
217                 }
218         }
219 @list_printcap_cache = @rv;
220 return @rv;
221 }
222
223 # apply_status(&details)
224 # Calls lpc to enable or disable a printer.
225 # Restarting lpd doesn't seem to be necessary?
226 sub apply_status
227 {
228 local($out);
229 local $esc = quotemeta($_[0]->{'name'});
230 $out = &backquote_command("lpc status $esc 2>&1", 1);
231 if ($_[0]->{'enabled'} && $out !~ /printing is enabled/)
232         { &backquote_logged("lpc up $esc"); }
233 elsif (!$_[0]->{'enabled'} && $out =~ /printing is enabled/)
234         { &backquote_logged("lpc down $esc"); }
235 if ($_[0]->{'accepting'} && $out !~ /queuing is enabled/)
236         { &backquote_logged("lpc enable $esc"); }
237 elsif (!$_[0]->{'accepting'} && $out =~ /queuing is enabled/)
238         { &backquote_logged("lpc disable $esc"); }
239 }
240
241 # sched_running()
242 # Returns the pid if lpsched is running, 0 if not, -1 if cannot be stopped
243 sub sched_running
244 {
245 @pid = &find_byname("lpd");
246 if (@pid) { return $pid[0]; }
247 return 0;
248 }
249
250 # start_sched()
251 # Start lpsched
252 sub start_sched
253 {
254 local $out = &backquote_logged("lpd 2>&1");
255 if ($?) { &error("failed to start lpd : <tt>$out</tt>"); }
256 }
257
258 # stop_sched(pid)
259 # Stop the running lpsched process
260 sub stop_sched
261 {
262 local @pid = &find_byname("lpd");
263 &kill_logged('TERM', @pid) || &error("Failed to stop lpd : $!");
264 }
265
266 # print_command(printer, file)
267 # Returns the command to print some file on some printer
268 sub print_command
269 {
270 local $esc = quotemeta($_[0]);
271 local $fesc = quotemeta($_[1]);
272 return "lpr -P$esc $fesc";
273 }
274
275 # check_print_system()
276 sub check_print_system
277 {
278 &has_command("lpr") || return &text('freebsd_ecmd', "<tt>lpr</tt>");
279 -d $config{'spool_dir'} || return &text('freebsd_espool', "<tt>$config{'spool_dir'}</tt>");
280 return undef;
281 }
282
283 if ($gconfig{'os_type'} eq 'openbsd') {
284         @device_files = ("/dev/lpt0", "/dev/cua00", "/dev/cua01");
285         }
286 else {
287         @device_files = ("/dev/lpt0", "/dev/cuaa0", "/dev/cuaa1");
288         }
289 @device_names = ($text{'freebsd_paralel'}, &text('freebsd_serial', "1"),
290                  &text('freebsd_serial', "2"));
291