2 Unix SMB/Netbios implementation.
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.
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;
30 if (lpq_caches <= snum) {
32 p = (BOOL *) Realloc(lpq_cache_reset,(snum+1)*sizeof(BOOL));
41 void lpq_reset(int snum)
43 if (check_lpq_cache(snum) > snum) lpq_cache_reset[snum]=True;
47 /****************************************************************************
48 Build the print command in the supplied buffer. This means getting the
49 print command for the service and inserting the printer name and the
50 print file name. Return NULL on error, else the passed buffer pointer.
51 ****************************************************************************/
52 static char *build_print_command(connection_struct *conn,
54 char *syscmd, char *filename1)
56 int snum = SNUM(conn);
60 /* get the print command for the service. */
62 if (!syscmd || !tstr) {
63 DEBUG(0,("No print command for service `%s'\n",
68 /* copy the command into the buffer for extensive meddling. */
69 StrnCpy(syscmd, tstr, sizeof(pstring) - 1);
71 /* look for "%s" in the string. If there is no %s, we cannot print. */
72 if (!strstr(syscmd, "%s") && !strstr(syscmd, "%f")) {
73 DEBUG(2,("WARNING! No placeholder for the filename in the print command for service %s!\n", SERVICE(snum)));
76 if (strstr(syscmd,"%s")) {
77 pstrcpy(filename,filename1);
79 string_sub(syscmd, "%s", filename);
82 string_sub(syscmd, "%f", filename1);
84 /* Does the service have a printername? If not, make a fake
86 /* printer name. That way a %p is treated sanely if no printer */
87 /* name was specified to replace it. This eventuality is logged. */
88 tstr = PRINTERNAME(snum);
89 if (tstr == NULL || tstr[0] == '\0') {
90 DEBUG(3,( "No printer name - using %s.\n", SERVICE(snum)));
94 string_sub(syscmd, "%p", tstr);
96 standard_sub(conn,syscmd);
102 /****************************************************************************
103 print a file - called on closing the file
104 ****************************************************************************/
105 void print_file(connection_struct *conn, files_struct *file)
108 int snum = SNUM(conn);
113 if (file_size(file->fsp_name) <= 0) {
114 DEBUG(3,("Discarding null print job %s\n",file->fsp_name));
115 dos_unlink(file->fsp_name);
119 tempstr = build_print_command(conn,
121 syscmd, file->fsp_name);
122 if (tempstr != NULL) {
123 int ret = smbrun(syscmd,NULL,False);
124 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
126 DEBUG(0,("Null print command?\n"));
132 static char *Months[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
133 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err"};
136 /*******************************************************************
138 ********************************************************************/
139 static time_t EntryTime(fstring tok[], int ptr, int count, int minimum)
141 time_t jobtime,jobtime1;
143 jobtime = time(NULL); /* default case: take current time */
144 if (count >= minimum) {
146 int i, day, hour, min, sec;
149 for (i=0; i<13; i++) if (!strncmp(tok[ptr], Months[i],3)) break; /* Find month */
151 t = localtime(&jobtime);
152 day = atoi(tok[ptr+1]);
153 c=(char *)(tok[ptr+2]);
158 if(*(c+6) != 0)sec = atoi(c+6);
161 if ((t->tm_mon < i)||
163 ((t->tm_mday < day)||
164 ((t->tm_mday == day)&&
165 (t->tm_hour*60+t->tm_min < hour*60+min)))))
166 t->tm_year--; /* last year's print job */
173 jobtime1 = mktime(t);
174 if (jobtime1 != (time_t)-1)
182 /****************************************************************************
185 here is an example of lpq output under bsd
187 Warning: no daemon present
188 Rank Owner Job Files Total Size
189 1st tridge 148 README 8096 bytes
191 here is an example of lpq output under osf/1
193 Warning: no daemon present
194 Rank Pri Owner Job Files Total Size
195 1st 0 tridge 148 README 8096 bytes
196 ****************************************************************************/
197 static BOOL parse_lpq_bsd(char *line,print_queue_struct *buf,BOOL first)
221 length = strlen(line);
222 if (line[length-3] == ':')
226 /* handle the case of "(standard input)" as a filename */
227 string_sub(line,"standard input","STDIN");
228 string_sub(line,"(","\"");
229 string_sub(line,")","\"");
233 next_token(&line,tok[count],NULL, sizeof(tok[count]));
236 /* we must get NTOK tokens */
240 /* the Job and Total columns must be integer */
241 if (!isdigit((int)*tok[JOBTOK]) || !isdigit((int)*tok[TOTALTOK])) return(False);
243 /* if the fname contains a space then use STDIN */
244 if (strchr(tok[FILETOK],' '))
245 fstrcpy(tok[FILETOK],"STDIN");
247 /* only take the last part of the filename */
250 char *p = strrchr(tok[FILETOK],'/');
254 fstrcpy(tok[FILETOK],tmp);
259 buf->job = atoi(tok[JOBTOK]);
260 buf->size = atoi(tok[TOTALTOK]);
261 buf->status = strequal(tok[RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED;
262 buf->time = time(NULL);
263 StrnCpy(buf->user,tok[USERTOK],sizeof(buf->user)-1);
264 StrnCpy(buf->file,tok[FILETOK],sizeof(buf->file)-1);
266 buf->priority = atoi(tok[PRIOTOK]);
275 LPRng_time modifies the current date by inserting the hour and minute from
276 the lpq output. The lpq time looks like "23:15:07"
278 static time_t LPRng_time(fstring tok[],int pos)
284 jobtime = time(NULL); /* default case: take current time */
285 t = localtime(&jobtime);
286 t->tm_hour = atoi(tok[pos]);
287 fstrcpy(tmp_time,tok[pos]);
288 t->tm_min = atoi(tmp_time+3);
289 t->tm_sec = atoi(tmp_time+6);
296 /****************************************************************************
299 Most of the code is directly reused from parse_lpq_bsd()
301 here are two examples of lpq output under lprng (LPRng-2.3.0)
303 Printer: humprn@hum-fak
304 Queue: 1 printable job
305 Server: pid 4840 active, Unspooler: pid 4841 active
306 Status: job 'cfA659hum-fak', closing device at Fri Jun 21 10:10:21 1996
307 Rank Owner Class Job Files Size Time
308 active magnus@hum-fak A 659 /var/spool/smb/Notesblok-ikke-na4024 10:03:31
310 Printer: humprn@hum-fak (printing disabled)
311 Queue: 1 printable job
312 Warning: no server present
313 Status: finished operations at Fri Jun 21 10:10:32 1996
314 Rank Owner Class Job Files Size Time
315 1 magnus@hum-fak A 387 /var/spool/smb/netbudget.xls 21230 10:50:53
317 ******************************************************************************
319 NEW FOR LPRng-3.3.5 !
322 This will not happen anymore: with LPRng-3.3.5 there is always a blank between
323 the filename and the size, and the format has changed:
325 Printer: lj6@lizard 'HP LaserJet 6P'
326 Queue: 2 printable jobs
327 Server: pid 11941 active
328 Unspooler: pid 11942 active
329 Status: printed all 1818 bytes at 19:49:59
330 Rank Owner/ID Class Job Files Size Time
331 active root@lizard+937 A 937 (stdin) 1818 19:49:58
332 2 root@lizard+969 A 969 junk.txt 2170 19:50:12
334 ****************************************************************************/
335 static BOOL parse_lpq_lprng(char *line,print_queue_struct *buf,BOOL first)
337 #define LPRNG_RANKTOK 0
338 #define LPRNG_USERTOK 1
339 #define LPRNG_PRIOTOK 2
340 #define LPRNG_JOBTOK 3
341 #define LPRNG_FILETOK 4
342 #define LPRNG_TOTALTOK 5
343 #define LPRNG_TIMETOK 6
346 /****************************************************************************
347 From lpd_status.c in LPRng source.
349 12345678901234567890123456789012345678901234567890123456789012345678901234
350 " Rank Owner Class Job Files Size Time"
351 plp_snprintf( msg, sizeof(msg), "%-6s %-19s %c %03d %-32s",
352 number, line, priority, cfp->number, error );
353 plp_snprintf( msg + len, sizeof(msg)-len, "%4d",
355 plp_snprintf( msg+len, sizeof(msg)-len, " %s",
356 Time_str( 1, cfp->statb.st_ctime ) );
357 ****************************************************************************/
358 /* The following define's are to be able to adjust the values if the
359 LPRng source changes. This is from version 2.3.0. Magnus */
366 /* The JOBSIZE_W is too small for big jobs, so time is pushed to the right */
370 #define OWNER_POS RANK_POS+RANK_W+SPACE_W
371 #define CLASS_POS OWNER_POS+OWNER_W+SPACE_W
372 #define JOB_POS CLASS_POS+CLASS_W+SPACE_W
373 #define FILE_POS JOB_POS+JOB_W+SPACE_W
374 #define JOBSIZE_POS FILE_POS+FILE_W
377 fstring tok[LPRNG_NTOK];
381 /* We only need this bugfix for older versions of lprng - current
382 information is that version 3.3.5 must not have this line
383 in order to work correctly.
387 Need to insert one space in front of the size, to be able to use
388 next_token() unchanged. I would have liked to be able to insert a
389 space instead, to prevent losing that one char, but perl has spoiled
390 me :-\ So I did it the easiest way.
392 HINT: Use as short a path as possible for the samba spool directory.
393 A long spool-path will just waste significant chars of the file name.
396 line[JOBSIZE_POS-1]=' ';
397 #endif /* OLD_LPRNG */
399 /* handle the case of "(stdin)" as a filename */
400 string_sub(line,"stdin","STDIN");
401 string_sub(line,"(","\"");
402 string_sub(line,")","\"");
406 next_token(&line,tok[count],NULL, sizeof(tok[count]));
409 /* we must get LPRNG_NTOK tokens */
410 if (count < LPRNG_NTOK)
413 /* the Job and Total columns must be integer */
414 if (!isdigit((int)*tok[LPRNG_JOBTOK]) || !isdigit((int)*tok[LPRNG_TOTALTOK])) return(False);
416 /* if the fname contains a space then use STDIN */
417 /* I do not understand how this would be possible. Magnus. */
418 if (strchr(tok[LPRNG_FILETOK],' '))
419 fstrcpy(tok[LPRNG_FILETOK],"STDIN");
421 /* only take the last part of the filename */
424 char *p = strrchr(tok[LPRNG_FILETOK],'/');
428 fstrcpy(tok[LPRNG_FILETOK],tmp);
433 buf->job = atoi(tok[LPRNG_JOBTOK]);
434 buf->size = atoi(tok[LPRNG_TOTALTOK]);
435 if (strequal(tok[LPRNG_RANKTOK],"active"))
436 buf->status = LPQ_PRINTING;
437 else if (strequal(tok[LPRNG_RANKTOK],"hold"))
438 buf->status = LPQ_PAUSED;
440 buf->status = LPQ_QUEUED;
441 /* buf->time = time(NULL); */
442 buf->time = LPRng_time(tok,LPRNG_TIMETOK);
443 DEBUG(3,("Time reported for job %d is %s", buf->job, ctime(&buf->time)));
444 StrnCpy(buf->user,tok[LPRNG_USERTOK],sizeof(buf->user)-1);
445 StrnCpy(buf->file,tok[LPRNG_FILETOK],sizeof(buf->file)-1);
447 /* Here I try to map the CLASS char to a number, but the number
448 is never shown in Print Manager under NT anyway... Magnus. */
449 buf->priority = atoi(tok[LPRNG_PRIOTOK]-('A'-1));
458 /*******************************************************************
459 parse lpq on an aix system
461 Queue Dev Status Job Files User PP % Blks Cp Rnk
462 ------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
464 lazer lazer RUNNING 537 6297doc.A kvintus@IE 0 10 2445 1 1
465 QUEUED 538 C.ps root@IEDVB 124 1 2
466 QUEUED 539 E.ps root@IEDVB 28 1 3
467 QUEUED 540 L.ps root@IEDVB 172 1 4
468 QUEUED 541 P.ps root@IEDVB 22 1 5
469 ********************************************************************/
470 static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first)
475 /* handle the case of "(standard input)" as a filename */
476 string_sub(line,"standard input","STDIN");
477 string_sub(line,"(","\"");
478 string_sub(line,")","\"");
482 next_token(&line,tok[count],NULL, sizeof(tok[count]));
485 /* we must get 6 tokens */
488 if ((count == 7) && ((strcmp(tok[0],"QUEUED") == 0) || (strcmp(tok[0],"HELD") == 0)))
490 /* the 2nd and 5th columns must be integer */
491 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4])) return(False);
492 buf->size = atoi(tok[4]) * 1024;
493 /* if the fname contains a space then use STDIN */
494 if (strchr(tok[2],' '))
495 fstrcpy(tok[2],"STDIN");
497 /* only take the last part of the filename */
500 char *p = strrchr(tok[2],'/');
509 buf->job = atoi(tok[1]);
510 buf->status = strequal(tok[0],"HELD")?LPQ_PAUSED:LPQ_QUEUED;
512 buf->time = time(NULL);
513 StrnCpy(buf->user,tok[3],sizeof(buf->user)-1);
514 StrnCpy(buf->file,tok[2],sizeof(buf->file)-1);
518 DEBUG(6,("parse_lpq_aix count=%d\n", count));
524 /* the 4th and 9th columns must be integer */
525 if (!isdigit((int)*tok[3]) || !isdigit((int)*tok[8])) return(False);
526 buf->size = atoi(tok[8]) * 1024;
527 /* if the fname contains a space then use STDIN */
528 if (strchr(tok[4],' '))
529 fstrcpy(tok[4],"STDIN");
531 /* only take the last part of the filename */
534 char *p = strrchr(tok[4],'/');
543 buf->job = atoi(tok[3]);
544 buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED;
546 buf->time = time(NULL);
547 StrnCpy(buf->user,tok[5],sizeof(buf->user)-1);
548 StrnCpy(buf->file,tok[4],sizeof(buf->file)-1);
556 /****************************************************************************
558 here is an example of lpq output under hpux; note there's no space after -o !
560 ljplus-2153 user priority 0 Jan 19 08:14 on ljplus
562 server.c 110712 bytes
563 ljplus-2154 user priority 0 Jan 19 08:14 from client
564 (standard input) 7551 bytes
565 ****************************************************************************/
566 static BOOL parse_lpq_hpux(char * line, print_queue_struct *buf, BOOL first)
568 /* must read two lines to process, therefore keep some values static */
569 static BOOL header_line_ok=False, base_prio_reset=False;
570 static fstring jobuser;
573 static time_t jobtime;
574 static int jobstat=LPQ_QUEUED;
575 /* to store minimum priority to print, lpstat command should be invoked
576 with -p option first, to work */
577 static int base_prio;
583 /* If a line begins with a horizontal TAB, it is a subline type */
585 if (line[0] == TAB) { /* subline */
586 /* check if it contains the base priority */
587 if (!strncmp(line,"\tfence priority : ",18)) {
588 base_prio=atoi(&line[18]);
589 DEBUG(4, ("fence priority set at %d\n", base_prio));
591 if (!header_line_ok) return (False); /* incorrect header line */
592 /* handle the case of "(standard input)" as a filename */
593 string_sub(line,"standard input","STDIN");
594 string_sub(line,"(","\"");
595 string_sub(line,")","\"");
597 for (count=0; count<2 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
598 /* we must get 2 tokens */
599 if (count < 2) return(False);
601 /* the 2nd column must be integer */
602 if (!isdigit((int)*tok[1])) return(False);
604 /* if the fname contains a space then use STDIN */
605 if (strchr(tok[0],' '))
606 fstrcpy(tok[0],"STDIN");
608 buf->size = atoi(tok[1]);
609 StrnCpy(buf->file,tok[0],sizeof(buf->file)-1);
611 /* fill things from header line */
614 buf->status = jobstat;
615 buf->priority = jobprio;
616 StrnCpy(buf->user,jobuser,sizeof(buf->user)-1);
620 else { /* header line */
621 header_line_ok=False; /* reset it */
623 if (!base_prio_reset) {
624 base_prio=0; /* reset it */
625 base_prio_reset=True;
628 else if (base_prio) base_prio_reset=False;
630 /* handle the dash in the job id */
631 string_sub(line,"-"," ");
633 for (count=0; count<12 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
635 /* we must get 8 tokens */
636 if (count < 8) return(False);
638 /* first token must be printer name (cannot check ?) */
639 /* the 2nd, 5th & 7th column must be integer */
640 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4]) || !isdigit((int)*tok[6])) return(False);
641 jobid = atoi(tok[1]);
642 StrnCpy(jobuser,tok[2],sizeof(buf->user)-1);
643 jobprio = atoi(tok[4]);
646 jobtime=EntryTime(tok, 5, count, 8);
647 if (jobprio < base_prio) {
648 jobstat = LPQ_PAUSED;
649 DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n", jobid, jobprio, base_prio, jobstat));
652 jobstat = LPQ_QUEUED;
653 if ((count >8) && (((strequal(tok[8],"on")) ||
654 ((strequal(tok[8],"from")) &&
655 ((count > 10)&&(strequal(tok[10],"on")))))))
656 jobstat = LPQ_PRINTING;
659 header_line_ok=True; /* information is correct */
660 return(False); /* need subline info to include into queuelist */
665 /****************************************************************************
668 here is an example of "lpstat -o dcslw" output under sysv
670 dcslw-896 tridge 4712 Dec 20 10:30:30 on dcslw
671 dcslw-897 tridge 4712 Dec 20 10:30:30 being held
673 ****************************************************************************/
674 static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first)
680 /* handle the dash in the job id */
681 string_sub(line,"-"," ");
683 for (count=0; count<9 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
685 /* we must get 7 tokens */
689 /* the 2nd and 4th, 6th columns must be integer */
690 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[3])) return(False);
691 if (!isdigit((int)*tok[5])) return(False);
693 /* if the user contains a ! then trim the first part of it */
694 if ((p=strchr(tok[2],'!')))
702 buf->job = atoi(tok[1]);
703 buf->size = atoi(tok[3]);
704 if (count > 7 && strequal(tok[7],"on"))
705 buf->status = LPQ_PRINTING;
706 else if (count > 8 && strequal(tok[7],"being") && strequal(tok[8],"held"))
707 buf->status = LPQ_PAUSED;
709 buf->status = LPQ_QUEUED;
711 buf->time = EntryTime(tok, 4, count, 7);
712 StrnCpy(buf->user,tok[2],sizeof(buf->user)-1);
713 StrnCpy(buf->file,tok[2],sizeof(buf->file)-1);
717 /****************************************************************************
720 here is an example of lpq output under qnx
721 Spooler: /qnx/spooler, on node 1
723 0000: root [job #1 ] active 1146 bytes /etc/profile
724 0001: root [job #2 ] ready 2378 bytes /etc/install
725 0002: root [job #3 ] ready 1146 bytes -- standard input --
726 ****************************************************************************/
727 static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first)
732 DEBUG(0,("antes [%s]\n", line));
734 /* handle the case of "-- standard input --" as a filename */
735 string_sub(line,"standard input","STDIN");
736 DEBUG(0,("despues [%s]\n", line));
737 string_sub(line,"-- ","\"");
738 string_sub(line," --","\"");
739 DEBUG(0,("despues 1 [%s]\n", line));
741 string_sub(line,"[job #","");
742 string_sub(line,"]","");
743 DEBUG(0,("despues 2 [%s]\n", line));
747 for (count=0; count<7 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
749 /* we must get 7 tokens */
753 /* the 3rd and 5th columns must be integer */
754 if (!isdigit((int)*tok[2]) || !isdigit((int)*tok[4])) return(False);
756 /* only take the last part of the filename */
759 char *p = strrchr(tok[6],'/');
768 buf->job = atoi(tok[2]);
769 buf->size = atoi(tok[4]);
770 buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED;
772 buf->time = time(NULL);
773 StrnCpy(buf->user,tok[1],sizeof(buf->user)-1);
774 StrnCpy(buf->file,tok[6],sizeof(buf->file)-1);
779 /****************************************************************************
780 parse a lpq line for the plp printing system
781 Bertrand Wallrich <Bertrand.Wallrich@loria.fr>
783 redone by tridge. Here is a sample queue:
785 Local Printer 'lp2' (fjall):
786 Printing (started at Jun 15 13:33:58, attempt 1).
787 Rank Owner Pr Opt Job Host Files Size Date
788 active tridge X - 6 fjall /etc/hosts 739 Jun 15 13:33
789 3rd tridge X - 7 fjall /etc/hosts 739 Jun 15 13:33
791 ****************************************************************************/
792 static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first)
797 /* handle the case of "(standard input)" as a filename */
798 string_sub(line,"stdin","STDIN");
799 string_sub(line,"(","\"");
800 string_sub(line,")","\"");
802 for (count=0; count<11 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
804 /* we must get 11 tokens */
808 /* the first must be "active" or begin with an integer */
809 if (strcmp(tok[0],"active") && !isdigit((int)tok[0][0]))
812 /* the 5th and 8th must be integer */
813 if (!isdigit((int)*tok[4]) || !isdigit((int)*tok[7]))
816 /* if the fname contains a space then use STDIN */
817 if (strchr(tok[6],' '))
818 fstrcpy(tok[6],"STDIN");
820 /* only take the last part of the filename */
823 char *p = strrchr(tok[6],'/');
832 buf->job = atoi(tok[4]);
834 buf->size = atoi(tok[7]);
835 if (strchr(tok[7],'K'))
837 if (strchr(tok[7],'M'))
838 buf->size *= 1024*1024;
840 buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED;
842 buf->time = time(NULL);
843 StrnCpy(buf->user,tok[1],sizeof(buf->user)-1);
844 StrnCpy(buf->file,tok[6],sizeof(buf->file)-1);
848 /****************************************************************************
851 here is an example of "qstat -l -d qms" output under softq
853 Queue qms: 2 jobs; daemon active (313); enabled; accepting;
854 job-ID submission-time pri size owner title
855 205980: H 98/03/09 13:04:05 0 15733 stephenf chap1.ps
856 206086:> 98/03/12 17:24:40 0 659 chris -
857 206087: 98/03/12 17:24:45 0 4876 chris -
858 Total: 21268 bytes in queue
861 ****************************************************************************/
862 static BOOL parse_lpq_softq(char *line,print_queue_struct *buf,BOOL first)
867 /* mung all the ":"s to spaces*/
868 string_sub(line,":"," ");
870 for (count=0; count<10 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
872 /* we must get 9 tokens */
876 /* the 1st and 7th columns must be integer */
877 if (!isdigit((int)*tok[0]) || !isdigit((int)*tok[6])) return(False);
878 /* if the 2nd column is either '>' or 'H' then the 7th and 8th must be
879 * integer, else it's the 6th and 7th that must be
881 if (*tok[1] == 'H' || *tok[1] == '>')
883 if (!isdigit((int)*tok[7]))
885 buf->status = *tok[1] == '>' ? LPQ_PRINTING : LPQ_PAUSED;
890 if (!isdigit((int)*tok[5]))
892 buf->status = LPQ_QUEUED;
897 buf->job = atoi(tok[0]);
898 buf->size = atoi(tok[count+6]);
899 buf->priority = atoi(tok[count+5]);
900 StrnCpy(buf->user,tok[count+7],sizeof(buf->user)-1);
901 StrnCpy(buf->file,tok[count+8],sizeof(buf->file)-1);
902 buf->time = time(NULL); /* default case: take current time */
907 t = localtime(&buf->time);
908 t->tm_mday = atoi(tok[count+2]+6);
909 t->tm_mon = atoi(tok[count+2]+3);
910 switch (*tok[count+2])
912 case 7: case 8: case 9: t->tm_year = atoi(tok[count+2]) + 1900; break;
913 default: t->tm_year = atoi(tok[count+2]) + 2000; break;
916 t->tm_hour = atoi(tok[count+3]);
917 t->tm_min = atoi(tok[count+4]);
918 t->tm_sec = atoi(tok[count+5]);
920 if (jobtime != (time_t)-1)
928 char *stat0_strings[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL };
929 char *stat1_strings[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL };
930 char *stat2_strings[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL };
932 /****************************************************************************
933 parse a lpq line. Choose printing style
934 ****************************************************************************/
935 static BOOL parse_lpq_entry(int snum,char *line,
936 print_queue_struct *buf,
937 print_status_struct *status,BOOL first)
941 switch (lp_printing(snum))
944 ret = parse_lpq_sysv(line,buf,first);
947 ret = parse_lpq_aix(line,buf,first);
950 ret = parse_lpq_hpux(line,buf,first);
953 ret = parse_lpq_qnx(line,buf,first);
956 ret = parse_lpq_lprng(line,buf,first);
959 ret = parse_lpq_plp(line,buf,first);
962 ret = parse_lpq_softq(line,buf,first);
965 ret = parse_lpq_bsd(line,buf,first);
969 #ifdef LPQ_GUEST_TO_USER
971 extern pstring sesssetup_user;
972 /* change guest entries to the current logged in user to make
973 them appear deletable to windows */
974 if (sesssetup_user[0] && strequal(buf->user,lp_guestaccount(snum)))
975 pstrcpy(buf->user,sesssetup_user);
979 /* We don't want the newline in the status message. */
981 char *p = strchr(line,'\n');
987 /* a few simple checks to see if the line might be a
989 handle them so that most severe condition is shown */
993 switch (status->status) {
995 for (i=0; stat0_strings[i]; i++)
996 if (strstr(line,stat0_strings[i])) {
997 StrnCpy(status->message,line,sizeof(status->message)-1);
998 status->status=LPSTAT_OK;
1001 case LPSTAT_STOPPED:
1002 for (i=0; stat1_strings[i]; i++)
1003 if (strstr(line,stat1_strings[i])) {
1004 StrnCpy(status->message,line,sizeof(status->message)-1);
1005 status->status=LPSTAT_STOPPED;
1009 for (i=0; stat2_strings[i]; i++)
1010 if (strstr(line,stat2_strings[i])) {
1011 StrnCpy(status->message,line,sizeof(status->message)-1);
1012 status->status=LPSTAT_ERROR;
1022 /****************************************************************************
1024 ****************************************************************************/
1025 int get_printqueue(int snum,
1026 connection_struct *conn,print_queue_struct **queue,
1027 print_status_struct *status)
1029 char *lpq_command = lp_lpqcommand(snum);
1030 char *printername = PRINTERNAME(snum);
1036 SMB_STRUCT_STAT sbuf;
1038 int cachetime = lp_lpqcachetime();
1041 check_lpq_cache(snum);
1043 if (!printername || !*printername) {
1044 DEBUG(6,("xx replacing printer name with service (snum=(%s,%d))\n",
1045 lp_servicename(snum),snum));
1046 printername = lp_servicename(snum);
1049 if (!lpq_command || !(*lpq_command)) {
1050 DEBUG(5,("No lpq command\n"));
1054 pstrcpy(syscmd,lpq_command);
1055 string_sub(syscmd,"%p",printername);
1057 standard_sub(conn,syscmd);
1059 slprintf(outfile,sizeof(outfile)-1, "%s/lpq.%08x",tmpdir(),str_checksum(syscmd));
1061 if (!lpq_cache_reset[snum] && cachetime && !sys_stat(outfile,&sbuf)) {
1062 if (time(NULL) - sbuf.st_mtime < cachetime) {
1063 DEBUG(3,("Using cached lpq output\n"));
1069 ret = smbrun(syscmd,outfile,True);
1070 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1073 lpq_cache_reset[snum] = False;
1075 f = fopen(outfile,"r");
1081 fstrcpy(status->message,"");
1082 status->status = LPSTAT_OK;
1085 while (fgets(line,sizeof(pstring),f)) {
1086 DEBUG(6,("QUEUE2: %s\n",line));
1088 *queue = Realloc(*queue,sizeof(print_queue_struct)*(count+1));
1094 bzero((char *)&(*queue)[count],sizeof(**queue));
1097 if (!parse_lpq_entry(snum,line,
1098 &(*queue)[count],status,count==0))
1109 /* we only expect this to succeed on trapdoor systems,
1110 on normal systems the file is owned by root */
1111 chmod(outfile,0666);
1117 /****************************************************************************
1118 delete a printer queue entry
1119 ****************************************************************************/
1120 void del_printqueue(connection_struct *conn,int snum,int jobid)
1122 char *lprm_command = lp_lprmcommand(snum);
1123 char *printername = PRINTERNAME(snum);
1128 if (!printername || !*printername)
1130 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1131 lp_servicename(snum),snum));
1132 printername = lp_servicename(snum);
1135 if (!lprm_command || !(*lprm_command))
1137 DEBUG(5,("No lprm command\n"));
1141 slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);
1143 pstrcpy(syscmd,lprm_command);
1144 string_sub(syscmd,"%p",printername);
1145 string_sub(syscmd,"%j",jobstr);
1146 standard_sub(conn,syscmd);
1148 ret = smbrun(syscmd,NULL,False);
1149 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1150 lpq_reset(snum); /* queue has changed */
1153 /****************************************************************************
1154 change status of a printer queue entry
1155 ****************************************************************************/
1156 void status_printjob(connection_struct *conn,int snum,int jobid,int status)
1158 char *lpstatus_command =
1159 (status==LPQ_PAUSED?lp_lppausecommand(snum):lp_lpresumecommand(snum));
1160 char *printername = PRINTERNAME(snum);
1165 if (!printername || !*printername)
1167 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1168 lp_servicename(snum),snum));
1169 printername = lp_servicename(snum);
1172 if (!lpstatus_command || !(*lpstatus_command))
1174 DEBUG(5,("No lpstatus command to %s job\n",
1175 (status==LPQ_PAUSED?"pause":"resume")));
1179 slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);
1181 pstrcpy(syscmd,lpstatus_command);
1182 string_sub(syscmd,"%p",printername);
1183 string_sub(syscmd,"%j",jobstr);
1184 standard_sub(conn,syscmd);
1186 ret = smbrun(syscmd,NULL,False);
1187 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1188 lpq_reset(snum); /* queue has changed */
1193 /****************************************************************************
1194 we encode print job numbers over the wire so that when we get them back we can
1195 tell not only what print job they are but also what service it belongs to,
1196 this is to overcome the problem that windows clients tend to send the wrong
1197 service number when doing print queue manipulation!
1198 ****************************************************************************/
1199 int printjob_encode(int snum, int job)
1201 return ((snum&0xFF)<<8) | (job & 0xFF);
1204 /****************************************************************************
1205 and now decode them again ...
1206 ****************************************************************************/
1207 void printjob_decode(int jobid, int *snum, int *job)
1209 (*snum) = (jobid >> 8) & 0xFF;
1210 (*job) = jobid & 0xFF;
1213 /****************************************************************************
1214 Change status of a printer queue
1215 ****************************************************************************/
1217 void status_printqueue(connection_struct *conn,int snum,int status)
1219 char *queuestatus_command = (status==LPSTAT_STOPPED ?
1220 lp_queuepausecommand(snum):lp_queueresumecommand(snum));
1221 char *printername = PRINTERNAME(snum);
1225 if (!printername || !*printername) {
1226 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1227 lp_servicename(snum),snum));
1228 printername = lp_servicename(snum);
1231 if (!queuestatus_command || !(*queuestatus_command)) {
1232 DEBUG(5,("No queuestatus command to %s job\n",
1233 (status==LPSTAT_STOPPED?"pause":"resume")));
1237 pstrcpy(syscmd,queuestatus_command);
1238 string_sub(syscmd,"%p",printername);
1239 standard_sub(conn,syscmd);
1241 ret = smbrun(syscmd,NULL,False);
1242 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1243 lpq_reset(snum); /* queue has changed */
1248 /***************************************************************************
1249 auto-load printer services
1250 ***************************************************************************/
1251 static void add_all_printers(void)
1253 int printers = lp_servicenumber(PRINTERS_NAME);
1255 if (printers < 0) return;
1257 pcap_printer_fn(lp_add_one_printer);
1260 /***************************************************************************
1261 auto-load some homes and printer services
1262 ***************************************************************************/
1263 static void add_auto_printers(void)
1267 char *str = lp_auto_services();
1271 printers = lp_servicenumber(PRINTERS_NAME);
1273 if (printers < 0) return;
1275 for (p=strtok(str,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) {
1276 if (lp_servicenumber(p) >= 0) continue;
1278 if (pcap_printername_ok(p,NULL)) {
1279 lp_add_printer(p,printers);
1284 /***************************************************************************
1285 load automatic printer services
1286 ***************************************************************************/
1287 void load_printers(void)
1289 add_auto_printers();
1290 if (lp_load_printers())