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
198 <allan@umich.edu> June 30, 1998.
199 Modified to handle file names with spaces, like the parse_lpq_lprng code
201 ****************************************************************************/
202 static BOOL parse_lpq_bsd(char *line,print_queue_struct *buf,BOOL first)
210 #define TOTALTOK (count - 2)
218 #define TOTALTOK (count - 2)
231 length = strlen(line2);
232 if (line2[length-3] == ':')
236 tok[0] = strtok(line2," \t");
239 while (((tok[count] = strtok(NULL," \t")) != NULL) && (count < MAXTOK)) {
243 /* we must get at least NTOK tokens */
247 /* the Job and Total columns must be integer */
248 if (!isdigit(*tok[JOBTOK]) || !isdigit(*tok[TOTALTOK])) return(False);
250 buf->job = atoi(tok[JOBTOK]);
251 buf->size = atoi(tok[TOTALTOK]);
252 buf->status = strequal(tok[RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED;
253 buf->time = time(NULL);
254 StrnCpy(buf->user,tok[USERTOK],sizeof(buf->user)-1);
255 StrnCpy(buf->file,tok[FILETOK],sizeof(buf->file)-1);
257 if ((FILETOK + 1) != TOTALTOK) {
261 bufsize = sizeof(buf->file) - strlen(buf->file) - 1;
263 for (i = (FILETOK + 1); i < TOTALTOK; i++) {
264 strncat(buf->file," ",bufsize);
265 strncat(buf->file,tok[i],bufsize - 1);
266 bufsize = sizeof(buf->file) - strlen(buf->file) - 1;
274 buf->priority = atoi(tok[PRIOTOK]);
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)
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);
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
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)
321 #define LPRNG_MAXTOK 128 /* PFMA just to keep us from running away. */
323 char *tokarr[LPRNG_MAXTOK];
329 tokarr[0] = strtok(line2," \t");
331 while (((tokarr[num_tok] = strtok(NULL," \t")) != NULL)
332 && (num_tok < LPRNG_MAXTOK)) {
336 /* We must get at least LPRNG_NTOK tokens. */
337 if (num_tok < LPRNG_NTOK) {
341 if (!isdigit(*tokarr[LPRNG_JOBTOK]) || !isdigit(*tokarr[LPRNG_TOTALTOK])) {
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(*tokarr[LPRNG_RANKTOK])) {
351 buf->status = LPQ_QUEUED;
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) {
370 StrnCpy(buf->file,tokarr[LPRNG_FILETOK],sizeof(buf->file)-1);
372 if ((LPRNG_FILETOK + 1) != LPRNG_TOTALTOK) {
376 bufsize = sizeof(buf->file) - strlen(buf->file) - 1;
378 for (i = (LPRNG_FILETOK + 1); i < LPRNG_TOTALTOK; i++) {
379 strncat(buf->file," ",bufsize);
380 strncat(buf->file,tokarr[i],bufsize - 1);
381 bufsize = sizeof(buf->file) - strlen(buf->file) - 1;
393 /*******************************************************************
394 parse lpq on an aix system
396 Queue Dev Status Job Files User PP % Blks Cp Rnk
397 ------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
399 lazer lazer RUNNING 537 6297doc.A kvintus@IE 0 10 2445 1 1
400 QUEUED 538 C.ps root@IEDVB 124 1 2
401 QUEUED 539 E.ps root@IEDVB 28 1 3
402 QUEUED 540 L.ps root@IEDVB 172 1 4
403 QUEUED 541 P.ps root@IEDVB 22 1 5
404 ********************************************************************/
405 static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first)
410 /* handle the case of "(standard input)" as a filename */
411 string_sub(line,"standard input","STDIN");
412 string_sub(line,"(","\"");
413 string_sub(line,")","\"");
417 next_token(&line,tok[count],NULL, sizeof(tok[count]));
420 /* we must get 6 tokens */
423 if ((count == 7) && ((strcmp(tok[0],"QUEUED") == 0) || (strcmp(tok[0],"HELD") == 0)))
425 /* the 2nd and 5th columns must be integer */
426 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4])) return(False);
427 buf->size = atoi(tok[4]) * 1024;
428 /* if the fname contains a space then use STDIN */
429 if (strchr(tok[2],' '))
430 fstrcpy(tok[2],"STDIN");
432 /* only take the last part of the filename */
435 char *p = strrchr(tok[2],'/');
444 buf->job = atoi(tok[1]);
445 buf->status = strequal(tok[0],"HELD")?LPQ_PAUSED:LPQ_QUEUED;
447 buf->time = time(NULL);
448 StrnCpy(buf->user,tok[3],sizeof(buf->user)-1);
449 StrnCpy(buf->file,tok[2],sizeof(buf->file)-1);
453 DEBUG(6,("parse_lpq_aix count=%d\n", count));
459 /* the 4th and 9th columns must be integer */
460 if (!isdigit((int)*tok[3]) || !isdigit((int)*tok[8])) return(False);
461 buf->size = atoi(tok[8]) * 1024;
462 /* if the fname contains a space then use STDIN */
463 if (strchr(tok[4],' '))
464 fstrcpy(tok[4],"STDIN");
466 /* only take the last part of the filename */
469 char *p = strrchr(tok[4],'/');
478 buf->job = atoi(tok[3]);
479 buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED;
481 buf->time = time(NULL);
482 StrnCpy(buf->user,tok[5],sizeof(buf->user)-1);
483 StrnCpy(buf->file,tok[4],sizeof(buf->file)-1);
491 /****************************************************************************
493 here is an example of lpq output under hpux; note there's no space after -o !
495 ljplus-2153 user priority 0 Jan 19 08:14 on ljplus
497 server.c 110712 bytes
498 ljplus-2154 user priority 0 Jan 19 08:14 from client
499 (standard input) 7551 bytes
500 ****************************************************************************/
501 static BOOL parse_lpq_hpux(char * line, print_queue_struct *buf, BOOL first)
503 /* must read two lines to process, therefore keep some values static */
504 static BOOL header_line_ok=False, base_prio_reset=False;
505 static fstring jobuser;
508 static time_t jobtime;
509 static int jobstat=LPQ_QUEUED;
510 /* to store minimum priority to print, lpstat command should be invoked
511 with -p option first, to work */
512 static int base_prio;
518 /* If a line begins with a horizontal TAB, it is a subline type */
520 if (line[0] == htab) { /* subline */
521 /* check if it contains the base priority */
522 if (!strncmp(line,"\tfence priority : ",18)) {
523 base_prio=atoi(&line[18]);
524 DEBUG(4, ("fence priority set at %d\n", base_prio));
526 if (!header_line_ok) return (False); /* incorrect header line */
527 /* handle the case of "(standard input)" as a filename */
528 string_sub(line,"standard input","STDIN");
529 string_sub(line,"(","\"");
530 string_sub(line,")","\"");
532 for (count=0; count<2 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
533 /* we must get 2 tokens */
534 if (count < 2) return(False);
536 /* the 2nd column must be integer */
537 if (!isdigit((int)*tok[1])) return(False);
539 /* if the fname contains a space then use STDIN */
540 if (strchr(tok[0],' '))
541 fstrcpy(tok[0],"STDIN");
543 buf->size = atoi(tok[1]);
544 StrnCpy(buf->file,tok[0],sizeof(buf->file)-1);
546 /* fill things from header line */
549 buf->status = jobstat;
550 buf->priority = jobprio;
551 StrnCpy(buf->user,jobuser,sizeof(buf->user)-1);
555 else { /* header line */
556 header_line_ok=False; /* reset it */
558 if (!base_prio_reset) {
559 base_prio=0; /* reset it */
560 base_prio_reset=True;
563 else if (base_prio) base_prio_reset=False;
565 /* handle the dash in the job id */
566 string_sub(line,"-"," ");
568 for (count=0; count<12 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
570 /* we must get 8 tokens */
571 if (count < 8) return(False);
573 /* first token must be printer name (cannot check ?) */
574 /* the 2nd, 5th & 7th column must be integer */
575 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4]) || !isdigit((int)*tok[6])) return(False);
576 jobid = atoi(tok[1]);
577 StrnCpy(jobuser,tok[2],sizeof(buf->user)-1);
578 jobprio = atoi(tok[4]);
581 jobtime=EntryTime(tok, 5, count, 8);
582 if (jobprio < base_prio) {
583 jobstat = LPQ_PAUSED;
584 DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n", jobid, jobprio, base_prio, jobstat));
587 jobstat = LPQ_QUEUED;
588 if ((count >8) && (((strequal(tok[8],"on")) ||
589 ((strequal(tok[8],"from")) &&
590 ((count > 10)&&(strequal(tok[10],"on")))))))
591 jobstat = LPQ_PRINTING;
594 header_line_ok=True; /* information is correct */
595 return(False); /* need subline info to include into queuelist */
600 /****************************************************************************
603 here is an example of "lpstat -o dcslw" output under sysv
605 dcslw-896 tridge 4712 Dec 20 10:30:30 on dcslw
606 dcslw-897 tridge 4712 Dec 20 10:30:30 being held
608 ****************************************************************************/
609 static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first)
615 /* handle the dash in the job id */
616 string_sub(line,"-"," ");
618 for (count=0; count<9 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
620 /* we must get 7 tokens */
624 /* the 2nd and 4th, 6th columns must be integer */
625 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[3])) return(False);
626 if (!isdigit((int)*tok[5])) return(False);
628 /* if the user contains a ! then trim the first part of it */
629 if ((p=strchr(tok[2],'!')))
637 buf->job = atoi(tok[1]);
638 buf->size = atoi(tok[3]);
639 if (count > 7 && strequal(tok[7],"on"))
640 buf->status = LPQ_PRINTING;
641 else if (count > 8 && strequal(tok[7],"being") && strequal(tok[8],"held"))
642 buf->status = LPQ_PAUSED;
644 buf->status = LPQ_QUEUED;
646 buf->time = EntryTime(tok, 4, count, 7);
647 StrnCpy(buf->user,tok[2],sizeof(buf->user)-1);
648 StrnCpy(buf->file,tok[2],sizeof(buf->file)-1);
652 /****************************************************************************
655 here is an example of lpq output under qnx
656 Spooler: /qnx/spooler, on node 1
658 0000: root [job #1 ] active 1146 bytes /etc/profile
659 0001: root [job #2 ] ready 2378 bytes /etc/install
660 0002: root [job #3 ] ready 1146 bytes -- standard input --
661 ****************************************************************************/
662 static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first)
667 DEBUG(0,("antes [%s]\n", line));
669 /* handle the case of "-- standard input --" as a filename */
670 string_sub(line,"standard input","STDIN");
671 DEBUG(0,("despues [%s]\n", line));
672 string_sub(line,"-- ","\"");
673 string_sub(line," --","\"");
674 DEBUG(0,("despues 1 [%s]\n", line));
676 string_sub(line,"[job #","");
677 string_sub(line,"]","");
678 DEBUG(0,("despues 2 [%s]\n", line));
682 for (count=0; count<7 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
684 /* we must get 7 tokens */
688 /* the 3rd and 5th columns must be integer */
689 if (!isdigit((int)*tok[2]) || !isdigit((int)*tok[4])) return(False);
691 /* only take the last part of the filename */
694 char *p = strrchr(tok[6],'/');
703 buf->job = atoi(tok[2]);
704 buf->size = atoi(tok[4]);
705 buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED;
707 buf->time = time(NULL);
708 StrnCpy(buf->user,tok[1],sizeof(buf->user)-1);
709 StrnCpy(buf->file,tok[6],sizeof(buf->file)-1);
714 /****************************************************************************
715 parse a lpq line for the plp printing system
716 Bertrand Wallrich <Bertrand.Wallrich@loria.fr>
718 redone by tridge. Here is a sample queue:
720 Local Printer 'lp2' (fjall):
721 Printing (started at Jun 15 13:33:58, attempt 1).
722 Rank Owner Pr Opt Job Host Files Size Date
723 active tridge X - 6 fjall /etc/hosts 739 Jun 15 13:33
724 3rd tridge X - 7 fjall /etc/hosts 739 Jun 15 13:33
726 ****************************************************************************/
727 static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first)
732 /* handle the case of "(standard input)" as a filename */
733 string_sub(line,"stdin","STDIN");
734 string_sub(line,"(","\"");
735 string_sub(line,")","\"");
737 for (count=0; count<11 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
739 /* we must get 11 tokens */
743 /* the first must be "active" or begin with an integer */
744 if (strcmp(tok[0],"active") && !isdigit((int)tok[0][0]))
747 /* the 5th and 8th must be integer */
748 if (!isdigit((int)*tok[4]) || !isdigit((int)*tok[7]))
751 /* if the fname contains a space then use STDIN */
752 if (strchr(tok[6],' '))
753 fstrcpy(tok[6],"STDIN");
755 /* only take the last part of the filename */
758 char *p = strrchr(tok[6],'/');
767 buf->job = atoi(tok[4]);
769 buf->size = atoi(tok[7]);
770 if (strchr(tok[7],'K'))
772 if (strchr(tok[7],'M'))
773 buf->size *= 1024*1024;
775 buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED;
777 buf->time = time(NULL);
778 StrnCpy(buf->user,tok[1],sizeof(buf->user)-1);
779 StrnCpy(buf->file,tok[6],sizeof(buf->file)-1);
783 /****************************************************************************
786 here is an example of "qstat -l -d qms" output under softq
788 Queue qms: 2 jobs; daemon active (313); enabled; accepting;
789 job-ID submission-time pri size owner title
790 205980: H 98/03/09 13:04:05 0 15733 stephenf chap1.ps
791 206086:> 98/03/12 17:24:40 0 659 chris -
792 206087: 98/03/12 17:24:45 0 4876 chris -
793 Total: 21268 bytes in queue
796 ****************************************************************************/
797 static BOOL parse_lpq_softq(char *line,print_queue_struct *buf,BOOL first)
802 /* mung all the ":"s to spaces*/
803 string_sub(line,":"," ");
805 for (count=0; count<10 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
807 /* we must get 9 tokens */
811 /* the 1st and 7th columns must be integer */
812 if (!isdigit((int)*tok[0]) || !isdigit((int)*tok[6])) return(False);
813 /* if the 2nd column is either '>' or 'H' then the 7th and 8th must be
814 * integer, else it's the 6th and 7th that must be
816 if (*tok[1] == 'H' || *tok[1] == '>')
818 if (!isdigit((int)*tok[7]))
820 buf->status = *tok[1] == '>' ? LPQ_PRINTING : LPQ_PAUSED;
825 if (!isdigit((int)*tok[5]))
827 buf->status = LPQ_QUEUED;
832 buf->job = atoi(tok[0]);
833 buf->size = atoi(tok[count+6]);
834 buf->priority = atoi(tok[count+5]);
835 StrnCpy(buf->user,tok[count+7],sizeof(buf->user)-1);
836 StrnCpy(buf->file,tok[count+8],sizeof(buf->file)-1);
837 buf->time = time(NULL); /* default case: take current time */
842 t = localtime(&buf->time);
843 t->tm_mday = atoi(tok[count+2]+6);
844 t->tm_mon = atoi(tok[count+2]+3);
845 switch (*tok[count+2])
847 case 7: case 8: case 9: t->tm_year = atoi(tok[count+2]) + 1900; break;
848 default: t->tm_year = atoi(tok[count+2]) + 2000; break;
851 t->tm_hour = atoi(tok[count+3]);
852 t->tm_min = atoi(tok[count+4]);
853 t->tm_sec = atoi(tok[count+5]);
855 if (jobtime != (time_t)-1)
863 char *stat0_strings[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL };
864 char *stat1_strings[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL };
865 char *stat2_strings[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL };
867 /****************************************************************************
868 parse a lpq line. Choose printing style
869 ****************************************************************************/
870 static BOOL parse_lpq_entry(int snum,char *line,
871 print_queue_struct *buf,
872 print_status_struct *status,BOOL first)
876 switch (lp_printing(snum))
879 ret = parse_lpq_sysv(line,buf,first);
882 ret = parse_lpq_aix(line,buf,first);
885 ret = parse_lpq_hpux(line,buf,first);
888 ret = parse_lpq_qnx(line,buf,first);
891 ret = parse_lpq_lprng(line,buf,first);
894 ret = parse_lpq_plp(line,buf,first);
897 ret = parse_lpq_softq(line,buf,first);
900 ret = parse_lpq_bsd(line,buf,first);
904 #ifdef LPQ_GUEST_TO_USER
906 extern pstring sesssetup_user;
907 /* change guest entries to the current logged in user to make
908 them appear deletable to windows */
909 if (sesssetup_user[0] && strequal(buf->user,lp_guestaccount(snum)))
910 pstrcpy(buf->user,sesssetup_user);
914 /* We don't want the newline in the status message. */
916 char *p = strchr(line,'\n');
922 /* a few simple checks to see if the line might be a
924 handle them so that most severe condition is shown */
928 switch (status->status) {
930 for (i=0; stat0_strings[i]; i++)
931 if (strstr(line,stat0_strings[i])) {
932 StrnCpy(status->message,line,sizeof(status->message)-1);
933 status->status=LPSTAT_OK;
937 for (i=0; stat1_strings[i]; i++)
938 if (strstr(line,stat1_strings[i])) {
939 StrnCpy(status->message,line,sizeof(status->message)-1);
940 status->status=LPSTAT_STOPPED;
944 for (i=0; stat2_strings[i]; i++)
945 if (strstr(line,stat2_strings[i])) {
946 StrnCpy(status->message,line,sizeof(status->message)-1);
947 status->status=LPSTAT_ERROR;
957 /****************************************************************************
959 ****************************************************************************/
960 int get_printqueue(int snum,
961 connection_struct *conn,print_queue_struct **queue,
962 print_status_struct *status)
964 char *lpq_command = lp_lpqcommand(snum);
965 char *printername = PRINTERNAME(snum);
971 SMB_STRUCT_STAT sbuf;
973 int cachetime = lp_lpqcachetime();
976 check_lpq_cache(snum);
978 if (!printername || !*printername) {
979 DEBUG(6,("xx replacing printer name with service (snum=(%s,%d))\n",
980 lp_servicename(snum),snum));
981 printername = lp_servicename(snum);
984 if (!lpq_command || !(*lpq_command)) {
985 DEBUG(5,("No lpq command\n"));
989 pstrcpy(syscmd,lpq_command);
990 string_sub(syscmd,"%p",printername);
992 standard_sub(conn,syscmd);
994 slprintf(outfile,sizeof(outfile)-1, "%s/lpq.%08x",tmpdir(),str_checksum(syscmd));
996 if (!lpq_cache_reset[snum] && cachetime && !sys_stat(outfile,&sbuf)) {
997 if (time(NULL) - sbuf.st_mtime < cachetime) {
998 DEBUG(3,("Using cached lpq output\n"));
1004 ret = smbrun(syscmd,outfile,True);
1005 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1008 lpq_cache_reset[snum] = False;
1010 f = fopen(outfile,"r");
1016 fstrcpy(status->message,"");
1017 status->status = LPSTAT_OK;
1020 while (fgets(line,sizeof(pstring),f)) {
1021 DEBUG(6,("QUEUE2: %s\n",line));
1023 *queue = Realloc(*queue,sizeof(print_queue_struct)*(count+1));
1029 bzero((char *)&(*queue)[count],sizeof(**queue));
1032 if (!parse_lpq_entry(snum,line,
1033 &(*queue)[count],status,count==0))
1044 /* we only expect this to succeed on trapdoor systems,
1045 on normal systems the file is owned by root */
1046 chmod(outfile,0666);
1052 /****************************************************************************
1053 delete a printer queue entry
1054 ****************************************************************************/
1055 void del_printqueue(connection_struct *conn,int snum,int jobid)
1057 char *lprm_command = lp_lprmcommand(snum);
1058 char *printername = PRINTERNAME(snum);
1063 if (!printername || !*printername)
1065 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1066 lp_servicename(snum),snum));
1067 printername = lp_servicename(snum);
1070 if (!lprm_command || !(*lprm_command))
1072 DEBUG(5,("No lprm command\n"));
1076 slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);
1078 pstrcpy(syscmd,lprm_command);
1079 string_sub(syscmd,"%p",printername);
1080 string_sub(syscmd,"%j",jobstr);
1081 standard_sub(conn,syscmd);
1083 ret = smbrun(syscmd,NULL,False);
1084 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1085 lpq_reset(snum); /* queue has changed */
1088 /****************************************************************************
1089 change status of a printer queue entry
1090 ****************************************************************************/
1091 void status_printjob(connection_struct *conn,int snum,int jobid,int status)
1093 char *lpstatus_command =
1094 (status==LPQ_PAUSED?lp_lppausecommand(snum):lp_lpresumecommand(snum));
1095 char *printername = PRINTERNAME(snum);
1100 if (!printername || !*printername)
1102 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1103 lp_servicename(snum),snum));
1104 printername = lp_servicename(snum);
1107 if (!lpstatus_command || !(*lpstatus_command))
1109 DEBUG(5,("No lpstatus command to %s job\n",
1110 (status==LPQ_PAUSED?"pause":"resume")));
1114 slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);
1116 pstrcpy(syscmd,lpstatus_command);
1117 string_sub(syscmd,"%p",printername);
1118 string_sub(syscmd,"%j",jobstr);
1119 standard_sub(conn,syscmd);
1121 ret = smbrun(syscmd,NULL,False);
1122 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1123 lpq_reset(snum); /* queue has changed */
1128 /****************************************************************************
1129 we encode print job numbers over the wire so that when we get them back we can
1130 tell not only what print job they are but also what service it belongs to,
1131 this is to overcome the problem that windows clients tend to send the wrong
1132 service number when doing print queue manipulation!
1133 ****************************************************************************/
1134 int printjob_encode(int snum, int job)
1136 return ((snum&0xFF)<<8) | (job & 0xFF);
1139 /****************************************************************************
1140 and now decode them again ...
1141 ****************************************************************************/
1142 void printjob_decode(int jobid, int *snum, int *job)
1144 (*snum) = (jobid >> 8) & 0xFF;
1145 (*job) = jobid & 0xFF;
1148 /****************************************************************************
1149 Change status of a printer queue
1150 ****************************************************************************/
1152 void status_printqueue(connection_struct *conn,int snum,int status)
1154 char *queuestatus_command = (status==LPSTAT_STOPPED ?
1155 lp_queuepausecommand(snum):lp_queueresumecommand(snum));
1156 char *printername = PRINTERNAME(snum);
1160 if (!printername || !*printername) {
1161 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1162 lp_servicename(snum),snum));
1163 printername = lp_servicename(snum);
1166 if (!queuestatus_command || !(*queuestatus_command)) {
1167 DEBUG(5,("No queuestatus command to %s job\n",
1168 (status==LPSTAT_STOPPED?"pause":"resume")));
1172 pstrcpy(syscmd,queuestatus_command);
1173 string_sub(syscmd,"%p",printername);
1174 standard_sub(conn,syscmd);
1176 ret = smbrun(syscmd,NULL,False);
1177 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1178 lpq_reset(snum); /* queue has changed */
1183 /***************************************************************************
1184 auto-load printer services
1185 ***************************************************************************/
1186 static void add_all_printers(void)
1188 int printers = lp_servicenumber(PRINTERS_NAME);
1190 if (printers < 0) return;
1192 pcap_printer_fn(lp_add_one_printer);
1195 /***************************************************************************
1196 auto-load some homes and printer services
1197 ***************************************************************************/
1198 static void add_auto_printers(void)
1202 char *str = lp_auto_services();
1206 printers = lp_servicenumber(PRINTERS_NAME);
1208 if (printers < 0) return;
1210 for (p=strtok(str,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) {
1211 if (lp_servicenumber(p) >= 0) continue;
1213 if (pcap_printername_ok(p,NULL)) {
1214 lp_add_printer(p,printers);
1219 /***************************************************************************
1220 load automatic printer services
1221 ***************************************************************************/
1222 void load_printers(void)
1224 add_auto_printers();
1225 if (lp_load_printers())