Handle hostnames with upper-case letters
[webmin.git] / lpadmin / hpux-lib.pl
1 # hpux-lib.pl
2 # Functions for hpux-style printer management
3
4 $hpux_iface_path = "/usr/spool/lp/interface";
5
6 # list_printers()
7 # Returns an array of known printer names
8 sub list_printers
9 {
10 local(@rv, $_);
11 open(STAT, "lpstat -p |");
12 while(<STAT>) {
13         if (/^printer\s+(\S+)/) { push(@rv, $1); }
14         }
15 close(STAT);
16
17 # make models executable
18 &system_logged("chmod 755 $config{'model_path'}/* >/dev/null 2>&1");
19
20 return &unique(@rv);
21 }
22
23 # get_printer(name, [nostatus])
24 # Returns a reference to an associative array of printer details
25 sub get_printer
26 {
27 local($stat, @rv, $body1, $body2, $avl, $con, $sys, %prn, $_, $out);
28 local $esc = quotemeta($_[0]);
29 $out = &backquote_command("lpstat -p$esc", 1);
30 if ($out =~ /^printer\s+(\S+)\s+(.*)\n(.*)\n(.*)$/) {
31         # printer exists
32         $prn{'name'} = $1;
33         if ($2 =~ /enabled/) {$prn{'enabled'} = "enabled"};
34         $body1 = $3;
35         $body2 = $4;
36         }
37 else {
38         # no printer found
39         return undef;
40         }
41
42 # Interface
43 $prn{'iface'} = "$hpux_iface_path/$prn{'name'}";
44
45 # Description
46 local $wdrv = &is_windows_driver($prn{'iface'});
47 local $hdrv = &is_hpnp_driver($prn{'iface'});
48 $prn{'desc'} = $wdrv ? &grep_interface($wdrv->{'program'}) :
49                $hdrv ? &grep_interface($hdrv->{'program'}) :
50                        &grep_interface($prn{'iface'});
51
52 # printer enabled?
53 if (!$prn{'enabled'} && $body1 =~ /^\s+(.*)/) {
54         $prn{'enabled_why'} = $1 eq "reason unknown" ? "" : $1;
55         }
56
57 if (!$_[1]) {
58         # request availability
59         $avl = &backquote_command("lpstat -a$esc 2>&1", 1);
60         if ($avl =~ /^\S+\s+not accepting.*\n\s+(.*)/) {
61                 $prn{'accepting'} = 0;
62                 $prn{'accepting_why'} = $1;
63                 if ($prn{'accepting_why'} eq "reason unknown") {
64                         $prn{'accepting_why'} = "";
65                         }
66                 }
67         else { $prn{'accepting'} = 1; }
68         }
69
70 # request connection
71 $con = &backquote_command("lpstat -v$esc 2>&1", 1);
72 if ($con =~ /^device for \S+:\s+(\S+)\n\s+(remote to:)\s+(\S+)\s+(on)\s+(\S+)/) {
73         $prn{'rhost'} = $5;
74         $prn{'rqueue'} = $3;
75         }
76 elsif ($con =~ /^device for \S+:\s+(\S+)/) { $prn{'dev'} = $1; }
77
78 # Check if this is the default printer
79 if (&backquote_command("lpstat -d 2>&1", 1) =~ /: (\S+)/ &&
80     $1 eq $prn{'name'}) {
81         $prn{'default'} = 1;
82         }
83
84 return \%prn;
85 }
86
87 sub get_jobs
88 {
89 local $esc = quotemeta($_[0]);
90 open(STAT, "lpstat -o$esc |");
91 local($id, $user, $prio, $when, $printing);
92 while(<STAT>) {
93         if (/^(\S+-\d+)\s+(\S+)\s+priority\s+(\S+)\s+(\S+.*\d+ \d+:\d+)\s+(.*)/) {
94                 $id = $1;
95                 $user = $2;
96                 $prio = $3;
97                 $when = $4;
98                 $printing = ($5 =~ /^on /);
99                 }
100         elsif (/^(\S+-\d+)\s+(\S+)\s+priority\s+(\S+)\s+from\s+(\S+)\s+(.*)/) {
101                 $id = $1;
102                 $user = "$2\@$4";
103                 $prio = $3;
104                 $when = "?";
105                 $printing = ($5 =~ /^on /);
106                 }
107         elsif (/^(.*)\s+(\d+) bytes/) {
108                 local(%job);
109                 $job{'id'} = $id;
110                 $job{'user'} = $user;
111                 $job{'prio'} = $prio;
112                 $job{'when'} = $when;
113                 $job{'printing'} = $printing;
114                 $job{'file'} = $1;
115                 $job{'size'} = $2;
116                 push(@jobs, \%job);
117                 }
118         }
119 close(STAT);
120 return @jobs;
121 }
122
123 # grep_interface($iface)
124 # try to find a description in the interface/model
125 sub grep_interface
126 {
127 local($iface, $desc, $out);
128 $iface = $_[0];
129
130 local $drv = &is_driver($iface);
131 if ($drv->{'mode'} == 1) {
132         $desc = $drv->{'desc'};
133         }
134 elsif ($drv->{'mode'} == 2) {
135         $out = &backquote_command("head $drv->{'prog'} | grep -e interface -e Printer -e /model/", 1);
136         if ($out =~ /interface for\s+(.*)/) { $desc = $1; }
137         elsif ($out =~ /\s+(\S.*)interface/) { $desc = $1; }
138         elsif ($out =~ /Printer Command Language level\s+(\S+)/) { $desc = "PCL$1"; }
139         elsif ($out =~ /\/model\/(\S+).*/) { $desc = $1; }
140         elsif ($out =~ /^#\s+(.*)/) { $desc = $1; }
141         else { $desc = "None"; }
142         }
143 else {
144         $desc = "None";
145         }
146 return $desc;
147 }
148
149 # printer_support(option)
150 sub printer_support
151 {
152 return $_[0] !~ /^(allow|alias|ctype|banner|desc|editdest|msize|direct|rnoqueue|ipp)$/;
153 }
154
155 # list_classes()
156 # Returns an associative array of print classes
157 sub list_classes
158 {
159 local($stat, %rv);
160 $stat = &backquote_command("lpstat -c 2>&1", 1);
161 while($stat =~ /^members of class (\S+):\n((\s+\S+\n)+)([\000-\377]*)$/) {
162         $stat = $4;
163         $rv{$1} = [ grep { $_ ne "" } split(/\s+/, $2) ];
164         }
165 return \%rv;
166 }
167
168 # create_printer(&details)
169 # Create a new printer
170 sub create_printer
171 {
172 local(%prn, $cmd, $out, $model, $dummy, $scheduler);
173 %prn = %{$_[0]};
174 local $wdrv = &is_windows_driver($prn{'iface'});
175 local $hdrv = &is_hpnp_driver($prn{'iface'});
176 $scheduler = &sched_running();
177 $dummy = "webmin.tmp";
178 &system_logged("touch $config{'model_path'}/$dummy");
179
180 # create lpadmin command
181 local $esc = quotemeta($prn{'name'});
182 $cmd = "lpadmin -p$esc";
183
184 ## remote unix printer
185 if ($prn{'rhost'}) {
186         if ($prn{'iface'}) {
187                 &error("lpadmin failed : <pre>No model allowed for remote unix printer.</pre>");
188         }
189         $cmd .= " -orm".quotemeta($prn{'rhost'});
190         $cmd .= " -orp".quotemeta($prn{'rqueue'});
191         $cmd .= " -mrmodel";
192         $cmd .= " -ocmrcmodel";
193         $cmd .= " -osmrsmodel";
194         $cmd .= " -v/dev/null";
195         $cmd .= " -orc";
196         if ($prn{'rtype'} =~ /^BSD$/) {
197                 $cmd .= " -ob3";
198                 }
199         }
200
201 ## remote windows printer
202 elsif ($wdrv) {
203         $cmd .= " -m$dummy";
204         $cmd .= " -v/dev/null";
205         $cmd .= " -g0";
206         }
207
208 ## remote HPNP printer
209 elsif ($hdrv) {
210         $cmd .= " -m$dummy";
211         $cmd .= " -v/dev/null";
212         $cmd .= " -g0";
213         }
214
215 ## local printer with webmin driver
216 elsif ($prn{'iface'} eq "$drivers_directory/$prn{'name'}") {
217         $cmd .= " -m$dummy";
218         $cmd .= " -v".quotemeta($prn{'dev'});
219         $cmd .= " -g0";
220         }
221
222 ## local printer with HP-UX model
223 elsif ($prn{'iface'} =~ $config{'model_path'}) {
224         $model = substr($prn{'iface'}, length($config{'model_path'}) + 1);
225         $cmd .= " -m$model";
226         $cmd .= " -v".quotemeta($prn{'dev'});
227         $cmd .= " -g0";
228         }
229 else {
230         &error("lpadmin failed : <pre>Action not supported.</pre>");
231         }
232
233 # stop scheduler
234 $out = &backquote_logged("lpshut 2>&1");
235
236 # call lpadmin
237 $out = &backquote_logged("$cmd 2>&1");
238 if ($?) { &error("lpsched failed : <pre>$out</pre>"); }
239
240 ## Link to windows webmin driver
241 &lock_file("$hpux_iface_path/$prn{'name'}");
242 if ($wdrv) {
243         &unlink_file("$hpux_iface_path/$prn{'name'}");
244         &symlink_file("$drivers_directory/$prn{'name'}.smb",
245                         "$hpux_iface_path/$prn{'name'}");
246         }
247
248 ## Link to webmin hpnp driver
249 if ($hdrv) {
250         &unlink_file("$hpux_iface_path/$prn{'name'}");
251         &symlink_file("$drivers_directory/$prn{'name'}.hpnp",
252                         "$hpux_iface_path/$prn{'name'}");
253         }
254
255 ## Link to webmin driver
256 if ($prn{'iface'} eq "$drivers_directory/$prn{'name'}" && !$wdrv) {
257         &unlink_file("$hpux_iface_path/$prn{'name'}");
258         &symlink_file("$drivers_directory/$prn{'name'}",
259                         "$hpux_iface_path/$prn{'name'}");
260         }
261 &unlock_file("$hpux_iface_path/$prn{'name'}");
262
263 &lock_file("$config{'model_path'}/$dummy");
264 &unlink_file("$config{'model_path'}/$dummy");
265 &unlock_file("$config{'model_path'}/$dummy");
266
267 # start scheduler
268 if ($scheduler) {
269         $out = &backquote_logged("lpsched 2>&1");
270         if ($?) { &error("lpsched failed : <pre>$out</pre>"); }
271         }
272
273 &modify_printer($_[0]);
274 }
275
276 # modify_printer(&details)
277 # Change an existing printer
278 sub modify_printer
279 {
280 local(%prn, $cmd, $out);
281 %prn = %{$_[0]};
282
283 # make the default
284 local $esc = quotemeta($prn{'name'});
285 if ($prn{'default'}) {
286         $out = &backquote_logged("lpadmin -d$esc 2>&1");
287         if ($?) { &error("Failed to set default : <pre>$out</pre>"); }
288         }
289
290 # enable or disable
291 if ($prn{'enabled'}) { $cmd = "enable $esc"; }
292 elsif ($prn{'enabled_why'}) {
293         local $wesc = quotemeta($prn{'enabled_why'});
294         $cmd = "enable $esc ; disable -r$wesc $esc";
295         }
296 else { $cmd = "enable $esc ; disable $esc"; }
297 $out = &backquote_logged("$cmd 2>&1");
298
299 # accepting or rejecting requests
300 if ($prn{'accepting'}) { $cmd = "accept $esc"; }
301 elsif ($prn{'accepting_why'}) {
302         local $wesc = quotemeta($prn{'accepting_why'});
303         $cmd = "accept $esc ; reject -r$wesc $esc";
304         }
305 else { $cmd = "accept $esc ; reject $esc"; }
306 $out = &backquote_logged("$cmd 2>&1");
307 }
308
309 # delete_printer(name)
310 # Deletes some existing printer
311 sub delete_printer
312 {
313 local($out, $scheduler);
314 $scheduler = &sched_running();
315
316 # delete print jobs
317 local $esc = quotemeta($_[0]);
318 $out = &backquote_logged("cancel $esc -a 2>1");
319 if ($?) { &error("cancel failed : <pre>$out</pre>"); }
320
321 # stop scheduler
322 $out = &backquote_logged("lpshut 2>&1");
323
324 # call lpadmin
325 $out = &backquote_logged("lpadmin -x$esc 2>&1");
326 if ($?) { &error("lpadmin failed : <pre>$out</pre>"); }
327
328 # start scheduler
329 if ($scheduler) {
330         $out = &backquote_logged("lpsched 2>&1");
331         if ($?) { &error("lpsched failed : <pre>$out</pre>"); }
332         }
333 }
334
335 # cancel_job(printer, id)
336 # Cancels some print job
337 sub cancel_job
338 {
339 local($out);
340 local $esc = quotemeta($_[1]);
341 $out = &backquote_logged("cancel $esc 2>&1");
342 if ($?) { &error("cancel failed : <pre>$out</pre>"); }
343 sleep(1);
344 }
345
346 # sched_running()
347 # Returns 1 if running and 0 if not running
348 sub sched_running
349 {
350 local $out = &backquote_command("lpstat -r 2>&1", 1);
351 if ($out =~ /not/) { return 0; }
352 else { return 1; }
353 }
354
355 # start_sched()
356 # Start lpsched
357 sub start_sched
358 {
359 local $out = &backquote_logged("lpsched 2>&1");
360 if ($?) { &error("failed to start lpsched : <tt>$out</tt>"); }
361 }
362
363 # stop_sched(pid)
364 # Stop the running lpsched process
365 sub stop_sched
366 {
367 local $out = &backquote_logged("lpshut 2>&1");
368 if ($?) { &error("lpshut failed : <tt>$out</tt>"); }
369 }
370
371 # print_command(printer, file)
372 # Returns the command to print some file on some printer
373 sub print_command
374 {
375 local $esc = quotemeta($_[0]);
376 local $iesc = quotemeta($_[1]);
377 return "lp -d $esc $iesc";
378 }
379
380 # check_print_system()
381 sub check_print_system
382 {
383 &has_command("lpstat") || return &text('hpux_ecmd', "<tt>lpstat</tt>");
384 -d $hpux_iface_path || return &text('hpux_eiface',"<tt>$hpux_iface_path</tt>");
385 return undef;
386 }
387
388 @device_files = ("/dev/c1t0d0_lp", "/dev/c2t0d0_lp",
389                  "/dev/c0p0_lp", "/dev/c0p1_lp",
390                  "/dev/c0p2_lp", "/dev/c0p3_lp",
391                  "/dev/c0p4_lp", "/dev/c0p4_lp",
392                  "/dev/c0p5_lp", "/dev/c0p5_lp",
393                  "/dev/c1p0_lp",
394                  "/dev/null");
395 @device_names = (&text('hpux_paralel', "c1t0d0"), &text('hpux_paralel', "c2t0d0"),
396                  &text('hpux_serial', "c0p0"), &text('hpux_serial', "c0p1"),
397                  &text('hpux_serial', "c0p2"), &text('hpux_serial', "c0p3"),
398                  &text('hpux_serial', "c0p4"), &text('hpux_serial', "c0p5"),
399                  &text('hpux_serial', "c0p6"), &text('hpux_serial', "c0p7"),
400                  &text('hpux_serial', "c1p0"), $text{'hpux_null'});