if we are adding a new sambaAccount, make sure that we add a
[Samba.git] / source / printing / lpq_parse.c
blob96484eaf583f3e5ab5bc51630d3b98c387736a6d
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 lpq parsing routines
5 Copyright (C) Andrew Tridgell 2000
6 Copyright (C) 2002 by Martin Pool
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
26 static char *Months[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
27 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err"};
30 /*******************************************************************
31 process time fields
32 ********************************************************************/
33 static time_t EntryTime(fstring tok[], int ptr, int count, int minimum)
35 time_t jobtime,jobtime1;
37 jobtime = time(NULL); /* default case: take current time */
38 if (count >= minimum) {
39 struct tm *t;
40 int i, day, hour, min, sec;
41 char *c;
43 for (i=0; i<13; i++) if (!strncmp(tok[ptr], Months[i],3)) break; /* Find month */
44 if (i<12) {
45 t = localtime(&jobtime);
46 day = atoi(tok[ptr+1]);
47 c=(char *)(tok[ptr+2]);
48 *(c+2)=0;
49 hour = atoi(c);
50 *(c+5)=0;
51 min = atoi(c+3);
52 if(*(c+6) != 0)sec = atoi(c+6);
53 else sec=0;
55 if ((t->tm_mon < i)||
56 ((t->tm_mon == i)&&
57 ((t->tm_mday < day)||
58 ((t->tm_mday == day)&&
59 (t->tm_hour*60+t->tm_min < hour*60+min)))))
60 t->tm_year--; /* last year's print job */
62 t->tm_mon = i;
63 t->tm_mday = day;
64 t->tm_hour = hour;
65 t->tm_min = min;
66 t->tm_sec = sec;
67 jobtime1 = mktime(t);
68 if (jobtime1 != (time_t)-1)
69 jobtime = jobtime1;
72 return jobtime;
76 /****************************************************************************
77 parse a lpq line
79 here is an example of lpq output under bsd
81 Warning: no daemon present
82 Rank Owner Job Files Total Size
83 1st tridge 148 README 8096 bytes
85 here is an example of lpq output under osf/1
87 Warning: no daemon present
88 Rank Pri Owner Job Files Total Size
89 1st 0 tridge 148 README 8096 bytes
92 <allan@umich.edu> June 30, 1998.
93 Modified to handle file names with spaces, like the parse_lpq_lprng code
94 further below.
95 ****************************************************************************/
96 static BOOL parse_lpq_bsd(char *line,print_queue_struct *buf,BOOL first)
98 #ifdef OSF1
99 #define RANKTOK 0
100 #define PRIOTOK 1
101 #define USERTOK 2
102 #define JOBTOK 3
103 #define FILETOK 4
104 #define TOTALTOK (count - 2)
105 #define NTOK 6
106 #define MAXTOK 128
107 #else /* OSF1 */
108 #define RANKTOK 0
109 #define USERTOK 1
110 #define JOBTOK 2
111 #define FILETOK 3
112 #define TOTALTOK (count - 2)
113 #define NTOK 5
114 #define MAXTOK 128
115 #endif /* OSF1 */
117 char *tok[MAXTOK];
118 int count = 0;
119 pstring line2;
121 pstrcpy(line2,line);
123 #ifdef OSF1
125 size_t length;
126 length = strlen(line2);
127 if (line2[length-3] == ':')
128 return(False);
130 #endif /* OSF1 */
132 tok[0] = strtok(line2," \t");
133 count++;
135 while (((tok[count] = strtok(NULL," \t")) != NULL) && (count < MAXTOK)) {
136 count++;
139 /* we must get at least NTOK tokens */
140 if (count < NTOK)
141 return(False);
143 /* the Job and Total columns must be integer */
144 if (!isdigit((int)*tok[JOBTOK]) || !isdigit((int)*tok[TOTALTOK])) return(False);
146 buf->job = atoi(tok[JOBTOK]);
147 buf->size = atoi(tok[TOTALTOK]);
148 buf->status = strequal(tok[RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED;
149 buf->time = time(NULL);
150 fstrcpy(buf->fs_user,tok[USERTOK]);
151 fstrcpy(buf->fs_file,tok[FILETOK]);
153 if ((FILETOK + 1) != TOTALTOK) {
154 int i;
156 for (i = (FILETOK + 1); i < TOTALTOK; i++) {
157 /* FIXME: Using fstrcat rather than other means is a bit
158 * inefficient; this might be a problem for enormous queues with
159 * many fields. */
160 fstrcat(buf->fs_file, " ");
161 fstrcat(buf->fs_file, tok[i]);
163 /* Ensure null termination. */
164 fstrterminate(buf->fs_file);
167 #ifdef PRIOTOK
168 buf->priority = atoi(tok[PRIOTOK]);
169 #else
170 buf->priority = 1;
171 #endif
172 return(True);
176 <magnus@hum.auc.dk>
177 LPRng_time modifies the current date by inserting the hour and minute from
178 the lpq output. The lpq time looks like "23:15:07"
180 <allan@umich.edu> June 30, 1998.
181 Modified to work with the re-written parse_lpq_lprng routine.
183 <J.P.M.v.Itegem@tue.nl> Dec 17,1999
184 Modified to work with lprng 3.16
185 With lprng 3.16 The lpq time looks like
186 "23:15:07"
187 "23:15:07.100"
188 "1999-12-16-23:15:07"
189 "1999-12-16-23:15:07.100"
192 static time_t LPRng_time(char *time_string)
194 time_t jobtime;
195 struct tm t;
197 jobtime = time(NULL); /* default case: take current time */
198 t = *localtime(&jobtime);
200 if ( atoi(time_string) < 24 ){
201 t.tm_hour = atoi(time_string);
202 t.tm_min = atoi(time_string+3);
203 t.tm_sec = atoi(time_string+6);
204 } else {
205 t.tm_year = atoi(time_string)-1900;
206 t.tm_mon = atoi(time_string+5)-1;
207 t.tm_mday = atoi(time_string+8);
208 t.tm_hour = atoi(time_string+11);
209 t.tm_min = atoi(time_string+14);
210 t.tm_sec = atoi(time_string+17);
212 jobtime = mktime(&t);
214 return jobtime;
218 /****************************************************************************
219 parse a lprng lpq line
220 <allan@umich.edu> June 30, 1998.
221 Re-wrote this to handle file names with spaces, multiple file names on one
222 lpq line, etc;
223 ****************************************************************************/
224 static BOOL parse_lpq_lprng(char *line,print_queue_struct *buf,BOOL first)
226 #define LPRNG_RANKTOK 0
227 #define LPRNG_USERTOK 1
228 #define LPRNG_PRIOTOK 2
229 #define LPRNG_JOBTOK 3
230 #define LPRNG_FILETOK 4
231 #define LPRNG_TOTALTOK (num_tok - 2)
232 #define LPRNG_TIMETOK (num_tok - 1)
233 #define LPRNG_NTOK 7
234 #define LPRNG_MAXTOK 128 /* PFMA just to keep us from running away. */
236 fstring tokarr[LPRNG_MAXTOK];
237 char *cptr;
238 int num_tok = 0;
239 pstring line2;
241 pstrcpy(line2,line);
242 cptr = line2;
243 while(next_token( &cptr, tokarr[num_tok], " \t", sizeof(fstring)) && (num_tok < LPRNG_MAXTOK))
244 num_tok++;
246 /* We must get at least LPRNG_NTOK tokens. */
247 if (num_tok < LPRNG_NTOK) {
248 return(False);
251 if (!isdigit((int)*tokarr[LPRNG_JOBTOK]) || !isdigit((int)*tokarr[LPRNG_TOTALTOK])) {
252 return(False);
255 buf->job = atoi(tokarr[LPRNG_JOBTOK]);
256 buf->size = atoi(tokarr[LPRNG_TOTALTOK]);
258 if (strequal(tokarr[LPRNG_RANKTOK],"active")) {
259 buf->status = LPQ_PRINTING;
260 } else if (strequal(tokarr[LPRNG_RANKTOK],"done")) {
261 buf->status = LPQ_PRINTED;
262 } else if (isdigit((int)*tokarr[LPRNG_RANKTOK])) {
263 buf->status = LPQ_QUEUED;
264 } else {
265 buf->status = LPQ_PAUSED;
268 buf->priority = *tokarr[LPRNG_PRIOTOK] -'A';
270 buf->time = LPRng_time(tokarr[LPRNG_TIMETOK]);
272 fstrcpy(buf->fs_user,tokarr[LPRNG_USERTOK]);
274 /* The '@hostname' prevents windows from displaying the printing icon
275 * for the current user on the taskbar. Plop in a null.
278 if ((cptr = strchr(buf->fs_user,'@')) != NULL) {
279 *cptr = '\0';
282 fstrcpy(buf->fs_file,tokarr[LPRNG_FILETOK]);
284 if ((LPRNG_FILETOK + 1) != LPRNG_TOTALTOK) {
285 int i;
287 for (i = (LPRNG_FILETOK + 1); i < LPRNG_TOTALTOK; i++) {
288 /* FIXME: Using fstrcat rather than other means is a bit
289 * inefficient; this might be a problem for enormous queues with
290 * many fields. */
291 fstrcat(buf->fs_file, " ");
292 fstrcat(buf->fs_file, tokarr[i]);
294 /* Ensure null termination. */
295 fstrterminate(buf->fs_file);
298 return(True);
303 /*******************************************************************
304 parse lpq on an aix system
306 Queue Dev Status Job Files User PP % Blks Cp Rnk
307 ------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
308 lazer lazer READY
309 lazer lazer RUNNING 537 6297doc.A kvintus@IE 0 10 2445 1 1
310 QUEUED 538 C.ps root@IEDVB 124 1 2
311 QUEUED 539 E.ps root@IEDVB 28 1 3
312 QUEUED 540 L.ps root@IEDVB 172 1 4
313 QUEUED 541 P.ps root@IEDVB 22 1 5
314 ********************************************************************/
315 static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first)
317 fstring tok[11];
318 int count=0;
320 /* handle the case of "(standard input)" as a filename */
321 pstring_sub(line,"standard input","STDIN");
322 all_string_sub(line,"(","\"",0);
323 all_string_sub(line,")","\"",0);
325 for (count=0;
326 count<10 &&
327 next_token(&line,tok[count],NULL, sizeof(tok[count]));
328 count++) ;
330 /* we must get 6 tokens */
331 if (count < 10)
333 if ((count == 7) && ((strcmp(tok[0],"QUEUED") == 0) || (strcmp(tok[0],"HELD") == 0)))
335 /* the 2nd and 5th columns must be integer */
336 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4])) return(False);
337 buf->size = atoi(tok[4]) * 1024;
338 /* if the fname contains a space then use STDIN */
339 if (strchr(tok[2],' '))
340 fstrcpy(tok[2],"STDIN");
342 /* only take the last part of the filename */
344 fstring tmp;
345 char *p = strrchr(tok[2],'/');
346 if (p)
348 fstrcpy(tmp,p+1);
349 fstrcpy(tok[2],tmp);
354 buf->job = atoi(tok[1]);
355 buf->status = strequal(tok[0],"HELD")?LPQ_PAUSED:LPQ_QUEUED;
356 buf->priority = 0;
357 buf->time = time(NULL);
358 fstrcpy(buf->fs_user, tok[3]);
359 fstrcpy(buf->fs_file, tok[2]);
361 else
363 DEBUG(6,("parse_lpq_aix count=%d\n", count));
364 return(False);
367 else
369 /* the 4th and 9th columns must be integer */
370 if (!isdigit((int)*tok[3]) || !isdigit((int)*tok[8])) return(False);
371 buf->size = atoi(tok[8]) * 1024;
372 /* if the fname contains a space then use STDIN */
373 if (strchr(tok[4],' '))
374 fstrcpy(tok[4],"STDIN");
376 /* only take the last part of the filename */
378 fstring tmp;
379 char *p = strrchr(tok[4],'/');
380 if (p)
382 fstrcpy(tmp,p+1);
383 fstrcpy(tok[4],tmp);
388 buf->job = atoi(tok[3]);
389 buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED;
390 buf->priority = 0;
391 buf->time = time(NULL);
392 fstrcpy(buf->fs_user, tok[5]);
393 fstrcpy(buf->fs_file, tok[4]);
397 return(True);
401 /****************************************************************************
402 parse a lpq line
403 here is an example of lpq output under hpux; note there's no space after -o !
404 $> lpstat -oljplus
405 ljplus-2153 user priority 0 Jan 19 08:14 on ljplus
406 util.c 125697 bytes
407 server.c 110712 bytes
408 ljplus-2154 user priority 0 Jan 19 08:14 from client
409 (standard input) 7551 bytes
410 ****************************************************************************/
411 static BOOL parse_lpq_hpux(char * line, print_queue_struct *buf, BOOL first)
413 /* must read two lines to process, therefore keep some values static */
414 static BOOL header_line_ok=False, base_prio_reset=False;
415 static fstring jobuser;
416 static int jobid;
417 static int jobprio;
418 static time_t jobtime;
419 static int jobstat=LPQ_QUEUED;
420 /* to store minimum priority to print, lpstat command should be invoked
421 with -p option first, to work */
422 static int base_prio;
424 int count;
425 char htab = '\011';
426 fstring tok[12];
428 /* If a line begins with a horizontal TAB, it is a subline type */
430 if (line[0] == htab) { /* subline */
431 /* check if it contains the base priority */
432 if (!strncmp(line,"\tfence priority : ",18)) {
433 base_prio=atoi(&line[18]);
434 DEBUG(4, ("fence priority set at %d\n", base_prio));
436 if (!header_line_ok) return (False); /* incorrect header line */
437 /* handle the case of "(standard input)" as a filename */
438 pstring_sub(line,"standard input","STDIN");
439 all_string_sub(line,"(","\"",0);
440 all_string_sub(line,")","\"",0);
442 for (count=0; count<2 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
443 /* we must get 2 tokens */
444 if (count < 2) return(False);
446 /* the 2nd column must be integer */
447 if (!isdigit((int)*tok[1])) return(False);
449 /* if the fname contains a space then use STDIN */
450 if (strchr(tok[0],' '))
451 fstrcpy(tok[0],"STDIN");
453 buf->size = atoi(tok[1]);
454 fstrcpy(buf->fs_file,tok[0]);
456 /* fill things from header line */
457 buf->time = jobtime;
458 buf->job = jobid;
459 buf->status = jobstat;
460 buf->priority = jobprio;
461 fstrcpy(buf->fs_user, jobuser);
463 return(True);
465 else { /* header line */
466 header_line_ok=False; /* reset it */
467 if (first) {
468 if (!base_prio_reset) {
469 base_prio=0; /* reset it */
470 base_prio_reset=True;
473 else if (base_prio) base_prio_reset=False;
475 /* handle the dash in the job id */
476 pstring_sub(line,"-"," ");
478 for (count=0; count<12 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
480 /* we must get 8 tokens */
481 if (count < 8) return(False);
483 /* first token must be printer name (cannot check ?) */
484 /* the 2nd, 5th & 7th column must be integer */
485 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4]) || !isdigit((int)*tok[6])) return(False);
486 jobid = atoi(tok[1]);
487 fstrcpy(jobuser, tok[2]);
488 jobprio = atoi(tok[4]);
490 /* process time */
491 jobtime=EntryTime(tok, 5, count, 8);
492 if (jobprio < base_prio) {
493 jobstat = LPQ_PAUSED;
494 DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n", jobid, jobprio, base_prio, jobstat));
496 else {
497 jobstat = LPQ_QUEUED;
498 if ((count >8) && (((strequal(tok[8],"on")) ||
499 ((strequal(tok[8],"from")) &&
500 ((count > 10)&&(strequal(tok[10],"on")))))))
501 jobstat = LPQ_PRINTING;
504 header_line_ok=True; /* information is correct */
505 return(False); /* need subline info to include into queuelist */
510 /****************************************************************************
511 parse a lpstat line
513 here is an example of "lpstat -o dcslw" output under sysv
515 dcslw-896 tridge 4712 Dec 20 10:30:30 on dcslw
516 dcslw-897 tridge 4712 Dec 20 10:30:30 being held
518 ****************************************************************************/
519 static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first)
521 fstring tok[9];
522 int count=0;
523 char *p;
526 * Handle the dash in the job id, but make sure that we skip over
527 * the printer name in case we have a dash in that.
528 * Patch from Dom.Mitchell@palmerharvey.co.uk.
532 * Move to the first space.
534 for (p = line ; !isspace(*p) && *p; p++)
538 * Back up until the last '-' character or
539 * start of line.
541 for (; (p >= line) && (*p != '-'); p--)
544 if((p >= line) && (*p == '-'))
545 *p = ' ';
547 for (count=0; count<9 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++)
550 /* we must get 7 tokens */
551 if (count < 7)
552 return(False);
554 /* the 2nd and 4th, 6th columns must be integer */
555 if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[3]))
556 return(False);
557 if (!isdigit((int)*tok[5]))
558 return(False);
560 /* if the user contains a ! then trim the first part of it */
561 if ((p=strchr(tok[2],'!'))) {
562 fstring tmp;
563 fstrcpy(tmp,p+1);
564 fstrcpy(tok[2],tmp);
567 buf->job = atoi(tok[1]);
568 buf->size = atoi(tok[3]);
569 if (count > 7 && strequal(tok[7],"on"))
570 buf->status = LPQ_PRINTING;
571 else if (count > 8 && strequal(tok[7],"being") && strequal(tok[8],"held"))
572 buf->status = LPQ_PAUSED;
573 else
574 buf->status = LPQ_QUEUED;
575 buf->priority = 0;
576 buf->time = EntryTime(tok, 4, count, 7);
577 fstrcpy(buf->fs_user, tok[2]);
578 fstrcpy(buf->fs_file, tok[2]);
579 return(True);
582 /****************************************************************************
583 parse a lpq line
585 here is an example of lpq output under qnx
586 Spooler: /qnx/spooler, on node 1
587 Printer: txt (ready)
588 0000: root [job #1 ] active 1146 bytes /etc/profile
589 0001: root [job #2 ] ready 2378 bytes /etc/install
590 0002: root [job #3 ] ready 1146 bytes -- standard input --
591 ****************************************************************************/
592 static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first)
594 fstring tok[7];
595 int count=0;
597 DEBUG(4,("antes [%s]\n", line));
599 /* handle the case of "-- standard input --" as a filename */
600 pstring_sub(line,"standard input","STDIN");
601 DEBUG(4,("despues [%s]\n", line));
602 all_string_sub(line,"-- ","\"",0);
603 all_string_sub(line," --","\"",0);
604 DEBUG(4,("despues 1 [%s]\n", line));
606 pstring_sub(line,"[job #","");
607 pstring_sub(line,"]","");
608 DEBUG(4,("despues 2 [%s]\n", line));
612 for (count=0; count<7 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
614 /* we must get 7 tokens */
615 if (count < 7)
616 return(False);
618 /* the 3rd and 5th columns must be integer */
619 if (!isdigit((int)*tok[2]) || !isdigit((int)*tok[4])) return(False);
621 /* only take the last part of the filename */
623 fstring tmp;
624 char *p = strrchr(tok[6],'/');
625 if (p)
627 fstrcpy(tmp,p+1);
628 fstrcpy(tok[6],tmp);
633 buf->job = atoi(tok[2]);
634 buf->size = atoi(tok[4]);
635 buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED;
636 buf->priority = 0;
637 buf->time = time(NULL);
638 fstrcpy(buf->fs_user,tok[1]);
639 fstrcpy(buf->fs_file,tok[6]);
640 return(True);
644 /****************************************************************************
645 parse a lpq line for the plp printing system
646 Bertrand Wallrich <Bertrand.Wallrich@loria.fr>
648 redone by tridge. Here is a sample queue:
650 Local Printer 'lp2' (fjall):
651 Printing (started at Jun 15 13:33:58, attempt 1).
652 Rank Owner Pr Opt Job Host Files Size Date
653 active tridge X - 6 fjall /etc/hosts 739 Jun 15 13:33
654 3rd tridge X - 7 fjall /etc/hosts 739 Jun 15 13:33
656 ****************************************************************************/
657 static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first)
659 fstring tok[11];
660 int count=0;
662 /* handle the case of "(standard input)" as a filename */
663 pstring_sub(line,"stdin","STDIN");
664 all_string_sub(line,"(","\"",0);
665 all_string_sub(line,")","\"",0);
667 for (count=0; count<11 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
669 /* we must get 11 tokens */
670 if (count < 11)
671 return(False);
673 /* the first must be "active" or begin with an integer */
674 if (strcmp(tok[0],"active") && !isdigit((int)tok[0][0]))
675 return(False);
677 /* the 5th and 8th must be integer */
678 if (!isdigit((int)*tok[4]) || !isdigit((int)*tok[7]))
679 return(False);
681 /* if the fname contains a space then use STDIN */
682 if (strchr(tok[6],' '))
683 fstrcpy(tok[6],"STDIN");
685 /* only take the last part of the filename */
687 fstring tmp;
688 char *p = strrchr(tok[6],'/');
689 if (p)
691 fstrcpy(tmp,p+1);
692 fstrcpy(tok[6],tmp);
697 buf->job = atoi(tok[4]);
699 buf->size = atoi(tok[7]);
700 if (strchr(tok[7],'K'))
701 buf->size *= 1024;
702 if (strchr(tok[7],'M'))
703 buf->size *= 1024*1024;
705 buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED;
706 buf->priority = 0;
707 buf->time = time(NULL);
708 fstrcpy(buf->fs_user,tok[1]);
709 fstrcpy(buf->fs_file,tok[6]);
710 return(True);
713 /****************************************************************************
714 parse a qstat line
716 here is an example of "qstat -l -d qms" output under softq
718 Queue qms: 2 jobs; daemon active (313); enabled; accepting;
719 job-ID submission-time pri size owner title
720 205980: H 98/03/09 13:04:05 0 15733 stephenf chap1.ps
721 206086:> 98/03/12 17:24:40 0 659 chris -
722 206087: 98/03/12 17:24:45 0 4876 chris -
723 Total: 21268 bytes in queue
726 ****************************************************************************/
727 static BOOL parse_lpq_softq(char *line,print_queue_struct *buf,BOOL first)
729 fstring tok[10];
730 int count=0;
732 /* mung all the ":"s to spaces*/
733 pstring_sub(line,":"," ");
735 for (count=0; count<10 && next_token(&line,tok[count],NULL,sizeof(tok[count])); count++) ;
737 /* we must get 9 tokens */
738 if (count < 9)
739 return(False);
741 /* the 1st and 7th columns must be integer */
742 if (!isdigit((int)*tok[0]) || !isdigit((int)*tok[6])) return(False);
743 /* if the 2nd column is either '>' or 'H' then the 7th and 8th must be
744 * integer, else it's the 6th and 7th that must be
746 if (*tok[1] == 'H' || *tok[1] == '>')
748 if (!isdigit((int)*tok[7]))
749 return(False);
750 buf->status = *tok[1] == '>' ? LPQ_PRINTING : LPQ_PAUSED;
751 count = 1;
753 else
755 if (!isdigit((int)*tok[5]))
756 return(False);
757 buf->status = LPQ_QUEUED;
758 count = 0;
762 buf->job = atoi(tok[0]);
763 buf->size = atoi(tok[count+6]);
764 buf->priority = atoi(tok[count+5]);
765 fstrcpy(buf->fs_user,tok[count+7]);
766 fstrcpy(buf->fs_file,tok[count+8]);
767 buf->time = time(NULL); /* default case: take current time */
769 time_t jobtime;
770 struct tm *t;
772 t = localtime(&buf->time);
773 t->tm_mday = atoi(tok[count+2]+6);
774 t->tm_mon = atoi(tok[count+2]+3);
775 switch (*tok[count+2])
777 case 7: case 8: case 9: t->tm_year = atoi(tok[count+2]); break;
778 default: t->tm_year = atoi(tok[count+2]); break;
781 t->tm_hour = atoi(tok[count+3]);
782 t->tm_min = atoi(tok[count+4]);
783 t->tm_sec = atoi(tok[count+5]);
784 jobtime = mktime(t);
785 if (jobtime != (time_t)-1)
786 buf->time = jobtime;
789 return(True);
792 /*******************************************************************
793 parse lpq on an NT system
795 Windows 2000 LPD Server
796 Printer \\10.0.0.2\NP17PCL (Paused)
798 Owner Status Jobname Job-Id Size Pages Priority
799 ----------------------------------------------------------------------------
800 root (9.99. Printing /usr/lib/rhs/rhs-pr 3 625 0 1
801 root (9.99. Paused /usr/lib/rhs/rhs-pr 4 625 0 1
802 jmcd Waiting Re: Samba Open Sour 26 32476 1 1
804 ********************************************************************/
805 static BOOL parse_lpq_nt(char *line,print_queue_struct *buf,BOOL first)
807 #define LPRNT_OWNSIZ 11
808 #define LPRNT_STATSIZ 9
809 #define LPRNT_JOBSIZ 19
810 #define LPRNT_IDSIZ 6
811 #define LPRNT_SIZSIZ 9
812 typedef struct
814 char owner[LPRNT_OWNSIZ];
815 char space1;
816 char status[LPRNT_STATSIZ];
817 char space2;
818 char jobname[LPRNT_JOBSIZ];
819 char space3;
820 char jobid[LPRNT_IDSIZ];
821 char space4;
822 char size[LPRNT_SIZSIZ];
823 char terminator;
824 } nt_lpq_line;
826 nt_lpq_line parse_line;
827 #define LPRNT_PRINTING "Printing"
828 #define LPRNT_WAITING "Waiting"
829 #define LPRNT_PAUSED "Paused"
831 memset(&parse_line, '\0', sizeof(parse_line));
832 strncpy((char *) &parse_line, line, sizeof(parse_line) -1);
834 if (strlen((char *) &parse_line) != sizeof(parse_line) - 1)
835 return(False);
837 /* Just want the first word in the owner field - the username */
838 if (strchr(parse_line.owner, ' '))
839 *(strchr(parse_line.owner, ' ')) = '\0';
840 else
841 parse_line.space1 = '\0';
843 /* Make sure we have an owner */
844 if (!strlen(parse_line.owner))
845 return(False);
847 /* Make sure the status is valid */
848 parse_line.space2 = '\0';
849 trim_string(parse_line.status, NULL, " ");
850 if (!strequal(parse_line.status, LPRNT_PRINTING) &&
851 !strequal(parse_line.status, LPRNT_PAUSED) &&
852 !strequal(parse_line.status, LPRNT_WAITING))
853 return(False);
855 parse_line.space3 = '\0';
856 trim_string(parse_line.jobname, NULL, " ");
858 buf->job = atoi(parse_line.jobid);
859 buf->priority = 0;
860 buf->size = atoi(parse_line.size);
861 buf->time = time(NULL);
862 fstrcpy(buf->fs_user, parse_line.owner);
863 fstrcpy(buf->fs_file, parse_line.jobname);
864 if (strequal(parse_line.status, LPRNT_PRINTING))
865 buf->status = LPQ_PRINTING;
866 else if (strequal(parse_line.status, LPRNT_PAUSED))
867 buf->status = LPQ_PAUSED;
868 else
869 buf->status = LPQ_QUEUED;
871 return(True);
874 /*******************************************************************
875 parse lpq on an OS2 system
877 JobID File Name Rank Size Status Comment
878 ----- --------------- ------ -------- ------------ ------------
879 3 Control 1 68 Queued root@psflinu
880 4 /etc/motd 2 11666 Queued root@psflinu
882 ********************************************************************/
883 static BOOL parse_lpq_os2(char *line,print_queue_struct *buf,BOOL first)
885 #define LPROS2_IDSIZ 5
886 #define LPROS2_JOBSIZ 15
887 #define LPROS2_SIZSIZ 8
888 #define LPROS2_STATSIZ 12
889 #define LPROS2_OWNSIZ 12
890 typedef struct
892 char jobid[LPROS2_IDSIZ];
893 char space1[2];
894 char jobname[LPROS2_JOBSIZ];
895 char space2[14];
896 char size[LPROS2_SIZSIZ];
897 char space3[4];
898 char status[LPROS2_STATSIZ];
899 char space4[4];
900 char owner[LPROS2_OWNSIZ];
901 char terminator;
902 } os2_lpq_line;
904 os2_lpq_line parse_line;
905 #define LPROS2_PRINTING "Printing"
906 #define LPROS2_WAITING "Queued"
907 #define LPROS2_PAUSED "Paused"
909 memset(&parse_line, '\0', sizeof(parse_line));
910 strncpy((char *) &parse_line, line, sizeof(parse_line) -1);
912 if (strlen((char *) &parse_line) != sizeof(parse_line) - 1)
913 return(False);
915 /* Get the jobid */
916 buf->job = atoi(parse_line.jobid);
918 /* Get the job name */
919 parse_line.space2[0] = '\0';
920 trim_string(parse_line.jobname, NULL, " ");
921 fstrcpy(buf->fs_file, parse_line.jobname);
923 buf->priority = 0;
924 buf->size = atoi(parse_line.size);
925 buf->time = time(NULL);
927 /* Make sure we have an owner */
928 if (!strlen(parse_line.owner))
929 return(False);
931 /* Make sure we have a valid status */
932 parse_line.space4[0] = '\0';
933 trim_string(parse_line.status, NULL, " ");
934 if (!strequal(parse_line.status, LPROS2_PRINTING) &&
935 !strequal(parse_line.status, LPROS2_PAUSED) &&
936 !strequal(parse_line.status, LPROS2_WAITING))
937 return(False);
939 fstrcpy(buf->fs_user, parse_line.owner);
940 if (strequal(parse_line.status, LPROS2_PRINTING))
941 buf->status = LPQ_PRINTING;
942 else if (strequal(parse_line.status, LPROS2_PAUSED))
943 buf->status = LPQ_PAUSED;
944 else
945 buf->status = LPQ_QUEUED;
947 return(True);
950 static char *stat0_strings[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL };
951 static char *stat1_strings[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL };
952 static char *stat2_strings[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL };
954 #ifdef DEVELOPER
956 /****************************************************************************
957 parse a vlp line
958 ****************************************************************************/
959 static BOOL parse_lpq_vlp(char *line,print_queue_struct *buf,BOOL first)
961 int toknum = 0;
962 fstring tok;
964 /* First line is printer status */
966 if (!isdigit(line[0])) return False;
968 /* Parse a print job entry */
970 while(next_token(&line, tok, NULL, sizeof(fstring))) {
971 switch (toknum) {
972 case 0:
973 buf->job = atoi(tok);
974 break;
975 case 1:
976 buf->size = atoi(tok);
977 break;
978 case 2:
979 buf->status = atoi(tok);
980 break;
981 case 3:
982 buf->time = atoi(tok);
983 break;
984 case 4:
985 fstrcpy(buf->fs_user, tok);
986 break;
987 case 5:
988 fstrcpy(buf->fs_file, tok);
989 break;
991 toknum++;
994 return True;
997 #endif /* DEVELOPER */
999 /****************************************************************************
1000 parse a lpq line. Choose printing style
1001 ****************************************************************************/
1002 BOOL parse_lpq_entry(int snum,char *line,
1003 print_queue_struct *buf,
1004 print_status_struct *status,BOOL first)
1006 BOOL ret;
1008 switch (lp_printing(snum))
1010 case PRINT_SYSV:
1011 ret = parse_lpq_sysv(line,buf,first);
1012 break;
1013 case PRINT_AIX:
1014 ret = parse_lpq_aix(line,buf,first);
1015 break;
1016 case PRINT_HPUX:
1017 ret = parse_lpq_hpux(line,buf,first);
1018 break;
1019 case PRINT_QNX:
1020 ret = parse_lpq_qnx(line,buf,first);
1021 break;
1022 case PRINT_LPRNG:
1023 ret = parse_lpq_lprng(line,buf,first);
1024 break;
1025 case PRINT_PLP:
1026 ret = parse_lpq_plp(line,buf,first);
1027 break;
1028 case PRINT_SOFTQ:
1029 ret = parse_lpq_softq(line,buf,first);
1030 break;
1031 case PRINT_LPRNT:
1032 ret = parse_lpq_nt(line,buf,first);
1033 break;
1034 case PRINT_LPROS2:
1035 ret = parse_lpq_os2(line,buf,first);
1036 break;
1037 #ifdef DEVELOPER
1038 case PRINT_VLP:
1039 case PRINT_TEST:
1040 ret = parse_lpq_vlp(line,buf,first);
1041 break;
1042 #endif /* DEVELOPER */
1043 default:
1044 ret = parse_lpq_bsd(line,buf,first);
1045 break;
1048 /* We don't want the newline in the status message. */
1050 char *p = strchr(line,'\n');
1051 if (p) *p = 0;
1054 /* in the LPRNG case, we skip lines starting by a space.*/
1055 if (line && !ret && (lp_printing(snum)==PRINT_LPRNG) )
1057 if (line[0]==' ')
1058 return ret;
1062 if (status && !ret)
1064 /* a few simple checks to see if the line might be a
1065 printer status line:
1066 handle them so that most severe condition is shown */
1067 int i;
1068 strlower(line);
1070 switch (status->status) {
1071 case LPSTAT_OK:
1072 for (i=0; stat0_strings[i]; i++)
1073 if (strstr(line,stat0_strings[i])) {
1074 StrnCpy(status->message,line,sizeof(status->message)-1);
1075 status->status=LPSTAT_OK;
1076 return ret;
1078 case LPSTAT_STOPPED:
1079 for (i=0; stat1_strings[i]; i++)
1080 if (strstr(line,stat1_strings[i])) {
1081 StrnCpy(status->message,line,sizeof(status->message)-1);
1082 status->status=LPSTAT_STOPPED;
1083 return ret;
1085 case LPSTAT_ERROR:
1086 for (i=0; stat2_strings[i]; i++)
1087 if (strstr(line,stat2_strings[i])) {
1088 StrnCpy(status->message,line,sizeof(status->message)-1);
1089 status->status=LPSTAT_ERROR;
1090 return ret;
1092 break;
1096 return(ret);