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];
327 tokarr[0] = strtok(line," \t");
329 while (((tokarr[num_tok] = strtok(NULL," \t")) != NULL)
330 && (num_tok < LPRNG_MAXTOK)) {
334 /* We must get at least LPRNG_NTOK tokens. */
335 if (num_tok < LPRNG_NTOK) {
339 if (!isdigit(*tokarr[LPRNG_JOBTOK]) || !isdigit(*tokarr[LPRNG_TOTALTOK])) {
343 buf->job = atoi(tokarr[LPRNG_JOBTOK]);
344 buf->size = atoi(tokarr[LPRNG_TOTALTOK]);
346 if (strequal(tokarr[LPRNG_RANKTOK],"active")) {
347 buf->status = LPQ_PRINTING;
348 } else if (isdigit(*tokarr[LPRNG_RANKTOK])) {
349 buf->status = LPQ_QUEUED;
351 buf->status = LPQ_PAUSED;
354 buf->priority = *tokarr[LPRNG_PRIOTOK] -'A';
356 buf->time = LPRng_time(tokarr[LPRNG_TIMETOK]);
358 StrnCpy(buf->user,tokarr[LPRNG_USERTOK],sizeof(buf->user)-1);
360 /* The '@hostname' prevents windows from displaying the printing icon
361 * for the current user on the taskbar. Plop in a null.
364 if ((cptr = strchr(buf->user,'@')) != NULL) {
368 StrnCpy(buf->file,tokarr[LPRNG_FILETOK],sizeof(buf->file)-1);
370 if ((LPRNG_FILETOK + 1) != LPRNG_TOTALTOK) {
374 bufsize = sizeof(buf->file) - strlen(buf->file) - 1;
376 for (i = (LPRNG_FILETOK + 1); i < LPRNG_TOTALTOK; i++) {
377 strncat(buf->file," ",bufsize);
378 strncat(buf->file,tokarr[i],bufsize - 1);
379 bufsize = sizeof(buf->file) - strlen(buf->file) - 1;
391 /*******************************************************************
392 parse lpq on an aix system
394 Queue Dev Status Job Files User PP % Blks Cp Rnk
395 ------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
397 lazer lazer RUNNING 537 6297doc.A kvintus@IE 0 10 2445 1 1
398 QUEUED 538 C.ps root@IEDVB 124 1 2
399 QUEUED 539 E.ps root@IEDVB 28 1 3
400 QUEUED 540 L.ps root@IEDVB 172 1 4
401 QUEUED 541 P.ps root@IEDVB 22 1 5
402 ********************************************************************/
403 static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first)
408 /* handle the case of "(standard input)" as a filename */
409 string_sub(line,"standard input","STDIN");
410 string_sub(line,"(","\"");
411 string_sub(line,")","\"");
415 next_token(&line,tok[count],NULL, sizeof(tok[count]));
418 /* we must get 6 tokens */
421 if ((count == 7) && ((strcmp(tok[0],"QUEUED") == 0) || (strcmp(tok[0],"HELD") == 0)))
423 /* the 2nd and 5th columns must be integer */
424 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4])) return(False);
425 buf->size = atoi(tok[4]) * 1024;
426 /* if the fname contains a space then use STDIN */
427 if (strchr(tok[2],' '))
428 fstrcpy(tok[2],"STDIN");
430 /* only take the last part of the filename */
433 char *p = strrchr(tok[2],'/');
442 buf->job = atoi(tok[1]);
443 buf->status = strequal(tok[0],"HELD")?LPQ_PAUSED:LPQ_QUEUED;
445 buf->time = time(NULL);
446 StrnCpy(buf->user,tok[3],sizeof(buf->user)-1);
447 StrnCpy(buf->file,tok[2],sizeof(buf->file)-1);
451 DEBUG(6,("parse_lpq_aix count=%d\n", count));
457 /* the 4th and 9th columns must be integer */
458 if (!isdigit((int)*tok[3]) || !isdigit((int)*tok[8])) return(False);
459 buf->size = atoi(tok[8]) * 1024;
460 /* if the fname contains a space then use STDIN */
461 if (strchr(tok[4],' '))
462 fstrcpy(tok[4],"STDIN");
464 /* only take the last part of the filename */
467 char *p = strrchr(tok[4],'/');
476 buf->job = atoi(tok[3]);
477 buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED;
479 buf->time = time(NULL);
480 StrnCpy(buf->user,tok[5],sizeof(buf->user)-1);
481 StrnCpy(buf->file,tok[4],sizeof(buf->file)-1);
489 /****************************************************************************
491 here is an example of lpq output under hpux; note there's no space after -o !
493 ljplus-2153 user priority 0 Jan 19 08:14 on ljplus
495 server.c 110712 bytes
496 ljplus-2154 user priority 0 Jan 19 08:14 from client
497 (standard input) 7551 bytes
498 ****************************************************************************/
499 static BOOL parse_lpq_hpux(char * line, print_queue_struct *buf, BOOL first)
501 /* must read two lines to process, therefore keep some values static */
502 static BOOL header_line_ok=False, base_prio_reset=False;
503 static fstring jobuser;
506 static time_t jobtime;
507 static int jobstat=LPQ_QUEUED;
508 /* to store minimum priority to print, lpstat command should be invoked
509 with -p option first, to work */
510 static int base_prio;
516 /* If a line begins with a horizontal TAB, it is a subline type */
518 if (line[0] == htab) { /* subline */
519 /* check if it contains the base priority */
520 if (!strncmp(line,"\tfence priority : ",18)) {
521 base_prio=atoi(&line[18]);
522 DEBUG(4, ("fence priority set at %d\n", base_prio));
524 if (!header_line_ok) return (False); /* incorrect header line */
525 /* handle the case of "(standard input)" as a filename */
526 string_sub(line,"standard input","STDIN");
527 string_sub(line,"(","\"");
528 string_sub(line,")","\"");
530 for (count=0; count<2 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
531 /* we must get 2 tokens */
532 if (count < 2) return(False);
534 /* the 2nd column must be integer */
535 if (!isdigit((int)*tok[1])) return(False);
537 /* if the fname contains a space then use STDIN */
538 if (strchr(tok[0],' '))
539 fstrcpy(tok[0],"STDIN");
541 buf->size = atoi(tok[1]);
542 StrnCpy(buf->file,tok[0],sizeof(buf->file)-1);
544 /* fill things from header line */
547 buf->status = jobstat;
548 buf->priority = jobprio;
549 StrnCpy(buf->user,jobuser,sizeof(buf->user)-1);
553 else { /* header line */
554 header_line_ok=False; /* reset it */
556 if (!base_prio_reset) {
557 base_prio=0; /* reset it */
558 base_prio_reset=True;
561 else if (base_prio) base_prio_reset=False;
563 /* handle the dash in the job id */
564 string_sub(line,"-"," ");
566 for (count=0; count<12 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
568 /* we must get 8 tokens */
569 if (count < 8) return(False);
571 /* first token must be printer name (cannot check ?) */
572 /* the 2nd, 5th & 7th column must be integer */
573 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4]) || !isdigit((int)*tok[6])) return(False);
574 jobid = atoi(tok[1]);
575 StrnCpy(jobuser,tok[2],sizeof(buf->user)-1);
576 jobprio = atoi(tok[4]);
579 jobtime=EntryTime(tok, 5, count, 8);
580 if (jobprio < base_prio) {
581 jobstat = LPQ_PAUSED;
582 DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n", jobid, jobprio, base_prio, jobstat));
585 jobstat = LPQ_QUEUED;
586 if ((count >8) && (((strequal(tok[8],"on")) ||
587 ((strequal(tok[8],"from")) &&
588 ((count > 10)&&(strequal(tok[10],"on")))))))
589 jobstat = LPQ_PRINTING;
592 header_line_ok=True; /* information is correct */
593 return(False); /* need subline info to include into queuelist */
598 /****************************************************************************
601 here is an example of "lpstat -o dcslw" output under sysv
603 dcslw-896 tridge 4712 Dec 20 10:30:30 on dcslw
604 dcslw-897 tridge 4712 Dec 20 10:30:30 being held
606 ****************************************************************************/
607 static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first)
613 /* handle the dash in the job id */
614 string_sub(line,"-"," ");
616 for (count=0; count<9 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
618 /* we must get 7 tokens */
622 /* the 2nd and 4th, 6th columns must be integer */
623 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[3])) return(False);
624 if (!isdigit((int)*tok[5])) return(False);
626 /* if the user contains a ! then trim the first part of it */
627 if ((p=strchr(tok[2],'!')))
635 buf->job = atoi(tok[1]);
636 buf->size = atoi(tok[3]);
637 if (count > 7 && strequal(tok[7],"on"))
638 buf->status = LPQ_PRINTING;
639 else if (count > 8 && strequal(tok[7],"being") && strequal(tok[8],"held"))
640 buf->status = LPQ_PAUSED;
642 buf->status = LPQ_QUEUED;
644 buf->time = EntryTime(tok, 4, count, 7);
645 StrnCpy(buf->user,tok[2],sizeof(buf->user)-1);
646 StrnCpy(buf->file,tok[2],sizeof(buf->file)-1);
650 /****************************************************************************
653 here is an example of lpq output under qnx
654 Spooler: /qnx/spooler, on node 1
656 0000: root [job #1 ] active 1146 bytes /etc/profile
657 0001: root [job #2 ] ready 2378 bytes /etc/install
658 0002: root [job #3 ] ready 1146 bytes -- standard input --
659 ****************************************************************************/
660 static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first)
665 DEBUG(0,("antes [%s]\n", line));
667 /* handle the case of "-- standard input --" as a filename */
668 string_sub(line,"standard input","STDIN");
669 DEBUG(0,("despues [%s]\n", line));
670 string_sub(line,"-- ","\"");
671 string_sub(line," --","\"");
672 DEBUG(0,("despues 1 [%s]\n", line));
674 string_sub(line,"[job #","");
675 string_sub(line,"]","");
676 DEBUG(0,("despues 2 [%s]\n", line));
680 for (count=0; count<7 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
682 /* we must get 7 tokens */
686 /* the 3rd and 5th columns must be integer */
687 if (!isdigit((int)*tok[2]) || !isdigit((int)*tok[4])) return(False);
689 /* only take the last part of the filename */
692 char *p = strrchr(tok[6],'/');
701 buf->job = atoi(tok[2]);
702 buf->size = atoi(tok[4]);
703 buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED;
705 buf->time = time(NULL);
706 StrnCpy(buf->user,tok[1],sizeof(buf->user)-1);
707 StrnCpy(buf->file,tok[6],sizeof(buf->file)-1);
712 /****************************************************************************
713 parse a lpq line for the plp printing system
714 Bertrand Wallrich <Bertrand.Wallrich@loria.fr>
716 redone by tridge. Here is a sample queue:
718 Local Printer 'lp2' (fjall):
719 Printing (started at Jun 15 13:33:58, attempt 1).
720 Rank Owner Pr Opt Job Host Files Size Date
721 active tridge X - 6 fjall /etc/hosts 739 Jun 15 13:33
722 3rd tridge X - 7 fjall /etc/hosts 739 Jun 15 13:33
724 ****************************************************************************/
725 static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first)
730 /* handle the case of "(standard input)" as a filename */
731 string_sub(line,"stdin","STDIN");
732 string_sub(line,"(","\"");
733 string_sub(line,")","\"");
735 for (count=0; count<11 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
737 /* we must get 11 tokens */
741 /* the first must be "active" or begin with an integer */
742 if (strcmp(tok[0],"active") && !isdigit((int)tok[0][0]))
745 /* the 5th and 8th must be integer */
746 if (!isdigit((int)*tok[4]) || !isdigit((int)*tok[7]))
749 /* if the fname contains a space then use STDIN */
750 if (strchr(tok[6],' '))
751 fstrcpy(tok[6],"STDIN");
753 /* only take the last part of the filename */
756 char *p = strrchr(tok[6],'/');
765 buf->job = atoi(tok[4]);
767 buf->size = atoi(tok[7]);
768 if (strchr(tok[7],'K'))
770 if (strchr(tok[7],'M'))
771 buf->size *= 1024*1024;
773 buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED;
775 buf->time = time(NULL);
776 StrnCpy(buf->user,tok[1],sizeof(buf->user)-1);
777 StrnCpy(buf->file,tok[6],sizeof(buf->file)-1);
781 /****************************************************************************
784 here is an example of "qstat -l -d qms" output under softq
786 Queue qms: 2 jobs; daemon active (313); enabled; accepting;
787 job-ID submission-time pri size owner title
788 205980: H 98/03/09 13:04:05 0 15733 stephenf chap1.ps
789 206086:> 98/03/12 17:24:40 0 659 chris -
790 206087: 98/03/12 17:24:45 0 4876 chris -
791 Total: 21268 bytes in queue
794 ****************************************************************************/
795 static BOOL parse_lpq_softq(char *line,print_queue_struct *buf,BOOL first)
800 /* mung all the ":"s to spaces*/
801 string_sub(line,":"," ");
803 for (count=0; count<10 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
805 /* we must get 9 tokens */
809 /* the 1st and 7th columns must be integer */
810 if (!isdigit((int)*tok[0]) || !isdigit((int)*tok[6])) return(False);
811 /* if the 2nd column is either '>' or 'H' then the 7th and 8th must be
812 * integer, else it's the 6th and 7th that must be
814 if (*tok[1] == 'H' || *tok[1] == '>')
816 if (!isdigit((int)*tok[7]))
818 buf->status = *tok[1] == '>' ? LPQ_PRINTING : LPQ_PAUSED;
823 if (!isdigit((int)*tok[5]))
825 buf->status = LPQ_QUEUED;
830 buf->job = atoi(tok[0]);
831 buf->size = atoi(tok[count+6]);
832 buf->priority = atoi(tok[count+5]);
833 StrnCpy(buf->user,tok[count+7],sizeof(buf->user)-1);
834 StrnCpy(buf->file,tok[count+8],sizeof(buf->file)-1);
835 buf->time = time(NULL); /* default case: take current time */
840 t = localtime(&buf->time);
841 t->tm_mday = atoi(tok[count+2]+6);
842 t->tm_mon = atoi(tok[count+2]+3);
843 switch (*tok[count+2])
845 case 7: case 8: case 9: t->tm_year = atoi(tok[count+2]) + 1900; break;
846 default: t->tm_year = atoi(tok[count+2]) + 2000; break;
849 t->tm_hour = atoi(tok[count+3]);
850 t->tm_min = atoi(tok[count+4]);
851 t->tm_sec = atoi(tok[count+5]);
853 if (jobtime != (time_t)-1)
861 char *stat0_strings[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL };
862 char *stat1_strings[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL };
863 char *stat2_strings[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL };
865 /****************************************************************************
866 parse a lpq line. Choose printing style
867 ****************************************************************************/
868 static BOOL parse_lpq_entry(int snum,char *line,
869 print_queue_struct *buf,
870 print_status_struct *status,BOOL first)
874 switch (lp_printing(snum))
877 ret = parse_lpq_sysv(line,buf,first);
880 ret = parse_lpq_aix(line,buf,first);
883 ret = parse_lpq_hpux(line,buf,first);
886 ret = parse_lpq_qnx(line,buf,first);
889 ret = parse_lpq_lprng(line,buf,first);
892 ret = parse_lpq_plp(line,buf,first);
895 ret = parse_lpq_softq(line,buf,first);
898 ret = parse_lpq_bsd(line,buf,first);
902 #ifdef LPQ_GUEST_TO_USER
904 extern pstring sesssetup_user;
905 /* change guest entries to the current logged in user to make
906 them appear deletable to windows */
907 if (sesssetup_user[0] && strequal(buf->user,lp_guestaccount(snum)))
908 pstrcpy(buf->user,sesssetup_user);
912 /* We don't want the newline in the status message. */
914 char *p = strchr(line,'\n');
920 /* a few simple checks to see if the line might be a
922 handle them so that most severe condition is shown */
926 switch (status->status) {
928 for (i=0; stat0_strings[i]; i++)
929 if (strstr(line,stat0_strings[i])) {
930 StrnCpy(status->message,line,sizeof(status->message)-1);
931 status->status=LPSTAT_OK;
935 for (i=0; stat1_strings[i]; i++)
936 if (strstr(line,stat1_strings[i])) {
937 StrnCpy(status->message,line,sizeof(status->message)-1);
938 status->status=LPSTAT_STOPPED;
942 for (i=0; stat2_strings[i]; i++)
943 if (strstr(line,stat2_strings[i])) {
944 StrnCpy(status->message,line,sizeof(status->message)-1);
945 status->status=LPSTAT_ERROR;
955 /****************************************************************************
957 ****************************************************************************/
958 int get_printqueue(int snum,
959 connection_struct *conn,print_queue_struct **queue,
960 print_status_struct *status)
962 char *lpq_command = lp_lpqcommand(snum);
963 char *printername = PRINTERNAME(snum);
969 SMB_STRUCT_STAT sbuf;
971 int cachetime = lp_lpqcachetime();
974 check_lpq_cache(snum);
976 if (!printername || !*printername) {
977 DEBUG(6,("xx replacing printer name with service (snum=(%s,%d))\n",
978 lp_servicename(snum),snum));
979 printername = lp_servicename(snum);
982 if (!lpq_command || !(*lpq_command)) {
983 DEBUG(5,("No lpq command\n"));
987 pstrcpy(syscmd,lpq_command);
988 string_sub(syscmd,"%p",printername);
990 standard_sub(conn,syscmd);
992 slprintf(outfile,sizeof(outfile)-1, "%s/lpq.%08x",tmpdir(),str_checksum(syscmd));
994 if (!lpq_cache_reset[snum] && cachetime && !sys_stat(outfile,&sbuf)) {
995 if (time(NULL) - sbuf.st_mtime < cachetime) {
996 DEBUG(3,("Using cached lpq output\n"));
1002 ret = smbrun(syscmd,outfile,True);
1003 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1006 lpq_cache_reset[snum] = False;
1008 f = fopen(outfile,"r");
1014 fstrcpy(status->message,"");
1015 status->status = LPSTAT_OK;
1018 while (fgets(line,sizeof(pstring),f)) {
1019 DEBUG(6,("QUEUE2: %s\n",line));
1021 *queue = Realloc(*queue,sizeof(print_queue_struct)*(count+1));
1027 bzero((char *)&(*queue)[count],sizeof(**queue));
1030 if (!parse_lpq_entry(snum,line,
1031 &(*queue)[count],status,count==0))
1042 /* we only expect this to succeed on trapdoor systems,
1043 on normal systems the file is owned by root */
1044 chmod(outfile,0666);
1050 /****************************************************************************
1051 delete a printer queue entry
1052 ****************************************************************************/
1053 void del_printqueue(connection_struct *conn,int snum,int jobid)
1055 char *lprm_command = lp_lprmcommand(snum);
1056 char *printername = PRINTERNAME(snum);
1061 if (!printername || !*printername)
1063 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1064 lp_servicename(snum),snum));
1065 printername = lp_servicename(snum);
1068 if (!lprm_command || !(*lprm_command))
1070 DEBUG(5,("No lprm command\n"));
1074 slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);
1076 pstrcpy(syscmd,lprm_command);
1077 string_sub(syscmd,"%p",printername);
1078 string_sub(syscmd,"%j",jobstr);
1079 standard_sub(conn,syscmd);
1081 ret = smbrun(syscmd,NULL,False);
1082 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1083 lpq_reset(snum); /* queue has changed */
1086 /****************************************************************************
1087 change status of a printer queue entry
1088 ****************************************************************************/
1089 void status_printjob(connection_struct *conn,int snum,int jobid,int status)
1091 char *lpstatus_command =
1092 (status==LPQ_PAUSED?lp_lppausecommand(snum):lp_lpresumecommand(snum));
1093 char *printername = PRINTERNAME(snum);
1098 if (!printername || !*printername)
1100 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1101 lp_servicename(snum),snum));
1102 printername = lp_servicename(snum);
1105 if (!lpstatus_command || !(*lpstatus_command))
1107 DEBUG(5,("No lpstatus command to %s job\n",
1108 (status==LPQ_PAUSED?"pause":"resume")));
1112 slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);
1114 pstrcpy(syscmd,lpstatus_command);
1115 string_sub(syscmd,"%p",printername);
1116 string_sub(syscmd,"%j",jobstr);
1117 standard_sub(conn,syscmd);
1119 ret = smbrun(syscmd,NULL,False);
1120 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1121 lpq_reset(snum); /* queue has changed */
1126 /****************************************************************************
1127 we encode print job numbers over the wire so that when we get them back we can
1128 tell not only what print job they are but also what service it belongs to,
1129 this is to overcome the problem that windows clients tend to send the wrong
1130 service number when doing print queue manipulation!
1131 ****************************************************************************/
1132 int printjob_encode(int snum, int job)
1134 return ((snum&0xFF)<<8) | (job & 0xFF);
1137 /****************************************************************************
1138 and now decode them again ...
1139 ****************************************************************************/
1140 void printjob_decode(int jobid, int *snum, int *job)
1142 (*snum) = (jobid >> 8) & 0xFF;
1143 (*job) = jobid & 0xFF;
1146 /****************************************************************************
1147 Change status of a printer queue
1148 ****************************************************************************/
1150 void status_printqueue(connection_struct *conn,int snum,int status)
1152 char *queuestatus_command = (status==LPSTAT_STOPPED ?
1153 lp_queuepausecommand(snum):lp_queueresumecommand(snum));
1154 char *printername = PRINTERNAME(snum);
1158 if (!printername || !*printername) {
1159 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1160 lp_servicename(snum),snum));
1161 printername = lp_servicename(snum);
1164 if (!queuestatus_command || !(*queuestatus_command)) {
1165 DEBUG(5,("No queuestatus command to %s job\n",
1166 (status==LPSTAT_STOPPED?"pause":"resume")));
1170 pstrcpy(syscmd,queuestatus_command);
1171 string_sub(syscmd,"%p",printername);
1172 standard_sub(conn,syscmd);
1174 ret = smbrun(syscmd,NULL,False);
1175 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
1176 lpq_reset(snum); /* queue has changed */
1181 /***************************************************************************
1182 auto-load printer services
1183 ***************************************************************************/
1184 static void add_all_printers(void)
1186 int printers = lp_servicenumber(PRINTERS_NAME);
1188 if (printers < 0) return;
1190 pcap_printer_fn(lp_add_one_printer);
1193 /***************************************************************************
1194 auto-load some homes and printer services
1195 ***************************************************************************/
1196 static void add_auto_printers(void)
1200 char *str = lp_auto_services();
1204 printers = lp_servicenumber(PRINTERS_NAME);
1206 if (printers < 0) return;
1208 for (p=strtok(str,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) {
1209 if (lp_servicenumber(p) >= 0) continue;
1211 if (pcap_printername_ok(p,NULL)) {
1212 lp_add_printer(p,printers);
1217 /***************************************************************************
1218 load automatic printer services
1219 ***************************************************************************/
1220 void load_printers(void)
1222 add_auto_printers();
1223 if (lp_load_printers())