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;
24 extern connection_struct Connections[];
25 extern files_struct Files[];
27 static BOOL * lpq_cache_reset=NULL;
29 static int check_lpq_cache(int snum) {
30 static int lpq_caches=0;
32 if (lpq_caches <= snum) {
34 p = (BOOL *) Realloc(lpq_cache_reset,(snum+1)*sizeof(BOOL));
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(int cnum, char *command, char *syscmd, char *filename1)
56 int snum = SNUM(cnum);
60 /* get the print command for the service. */
62 if (!syscmd || !tstr) {
63 DEBUG(0,("No print command for service `%s'\n", SERVICE(snum)));
67 /* copy the command into the buffer for extensive meddling. */
68 StrnCpy(syscmd, tstr, sizeof(pstring) - 1);
70 /* look for "%s" in the string. If there is no %s, we cannot print. */
71 if (!strstr(syscmd, "%s") && !strstr(syscmd, "%f")) {
72 DEBUG(2,("WARNING! No placeholder for the filename in the print command for service %s!\n", SERVICE(snum)));
75 if (strstr(syscmd,"%s")) {
76 int iOffset = PTR_DIFF(strstr(syscmd, "%s"),syscmd);
78 /* construct the full path for the filename, shouldn't be necessary unless
79 the subshell causes a "cd" to be executed.
80 Only use the full path if there isn't a / preceding the %s */
81 if (iOffset==0 || syscmd[iOffset-1] != '/') {
82 StrnCpy(filename,Connections[cnum].connectpath,sizeof(filename)-1);
83 trim_string(filename,"","/");
84 pstrcat(filename,"/");
85 pstrcat(filename,filename1);
88 pstrcpy(filename,filename1);
90 string_sub(syscmd, "%s", filename);
93 string_sub(syscmd, "%f", filename1);
95 /* Does the service have a printername? If not, make a fake and empty */
96 /* printer name. That way a %p is treated sanely if no printer */
97 /* name was specified to replace it. This eventuality is logged. */
98 tstr = PRINTERNAME(snum);
99 if (tstr == NULL || tstr[0] == '\0') {
100 DEBUG(3,( "No printer name - using %s.\n", SERVICE(snum)));
101 tstr = SERVICE(snum);
104 string_sub(syscmd, "%p", tstr);
106 standard_sub(cnum,syscmd);
112 /****************************************************************************
113 print a file - called on closing the file
114 ****************************************************************************/
115 void print_file(int fnum)
118 int cnum = Files[fnum].cnum;
124 if (file_size(Files[fnum].name) <= 0) {
125 DEBUG(3,("Discarding null print job %s\n",Files[fnum].name));
126 sys_unlink(Files[fnum].name);
130 tempstr = build_print_command(cnum, PRINTCOMMAND(snum), syscmd, Files[fnum].name);
133 int ret = smbrun(syscmd,NULL,False);
134 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
137 DEBUG(0,("Null print command?\n"));
142 static char *Months[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
143 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err"};
146 /*******************************************************************
148 ********************************************************************/
149 static time_t EntryTime(fstring tok[], int ptr, int count, int minimum)
151 time_t jobtime,jobtime1;
153 jobtime = time(NULL); /* default case: take current time */
154 if (count >= minimum) {
156 int i, day, hour, min, sec;
159 for (i=0; i<13; i++) if (!strncmp(tok[ptr], Months[i],3)) break; /* Find month */
161 t = localtime(&jobtime);
162 day = atoi(tok[ptr+1]);
163 c=(char *)(tok[ptr+2]);
168 if(*(c+6) != 0)sec = atoi(c+6);
171 if ((t->tm_mon < i)||
173 ((t->tm_mday < day)||
174 ((t->tm_mday == day)&&
175 (t->tm_hour*60+t->tm_min < hour*60+min)))))
176 t->tm_year--; /* last year's print job */
183 jobtime1 = mktime(t);
184 if (jobtime1 != (time_t)-1)
192 /****************************************************************************
195 here is an example of lpq output under bsd
197 Warning: no daemon present
198 Rank Owner Job Files Total Size
199 1st tridge 148 README 8096 bytes
201 here is an example of lpq output under osf/1
203 Warning: no daemon present
204 Rank Pri Owner Job Files Total Size
205 1st 0 tridge 148 README 8096 bytes
206 ****************************************************************************/
207 static BOOL parse_lpq_bsd(char *line,print_queue_struct *buf,BOOL first)
231 length = strlen(line);
232 if (line[length-3] == ':')
236 /* handle the case of "(standard input)" as a filename */
237 string_sub(line,"standard input","STDIN");
238 string_sub(line,"(","\"");
239 string_sub(line,")","\"");
241 for (count=0; count<NTOK && next_token(&line,tok[count],NULL); count++) ;
243 /* we must get NTOK tokens */
247 /* the Job and Total columns must be integer */
248 if (!isdigit(*tok[JOBTOK]) || !isdigit(*tok[TOTALTOK])) return(False);
250 /* if the fname contains a space then use STDIN */
251 if (strchr(tok[FILETOK],' '))
252 fstrcpy(tok[FILETOK],"STDIN");
254 /* only take the last part of the filename */
257 char *p = strrchr(tok[FILETOK],'/');
261 fstrcpy(tok[FILETOK],tmp);
266 buf->job = atoi(tok[JOBTOK]);
267 buf->size = atoi(tok[TOTALTOK]);
268 buf->status = strequal(tok[RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED;
269 buf->time = time(NULL);
270 StrnCpy(buf->user,tok[USERTOK],sizeof(buf->user)-1);
271 StrnCpy(buf->file,tok[FILETOK],sizeof(buf->file)-1);
273 buf->priority = atoi(tok[PRIOTOK]);
282 LPRng_time modifies the current date by inserting the hour and minute from
283 the lpq output. The lpq time looks like "23:15:07"
285 static time_t LPRng_time(fstring tok[],int pos)
291 jobtime = time(NULL); /* default case: take current time */
292 t = localtime(&jobtime);
293 t->tm_hour = atoi(tok[pos]);
294 fstrcpy(tmp_time,tok[pos]);
295 t->tm_min = atoi(tmp_time+3);
296 t->tm_sec = atoi(tmp_time+6);
303 /****************************************************************************
306 Most of the code is directly reused from parse_lpq_bsd()
308 here are two examples of lpq output under lprng (LPRng-2.3.0)
310 Printer: humprn@hum-fak
311 Queue: 1 printable job
312 Server: pid 4840 active, Unspooler: pid 4841 active
313 Status: job 'cfA659hum-fak', closing device at Fri Jun 21 10:10:21 1996
314 Rank Owner Class Job Files Size Time
315 active magnus@hum-fak A 659 /var/spool/smb/Notesblok-ikke-na4024 10:03:31
317 Printer: humprn@hum-fak (printing disabled)
318 Queue: 1 printable job
319 Warning: no server present
320 Status: finished operations at Fri Jun 21 10:10:32 1996
321 Rank Owner Class Job Files Size Time
322 1 magnus@hum-fak A 387 /var/spool/smb/netbudget.xls 21230 10:50:53
324 ******************************************************************************
326 NEW FOR LPRng-3.3.5 !
329 This will not happen anymore: with LPRng-3.3.5 there is always a blank between
330 the filename and the size, and the format has changed:
332 Printer: lj6@lizard 'HP LaserJet 6P'
333 Queue: 2 printable jobs
334 Server: pid 11941 active
335 Unspooler: pid 11942 active
336 Status: printed all 1818 bytes at 19:49:59
337 Rank Owner/ID Class Job Files Size Time
338 active root@lizard+937 A 937 (stdin) 1818 19:49:58
339 2 root@lizard+969 A 969 junk.txt 2170 19:50:12
341 ****************************************************************************/
342 static BOOL parse_lpq_lprng(char *line,print_queue_struct *buf,BOOL first)
344 #define LPRNG_RANKTOK 0
345 #define LPRNG_USERTOK 1
346 #define LPRNG_PRIOTOK 2
347 #define LPRNG_JOBTOK 3
348 #define LPRNG_FILETOK 4
349 #define LPRNG_TOTALTOK 5
350 #define LPRNG_TIMETOK 6
353 /****************************************************************************
354 From lpd_status.c in LPRng source.
356 12345678901234567890123456789012345678901234567890123456789012345678901234
357 " Rank Owner Class Job Files Size Time"
358 plp_snprintf( msg, sizeof(msg), "%-6s %-19s %c %03d %-32s",
359 number, line, priority, cfp->number, error );
360 plp_snprintf( msg + len, sizeof(msg)-len, "%4d",
362 plp_snprintf( msg+len, sizeof(msg)-len, " %s",
363 Time_str( 1, cfp->statb.st_ctime ) );
364 ****************************************************************************/
365 /* The following define's are to be able to adjust the values if the
366 LPRng source changes. This is from version 2.3.0. Magnus */
373 /* The JOBSIZE_W is too small for big jobs, so time is pushed to the right */
377 #define OWNER_POS RANK_POS+RANK_W+SPACE_W
378 #define CLASS_POS OWNER_POS+OWNER_W+SPACE_W
379 #define JOB_POS CLASS_POS+CLASS_W+SPACE_W
380 #define FILE_POS JOB_POS+JOB_W+SPACE_W
381 #define JOBSIZE_POS FILE_POS+FILE_W
384 fstring tok[LPRNG_NTOK];
388 /* We only need this bugfix for older versions of lprng - current
389 information is that version 3.3.5 must not have this line
390 in order to work correctly.
394 Need to insert one space in front of the size, to be able to use
395 next_token() unchanged. I would have liked to be able to insert a
396 space instead, to prevent losing that one char, but perl has spoiled
397 me :-\ So I did it the easiest way.
399 HINT: Use as short a path as possible for the samba spool directory.
400 A long spool-path will just waste significant chars of the file name.
403 line[JOBSIZE_POS-1]=' ';
404 #endif /* OLD_LPRNG */
406 /* handle the case of "(stdin)" as a filename */
407 string_sub(line,"stdin","STDIN");
408 string_sub(line,"(","\"");
409 string_sub(line,")","\"");
411 for (count=0; count<LPRNG_NTOK && next_token(&line,tok[count],NULL); count++) ;
413 /* we must get LPRNG_NTOK tokens */
414 if (count < LPRNG_NTOK)
417 /* the Job and Total columns must be integer */
418 if (!isdigit(*tok[LPRNG_JOBTOK]) || !isdigit(*tok[LPRNG_TOTALTOK])) return(False);
420 /* if the fname contains a space then use STDIN */
421 /* I do not understand how this would be possible. Magnus. */
422 if (strchr(tok[LPRNG_FILETOK],' '))
423 fstrcpy(tok[LPRNG_FILETOK],"STDIN");
425 /* only take the last part of the filename */
428 char *p = strrchr(tok[LPRNG_FILETOK],'/');
432 fstrcpy(tok[LPRNG_FILETOK],tmp);
437 buf->job = atoi(tok[LPRNG_JOBTOK]);
438 buf->size = atoi(tok[LPRNG_TOTALTOK]);
439 if (strequal(tok[LPRNG_RANKTOK],"active"))
440 buf->status = LPQ_PRINTING;
441 else if (strequal(tok[LPRNG_RANKTOK],"hold"))
442 buf->status = LPQ_PAUSED;
444 buf->status = LPQ_QUEUED;
445 /* buf->time = time(NULL); */
446 buf->time = LPRng_time(tok,LPRNG_TIMETOK);
447 DEBUG(3,("Time reported for job %d is %s", buf->job, ctime(&buf->time)));
448 StrnCpy(buf->user,tok[LPRNG_USERTOK],sizeof(buf->user)-1);
449 StrnCpy(buf->file,tok[LPRNG_FILETOK],sizeof(buf->file)-1);
451 /* Here I try to map the CLASS char to a number, but the number
452 is never shown in Print Manager under NT anyway... Magnus. */
453 buf->priority = atoi(tok[LPRNG_PRIOTOK]-('A'-1));
462 /*******************************************************************
463 parse lpq on an aix system
465 Queue Dev Status Job Files User PP % Blks Cp Rnk
466 ------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
468 lazer lazer RUNNING 537 6297doc.A kvintus@IE 0 10 2445 1 1
469 QUEUED 538 C.ps root@IEDVB 124 1 2
470 QUEUED 539 E.ps root@IEDVB 28 1 3
471 QUEUED 540 L.ps root@IEDVB 172 1 4
472 QUEUED 541 P.ps root@IEDVB 22 1 5
473 ********************************************************************/
474 static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first)
479 /* handle the case of "(standard input)" as a filename */
480 string_sub(line,"standard input","STDIN");
481 string_sub(line,"(","\"");
482 string_sub(line,")","\"");
484 for (count=0; count<10 && next_token(&line,tok[count],NULL); count++) ;
486 /* we must get 6 tokens */
489 if ((count == 7) && ((strcmp(tok[0],"QUEUED") == 0) || (strcmp(tok[0],"HELD") == 0)))
491 /* the 2nd and 5th columns must be integer */
492 if (!isdigit(*tok[1]) || !isdigit(*tok[4])) return(False);
493 buf->size = atoi(tok[4]) * 1024;
494 /* if the fname contains a space then use STDIN */
495 if (strchr(tok[2],' '))
496 fstrcpy(tok[2],"STDIN");
498 /* only take the last part of the filename */
501 char *p = strrchr(tok[2],'/');
510 buf->job = atoi(tok[1]);
511 buf->status = strequal(tok[0],"HELD")?LPQ_PAUSED:LPQ_QUEUED;
513 buf->time = time(NULL);
514 StrnCpy(buf->user,tok[3],sizeof(buf->user)-1);
515 StrnCpy(buf->file,tok[2],sizeof(buf->file)-1);
519 DEBUG(6,("parse_lpq_aix count=%d\n", count));
525 /* the 4th and 9th columns must be integer */
526 if (!isdigit(*tok[3]) || !isdigit(*tok[8])) return(False);
527 buf->size = atoi(tok[8]) * 1024;
528 /* if the fname contains a space then use STDIN */
529 if (strchr(tok[4],' '))
530 fstrcpy(tok[4],"STDIN");
532 /* only take the last part of the filename */
535 char *p = strrchr(tok[4],'/');
544 buf->job = atoi(tok[3]);
545 buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED;
547 buf->time = time(NULL);
548 StrnCpy(buf->user,tok[5],sizeof(buf->user)-1);
549 StrnCpy(buf->file,tok[4],sizeof(buf->file)-1);
557 /****************************************************************************
559 here is an example of lpq output under hpux; note there's no space after -o !
561 ljplus-2153 user priority 0 Jan 19 08:14 on ljplus
563 server.c 110712 bytes
564 ljplus-2154 user priority 0 Jan 19 08:14 from client
565 (standard input) 7551 bytes
566 ****************************************************************************/
567 static BOOL parse_lpq_hpux(char * line, print_queue_struct *buf, BOOL first)
569 /* must read two lines to process, therefore keep some values static */
570 static BOOL header_line_ok=False, base_prio_reset=False;
571 static fstring jobuser;
574 static time_t jobtime;
575 static int jobstat=LPQ_QUEUED;
576 /* to store minimum priority to print, lpstat command should be invoked
577 with -p option first, to work */
578 static int base_prio;
584 /* If a line begins with a horizontal TAB, it is a subline type */
586 if (line[0] == TAB) { /* subline */
587 /* check if it contains the base priority */
588 if (!strncmp(line,"\tfence priority : ",18)) {
589 base_prio=atoi(&line[18]);
590 DEBUG(4, ("fence priority set at %d\n", base_prio));
592 if (!header_line_ok) return (False); /* incorrect header line */
593 /* handle the case of "(standard input)" as a filename */
594 string_sub(line,"standard input","STDIN");
595 string_sub(line,"(","\"");
596 string_sub(line,")","\"");
598 for (count=0; count<2 && next_token(&line,tok[count],NULL); count++) ;
599 /* we must get 2 tokens */
600 if (count < 2) return(False);
602 /* the 2nd column must be integer */
603 if (!isdigit(*tok[1])) return(False);
605 /* if the fname contains a space then use STDIN */
606 if (strchr(tok[0],' '))
607 fstrcpy(tok[0],"STDIN");
609 buf->size = atoi(tok[1]);
610 StrnCpy(buf->file,tok[0],sizeof(buf->file)-1);
612 /* fill things from header line */
615 buf->status = jobstat;
616 buf->priority = jobprio;
617 StrnCpy(buf->user,jobuser,sizeof(buf->user)-1);
621 else { /* header line */
622 header_line_ok=False; /* reset it */
624 if (!base_prio_reset) {
625 base_prio=0; /* reset it */
626 base_prio_reset=True;
629 else if (base_prio) base_prio_reset=False;
631 /* handle the dash in the job id */
632 string_sub(line,"-"," ");
634 for (count=0; count<12 && next_token(&line,tok[count],NULL); count++) ;
636 /* we must get 8 tokens */
637 if (count < 8) return(False);
639 /* first token must be printer name (cannot check ?) */
640 /* the 2nd, 5th & 7th column must be integer */
641 if (!isdigit(*tok[1]) || !isdigit(*tok[4]) || !isdigit(*tok[6])) return(False);
642 jobid = atoi(tok[1]);
643 StrnCpy(jobuser,tok[2],sizeof(buf->user)-1);
644 jobprio = atoi(tok[4]);
647 jobtime=EntryTime(tok, 5, count, 8);
648 if (jobprio < base_prio) {
649 jobstat = LPQ_PAUSED;
650 DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n", jobid, jobprio, base_prio, jobstat));
653 jobstat = LPQ_QUEUED;
654 if ((count >8) && (((strequal(tok[8],"on")) ||
655 ((strequal(tok[8],"from")) &&
656 ((count > 10)&&(strequal(tok[10],"on")))))))
657 jobstat = LPQ_PRINTING;
660 header_line_ok=True; /* information is correct */
661 return(False); /* need subline info to include into queuelist */
666 /****************************************************************************
669 here is an example of "lpstat -o dcslw" output under sysv
671 dcslw-896 tridge 4712 Dec 20 10:30:30 on dcslw
672 dcslw-897 tridge 4712 Dec 20 10:30:30 being held
674 ****************************************************************************/
675 static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first)
681 /* handle the dash in the job id */
682 string_sub(line,"-"," ");
684 for (count=0; count<9 && next_token(&line,tok[count],NULL); count++) ;
686 /* we must get 7 tokens */
690 /* the 2nd and 4th, 6th columns must be integer */
691 if (!isdigit(*tok[1]) || !isdigit(*tok[3])) return(False);
692 if (!isdigit(*tok[5])) return(False);
694 /* if the user contains a ! then trim the first part of it */
695 if ((p=strchr(tok[2],'!')))
703 buf->job = atoi(tok[1]);
704 buf->size = atoi(tok[3]);
705 if (count > 7 && strequal(tok[7],"on"))
706 buf->status = LPQ_PRINTING;
707 else if (count > 8 && strequal(tok[7],"being") && strequal(tok[8],"held"))
708 buf->status = LPQ_PAUSED;
710 buf->status = LPQ_QUEUED;
712 buf->time = EntryTime(tok, 4, count, 7);
713 StrnCpy(buf->user,tok[2],sizeof(buf->user)-1);
714 StrnCpy(buf->file,tok[2],sizeof(buf->file)-1);
718 /****************************************************************************
721 here is an example of lpq output under qnx
722 Spooler: /qnx/spooler, on node 1
724 0000: root [job #1 ] active 1146 bytes /etc/profile
725 0001: root [job #2 ] ready 2378 bytes /etc/install
726 0002: root [job #3 ] ready 1146 bytes -- standard input --
727 ****************************************************************************/
728 static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first)
733 DEBUG(0,("antes [%s]\n", line));
735 /* handle the case of "-- standard input --" as a filename */
736 string_sub(line,"standard input","STDIN");
737 DEBUG(0,("despues [%s]\n", line));
738 string_sub(line,"-- ","\"");
739 string_sub(line," --","\"");
740 DEBUG(0,("despues 1 [%s]\n", line));
742 string_sub(line,"[job #","");
743 string_sub(line,"]","");
744 DEBUG(0,("despues 2 [%s]\n", line));
748 for (count=0; count<7 && next_token(&line,tok[count],NULL); count++) ;
750 /* we must get 7 tokens */
754 /* the 3rd and 5th columns must be integer */
755 if (!isdigit(*tok[2]) || !isdigit(*tok[4])) return(False);
757 /* only take the last part of the filename */
760 char *p = strrchr(tok[6],'/');
769 buf->job = atoi(tok[2]);
770 buf->size = atoi(tok[4]);
771 buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED;
773 buf->time = time(NULL);
774 StrnCpy(buf->user,tok[1],sizeof(buf->user)-1);
775 StrnCpy(buf->file,tok[6],sizeof(buf->file)-1);
780 /****************************************************************************
781 parse a lpq line for the plp printing system
782 Bertrand Wallrich <Bertrand.Wallrich@loria.fr>
784 redone by tridge. Here is a sample queue:
786 Local Printer 'lp2' (fjall):
787 Printing (started at Jun 15 13:33:58, attempt 1).
788 Rank Owner Pr Opt Job Host Files Size Date
789 active tridge X - 6 fjall /etc/hosts 739 Jun 15 13:33
790 3rd tridge X - 7 fjall /etc/hosts 739 Jun 15 13:33
792 ****************************************************************************/
793 static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first)
798 /* handle the case of "(standard input)" as a filename */
799 string_sub(line,"stdin","STDIN");
800 string_sub(line,"(","\"");
801 string_sub(line,")","\"");
803 for (count=0; count<11 && next_token(&line,tok[count],NULL); count++) ;
805 /* we must get 11 tokens */
809 /* the first must be "active" or begin with an integer */
810 if (strcmp(tok[0],"active") && !isdigit(tok[0][0]))
813 /* the 5th and 8th must be integer */
814 if (!isdigit(*tok[4]) || !isdigit(*tok[7]))
817 /* if the fname contains a space then use STDIN */
818 if (strchr(tok[6],' '))
819 fstrcpy(tok[6],"STDIN");
821 /* only take the last part of the filename */
824 char *p = strrchr(tok[6],'/');
833 buf->job = atoi(tok[4]);
835 buf->size = atoi(tok[7]);
836 if (strchr(tok[7],'K'))
838 if (strchr(tok[7],'M'))
839 buf->size *= 1024*1024;
841 buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED;
843 buf->time = time(NULL);
844 StrnCpy(buf->user,tok[1],sizeof(buf->user)-1);
845 StrnCpy(buf->file,tok[6],sizeof(buf->file)-1);
849 /****************************************************************************
852 here is an example of "qstat -l -d qms" output under softq
854 Queue qms: 2 jobs; daemon active (313); enabled; accepting;
855 job-ID submission-time pri size owner title
856 205980: H 98/03/09 13:04:05 0 15733 stephenf chap1.ps
857 206086:> 98/03/12 17:24:40 0 659 chris -
858 206087: 98/03/12 17:24:45 0 4876 chris -
859 Total: 21268 bytes in queue
862 ****************************************************************************/
863 static BOOL parse_lpq_softq(char *line,print_queue_struct *buf,BOOL first)
868 /* mung all the ":"s to spaces*/
869 string_sub(line,":"," ");
871 for (count=0; count<10 && next_token(&line,tok[count],NULL); count++) ;
873 /* we must get 9 tokens */
877 /* the 1st and 7th columns must be integer */
878 if (!isdigit(*tok[0]) || !isdigit(*tok[6])) return(False);
879 /* if the 2nd column is either '>' or 'H' then the 7th and 8th must be
880 * integer, else it's the 6th and 7th that must be
882 if (*tok[1] == 'H' || *tok[1] == '>')
884 if (!isdigit(*tok[7]))
886 buf->status = *tok[1] == '>' ? LPQ_PRINTING : LPQ_PAUSED;
891 if (!isdigit(*tok[5]))
893 buf->status = LPQ_QUEUED;
898 buf->job = atoi(tok[0]);
899 buf->size = atoi(tok[count+6]);
900 buf->priority = atoi(tok[count+5]);
901 StrnCpy(buf->user,tok[count+7],sizeof(buf->user)-1);
902 StrnCpy(buf->file,tok[count+8],sizeof(buf->file)-1);
903 buf->time = time(NULL); /* default case: take current time */
908 t = localtime(&buf->time);
909 t->tm_mday = atoi(tok[count+2]+6);
910 t->tm_mon = atoi(tok[count+2]+3);
911 switch (*tok[count+2])
913 case 7: case 8: case 9: t->tm_year = atoi(tok[count+2]) + 1900; break;
914 default: t->tm_year = atoi(tok[count+2]) + 2000; break;
917 t->tm_hour = atoi(tok[count+3]);
918 t->tm_min = atoi(tok[count+4]);
919 t->tm_sec = atoi(tok[count+5]);
921 if (jobtime != (time_t)-1)
929 char *stat0_strings[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL };
930 char *stat1_strings[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL };
931 char *stat2_strings[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL };
933 /****************************************************************************
934 parse a lpq line. Choose printing style
935 ****************************************************************************/
936 static BOOL parse_lpq_entry(int snum,char *line,
937 print_queue_struct *buf,
938 print_status_struct *status,BOOL first)
942 switch (lp_printing(snum))
945 ret = parse_lpq_sysv(line,buf,first);
948 ret = parse_lpq_aix(line,buf,first);
951 ret = parse_lpq_hpux(line,buf,first);
954 ret = parse_lpq_qnx(line,buf,first);
957 ret = parse_lpq_lprng(line,buf,first);
960 ret = parse_lpq_plp(line,buf,first);
963 ret = parse_lpq_softq(line,buf,first);
966 ret = parse_lpq_bsd(line,buf,first);
970 #ifdef LPQ_GUEST_TO_USER
972 extern pstring sesssetup_user;
973 /* change guest entries to the current logged in user to make
974 them appear deletable to windows */
975 if (sesssetup_user[0] && strequal(buf->user,lp_guestaccount(snum)))
976 pstrcpy(buf->user,sesssetup_user);
980 /* We don't want the newline in the status message. */
982 char *p = strchr(line,'\n');
988 /* a few simple checks to see if the line might be a
990 handle them so that most severe condition is shown */
994 switch (status->status) {
996 for (i=0; stat0_strings[i]; i++)
997 if (strstr(line,stat0_strings[i])) {
998 StrnCpy(status->message,line,sizeof(status->message)-1);
999 status->status=LPSTAT_OK;
1002 case LPSTAT_STOPPED:
1003 for (i=0; stat1_strings[i]; i++)
1004 if (strstr(line,stat1_strings[i])) {
1005 StrnCpy(status->message,line,sizeof(status->message)-1);
1006 status->status=LPSTAT_STOPPED;
1010 for (i=0; stat2_strings[i]; i++)
1011 if (strstr(line,stat2_strings[i])) {
1012 StrnCpy(status->message,line,sizeof(status->message)-1);
1013 status->status=LPSTAT_ERROR;
1023 /****************************************************************************
1025 ****************************************************************************/
1026 int get_printqueue(int snum,int cnum,print_queue_struct **queue,
1027 print_status_struct *status)
1029 char *lpq_command = lp_lpqcommand(snum);
1030 char *printername = PRINTERNAME(snum);
1038 int cachetime = lp_lpqcachetime();
1041 check_lpq_cache(snum);
1043 if (!printername || !*printername)
1045 DEBUG(6,("xx replacing printer name with service (snum=(%s,%d))\n",
1046 lp_servicename(snum),snum));
1047 printername = lp_servicename(snum);
1050 if (!lpq_command || !(*lpq_command))
1052 DEBUG(5,("No lpq command\n"));
1056 pstrcpy(syscmd,lpq_command);
1057 string_sub(syscmd,"%p",printername);
1059 standard_sub(cnum,syscmd);
1061 slprintf(outfile,sizeof(outfile)-1, "%s/lpq.%08x",tmpdir(),str_checksum(syscmd));
1063 if (!lpq_cache_reset[snum] && cachetime && !stat(outfile,&sbuf))
1065 if (time(NULL) - sbuf.st_mtime < cachetime) {
1066 DEBUG(3,("Using cached lpq output\n"));
1072 ret = smbrun(syscmd,outfile,True);
1073 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1076 lpq_cache_reset[snum] = False;
1078 f = fopen(outfile,"r");
1084 fstrcpy(status->message,"");
1085 status->status = LPSTAT_OK;
1088 while (fgets(line,sizeof(pstring),f))
1090 DEBUG(6,("QUEUE2: %s\n",line));
1092 *queue = Realloc(*queue,sizeof(print_queue_struct)*(count+1));
1099 bzero((char *)&(*queue)[count],sizeof(**queue));
1102 if (!parse_lpq_entry(snum,line,&(*queue)[count],status,count==0))
1113 /* we only expect this to succeed on trapdoor systems, on normal systems
1114 the file is owned by root */
1115 chmod(outfile,0666);
1121 /****************************************************************************
1122 delete a printer queue entry
1123 ****************************************************************************/
1124 void del_printqueue(int cnum,int snum,int jobid)
1126 char *lprm_command = lp_lprmcommand(snum);
1127 char *printername = PRINTERNAME(snum);
1132 if (!printername || !*printername)
1134 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1135 lp_servicename(snum),snum));
1136 printername = lp_servicename(snum);
1139 if (!lprm_command || !(*lprm_command))
1141 DEBUG(5,("No lprm command\n"));
1145 slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);
1147 pstrcpy(syscmd,lprm_command);
1148 string_sub(syscmd,"%p",printername);
1149 string_sub(syscmd,"%j",jobstr);
1150 standard_sub(cnum,syscmd);
1152 ret = smbrun(syscmd,NULL,False);
1153 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1154 lpq_reset(snum); /* queue has changed */
1157 /****************************************************************************
1158 change status of a printer queue entry
1159 ****************************************************************************/
1160 void status_printjob(int cnum,int snum,int jobid,int status)
1162 char *lpstatus_command =
1163 (status==LPQ_PAUSED?lp_lppausecommand(snum):lp_lpresumecommand(snum));
1164 char *printername = PRINTERNAME(snum);
1169 if (!printername || !*printername)
1171 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1172 lp_servicename(snum),snum));
1173 printername = lp_servicename(snum);
1176 if (!lpstatus_command || !(*lpstatus_command))
1178 DEBUG(5,("No lpstatus command to %s job\n",
1179 (status==LPQ_PAUSED?"pause":"resume")));
1183 slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);
1185 pstrcpy(syscmd,lpstatus_command);
1186 string_sub(syscmd,"%p",printername);
1187 string_sub(syscmd,"%j",jobstr);
1188 standard_sub(cnum,syscmd);
1190 ret = smbrun(syscmd,NULL,False);
1191 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1192 lpq_reset(snum); /* queue has changed */
1197 /****************************************************************************
1198 we encode print job numbers over the wire so that when we get them back we can
1199 tell not only what print job they are but also what service it belongs to,
1200 this is to overcome the problem that windows clients tend to send the wrong
1201 service number when doing print queue manipulation!
1202 ****************************************************************************/
1203 int printjob_encode(int snum, int job)
1205 return ((snum&0xFF)<<8) | (job & 0xFF);
1208 /****************************************************************************
1209 and now decode them again ...
1210 ****************************************************************************/
1211 void printjob_decode(int jobid, int *snum, int *job)
1213 (*snum) = (jobid >> 8) & 0xFF;
1214 (*job) = jobid & 0xFF;