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;
31 if (lpq_caches
<= snum
) {
33 p
= (BOOL
*) Realloc(lpq_cache_reset
,(snum
+1)*sizeof(BOOL
));
36 for (i
=lpq_caches
; i
<snum
+1; i
++) lpq_cache_reset
[i
] = False
;
43 void lpq_reset(int snum
)
45 if (check_lpq_cache(snum
) > snum
) lpq_cache_reset
[snum
]=True
;
49 /****************************************************************************
50 Build the print command in the supplied buffer. This means getting the
51 print command for the service and inserting the printer name and the
52 print file name. Return NULL on error, else the passed buffer pointer.
53 ****************************************************************************/
54 static char *build_print_command(connection_struct
*conn
,
56 char *syscmd
, char *filename
)
58 int snum
= SNUM(conn
);
61 /* get the print command for the service. */
63 if (!syscmd
|| !tstr
) {
64 DEBUG(0,("No print command for service `%s'\n",
69 /* copy the command into the buffer for extensive meddling. */
70 StrnCpy(syscmd
, tstr
, sizeof(pstring
) - 1);
72 /* look for "%s" in the string. If there is no %s, we cannot print. */
73 if (!strstr(syscmd
, "%s") && !strstr(syscmd
, "%f")) {
74 DEBUG(2,("WARNING! No placeholder for the filename in the print command for service %s!\n", SERVICE(snum
)));
77 pstring_sub(syscmd
, "%s", filename
);
78 pstring_sub(syscmd
, "%f", filename
);
80 /* Does the service have a printername? If not, make a fake
82 /* printer name. That way a %p is treated sanely if no printer */
83 /* name was specified to replace it. This eventuality is logged. */
84 tstr
= PRINTERNAME(snum
);
85 if (tstr
== NULL
|| tstr
[0] == '\0') {
86 DEBUG(3,( "No printer name - using %s.\n", SERVICE(snum
)));
90 pstring_sub(syscmd
, "%p", tstr
);
92 standard_sub(conn
,syscmd
);
98 /****************************************************************************
99 print a file - called on closing the file
100 ****************************************************************************/
101 void print_file(connection_struct
*conn
, files_struct
*file
)
104 int snum
= SNUM(conn
);
109 if (dos_file_size(file
->fsp_name
) <= 0) {
110 DEBUG(3,("Discarding null print job %s\n",file
->fsp_name
));
111 dos_unlink(file
->fsp_name
);
115 tempstr
= build_print_command(conn
,
117 syscmd
, file
->fsp_name
);
118 if (tempstr
!= NULL
) {
119 int ret
= smbrun(syscmd
,NULL
,False
);
120 DEBUG(3,("Running the command `%s' gave %d\n",syscmd
,ret
));
122 DEBUG(0,("Null print command?\n"));
128 static char *Months
[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
129 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err"};
132 /*******************************************************************
134 ********************************************************************/
135 static time_t EntryTime(fstring tok
[], int ptr
, int count
, int minimum
)
137 time_t jobtime
,jobtime1
;
139 jobtime
= time(NULL
); /* default case: take current time */
140 if (count
>= minimum
) {
142 int i
, day
, hour
, min
, sec
;
145 for (i
=0; i
<13; i
++) if (!strncmp(tok
[ptr
], Months
[i
],3)) break; /* Find month */
147 t
= localtime(&jobtime
);
148 day
= atoi(tok
[ptr
+1]);
149 c
=(char *)(tok
[ptr
+2]);
154 if(*(c
+6) != 0)sec
= atoi(c
+6);
157 if ((t
->tm_mon
< i
)||
159 ((t
->tm_mday
< day
)||
160 ((t
->tm_mday
== day
)&&
161 (t
->tm_hour
*60+t
->tm_min
< hour
*60+min
)))))
162 t
->tm_year
--; /* last year's print job */
169 jobtime1
= mktime(t
);
170 if (jobtime1
!= (time_t)-1)
178 /****************************************************************************
181 here is an example of lpq output under bsd
183 Warning: no daemon present
184 Rank Owner Job Files Total Size
185 1st tridge 148 README 8096 bytes
187 here is an example of lpq output under osf/1
189 Warning: no daemon present
190 Rank Pri Owner Job Files Total Size
191 1st 0 tridge 148 README 8096 bytes
194 <allan@umich.edu> June 30, 1998.
195 Modified to handle file names with spaces, like the parse_lpq_lprng code
197 ****************************************************************************/
198 static BOOL
parse_lpq_bsd(char *line
,print_queue_struct
*buf
,BOOL first
)
206 #define TOTALTOK (count - 2)
214 #define TOTALTOK (count - 2)
228 length
= strlen(line2
);
229 if (line2
[length
-3] == ':')
234 tok
[0] = strtok(line2
," \t");
237 while (((tok
[count
] = strtok(NULL
," \t")) != NULL
) && (count
< MAXTOK
)) {
241 /* we must get at least NTOK tokens */
245 /* the Job and Total columns must be integer */
246 if (!isdigit((int)*tok
[JOBTOK
]) || !isdigit((int)*tok
[TOTALTOK
])) return(False
);
248 buf
->job
= atoi(tok
[JOBTOK
]);
249 buf
->size
= atoi(tok
[TOTALTOK
]);
250 buf
->status
= strequal(tok
[RANKTOK
],"active")?LPQ_PRINTING
:LPQ_QUEUED
;
251 buf
->time
= time(NULL
);
252 StrnCpy(buf
->user
,tok
[USERTOK
],sizeof(buf
->user
)-1);
253 StrnCpy(buf
->file
,tok
[FILETOK
],sizeof(buf
->file
)-1);
255 if ((FILETOK
+ 1) != TOTALTOK
) {
259 bufsize
= sizeof(buf
->file
) - strlen(buf
->file
) - 1;
261 for (i
= (FILETOK
+ 1); i
< TOTALTOK
; i
++) {
262 safe_strcat(buf
->file
," ",bufsize
);
263 safe_strcat(buf
->file
,tok
[i
],bufsize
- 1);
264 bufsize
= sizeof(buf
->file
) - strlen(buf
->file
) - 1;
269 /* Ensure null termination. */
270 buf
->file
[sizeof(buf
->file
)-1] = '\0';
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((int)*tokarr
[LPRNG_JOBTOK
]) || !isdigit((int)*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((int)*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 safe_strcat(buf
->file
," ",bufsize
);
380 safe_strcat(buf
->file
,tokarr
[i
],bufsize
- 1);
381 bufsize
= sizeof(buf
->file
) - strlen(buf
->file
) - 1;
386 /* Ensure null termination. */
387 buf
->file
[sizeof(buf
->file
)-1] = '\0';
395 /*******************************************************************
396 parse lpq on an aix system
398 Queue Dev Status Job Files User PP % Blks Cp Rnk
399 ------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
401 lazer lazer RUNNING 537 6297doc.A kvintus@IE 0 10 2445 1 1
402 QUEUED 538 C.ps root@IEDVB 124 1 2
403 QUEUED 539 E.ps root@IEDVB 28 1 3
404 QUEUED 540 L.ps root@IEDVB 172 1 4
405 QUEUED 541 P.ps root@IEDVB 22 1 5
406 ********************************************************************/
407 static BOOL
parse_lpq_aix(char *line
,print_queue_struct
*buf
,BOOL first
)
412 /* handle the case of "(standard input)" as a filename */
413 pstring_sub(line
,"standard input","STDIN");
414 all_string_sub(line
,"(","\"",0);
415 all_string_sub(line
,")","\"",0);
419 next_token(&line
,tok
[count
],NULL
, sizeof(tok
[count
]));
422 /* we must get 6 tokens */
425 if ((count
== 7) && ((strcmp(tok
[0],"QUEUED") == 0) || (strcmp(tok
[0],"HELD") == 0)))
427 /* the 2nd and 5th columns must be integer */
428 if (!isdigit((int)*tok
[1]) || !isdigit((int)*tok
[4])) return(False
);
429 buf
->size
= atoi(tok
[4]) * 1024;
430 /* if the fname contains a space then use STDIN */
431 if (strchr(tok
[2],' '))
432 fstrcpy(tok
[2],"STDIN");
434 /* only take the last part of the filename */
437 char *p
= strrchr(tok
[2],'/');
446 buf
->job
= atoi(tok
[1]);
447 buf
->status
= strequal(tok
[0],"HELD")?LPQ_PAUSED
:LPQ_QUEUED
;
449 buf
->time
= time(NULL
);
450 StrnCpy(buf
->user
,tok
[3],sizeof(buf
->user
)-1);
451 StrnCpy(buf
->file
,tok
[2],sizeof(buf
->file
)-1);
455 DEBUG(6,("parse_lpq_aix count=%d\n", count
));
461 /* the 4th and 9th columns must be integer */
462 if (!isdigit((int)*tok
[3]) || !isdigit((int)*tok
[8])) return(False
);
463 buf
->size
= atoi(tok
[8]) * 1024;
464 /* if the fname contains a space then use STDIN */
465 if (strchr(tok
[4],' '))
466 fstrcpy(tok
[4],"STDIN");
468 /* only take the last part of the filename */
471 char *p
= strrchr(tok
[4],'/');
480 buf
->job
= atoi(tok
[3]);
481 buf
->status
= strequal(tok
[2],"RUNNING")?LPQ_PRINTING
:LPQ_QUEUED
;
483 buf
->time
= time(NULL
);
484 StrnCpy(buf
->user
,tok
[5],sizeof(buf
->user
)-1);
485 StrnCpy(buf
->file
,tok
[4],sizeof(buf
->file
)-1);
493 /****************************************************************************
495 here is an example of lpq output under hpux; note there's no space after -o !
497 ljplus-2153 user priority 0 Jan 19 08:14 on ljplus
499 server.c 110712 bytes
500 ljplus-2154 user priority 0 Jan 19 08:14 from client
501 (standard input) 7551 bytes
502 ****************************************************************************/
503 static BOOL
parse_lpq_hpux(char * line
, print_queue_struct
*buf
, BOOL first
)
505 /* must read two lines to process, therefore keep some values static */
506 static BOOL header_line_ok
=False
, base_prio_reset
=False
;
507 static fstring jobuser
;
510 static time_t jobtime
;
511 static int jobstat
=LPQ_QUEUED
;
512 /* to store minimum priority to print, lpstat command should be invoked
513 with -p option first, to work */
514 static int base_prio
;
520 /* If a line begins with a horizontal TAB, it is a subline type */
522 if (line
[0] == htab
) { /* subline */
523 /* check if it contains the base priority */
524 if (!strncmp(line
,"\tfence priority : ",18)) {
525 base_prio
=atoi(&line
[18]);
526 DEBUG(4, ("fence priority set at %d\n", base_prio
));
528 if (!header_line_ok
) return (False
); /* incorrect header line */
529 /* handle the case of "(standard input)" as a filename */
530 pstring_sub(line
,"standard input","STDIN");
531 all_string_sub(line
,"(","\"",0);
532 all_string_sub(line
,")","\"",0);
534 for (count
=0; count
<2 && next_token(&line
,tok
[count
],NULL
,sizeof(tok
[count
])); count
++) ;
535 /* we must get 2 tokens */
536 if (count
< 2) return(False
);
538 /* the 2nd column must be integer */
539 if (!isdigit((int)*tok
[1])) return(False
);
541 /* if the fname contains a space then use STDIN */
542 if (strchr(tok
[0],' '))
543 fstrcpy(tok
[0],"STDIN");
545 buf
->size
= atoi(tok
[1]);
546 StrnCpy(buf
->file
,tok
[0],sizeof(buf
->file
)-1);
548 /* fill things from header line */
551 buf
->status
= jobstat
;
552 buf
->priority
= jobprio
;
553 StrnCpy(buf
->user
,jobuser
,sizeof(buf
->user
)-1);
557 else { /* header line */
558 header_line_ok
=False
; /* reset it */
560 if (!base_prio_reset
) {
561 base_prio
=0; /* reset it */
562 base_prio_reset
=True
;
565 else if (base_prio
) base_prio_reset
=False
;
567 /* handle the dash in the job id */
568 pstring_sub(line
,"-"," ");
570 for (count
=0; count
<12 && next_token(&line
,tok
[count
],NULL
,sizeof(tok
[count
])); count
++) ;
572 /* we must get 8 tokens */
573 if (count
< 8) return(False
);
575 /* first token must be printer name (cannot check ?) */
576 /* the 2nd, 5th & 7th column must be integer */
577 if (!isdigit((int)*tok
[1]) || !isdigit((int)*tok
[4]) || !isdigit((int)*tok
[6])) return(False
);
578 jobid
= atoi(tok
[1]);
579 StrnCpy(jobuser
,tok
[2],sizeof(buf
->user
)-1);
580 jobprio
= atoi(tok
[4]);
583 jobtime
=EntryTime(tok
, 5, count
, 8);
584 if (jobprio
< base_prio
) {
585 jobstat
= LPQ_PAUSED
;
586 DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n", jobid
, jobprio
, base_prio
, jobstat
));
589 jobstat
= LPQ_QUEUED
;
590 if ((count
>8) && (((strequal(tok
[8],"on")) ||
591 ((strequal(tok
[8],"from")) &&
592 ((count
> 10)&&(strequal(tok
[10],"on")))))))
593 jobstat
= LPQ_PRINTING
;
596 header_line_ok
=True
; /* information is correct */
597 return(False
); /* need subline info to include into queuelist */
602 /****************************************************************************
605 here is an example of "lpstat -o dcslw" output under sysv
607 dcslw-896 tridge 4712 Dec 20 10:30:30 on dcslw
608 dcslw-897 tridge 4712 Dec 20 10:30:30 being held
610 ****************************************************************************/
611 static BOOL
parse_lpq_sysv(char *line
,print_queue_struct
*buf
,BOOL first
)
618 * Handle the dash in the job id, but make sure that we skip over
619 * the printer name in case we have a dash in that.
620 * Patch from Dom.Mitchell@palmerharvey.co.uk.
624 * Move to the first space.
626 for (p
= line
; !isspace(*p
) && *p
; p
++)
630 * Back up until the last '-' character or
633 for (; (p
>= line
) && (*p
!= '-'); p
--)
636 if((p
>= line
) && (*p
== '-'))
639 for (count
=0; count
<9 && next_token(&line
,tok
[count
],NULL
,sizeof(tok
[count
])); count
++)
642 /* we must get 7 tokens */
646 /* the 2nd and 4th, 6th columns must be integer */
647 if (!isdigit((int)*tok
[1]) || !isdigit((int)*tok
[3]))
649 if (!isdigit((int)*tok
[5]))
652 /* if the user contains a ! then trim the first part of it */
653 if ((p
=strchr(tok
[2],'!'))) {
659 buf
->job
= atoi(tok
[1]);
660 buf
->size
= atoi(tok
[3]);
661 if (count
> 7 && strequal(tok
[7],"on"))
662 buf
->status
= LPQ_PRINTING
;
663 else if (count
> 8 && strequal(tok
[7],"being") && strequal(tok
[8],"held"))
664 buf
->status
= LPQ_PAUSED
;
666 buf
->status
= LPQ_QUEUED
;
668 buf
->time
= EntryTime(tok
, 4, count
, 7);
669 StrnCpy(buf
->user
,tok
[2],sizeof(buf
->user
)-1);
670 StrnCpy(buf
->file
,tok
[2],sizeof(buf
->file
)-1);
674 /****************************************************************************
677 here is an example of lpq output under qnx
678 Spooler: /qnx/spooler, on node 1
680 0000: root [job #1 ] active 1146 bytes /etc/profile
681 0001: root [job #2 ] ready 2378 bytes /etc/install
682 0002: root [job #3 ] ready 1146 bytes -- standard input --
683 ****************************************************************************/
684 static BOOL
parse_lpq_qnx(char *line
,print_queue_struct
*buf
,BOOL first
)
689 DEBUG(4,("antes [%s]\n", line
));
691 /* handle the case of "-- standard input --" as a filename */
692 pstring_sub(line
,"standard input","STDIN");
693 DEBUG(4,("despues [%s]\n", line
));
694 all_string_sub(line
,"-- ","\"",0);
695 all_string_sub(line
," --","\"",0);
696 DEBUG(4,("despues 1 [%s]\n", line
));
698 pstring_sub(line
,"[job #","");
699 pstring_sub(line
,"]","");
700 DEBUG(4,("despues 2 [%s]\n", line
));
704 for (count
=0; count
<7 && next_token(&line
,tok
[count
],NULL
,sizeof(tok
[count
])); count
++) ;
706 /* we must get 7 tokens */
710 /* the 3rd and 5th columns must be integer */
711 if (!isdigit((int)*tok
[2]) || !isdigit((int)*tok
[4])) return(False
);
713 /* only take the last part of the filename */
716 char *p
= strrchr(tok
[6],'/');
725 buf
->job
= atoi(tok
[2]);
726 buf
->size
= atoi(tok
[4]);
727 buf
->status
= strequal(tok
[3],"active")?LPQ_PRINTING
:LPQ_QUEUED
;
729 buf
->time
= time(NULL
);
730 StrnCpy(buf
->user
,tok
[1],sizeof(buf
->user
)-1);
731 StrnCpy(buf
->file
,tok
[6],sizeof(buf
->file
)-1);
736 /****************************************************************************
737 parse a lpq line for the plp printing system
738 Bertrand Wallrich <Bertrand.Wallrich@loria.fr>
740 redone by tridge. Here is a sample queue:
742 Local Printer 'lp2' (fjall):
743 Printing (started at Jun 15 13:33:58, attempt 1).
744 Rank Owner Pr Opt Job Host Files Size Date
745 active tridge X - 6 fjall /etc/hosts 739 Jun 15 13:33
746 3rd tridge X - 7 fjall /etc/hosts 739 Jun 15 13:33
748 ****************************************************************************/
749 static BOOL
parse_lpq_plp(char *line
,print_queue_struct
*buf
,BOOL first
)
754 /* handle the case of "(standard input)" as a filename */
755 pstring_sub(line
,"stdin","STDIN");
756 all_string_sub(line
,"(","\"",0);
757 all_string_sub(line
,")","\"",0);
759 for (count
=0; count
<11 && next_token(&line
,tok
[count
],NULL
,sizeof(tok
[count
])); count
++) ;
761 /* we must get 11 tokens */
765 /* the first must be "active" or begin with an integer */
766 if (strcmp(tok
[0],"active") && !isdigit((int)tok
[0][0]))
769 /* the 5th and 8th must be integer */
770 if (!isdigit((int)*tok
[4]) || !isdigit((int)*tok
[7]))
773 /* if the fname contains a space then use STDIN */
774 if (strchr(tok
[6],' '))
775 fstrcpy(tok
[6],"STDIN");
777 /* only take the last part of the filename */
780 char *p
= strrchr(tok
[6],'/');
789 buf
->job
= atoi(tok
[4]);
791 buf
->size
= atoi(tok
[7]);
792 if (strchr(tok
[7],'K'))
794 if (strchr(tok
[7],'M'))
795 buf
->size
*= 1024*1024;
797 buf
->status
= strequal(tok
[0],"active")?LPQ_PRINTING
:LPQ_QUEUED
;
799 buf
->time
= time(NULL
);
800 StrnCpy(buf
->user
,tok
[1],sizeof(buf
->user
)-1);
801 StrnCpy(buf
->file
,tok
[6],sizeof(buf
->file
)-1);
805 /****************************************************************************
808 here is an example of "qstat -l -d qms" output under softq
810 Queue qms: 2 jobs; daemon active (313); enabled; accepting;
811 job-ID submission-time pri size owner title
812 205980: H 98/03/09 13:04:05 0 15733 stephenf chap1.ps
813 206086:> 98/03/12 17:24:40 0 659 chris -
814 206087: 98/03/12 17:24:45 0 4876 chris -
815 Total: 21268 bytes in queue
818 ****************************************************************************/
819 static BOOL
parse_lpq_softq(char *line
,print_queue_struct
*buf
,BOOL first
)
824 /* mung all the ":"s to spaces*/
825 pstring_sub(line
,":"," ");
827 for (count
=0; count
<10 && next_token(&line
,tok
[count
],NULL
,sizeof(tok
[count
])); count
++) ;
829 /* we must get 9 tokens */
833 /* the 1st and 7th columns must be integer */
834 if (!isdigit((int)*tok
[0]) || !isdigit((int)*tok
[6])) return(False
);
835 /* if the 2nd column is either '>' or 'H' then the 7th and 8th must be
836 * integer, else it's the 6th and 7th that must be
838 if (*tok
[1] == 'H' || *tok
[1] == '>')
840 if (!isdigit((int)*tok
[7]))
842 buf
->status
= *tok
[1] == '>' ? LPQ_PRINTING
: LPQ_PAUSED
;
847 if (!isdigit((int)*tok
[5]))
849 buf
->status
= LPQ_QUEUED
;
854 buf
->job
= atoi(tok
[0]);
855 buf
->size
= atoi(tok
[count
+6]);
856 buf
->priority
= atoi(tok
[count
+5]);
857 StrnCpy(buf
->user
,tok
[count
+7],sizeof(buf
->user
)-1);
858 StrnCpy(buf
->file
,tok
[count
+8],sizeof(buf
->file
)-1);
859 buf
->time
= time(NULL
); /* default case: take current time */
864 t
= localtime(&buf
->time
);
865 t
->tm_mday
= atoi(tok
[count
+2]+6);
866 t
->tm_mon
= atoi(tok
[count
+2]+3);
867 switch (*tok
[count
+2])
869 case 7: case 8: case 9: t
->tm_year
= atoi(tok
[count
+2]); break;
870 default: t
->tm_year
= atoi(tok
[count
+2]); break;
873 t
->tm_hour
= atoi(tok
[count
+3]);
874 t
->tm_min
= atoi(tok
[count
+4]);
875 t
->tm_sec
= atoi(tok
[count
+5]);
877 if (jobtime
!= (time_t)-1)
885 char *stat0_strings
[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL
};
886 char *stat1_strings
[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL
};
887 char *stat2_strings
[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL
};
889 /****************************************************************************
890 parse a lpq line. Choose printing style
891 ****************************************************************************/
892 static BOOL
parse_lpq_entry(int snum
,char *line
,
893 print_queue_struct
*buf
,
894 print_status_struct
*status
,BOOL first
)
898 switch (lp_printing(snum
))
901 ret
= parse_lpq_sysv(line
,buf
,first
);
904 ret
= parse_lpq_aix(line
,buf
,first
);
907 ret
= parse_lpq_hpux(line
,buf
,first
);
910 ret
= parse_lpq_qnx(line
,buf
,first
);
913 ret
= parse_lpq_lprng(line
,buf
,first
);
916 ret
= parse_lpq_plp(line
,buf
,first
);
919 ret
= parse_lpq_softq(line
,buf
,first
);
922 ret
= parse_lpq_bsd(line
,buf
,first
);
926 #ifdef LPQ_GUEST_TO_USER
928 extern pstring sesssetup_user
;
929 /* change guest entries to the current logged in user to make
930 them appear deletable to windows */
931 if (sesssetup_user
[0] && strequal(buf
->user
,lp_guestaccount(snum
)))
932 pstrcpy(buf
->user
,sesssetup_user
);
936 /* We don't want the newline in the status message. */
938 char *p
= strchr(line
,'\n');
942 /* in the LPRNG case, we skip lines starting by a space.*/
943 if (line
&& !ret
&& (lp_printing(snum
)==PRINT_LPRNG
) )
952 /* a few simple checks to see if the line might be a
954 handle them so that most severe condition is shown */
958 switch (status
->status
) {
960 for (i
=0; stat0_strings
[i
]; i
++)
961 if (strstr(line
,stat0_strings
[i
])) {
962 StrnCpy(status
->message
,line
,sizeof(status
->message
)-1);
963 status
->status
=LPSTAT_OK
;
967 for (i
=0; stat1_strings
[i
]; i
++)
968 if (strstr(line
,stat1_strings
[i
])) {
969 StrnCpy(status
->message
,line
,sizeof(status
->message
)-1);
970 status
->status
=LPSTAT_STOPPED
;
974 for (i
=0; stat2_strings
[i
]; i
++)
975 if (strstr(line
,stat2_strings
[i
])) {
976 StrnCpy(status
->message
,line
,sizeof(status
->message
)-1);
977 status
->status
=LPSTAT_ERROR
;
987 /****************************************************************************
989 ****************************************************************************/
990 int get_printqueue(int snum
,
991 connection_struct
*conn
,print_queue_struct
**queue
,
992 print_status_struct
*status
)
994 char *lpq_command
= lp_lpqcommand(snum
);
995 char *printername
= PRINTERNAME(snum
);
1001 SMB_STRUCT_STAT sbuf
;
1003 int cachetime
= lp_lpqcachetime();
1006 check_lpq_cache(snum
);
1008 if (!printername
|| !*printername
) {
1009 DEBUG(6,("xx replacing printer name with service (snum=(%s,%d))\n",
1010 lp_servicename(snum
),snum
));
1011 printername
= lp_servicename(snum
);
1014 if (!lpq_command
|| !(*lpq_command
)) {
1015 DEBUG(5,("No lpq command\n"));
1019 pstrcpy(syscmd
,lpq_command
);
1020 pstring_sub(syscmd
,"%p",printername
);
1022 standard_sub(conn
,syscmd
);
1024 slprintf(outfile
,sizeof(outfile
)-1, "%s/lpq.%08x",lp_lockdir(),str_checksum(syscmd
));
1026 if (!lpq_cache_reset
[snum
] && cachetime
&& !sys_stat(outfile
,&sbuf
)) {
1027 if (time(NULL
) - sbuf
.st_mtime
< cachetime
) {
1028 DEBUG(3,("Using cached lpq output\n"));
1034 ret
= smbrun(syscmd
,outfile
,True
);
1035 DEBUG(3,("Running the command `%s' gave %d\n",syscmd
,ret
));
1038 lpq_cache_reset
[snum
] = False
;
1040 f
= sys_fopen(outfile
,"r");
1046 fstrcpy(status
->message
,"");
1047 status
->status
= LPSTAT_OK
;
1050 while (fgets(line
,sizeof(pstring
),f
)) {
1051 DEBUG(6,("QUEUE2: %s\n",line
));
1053 *queue
= Realloc(*queue
,sizeof(print_queue_struct
)*(count
+1));
1059 memset((char *)&(*queue
)[count
],'\0',sizeof(**queue
));
1062 if (!parse_lpq_entry(snum
,line
,
1063 &(*queue
)[count
],status
,count
==0))
1078 /****************************************************************************
1079 delete a printer queue entry
1080 ****************************************************************************/
1081 void del_printqueue(connection_struct
*conn
,int snum
,int jobid
)
1083 char *lprm_command
= lp_lprmcommand(snum
);
1084 char *printername
= PRINTERNAME(snum
);
1089 if (!printername
|| !*printername
)
1091 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1092 lp_servicename(snum
),snum
));
1093 printername
= lp_servicename(snum
);
1096 if (!lprm_command
|| !(*lprm_command
))
1098 DEBUG(5,("No lprm command\n"));
1102 slprintf(jobstr
,sizeof(jobstr
)-1,"%d",jobid
);
1104 pstrcpy(syscmd
,lprm_command
);
1105 pstring_sub(syscmd
,"%p",printername
);
1106 pstring_sub(syscmd
,"%j",jobstr
);
1107 standard_sub(conn
,syscmd
);
1109 ret
= smbrun(syscmd
,NULL
,False
);
1110 DEBUG(3,("Running the command `%s' gave %d\n",syscmd
,ret
));
1111 lpq_reset(snum
); /* queue has changed */
1114 /****************************************************************************
1115 change status of a printer queue entry
1116 ****************************************************************************/
1117 void status_printjob(connection_struct
*conn
,int snum
,int jobid
,int status
)
1119 char *lpstatus_command
=
1120 (status
==LPQ_PAUSED
?lp_lppausecommand(snum
):lp_lpresumecommand(snum
));
1121 char *printername
= PRINTERNAME(snum
);
1126 if (!printername
|| !*printername
)
1128 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1129 lp_servicename(snum
),snum
));
1130 printername
= lp_servicename(snum
);
1133 if (!lpstatus_command
|| !(*lpstatus_command
))
1135 DEBUG(5,("No lpstatus command to %s job\n",
1136 (status
==LPQ_PAUSED
?"pause":"resume")));
1140 slprintf(jobstr
,sizeof(jobstr
)-1,"%d",jobid
);
1142 pstrcpy(syscmd
,lpstatus_command
);
1143 pstring_sub(syscmd
,"%p",printername
);
1144 pstring_sub(syscmd
,"%j",jobstr
);
1145 standard_sub(conn
,syscmd
);
1147 ret
= smbrun(syscmd
,NULL
,False
);
1148 DEBUG(3,("Running the command `%s' gave %d\n",syscmd
,ret
));
1149 lpq_reset(snum
); /* queue has changed */
1154 /****************************************************************************
1155 we encode print job numbers over the wire so that when we get them back we can
1156 tell not only what print job they are but also what service it belongs to,
1157 this is to overcome the problem that windows clients tend to send the wrong
1158 service number when doing print queue manipulation!
1159 ****************************************************************************/
1160 int printjob_encode(int snum
, int job
)
1162 return ((snum
&0xFF)<<8) | (job
& 0xFF);
1165 /****************************************************************************
1166 and now decode them again ...
1167 ****************************************************************************/
1168 void printjob_decode(int jobid
, int *snum
, int *job
)
1170 (*snum
) = (jobid
>> 8) & 0xFF;
1171 (*job
) = jobid
& 0xFF;
1174 /****************************************************************************
1175 Change status of a printer queue
1176 ****************************************************************************/
1178 void status_printqueue(connection_struct
*conn
,int snum
,int status
)
1180 char *queuestatus_command
= (status
==LPSTAT_STOPPED
?
1181 lp_queuepausecommand(snum
):lp_queueresumecommand(snum
));
1182 char *printername
= PRINTERNAME(snum
);
1186 if (!printername
|| !*printername
) {
1187 DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
1188 lp_servicename(snum
),snum
));
1189 printername
= lp_servicename(snum
);
1192 if (!queuestatus_command
|| !(*queuestatus_command
)) {
1193 DEBUG(5,("No queuestatus command to %s job\n",
1194 (status
==LPSTAT_STOPPED
?"pause":"resume")));
1198 pstrcpy(syscmd
,queuestatus_command
);
1199 pstring_sub(syscmd
,"%p",printername
);
1200 standard_sub(conn
,syscmd
);
1202 ret
= smbrun(syscmd
,NULL
,False
);
1203 DEBUG(3,("Running the command `%s' gave %d\n",syscmd
,ret
));
1204 lpq_reset(snum
); /* queue has changed */
1209 /***************************************************************************
1210 auto-load printer services
1211 ***************************************************************************/
1212 static void add_all_printers(void)
1214 int printers
= lp_servicenumber(PRINTERS_NAME
);
1216 if (printers
< 0) return;
1218 pcap_printer_fn(lp_add_one_printer
);
1221 /***************************************************************************
1222 auto-load some homes and printer services
1223 ***************************************************************************/
1224 static void add_auto_printers(void)
1228 char *str
= lp_auto_services();
1232 printers
= lp_servicenumber(PRINTERS_NAME
);
1234 if (printers
< 0) return;
1236 for (p
=strtok(str
,LIST_SEP
);p
;p
=strtok(NULL
,LIST_SEP
)) {
1237 if (lp_servicenumber(p
) >= 0) continue;
1239 if (pcap_printername_ok(p
,NULL
)) {
1240 lp_add_printer(p
,printers
);
1245 /***************************************************************************
1246 load automatic printer services
1247 ***************************************************************************/
1248 void load_printers(void)
1250 add_auto_printers();
1251 if (lp_load_printers())