Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / samba / source / printing / printing.c
blobe3743f138dab29c39f34506ba3d70d7baf18250c
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 printing routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
23 extern int DEBUGLEVEL;
25 static BOOL * lpq_cache_reset=NULL;
27 static int check_lpq_cache(int snum) {
28 static int lpq_caches=0;
29 int i;
31 if (lpq_caches <= snum) {
32 BOOL * p;
33 p = (BOOL *) Realloc(lpq_cache_reset,(snum+1)*sizeof(BOOL));
34 if (p) {
35 lpq_cache_reset=p;
36 for (i=lpq_caches; i<snum+1; i++) lpq_cache_reset[i] = False;
37 lpq_caches = snum+1;
40 return lpq_caches;
43 void lpq_reset(int snum)
45 if (check_lpq_cache(snum) > snum) lpq_cache_reset[snum]=True;
49 /****************************************************************************
50 Build the print command in the supplied buffer. This means getting the
51 print command for the service and inserting the printer name and the
52 print file name. Return NULL on error, else the passed buffer pointer.
53 ****************************************************************************/
54 static char *build_print_command(connection_struct *conn,
55 char *command,
56 char *syscmd, char *filename)
58 int snum = SNUM(conn);
59 char *tstr;
61 /* get the print command for the service. */
62 tstr = command;
63 if (!syscmd || !tstr) {
64 DEBUG(0,("No print command for service `%s'\n",
65 SERVICE(snum)));
66 return (NULL);
69 /* copy the command into the buffer for extensive meddling. */
70 StrnCpy(syscmd, tstr, sizeof(pstring) - 1);
72 /* look for "%s" in the string. If there is no %s, we cannot print. */
73 if (!strstr(syscmd, "%s") && !strstr(syscmd, "%f")) {
74 DEBUG(2,("WARNING! No placeholder for the filename in the print command for service %s!\n", SERVICE(snum)));
77 pstring_sub(syscmd, "%s", filename);
78 pstring_sub(syscmd, "%f", filename);
80 /* Does the service have a printername? If not, make a fake
81 and empty */
82 /* printer name. That way a %p is treated sanely if no printer */
83 /* name was specified to replace it. This eventuality is logged. */
84 tstr = PRINTERNAME(snum);
85 if (tstr == NULL || tstr[0] == '\0') {
86 DEBUG(3,( "No printer name - using %s.\n", SERVICE(snum)));
87 tstr = SERVICE(snum);
90 pstring_sub(syscmd, "%p", tstr);
92 standard_sub(conn,syscmd);
94 return (syscmd);
98 /****************************************************************************
99 print a file - called on closing the file
100 ****************************************************************************/
101 void print_file(connection_struct *conn, files_struct *file)
103 pstring syscmd;
104 int snum = SNUM(conn);
105 char *tempstr;
107 *syscmd = 0;
109 if (dos_file_size(file->fsp_name) <= 0) {
110 DEBUG(3,("Discarding null print job %s\n",file->fsp_name));
111 dos_unlink(file->fsp_name);
112 return;
115 tempstr = build_print_command(conn,
116 PRINTCOMMAND(snum),
117 syscmd, file->fsp_name);
118 if (tempstr != NULL) {
119 int ret = smbrun(syscmd,NULL,False);
120 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
121 } else {
122 DEBUG(0,("Null print command?\n"));
125 lpq_reset(snum);
128 static char *Months[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
129 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err"};
132 /*******************************************************************
133 process time fields
134 ********************************************************************/
135 static time_t EntryTime(fstring tok[], int ptr, int count, int minimum)
137 time_t jobtime,jobtime1;
139 jobtime = time(NULL); /* default case: take current time */
140 if (count >= minimum) {
141 struct tm *t;
142 int i, day, hour, min, sec;
143 char *c;
145 for (i=0; i<13; i++) if (!strncmp(tok[ptr], Months[i],3)) break; /* Find month */
146 if (i<12) {
147 t = localtime(&jobtime);
148 day = atoi(tok[ptr+1]);
149 c=(char *)(tok[ptr+2]);
150 *(c+2)=0;
151 hour = atoi(c);
152 *(c+5)=0;
153 min = atoi(c+3);
154 if(*(c+6) != 0)sec = atoi(c+6);
155 else sec=0;
157 if ((t->tm_mon < i)||
158 ((t->tm_mon == i)&&
159 ((t->tm_mday < day)||
160 ((t->tm_mday == day)&&
161 (t->tm_hour*60+t->tm_min < hour*60+min)))))
162 t->tm_year--; /* last year's print job */
164 t->tm_mon = i;
165 t->tm_mday = day;
166 t->tm_hour = hour;
167 t->tm_min = min;
168 t->tm_sec = sec;
169 jobtime1 = mktime(t);
170 if (jobtime1 != (time_t)-1)
171 jobtime = jobtime1;
174 return jobtime;
178 /****************************************************************************
179 parse a lpq line
181 here is an example of lpq output under bsd
183 Warning: no daemon present
184 Rank Owner Job Files Total Size
185 1st tridge 148 README 8096 bytes
187 here is an example of lpq output under osf/1
189 Warning: no daemon present
190 Rank Pri Owner Job Files Total Size
191 1st 0 tridge 148 README 8096 bytes
194 <allan@umich.edu> June 30, 1998.
195 Modified to handle file names with spaces, like the parse_lpq_lprng code
196 further below.
197 ****************************************************************************/
198 static BOOL parse_lpq_bsd(char *line,print_queue_struct *buf,BOOL first)
200 #ifdef OSF1
201 #define RANKTOK 0
202 #define PRIOTOK 1
203 #define USERTOK 2
204 #define JOBTOK 3
205 #define FILETOK 4
206 #define TOTALTOK (count - 2)
207 #define NTOK 6
208 #define MAXTOK 128
209 #else /* OSF1 */
210 #define RANKTOK 0
211 #define USERTOK 1
212 #define JOBTOK 2
213 #define FILETOK 3
214 #define TOTALTOK (count - 2)
215 #define NTOK 5
216 #define MAXTOK 128
217 #endif /* OSF1 */
219 char *tok[MAXTOK];
220 int count = 0;
221 pstring line2;
223 pstrcpy(line2,line);
225 #ifdef OSF1
227 size_t length;
228 length = strlen(line2);
229 if (line2[length-3] == ':')
230 return(False);
232 #endif /* OSF1 */
234 tok[0] = strtok(line2," \t");
235 count++;
237 while (((tok[count] = strtok(NULL," \t")) != NULL) && (count < MAXTOK)) {
238 count++;
241 /* we must get at least NTOK tokens */
242 if (count < NTOK)
243 return(False);
245 /* the Job and Total columns must be integer */
246 if (!isdigit((int)*tok[JOBTOK]) || !isdigit((int)*tok[TOTALTOK])) return(False);
248 buf->job = atoi(tok[JOBTOK]);
249 buf->size = atoi(tok[TOTALTOK]);
250 buf->status = strequal(tok[RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED;
251 buf->time = time(NULL);
252 StrnCpy(buf->user,tok[USERTOK],sizeof(buf->user)-1);
253 StrnCpy(buf->file,tok[FILETOK],sizeof(buf->file)-1);
255 if ((FILETOK + 1) != TOTALTOK) {
256 int bufsize;
257 int i;
259 bufsize = sizeof(buf->file) - strlen(buf->file) - 1;
261 for (i = (FILETOK + 1); i < TOTALTOK; i++) {
262 safe_strcat(buf->file," ",bufsize);
263 safe_strcat(buf->file,tok[i],bufsize - 1);
264 bufsize = sizeof(buf->file) - strlen(buf->file) - 1;
265 if (bufsize <= 0) {
266 break;
269 /* Ensure null termination. */
270 buf->file[sizeof(buf->file)-1] = '\0';
273 #ifdef PRIOTOK
274 buf->priority = atoi(tok[PRIOTOK]);
275 #else
276 buf->priority = 1;
277 #endif
278 return(True);
282 <magnus@hum.auc.dk>
283 LPRng_time modifies the current date by inserting the hour and minute from
284 the lpq output. The lpq time looks like "23:15:07"
286 <allan@umich.edu> June 30, 1998.
287 Modified to work with the re-written parse_lpq_lprng routine.
289 static time_t LPRng_time(char *time_string)
291 time_t jobtime;
292 struct tm *t;
294 jobtime = time(NULL); /* default case: take current time */
295 t = localtime(&jobtime);
296 t->tm_hour = atoi(time_string);
297 t->tm_min = atoi(time_string+3);
298 t->tm_sec = atoi(time_string+6);
299 jobtime = mktime(t);
301 return jobtime;
305 /****************************************************************************
306 parse a lprng lpq line
307 <allan@umich.edu> June 30, 1998.
308 Re-wrote this to handle file names with spaces, multiple file names on one
309 lpq line, etc;
310 ****************************************************************************/
311 static BOOL parse_lpq_lprng(char *line,print_queue_struct *buf,BOOL first)
313 #define LPRNG_RANKTOK 0
314 #define LPRNG_USERTOK 1
315 #define LPRNG_PRIOTOK 2
316 #define LPRNG_JOBTOK 3
317 #define LPRNG_FILETOK 4
318 #define LPRNG_TOTALTOK (num_tok - 2)
319 #define LPRNG_TIMETOK (num_tok - 1)
320 #define LPRNG_NTOK 7
321 #define LPRNG_MAXTOK 128 /* PFMA just to keep us from running away. */
323 char *tokarr[LPRNG_MAXTOK];
324 char *cptr;
325 int num_tok = 0;
326 pstring line2;
328 pstrcpy(line2,line);
329 tokarr[0] = strtok(line2," \t");
330 num_tok++;
331 while (((tokarr[num_tok] = strtok(NULL," \t")) != NULL)
332 && (num_tok < LPRNG_MAXTOK)) {
333 num_tok++;
336 /* We must get at least LPRNG_NTOK tokens. */
337 if (num_tok < LPRNG_NTOK) {
338 return(False);
341 if (!isdigit((int)*tokarr[LPRNG_JOBTOK]) || !isdigit((int)*tokarr[LPRNG_TOTALTOK])) {
342 return(False);
345 buf->job = atoi(tokarr[LPRNG_JOBTOK]);
346 buf->size = atoi(tokarr[LPRNG_TOTALTOK]);
348 if (strequal(tokarr[LPRNG_RANKTOK],"active")) {
349 buf->status = LPQ_PRINTING;
350 } else if (isdigit((int)*tokarr[LPRNG_RANKTOK])) {
351 buf->status = LPQ_QUEUED;
352 } else {
353 buf->status = LPQ_PAUSED;
356 buf->priority = *tokarr[LPRNG_PRIOTOK] -'A';
358 buf->time = LPRng_time(tokarr[LPRNG_TIMETOK]);
360 StrnCpy(buf->user,tokarr[LPRNG_USERTOK],sizeof(buf->user)-1);
362 /* The '@hostname' prevents windows from displaying the printing icon
363 * for the current user on the taskbar. Plop in a null.
366 if ((cptr = strchr(buf->user,'@')) != NULL) {
367 *cptr = '\0';
370 StrnCpy(buf->file,tokarr[LPRNG_FILETOK],sizeof(buf->file)-1);
372 if ((LPRNG_FILETOK + 1) != LPRNG_TOTALTOK) {
373 int bufsize;
374 int i;
376 bufsize = sizeof(buf->file) - strlen(buf->file) - 1;
378 for (i = (LPRNG_FILETOK + 1); i < LPRNG_TOTALTOK; i++) {
379 safe_strcat(buf->file," ",bufsize);
380 safe_strcat(buf->file,tokarr[i],bufsize - 1);
381 bufsize = sizeof(buf->file) - strlen(buf->file) - 1;
382 if (bufsize <= 0) {
383 break;
386 /* Ensure null termination. */
387 buf->file[sizeof(buf->file)-1] = '\0';
390 return(True);
395 /*******************************************************************
396 parse lpq on an aix system
398 Queue Dev Status Job Files User PP % Blks Cp Rnk
399 ------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
400 lazer lazer READY
401 lazer lazer RUNNING 537 6297doc.A kvintus@IE 0 10 2445 1 1
402 QUEUED 538 C.ps root@IEDVB 124 1 2
403 QUEUED 539 E.ps root@IEDVB 28 1 3
404 QUEUED 540 L.ps root@IEDVB 172 1 4
405 QUEUED 541 P.ps root@IEDVB 22 1 5
406 ********************************************************************/
407 static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first)
409 fstring tok[11];
410 int count=0;
412 /* handle the case of "(standard input)" as a filename */
413 pstring_sub(line,"standard input","STDIN");
414 all_string_sub(line,"(","\"",0);
415 all_string_sub(line,")","\"",0);
417 for (count=0;
418 count<10 &&
419 next_token(&line,tok[count],NULL, sizeof(tok[count]));
420 count++) ;
422 /* we must get 6 tokens */
423 if (count < 10)
425 if ((count == 7) && ((strcmp(tok[0],"QUEUED") == 0) || (strcmp(tok[0],"HELD") == 0)))
427 /* the 2nd and 5th columns must be integer */
428 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4])) return(False);
429 buf->size = atoi(tok[4]) * 1024;
430 /* if the fname contains a space then use STDIN */
431 if (strchr(tok[2],' '))
432 fstrcpy(tok[2],"STDIN");
434 /* only take the last part of the filename */
436 fstring tmp;
437 char *p = strrchr(tok[2],'/');
438 if (p)
440 fstrcpy(tmp,p+1);
441 fstrcpy(tok[2],tmp);
446 buf->job = atoi(tok[1]);
447 buf->status = strequal(tok[0],"HELD")?LPQ_PAUSED:LPQ_QUEUED;
448 buf->priority = 0;
449 buf->time = time(NULL);
450 StrnCpy(buf->user,tok[3],sizeof(buf->user)-1);
451 StrnCpy(buf->file,tok[2],sizeof(buf->file)-1);
453 else
455 DEBUG(6,("parse_lpq_aix count=%d\n", count));
456 return(False);
459 else
461 /* the 4th and 9th columns must be integer */
462 if (!isdigit((int)*tok[3]) || !isdigit((int)*tok[8])) return(False);
463 buf->size = atoi(tok[8]) * 1024;
464 /* if the fname contains a space then use STDIN */
465 if (strchr(tok[4],' '))
466 fstrcpy(tok[4],"STDIN");
468 /* only take the last part of the filename */
470 fstring tmp;
471 char *p = strrchr(tok[4],'/');
472 if (p)
474 fstrcpy(tmp,p+1);
475 fstrcpy(tok[4],tmp);
480 buf->job = atoi(tok[3]);
481 buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED;
482 buf->priority = 0;
483 buf->time = time(NULL);
484 StrnCpy(buf->user,tok[5],sizeof(buf->user)-1);
485 StrnCpy(buf->file,tok[4],sizeof(buf->file)-1);
489 return(True);
493 /****************************************************************************
494 parse a lpq line
495 here is an example of lpq output under hpux; note there's no space after -o !
496 $> lpstat -oljplus
497 ljplus-2153 user priority 0 Jan 19 08:14 on ljplus
498 util.c 125697 bytes
499 server.c 110712 bytes
500 ljplus-2154 user priority 0 Jan 19 08:14 from client
501 (standard input) 7551 bytes
502 ****************************************************************************/
503 static BOOL parse_lpq_hpux(char * line, print_queue_struct *buf, BOOL first)
505 /* must read two lines to process, therefore keep some values static */
506 static BOOL header_line_ok=False, base_prio_reset=False;
507 static fstring jobuser;
508 static int jobid;
509 static int jobprio;
510 static time_t jobtime;
511 static int jobstat=LPQ_QUEUED;
512 /* to store minimum priority to print, lpstat command should be invoked
513 with -p option first, to work */
514 static int base_prio;
516 int count;
517 char htab = '\011';
518 fstring tok[12];
520 /* If a line begins with a horizontal TAB, it is a subline type */
522 if (line[0] == htab) { /* subline */
523 /* check if it contains the base priority */
524 if (!strncmp(line,"\tfence priority : ",18)) {
525 base_prio=atoi(&line[18]);
526 DEBUG(4, ("fence priority set at %d\n", base_prio));
528 if (!header_line_ok) return (False); /* incorrect header line */
529 /* handle the case of "(standard input)" as a filename */
530 pstring_sub(line,"standard input","STDIN");
531 all_string_sub(line,"(","\"",0);
532 all_string_sub(line,")","\"",0);
534 for (count=0; count<2 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
535 /* we must get 2 tokens */
536 if (count < 2) return(False);
538 /* the 2nd column must be integer */
539 if (!isdigit((int)*tok[1])) return(False);
541 /* if the fname contains a space then use STDIN */
542 if (strchr(tok[0],' '))
543 fstrcpy(tok[0],"STDIN");
545 buf->size = atoi(tok[1]);
546 StrnCpy(buf->file,tok[0],sizeof(buf->file)-1);
548 /* fill things from header line */
549 buf->time = jobtime;
550 buf->job = jobid;
551 buf->status = jobstat;
552 buf->priority = jobprio;
553 StrnCpy(buf->user,jobuser,sizeof(buf->user)-1);
555 return(True);
557 else { /* header line */
558 header_line_ok=False; /* reset it */
559 if (first) {
560 if (!base_prio_reset) {
561 base_prio=0; /* reset it */
562 base_prio_reset=True;
565 else if (base_prio) base_prio_reset=False;
567 /* handle the dash in the job id */
568 pstring_sub(line,"-"," ");
570 for (count=0; count<12 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
572 /* we must get 8 tokens */
573 if (count < 8) return(False);
575 /* first token must be printer name (cannot check ?) */
576 /* the 2nd, 5th & 7th column must be integer */
577 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4]) || !isdigit((int)*tok[6])) return(False);
578 jobid = atoi(tok[1]);
579 StrnCpy(jobuser,tok[2],sizeof(buf->user)-1);
580 jobprio = atoi(tok[4]);
582 /* process time */
583 jobtime=EntryTime(tok, 5, count, 8);
584 if (jobprio < base_prio) {
585 jobstat = LPQ_PAUSED;
586 DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n", jobid, jobprio, base_prio, jobstat));
588 else {
589 jobstat = LPQ_QUEUED;
590 if ((count >8) && (((strequal(tok[8],"on")) ||
591 ((strequal(tok[8],"from")) &&
592 ((count > 10)&&(strequal(tok[10],"on")))))))
593 jobstat = LPQ_PRINTING;
596 header_line_ok=True; /* information is correct */
597 return(False); /* need subline info to include into queuelist */
602 /****************************************************************************
603 parse a lpstat line
605 here is an example of "lpstat -o dcslw" output under sysv
607 dcslw-896 tridge 4712 Dec 20 10:30:30 on dcslw
608 dcslw-897 tridge 4712 Dec 20 10:30:30 being held
610 ****************************************************************************/
611 static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first)
613 fstring tok[9];
614 int count=0;
615 char *p;
618 * Handle the dash in the job id, but make sure that we skip over
619 * the printer name in case we have a dash in that.
620 * Patch from Dom.Mitchell@palmerharvey.co.uk.
624 * Move to the first space.
626 for (p = line ; !isspace(*p) && *p; p++)
630 * Back up until the last '-' character or
631 * start of line.
633 for (; (p >= line) && (*p != '-'); p--)
636 if((p >= line) && (*p == '-'))
637 *p = ' ';
639 for (count=0; count<9 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++)
642 /* we must get 7 tokens */
643 if (count < 7)
644 return(False);
646 /* the 2nd and 4th, 6th columns must be integer */
647 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[3]))
648 return(False);
649 if (!isdigit((int)*tok[5]))
650 return(False);
652 /* if the user contains a ! then trim the first part of it */
653 if ((p=strchr(tok[2],'!'))) {
654 fstring tmp;
655 fstrcpy(tmp,p+1);
656 fstrcpy(tok[2],tmp);
659 buf->job = atoi(tok[1]);
660 buf->size = atoi(tok[3]);
661 if (count > 7 && strequal(tok[7],"on"))
662 buf->status = LPQ_PRINTING;
663 else if (count > 8 && strequal(tok[7],"being") && strequal(tok[8],"held"))
664 buf->status = LPQ_PAUSED;
665 else
666 buf->status = LPQ_QUEUED;
667 buf->priority = 0;
668 buf->time = EntryTime(tok, 4, count, 7);
669 StrnCpy(buf->user,tok[2],sizeof(buf->user)-1);
670 StrnCpy(buf->file,tok[2],sizeof(buf->file)-1);
671 return(True);
674 /****************************************************************************
675 parse a lpq line
677 here is an example of lpq output under qnx
678 Spooler: /qnx/spooler, on node 1
679 Printer: txt (ready)
680 0000: root [job #1 ] active 1146 bytes /etc/profile
681 0001: root [job #2 ] ready 2378 bytes /etc/install
682 0002: root [job #3 ] ready 1146 bytes -- standard input --
683 ****************************************************************************/
684 static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first)
686 fstring tok[7];
687 int count=0;
689 DEBUG(4,("antes [%s]\n", line));
691 /* handle the case of "-- standard input --" as a filename */
692 pstring_sub(line,"standard input","STDIN");
693 DEBUG(4,("despues [%s]\n", line));
694 all_string_sub(line,"-- ","\"",0);
695 all_string_sub(line," --","\"",0);
696 DEBUG(4,("despues 1 [%s]\n", line));
698 pstring_sub(line,"[job #","");
699 pstring_sub(line,"]","");
700 DEBUG(4,("despues 2 [%s]\n", line));
704 for (count=0; count<7 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
706 /* we must get 7 tokens */
707 if (count < 7)
708 return(False);
710 /* the 3rd and 5th columns must be integer */
711 if (!isdigit((int)*tok[2]) || !isdigit((int)*tok[4])) return(False);
713 /* only take the last part of the filename */
715 fstring tmp;
716 char *p = strrchr(tok[6],'/');
717 if (p)
719 fstrcpy(tmp,p+1);
720 fstrcpy(tok[6],tmp);
725 buf->job = atoi(tok[2]);
726 buf->size = atoi(tok[4]);
727 buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED;
728 buf->priority = 0;
729 buf->time = time(NULL);
730 StrnCpy(buf->user,tok[1],sizeof(buf->user)-1);
731 StrnCpy(buf->file,tok[6],sizeof(buf->file)-1);
732 return(True);
736 /****************************************************************************
737 parse a lpq line for the plp printing system
738 Bertrand Wallrich <Bertrand.Wallrich@loria.fr>
740 redone by tridge. Here is a sample queue:
742 Local Printer 'lp2' (fjall):
743 Printing (started at Jun 15 13:33:58, attempt 1).
744 Rank Owner Pr Opt Job Host Files Size Date
745 active tridge X - 6 fjall /etc/hosts 739 Jun 15 13:33
746 3rd tridge X - 7 fjall /etc/hosts 739 Jun 15 13:33
748 ****************************************************************************/
749 static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first)
751 fstring tok[11];
752 int count=0;
754 /* handle the case of "(standard input)" as a filename */
755 pstring_sub(line,"stdin","STDIN");
756 all_string_sub(line,"(","\"",0);
757 all_string_sub(line,")","\"",0);
759 for (count=0; count<11 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
761 /* we must get 11 tokens */
762 if (count < 11)
763 return(False);
765 /* the first must be "active" or begin with an integer */
766 if (strcmp(tok[0],"active") && !isdigit((int)tok[0][0]))
767 return(False);
769 /* the 5th and 8th must be integer */
770 if (!isdigit((int)*tok[4]) || !isdigit((int)*tok[7]))
771 return(False);
773 /* if the fname contains a space then use STDIN */
774 if (strchr(tok[6],' '))
775 fstrcpy(tok[6],"STDIN");
777 /* only take the last part of the filename */
779 fstring tmp;
780 char *p = strrchr(tok[6],'/');
781 if (p)
783 fstrcpy(tmp,p+1);
784 fstrcpy(tok[6],tmp);
789 buf->job = atoi(tok[4]);
791 buf->size = atoi(tok[7]);
792 if (strchr(tok[7],'K'))
793 buf->size *= 1024;
794 if (strchr(tok[7],'M'))
795 buf->size *= 1024*1024;
797 buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED;
798 buf->priority = 0;
799 buf->time = time(NULL);
800 StrnCpy(buf->user,tok[1],sizeof(buf->user)-1);
801 StrnCpy(buf->file,tok[6],sizeof(buf->file)-1);
802 return(True);
805 /****************************************************************************
806 parse a qstat line
808 here is an example of "qstat -l -d qms" output under softq
810 Queue qms: 2 jobs; daemon active (313); enabled; accepting;
811 job-ID submission-time pri size owner title
812 205980: H 98/03/09 13:04:05 0 15733 stephenf chap1.ps
813 206086:> 98/03/12 17:24:40 0 659 chris -
814 206087: 98/03/12 17:24:45 0 4876 chris -
815 Total: 21268 bytes in queue
818 ****************************************************************************/
819 static BOOL parse_lpq_softq(char *line,print_queue_struct *buf,BOOL first)
821 fstring tok[10];
822 int count=0;
824 /* mung all the ":"s to spaces*/
825 pstring_sub(line,":"," ");
827 for (count=0; count<10 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
829 /* we must get 9 tokens */
830 if (count < 9)
831 return(False);
833 /* the 1st and 7th columns must be integer */
834 if (!isdigit((int)*tok[0]) || !isdigit((int)*tok[6])) return(False);
835 /* if the 2nd column is either '>' or 'H' then the 7th and 8th must be
836 * integer, else it's the 6th and 7th that must be
838 if (*tok[1] == 'H' || *tok[1] == '>')
840 if (!isdigit((int)*tok[7]))
841 return(False);
842 buf->status = *tok[1] == '>' ? LPQ_PRINTING : LPQ_PAUSED;
843 count = 1;
845 else
847 if (!isdigit((int)*tok[5]))
848 return(False);
849 buf->status = LPQ_QUEUED;
850 count = 0;
854 buf->job = atoi(tok[0]);
855 buf->size = atoi(tok[count+6]);
856 buf->priority = atoi(tok[count+5]);
857 StrnCpy(buf->user,tok[count+7],sizeof(buf->user)-1);
858 StrnCpy(buf->file,tok[count+8],sizeof(buf->file)-1);
859 buf->time = time(NULL); /* default case: take current time */
861 time_t jobtime;
862 struct tm *t;
864 t = localtime(&buf->time);
865 t->tm_mday = atoi(tok[count+2]+6);
866 t->tm_mon = atoi(tok[count+2]+3);
867 switch (*tok[count+2])
869 case 7: case 8: case 9: t->tm_year = atoi(tok[count+2]); break;
870 default: t->tm_year = atoi(tok[count+2]); break;
873 t->tm_hour = atoi(tok[count+3]);
874 t->tm_min = atoi(tok[count+4]);
875 t->tm_sec = atoi(tok[count+5]);
876 jobtime = mktime(t);
877 if (jobtime != (time_t)-1)
878 buf->time = jobtime;
881 return(True);
885 char *stat0_strings[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL };
886 char *stat1_strings[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL };
887 char *stat2_strings[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL };
889 /****************************************************************************
890 parse a lpq line. Choose printing style
891 ****************************************************************************/
892 static BOOL parse_lpq_entry(int snum,char *line,
893 print_queue_struct *buf,
894 print_status_struct *status,BOOL first)
896 BOOL ret;
898 switch (lp_printing(snum))
900 case PRINT_SYSV:
901 ret = parse_lpq_sysv(line,buf,first);
902 break;
903 case PRINT_AIX:
904 ret = parse_lpq_aix(line,buf,first);
905 break;
906 case PRINT_HPUX:
907 ret = parse_lpq_hpux(line,buf,first);
908 break;
909 case PRINT_QNX:
910 ret = parse_lpq_qnx(line,buf,first);
911 break;
912 case PRINT_LPRNG:
913 ret = parse_lpq_lprng(line,buf,first);
914 break;
915 case PRINT_PLP:
916 ret = parse_lpq_plp(line,buf,first);
917 break;
918 case PRINT_SOFTQ:
919 ret = parse_lpq_softq(line,buf,first);
920 break;
921 default:
922 ret = parse_lpq_bsd(line,buf,first);
923 break;
926 #ifdef LPQ_GUEST_TO_USER
927 if (ret) {
928 extern pstring sesssetup_user;
929 /* change guest entries to the current logged in user to make
930 them appear deletable to windows */
931 if (sesssetup_user[0] && strequal(buf->user,lp_guestaccount(snum)))
932 pstrcpy(buf->user,sesssetup_user);
934 #endif
936 /* We don't want the newline in the status message. */
938 char *p = strchr(line,'\n');
939 if (p) *p = 0;
942 /* in the LPRNG case, we skip lines starting by a space.*/
943 if (line && !ret && (lp_printing(snum)==PRINT_LPRNG) )
945 if (line[0]==' ')
946 return ret;
950 if (status && !ret)
952 /* a few simple checks to see if the line might be a
953 printer status line:
954 handle them so that most severe condition is shown */
955 int i;
956 strlower(line);
958 switch (status->status) {
959 case LPSTAT_OK:
960 for (i=0; stat0_strings[i]; i++)
961 if (strstr(line,stat0_strings[i])) {
962 StrnCpy(status->message,line,sizeof(status->message)-1);
963 status->status=LPSTAT_OK;
964 return ret;
966 case LPSTAT_STOPPED:
967 for (i=0; stat1_strings[i]; i++)
968 if (strstr(line,stat1_strings[i])) {
969 StrnCpy(status->message,line,sizeof(status->message)-1);
970 status->status=LPSTAT_STOPPED;
971 return ret;
973 case LPSTAT_ERROR:
974 for (i=0; stat2_strings[i]; i++)
975 if (strstr(line,stat2_strings[i])) {
976 StrnCpy(status->message,line,sizeof(status->message)-1);
977 status->status=LPSTAT_ERROR;
978 return ret;
980 break;
984 return(ret);
987 /****************************************************************************
988 get a printer queue
989 ****************************************************************************/
990 int get_printqueue(int snum,
991 connection_struct *conn,print_queue_struct **queue,
992 print_status_struct *status)
994 char *lpq_command = lp_lpqcommand(snum);
995 char *printername = PRINTERNAME(snum);
996 int ret=0,count=0;
997 pstring syscmd;
998 fstring outfile;
999 pstring line;
1000 FILE *f;
1001 SMB_STRUCT_STAT sbuf;
1002 BOOL dorun=True;
1003 int cachetime = lp_lpqcachetime();
1005 *line = 0;
1006 check_lpq_cache(snum);
1008 if (!printername || !*printername) {
1009 DEBUG(6,("xx replacing printer name with service (snum=(%s,%d))\n",
1010 lp_servicename(snum),snum));
1011 printername = lp_servicename(snum);
1014 if (!lpq_command || !(*lpq_command)) {
1015 DEBUG(5,("No lpq command\n"));
1016 return(0);
1019 pstrcpy(syscmd,lpq_command);
1020 pstring_sub(syscmd,"%p",printername);
1022 standard_sub(conn,syscmd);
1024 slprintf(outfile,sizeof(outfile)-1, "%s/lpq.%08x",lp_lockdir(),str_checksum(syscmd));
1026 if (!lpq_cache_reset[snum] && cachetime && !sys_stat(outfile,&sbuf)) {
1027 if (time(NULL) - sbuf.st_mtime < cachetime) {
1028 DEBUG(3,("Using cached lpq output\n"));
1029 dorun = False;
1033 if (dorun) {
1034 ret = smbrun(syscmd,outfile,True);
1035 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1038 lpq_cache_reset[snum] = False;
1040 f = sys_fopen(outfile,"r");
1041 if (!f) {
1042 return(0);
1045 if (status) {
1046 fstrcpy(status->message,"");
1047 status->status = LPSTAT_OK;
1050 while (fgets(line,sizeof(pstring),f)) {
1051 DEBUG(6,("QUEUE2: %s\n",line));
1053 *queue = Realloc(*queue,sizeof(print_queue_struct)*(count+1));
1054 if (! *queue) {
1055 count = 0;
1056 break;
1059 memset((char *)&(*queue)[count],'\0',sizeof(**queue));
1061 /* parse it */
1062 if (!parse_lpq_entry(snum,line,
1063 &(*queue)[count],status,count==0))
1064 continue;
1066 count++;
1069 fclose(f);
1071 if (!cachetime) {
1072 unlink(outfile);
1074 return(count);
1078 /****************************************************************************
1079 delete a printer queue entry
1080 ****************************************************************************/
1081 void del_printqueue(connection_struct *conn,int snum,int jobid)
1083 char *lprm_command = lp_lprmcommand(snum);
1084 char *printername = PRINTERNAME(snum);
1085 pstring syscmd;
1086 char jobstr[20];
1087 int ret;
1089 if (!printername || !*printername)
1091 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1092 lp_servicename(snum),snum));
1093 printername = lp_servicename(snum);
1096 if (!lprm_command || !(*lprm_command))
1098 DEBUG(5,("No lprm command\n"));
1099 return;
1102 slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);
1104 pstrcpy(syscmd,lprm_command);
1105 pstring_sub(syscmd,"%p",printername);
1106 pstring_sub(syscmd,"%j",jobstr);
1107 standard_sub(conn,syscmd);
1109 ret = smbrun(syscmd,NULL,False);
1110 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1111 lpq_reset(snum); /* queue has changed */
1114 /****************************************************************************
1115 change status of a printer queue entry
1116 ****************************************************************************/
1117 void status_printjob(connection_struct *conn,int snum,int jobid,int status)
1119 char *lpstatus_command =
1120 (status==LPQ_PAUSED?lp_lppausecommand(snum):lp_lpresumecommand(snum));
1121 char *printername = PRINTERNAME(snum);
1122 pstring syscmd;
1123 char jobstr[20];
1124 int ret;
1126 if (!printername || !*printername)
1128 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1129 lp_servicename(snum),snum));
1130 printername = lp_servicename(snum);
1133 if (!lpstatus_command || !(*lpstatus_command))
1135 DEBUG(5,("No lpstatus command to %s job\n",
1136 (status==LPQ_PAUSED?"pause":"resume")));
1137 return;
1140 slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);
1142 pstrcpy(syscmd,lpstatus_command);
1143 pstring_sub(syscmd,"%p",printername);
1144 pstring_sub(syscmd,"%j",jobstr);
1145 standard_sub(conn,syscmd);
1147 ret = smbrun(syscmd,NULL,False);
1148 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1149 lpq_reset(snum); /* queue has changed */
1154 /****************************************************************************
1155 we encode print job numbers over the wire so that when we get them back we can
1156 tell not only what print job they are but also what service it belongs to,
1157 this is to overcome the problem that windows clients tend to send the wrong
1158 service number when doing print queue manipulation!
1159 ****************************************************************************/
1160 int printjob_encode(int snum, int job)
1162 return ((snum&0xFF)<<8) | (job & 0xFF);
1165 /****************************************************************************
1166 and now decode them again ...
1167 ****************************************************************************/
1168 void printjob_decode(int jobid, int *snum, int *job)
1170 (*snum) = (jobid >> 8) & 0xFF;
1171 (*job) = jobid & 0xFF;
1174 /****************************************************************************
1175 Change status of a printer queue
1176 ****************************************************************************/
1178 void status_printqueue(connection_struct *conn,int snum,int status)
1180 char *queuestatus_command = (status==LPSTAT_STOPPED ?
1181 lp_queuepausecommand(snum):lp_queueresumecommand(snum));
1182 char *printername = PRINTERNAME(snum);
1183 pstring syscmd;
1184 int ret;
1186 if (!printername || !*printername) {
1187 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1188 lp_servicename(snum),snum));
1189 printername = lp_servicename(snum);
1192 if (!queuestatus_command || !(*queuestatus_command)) {
1193 DEBUG(5,("No queuestatus command to %s job\n",
1194 (status==LPSTAT_STOPPED?"pause":"resume")));
1195 return;
1198 pstrcpy(syscmd,queuestatus_command);
1199 pstring_sub(syscmd,"%p",printername);
1200 standard_sub(conn,syscmd);
1202 ret = smbrun(syscmd,NULL,False);
1203 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1204 lpq_reset(snum); /* queue has changed */
1209 /***************************************************************************
1210 auto-load printer services
1211 ***************************************************************************/
1212 static void add_all_printers(void)
1214 int printers = lp_servicenumber(PRINTERS_NAME);
1216 if (printers < 0) return;
1218 pcap_printer_fn(lp_add_one_printer);
1221 /***************************************************************************
1222 auto-load some homes and printer services
1223 ***************************************************************************/
1224 static void add_auto_printers(void)
1226 char *p;
1227 int printers;
1228 char *str = lp_auto_services();
1230 if (!str) return;
1232 printers = lp_servicenumber(PRINTERS_NAME);
1234 if (printers < 0) return;
1236 for (p=strtok(str,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) {
1237 if (lp_servicenumber(p) >= 0) continue;
1239 if (pcap_printername_ok(p,NULL)) {
1240 lp_add_printer(p,printers);
1245 /***************************************************************************
1246 load automatic printer services
1247 ***************************************************************************/
1248 void load_printers(void)
1250 add_auto_printers();
1251 if (lp_load_printers())
1252 add_all_printers();