~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/printing/lpq_parse.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
   lpq parsing routines
 
4
   Copyright (C) Andrew Tridgell 2000
 
5
   
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 3 of the License, or
 
9
   (at your option) any later version.
 
10
   
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
   
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include "includes.h"
 
21
#include "printing.h"
 
22
 
 
23
static const char *Months[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
 
24
                              "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err"};
 
25
 
 
26
 
 
27
/*******************************************************************
 
28
 Process time fields
 
29
********************************************************************/
 
30
 
 
31
static time_t EntryTime(char *tok[], int ptr, int count, int minimum)
 
32
{
 
33
        time_t jobtime,jobtime1;
 
34
 
 
35
        jobtime = time(NULL);           /* default case: take current time */
 
36
        if (count >= minimum) {
 
37
                struct tm *t;
 
38
                int i, day, hour, min, sec;
 
39
 
 
40
                for (i=0; i<13; i++) {
 
41
                        if (!strncmp(tok[ptr], Months[i],3)) {
 
42
                                break; /* Find month */
 
43
                        }
 
44
                }
 
45
 
 
46
                if (i<12) {
 
47
                        fstring c;
 
48
                        t = localtime(&jobtime);
 
49
                        if (!t) {
 
50
                                return (time_t)-1;
 
51
                        }
 
52
                        day = atoi(tok[ptr+1]);
 
53
                        fstrcpy(c,tok[ptr+2]);
 
54
                        *(c+2)=0;
 
55
                        hour = atoi(c);
 
56
                        *(c+5)=0;
 
57
                        min = atoi(c+3);
 
58
                        if(*(c+6) != 0) {
 
59
                                sec = atoi(c+6);
 
60
                        } else {
 
61
                                sec=0;
 
62
                        }
 
63
 
 
64
                        if ((t->tm_mon < i)|| ((t->tm_mon == i)&&
 
65
                                        ((t->tm_mday < day)||
 
66
                                        ((t->tm_mday == day)&&
 
67
                                        (t->tm_hour*60+t->tm_min < hour*60+min))))) {
 
68
                                t->tm_year--;           /* last year's print job */
 
69
                        }
 
70
 
 
71
                        t->tm_mon = i;
 
72
                        t->tm_mday = day;
 
73
                        t->tm_hour = hour;
 
74
                        t->tm_min = min;
 
75
                        t->tm_sec = sec;
 
76
                        jobtime1 = mktime(t);
 
77
                        if (jobtime1 != (time_t)-1) {
 
78
                                jobtime = jobtime1;
 
79
                        }
 
80
                }
 
81
        }
 
82
        return jobtime;
 
83
}
 
84
 
 
85
/****************************************************************************
 
86
parse a lpq line
 
87
 
 
88
here is an example of lpq output under bsd
 
89
 
 
90
Warning: no daemon present
 
91
Rank   Owner      Job  Files                                 Total Size
 
92
1st    tridge     148  README                                8096 bytes
 
93
 
 
94
here is an example of lpq output under osf/1
 
95
 
 
96
Warning: no daemon present
 
97
Rank   Pri Owner      Job  Files                             Total Size
 
98
1st    0   tridge     148  README                            8096 bytes
 
99
 
 
100
 
 
101
<allan@umich.edu> June 30, 1998.
 
102
Modified to handle file names with spaces, like the parse_lpq_lprng code
 
103
further below.
 
104
****************************************************************************/
 
105
 
 
106
static bool parse_lpq_bsd(char *line,print_queue_struct *buf,bool first)
 
107
{
 
108
#ifdef  OSF1
 
109
#define RANKTOK 0
 
110
#define PRIOTOK 1
 
111
#define USERTOK 2
 
112
#define JOBTOK  3
 
113
#define FILETOK 4
 
114
#define TOTALTOK (count - 2)
 
115
#define NTOK    6
 
116
#define MAXTOK  128
 
117
#else   /* OSF1 */
 
118
#define RANKTOK 0
 
119
#define USERTOK 1
 
120
#define JOBTOK  2
 
121
#define FILETOK 3
 
122
#define TOTALTOK (count - 2)
 
123
#define NTOK    5
 
124
#define MAXTOK  128
 
125
#endif  /* OSF1 */
 
126
 
 
127
        char *tok[MAXTOK];
 
128
        int  count = 0;
 
129
        TALLOC_CTX *ctx = talloc_tos();
 
130
        char *line2 = NULL;
 
131
        char *saveptr;
 
132
 
 
133
        line2 = talloc_strdup(ctx, line);
 
134
        if (!line2) {
 
135
                return false;
 
136
        }
 
137
 
 
138
#ifdef  OSF1
 
139
        {
 
140
                size_t length;
 
141
                length = strlen(line2);
 
142
                if (line2[length-3] == ':') {
 
143
                        return False;
 
144
                }
 
145
        }
 
146
#endif  /* OSF1 */
 
147
 
 
148
        /* FIXME: Use next_token_talloc rather than strtok! */
 
149
        tok[0] = strtok_r(line2," \t", &saveptr);
 
150
        count++;
 
151
 
 
152
        while ((count < MAXTOK)
 
153
               && ((tok[count] = strtok_r(NULL, " \t", &saveptr)) != NULL)) {
 
154
                count++;
 
155
        }
 
156
 
 
157
        /* we must get at least NTOK tokens */
 
158
        if (count < NTOK) {
 
159
                return False;
 
160
        }
 
161
 
 
162
        /* the Job and Total columns must be integer */
 
163
        if (!isdigit((int)*tok[JOBTOK]) || !isdigit((int)*tok[TOTALTOK])) {
 
164
                return False;
 
165
        }
 
166
 
 
167
        buf->job = atoi(tok[JOBTOK]);
 
168
        buf->size = atoi(tok[TOTALTOK]);
 
169
        buf->status = strequal(tok[RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED;
 
170
        buf->time = time(NULL);
 
171
        fstrcpy(buf->fs_user,tok[USERTOK]);
 
172
        fstrcpy(buf->fs_file,tok[FILETOK]);
 
173
 
 
174
        if ((FILETOK + 1) != TOTALTOK) {
 
175
                int i;
 
176
 
 
177
                for (i = (FILETOK + 1); i < TOTALTOK; i++) {
 
178
                        /* FIXME: Using fstrcat rather than other means is a bit
 
179
                         * inefficient; this might be a problem for enormous queues with
 
180
                         * many fields. */
 
181
                        fstrcat(buf->fs_file, " ");
 
182
                        fstrcat(buf->fs_file, tok[i]);
 
183
                }
 
184
                /* Ensure null termination. */
 
185
                buf->fs_file[sizeof(buf->fs_file)-1] = '\0';
 
186
        }
 
187
 
 
188
#ifdef PRIOTOK
 
189
        buf->priority = atoi(tok[PRIOTOK]);
 
190
#else
 
191
        buf->priority = 1;
 
192
#endif
 
193
        return True;
 
194
}
 
195
 
 
196
/*
 
197
<magnus@hum.auc.dk>
 
198
LPRng_time modifies the current date by inserting the hour and minute from
 
199
the lpq output.  The lpq time looks like "23:15:07"
 
200
 
 
201
<allan@umich.edu> June 30, 1998.
 
202
Modified to work with the re-written parse_lpq_lprng routine.
 
203
 
 
204
<J.P.M.v.Itegem@tue.nl> Dec 17,1999
 
205
Modified to work with lprng 3.16
 
206
With lprng 3.16 The lpq time looks like
 
207
                       "23:15:07"
 
208
                       "23:15:07.100"
 
209
                       "1999-12-16-23:15:07"
 
210
                       "1999-12-16-23:15:07.100"
 
211
 
 
212
*/
 
213
static time_t LPRng_time(char *time_string)
 
214
{
 
215
        time_t jobtime;
 
216
        struct tm *t;
 
217
 
 
218
        jobtime = time(NULL);         /* default case: take current time */
 
219
        t = localtime(&jobtime);
 
220
        if (!t) {
 
221
                return (time_t)-1;
 
222
        }
 
223
 
 
224
        if ( atoi(time_string) < 24 ){
 
225
                t->tm_hour = atoi(time_string);
 
226
                t->tm_min = atoi(time_string+3);
 
227
                t->tm_sec = atoi(time_string+6);
 
228
        } else {
 
229
                t->tm_year = atoi(time_string)-1900;
 
230
                t->tm_mon = atoi(time_string+5)-1;
 
231
                t->tm_mday = atoi(time_string+8);
 
232
                t->tm_hour = atoi(time_string+11);
 
233
                t->tm_min = atoi(time_string+14);
 
234
                t->tm_sec = atoi(time_string+17);
 
235
        }    
 
236
        jobtime = mktime(t);
 
237
 
 
238
        return jobtime;
 
239
}
 
240
 
 
241
/****************************************************************************
 
242
  parse a lprng lpq line
 
243
  <allan@umich.edu> June 30, 1998.
 
244
  Re-wrote this to handle file names with spaces, multiple file names on one
 
245
  lpq line, etc;
 
246
 
 
247
****************************************************************************/
 
248
 
 
249
static bool parse_lpq_lprng(char *line,print_queue_struct *buf,bool first)
 
250
{
 
251
#define LPRNG_RANKTOK   0
 
252
#define LPRNG_USERTOK   1
 
253
#define LPRNG_PRIOTOK   2
 
254
#define LPRNG_JOBTOK    3
 
255
#define LPRNG_FILETOK   4
 
256
#define LPRNG_TOTALTOK  (num_tok - 2)
 
257
#define LPRNG_TIMETOK   (num_tok - 1)
 
258
#define LPRNG_NTOK      7
 
259
#define LPRNG_MAXTOK    128 /* PFMA just to keep us from running away. */
 
260
 
 
261
        char *tokarr[LPRNG_MAXTOK];
 
262
        const char *cptr;
 
263
        char *ptr;
 
264
        int num_tok = 0;
 
265
        TALLOC_CTX *frame = talloc_stackframe();
 
266
 
 
267
        cptr = line;
 
268
        while((num_tok < LPRNG_MAXTOK) && next_token_talloc(frame, &cptr,
 
269
                                &tokarr[num_tok], " \t")) {
 
270
                num_tok++;
 
271
        }
 
272
 
 
273
        /* We must get at least LPRNG_NTOK tokens. */
 
274
        if (num_tok < LPRNG_NTOK) {
 
275
                TALLOC_FREE(frame);
 
276
                return False;
 
277
        }
 
278
 
 
279
        if (!isdigit((int)*tokarr[LPRNG_JOBTOK]) || !isdigit((int)*tokarr[LPRNG_TOTALTOK])) {
 
280
                TALLOC_FREE(frame);
 
281
                return False;
 
282
        }
 
283
 
 
284
        buf->job  = atoi(tokarr[LPRNG_JOBTOK]);
 
285
        buf->size = atoi(tokarr[LPRNG_TOTALTOK]);
 
286
 
 
287
        if (strequal(tokarr[LPRNG_RANKTOK],"active")) {
 
288
                buf->status = LPQ_PRINTING;
 
289
        } else if (strequal(tokarr[LPRNG_RANKTOK],"done")) {
 
290
                buf->status = LPQ_PRINTED;
 
291
        } else if (isdigit((int)*tokarr[LPRNG_RANKTOK])) {
 
292
                buf->status = LPQ_QUEUED;
 
293
        } else {
 
294
                buf->status = LPQ_PAUSED;
 
295
        }
 
296
 
 
297
        buf->priority = *tokarr[LPRNG_PRIOTOK] -'A';
 
298
 
 
299
        buf->time = LPRng_time(tokarr[LPRNG_TIMETOK]);
 
300
 
 
301
        fstrcpy(buf->fs_user,tokarr[LPRNG_USERTOK]);
 
302
 
 
303
        /* The '@hostname' prevents windows from displaying the printing icon
 
304
         * for the current user on the taskbar.  Plop in a null.
 
305
         */
 
306
 
 
307
        if ((ptr = strchr_m(buf->fs_user,'@')) != NULL) {
 
308
                *ptr = '\0';
 
309
        }
 
310
 
 
311
        fstrcpy(buf->fs_file,tokarr[LPRNG_FILETOK]);
 
312
 
 
313
        if ((LPRNG_FILETOK + 1) != LPRNG_TOTALTOK) {
 
314
                int i;
 
315
 
 
316
                for (i = (LPRNG_FILETOK + 1); i < LPRNG_TOTALTOK; i++) {
 
317
                        /* FIXME: Using fstrcat rather than other means is a bit
 
318
                         * inefficient; this might be a problem for enormous queues with
 
319
                         * many fields. */
 
320
                        fstrcat(buf->fs_file, " ");
 
321
                        fstrcat(buf->fs_file, tokarr[i]);
 
322
                }
 
323
                /* Ensure null termination. */
 
324
                buf->fs_file[sizeof(buf->fs_file)-1] = '\0';
 
325
        }
 
326
 
 
327
        TALLOC_FREE(frame);
 
328
        return True;
 
329
}
 
330
 
 
331
/*******************************************************************
 
332
parse lpq on an aix system
 
333
 
 
334
Queue   Dev   Status    Job Files              User         PP %   Blks  Cp Rnk
 
335
------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
 
336
lazer   lazer READY
 
337
lazer   lazer RUNNING   537 6297doc.A          kvintus@IE    0 10  2445   1   1
 
338
              QUEUED    538 C.ps               root@IEDVB           124   1   2
 
339
              QUEUED    539 E.ps               root@IEDVB            28   1   3
 
340
              QUEUED    540 L.ps               root@IEDVB           172   1   4
 
341
              QUEUED    541 P.ps               root@IEDVB            22   1   5
 
342
********************************************************************/
 
343
 
 
344
static bool parse_lpq_aix(char *line,print_queue_struct *buf,bool first)
 
345
{
 
346
        char *tok[11];
 
347
        int count=0;
 
348
        const char *cline = line;
 
349
        TALLOC_CTX *frame = talloc_stackframe();
 
350
 
 
351
        /* handle the case of "(standard input)" as a filename */
 
352
        string_sub(line,"standard input","STDIN",0);
 
353
        all_string_sub(line,"(","\"",0);
 
354
        all_string_sub(line,")","\"",0);
 
355
 
 
356
        for (count=0; count<10 &&
 
357
                        next_token_talloc(frame,&cline,&tok[count],NULL); count++) {
 
358
                ;
 
359
        }
 
360
 
 
361
        /* we must get 6 tokens */
 
362
        if (count < 10) {
 
363
                if ((count == 7) && ((strcmp(tok[0],"QUEUED") == 0) || (strcmp(tok[0],"HELD") == 0))) {
 
364
                        /* the 2nd and 5th columns must be integer */
 
365
                        if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4])) {
 
366
                                TALLOC_FREE(frame);
 
367
                                return False;
 
368
                        }
 
369
                        buf->size = atoi(tok[4]) * 1024;
 
370
                        /* if the fname contains a space then use STDIN */
 
371
                        if (strchr_m(tok[2],' ')) {
 
372
                                tok[2] = talloc_strdup(frame,"STDIN");
 
373
                                if (!tok[2]) {
 
374
                                        TALLOC_FREE(frame);
 
375
                                        return false;
 
376
                                }
 
377
                        }
 
378
 
 
379
                        /* only take the last part of the filename */
 
380
                        {
 
381
                                char *p = strrchr_m(tok[2],'/');
 
382
                                if (p) {
 
383
                                        tok[2] = p+1;
 
384
                                }
 
385
                        }
 
386
 
 
387
                        buf->job = atoi(tok[1]);
 
388
                        buf->status = strequal(tok[0],"HELD")?LPQ_PAUSED:LPQ_QUEUED;
 
389
                        buf->priority = 0;
 
390
                        buf->time = time(NULL);
 
391
                        fstrcpy(buf->fs_user,tok[3]);
 
392
                        fstrcpy(buf->fs_file,tok[2]);
 
393
                } else {
 
394
                        DEBUG(6,("parse_lpq_aix count=%d\n", count));
 
395
                        TALLOC_FREE(frame);
 
396
                        return False;
 
397
                }
 
398
        } else {
 
399
                /* the 4th and 9th columns must be integer */
 
400
                if (!isdigit((int)*tok[3]) || !isdigit((int)*tok[8])) {
 
401
                        TALLOC_FREE(frame);
 
402
                        return False;
 
403
                }
 
404
 
 
405
                buf->size = atoi(tok[8]) * 1024;
 
406
                /* if the fname contains a space then use STDIN */
 
407
                if (strchr_m(tok[4],' ')) {
 
408
                        tok[4] = talloc_strdup(frame,"STDIN");
 
409
                        if (!tok[4]) {
 
410
                                TALLOC_FREE(frame);
 
411
                                return false;
 
412
                        }
 
413
                }
 
414
 
 
415
                /* only take the last part of the filename */
 
416
                {
 
417
                        char *p = strrchr_m(tok[4],'/');
 
418
                        if (p) {
 
419
                                tok[4] = p+1;
 
420
                        }
 
421
                }
 
422
 
 
423
                buf->job = atoi(tok[3]);
 
424
                buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED;
 
425
                buf->priority = 0;
 
426
                buf->time = time(NULL);
 
427
                fstrcpy(buf->fs_user,tok[5]);
 
428
                fstrcpy(buf->fs_file,tok[4]);
 
429
        }
 
430
 
 
431
        TALLOC_FREE(frame);
 
432
        return True;
 
433
}
 
434
 
 
435
/****************************************************************************
 
436
parse a lpq line
 
437
here is an example of lpq output under hpux; note there's no space after -o !
 
438
$> lpstat -oljplus
 
439
ljplus-2153         user           priority 0  Jan 19 08:14 on ljplus
 
440
      util.c                                  125697 bytes
 
441
      server.c                                110712 bytes
 
442
ljplus-2154         user           priority 0  Jan 19 08:14 from client
 
443
      (standard input)                          7551 bytes
 
444
****************************************************************************/
 
445
 
 
446
static bool parse_lpq_hpux(char *line, print_queue_struct *buf, bool first)
 
447
{
 
448
        /* must read two lines to process, therefore keep some values static */
 
449
        static bool header_line_ok=False, base_prio_reset=False;
 
450
        static char *jobuser;
 
451
        static int jobid;
 
452
        static int jobprio;
 
453
        static time_t jobtime;
 
454
        static int jobstat=LPQ_QUEUED;
 
455
        /* to store minimum priority to print, lpstat command should be invoked
 
456
                with -p option first, to work */
 
457
        static int base_prio;
 
458
        int count;
 
459
        char htab = '\011';
 
460
        const char *cline = line;
 
461
        char *tok[12];
 
462
        TALLOC_CTX *frame = talloc_stackframe();
 
463
 
 
464
        /* If a line begins with a horizontal TAB, it is a subline type */
 
465
 
 
466
        if (line[0] == htab) { /* subline */
 
467
                /* check if it contains the base priority */
 
468
                if (!strncmp(line,"\tfence priority : ",18)) {
 
469
                        base_prio=atoi(&line[18]);
 
470
                        DEBUG(4, ("fence priority set at %d\n", base_prio));
 
471
                }
 
472
 
 
473
                if (!header_line_ok) {
 
474
                        TALLOC_FREE(frame);
 
475
                        return  False; /* incorrect header line */
 
476
                }
 
477
 
 
478
                /* handle the case of "(standard input)" as a filename */
 
479
                string_sub(line,"standard input","STDIN",0);
 
480
                all_string_sub(line,"(","\"",0);
 
481
                all_string_sub(line,")","\"",0);
 
482
 
 
483
                for (count=0; count<2 &&
 
484
                                next_token_talloc(frame, &cline, &tok[count],NULL);
 
485
                                count++) {
 
486
                        ;
 
487
                }
 
488
                /* we must get 2 tokens */
 
489
                if (count < 2) {
 
490
                        TALLOC_FREE(frame);
 
491
                        return False;
 
492
                }
 
493
 
 
494
                /* the 2nd column must be integer */
 
495
                if (!isdigit((int)*tok[1])) {
 
496
                        TALLOC_FREE(frame);
 
497
                        return False;
 
498
                }
 
499
 
 
500
                /* if the fname contains a space then use STDIN */
 
501
                if (strchr_m(tok[0],' ')) {
 
502
                        tok[0] = talloc_strdup(frame, "STDIN");
 
503
                        if (!tok[0]) {
 
504
                                TALLOC_FREE(frame);
 
505
                                return false;
 
506
                        }
 
507
                }
 
508
 
 
509
                buf->size = atoi(tok[1]);
 
510
                fstrcpy(buf->fs_file,tok[0]);
 
511
 
 
512
                /* fill things from header line */
 
513
                buf->time = jobtime;
 
514
                buf->job = jobid;
 
515
                buf->status = jobstat;
 
516
                buf->priority = jobprio;
 
517
                if (jobuser) {
 
518
                        fstrcpy(buf->fs_user,jobuser);
 
519
                } else {
 
520
                        buf->fs_user[0] = '\0';
 
521
                }
 
522
 
 
523
                TALLOC_FREE(frame);
 
524
                return True;
 
525
        } else { /* header line */
 
526
                header_line_ok=False; /* reset it */
 
527
                if (first) {
 
528
                        if (!base_prio_reset) {
 
529
                                base_prio=0; /* reset it */
 
530
                                base_prio_reset=True;
 
531
                        }
 
532
                } else if (base_prio) {
 
533
                        base_prio_reset=False;
 
534
                }
 
535
 
 
536
                /* handle the dash in the job id */
 
537
                string_sub(line,"-"," ",0);
 
538
 
 
539
                for (count=0; count<12 &&
 
540
                                next_token_talloc(frame, &cline, &tok[count],NULL);
 
541
                                count++) {
 
542
                        ;
 
543
                }
 
544
 
 
545
                /* we must get 8 tokens */
 
546
                if (count < 8) {
 
547
                        TALLOC_FREE(frame);
 
548
                        return False;
 
549
                }
 
550
 
 
551
                /* first token must be printer name (cannot check ?) */
 
552
                /* the 2nd, 5th & 7th column must be integer */
 
553
                if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4]) || !isdigit((int)*tok[6])) {
 
554
                        TALLOC_FREE(frame);
 
555
                        return False;
 
556
                }
 
557
                jobid = atoi(tok[1]);
 
558
                SAFE_FREE(jobuser);
 
559
                jobuser = SMB_STRDUP(tok[2]);
 
560
                jobprio = atoi(tok[4]);
 
561
 
 
562
                /* process time */
 
563
                jobtime=EntryTime(tok, 5, count, 8);
 
564
                if (jobprio < base_prio) {
 
565
                        jobstat = LPQ_PAUSED;
 
566
                        DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n",
 
567
                                jobid, jobprio, base_prio, jobstat));
 
568
                } else {
 
569
                        jobstat = LPQ_QUEUED;
 
570
                        if ((count >8) && (((strequal(tok[8],"on")) ||
 
571
                                        ((strequal(tok[8],"from")) && 
 
572
                                        ((count > 10)&&(strequal(tok[10],"on"))))))) {
 
573
                                jobstat = LPQ_PRINTING;
 
574
                        }
 
575
                }
 
576
 
 
577
                header_line_ok=True; /* information is correct */
 
578
                TALLOC_FREE(frame);
 
579
                return False; /* need subline info to include into queuelist */
 
580
        }
 
581
}
 
582
 
 
583
/****************************************************************************
 
584
parse a lpstat line
 
585
 
 
586
here is an example of "lpstat -o dcslw" output under sysv
 
587
 
 
588
dcslw-896               tridge            4712   Dec 20 10:30:30 on dcslw
 
589
dcslw-897               tridge            4712   Dec 20 10:30:30 being held
 
590
 
 
591
****************************************************************************/
 
592
 
 
593
static bool parse_lpq_sysv(char *line,print_queue_struct *buf,bool first)
 
594
{
 
595
        char *tok[9];
 
596
        int count=0;
 
597
        char *p;
 
598
        const char *cline = line;
 
599
        TALLOC_CTX *frame = NULL;
 
600
 
 
601
        /*
 
602
         * Handle the dash in the job id, but make sure that we skip over
 
603
         * the printer name in case we have a dash in that.
 
604
         * Patch from Dom.Mitchell@palmerharvey.co.uk.
 
605
         */
 
606
 
 
607
        /*
 
608
         * Move to the first space.
 
609
         */
 
610
        for (p = line ; !isspace(*p) && *p; p++) {
 
611
                ;
 
612
        }
 
613
 
 
614
        /*
 
615
         * Back up until the last '-' character or
 
616
         * start of line.
 
617
         */
 
618
        for (; (p >= line) && (*p != '-'); p--) {
 
619
                ;
 
620
        }
 
621
 
 
622
        if((p >= line) && (*p == '-')) {
 
623
                *p = ' ';
 
624
        }
 
625
 
 
626
        frame = talloc_stackframe();
 
627
        for (count=0; count<9 &&
 
628
                        next_token_talloc(frame, &cline, &tok[count],NULL);
 
629
                        count++) {
 
630
                ;
 
631
        }
 
632
 
 
633
        /* we must get 7 tokens */
 
634
        if (count < 7) {
 
635
                TALLOC_FREE(frame);
 
636
                return False;
 
637
        }
 
638
 
 
639
        /* the 2nd and 4th, 6th columns must be integer */
 
640
        if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[3])) {
 
641
                TALLOC_FREE(frame);
 
642
                return False;
 
643
        }
 
644
        if (!isdigit((int)*tok[5])) {
 
645
                TALLOC_FREE(frame);
 
646
                return False;
 
647
        }
 
648
 
 
649
        /* if the user contains a ! then trim the first part of it */
 
650
        if ((p=strchr_m(tok[2],'!'))) {
 
651
                tok[2] = p+1;
 
652
        }
 
653
 
 
654
        buf->job = atoi(tok[1]);
 
655
        buf->size = atoi(tok[3]);
 
656
        if (count > 7 && strequal(tok[7],"on")) {
 
657
                buf->status = LPQ_PRINTING;
 
658
        } else if (count > 8 && strequal(tok[7],"being") && strequal(tok[8],"held")) {
 
659
                buf->status = LPQ_PAUSED;
 
660
        } else {
 
661
                buf->status = LPQ_QUEUED;
 
662
        }
 
663
        buf->priority = 0;
 
664
        buf->time = EntryTime(tok, 4, count, 7);
 
665
        fstrcpy(buf->fs_user,tok[2]);
 
666
        fstrcpy(buf->fs_file,tok[2]);
 
667
        TALLOC_FREE(frame);
 
668
        return True;
 
669
}
 
670
 
 
671
/****************************************************************************
 
672
parse a lpq line
 
673
 
 
674
here is an example of lpq output under qnx
 
675
Spooler: /qnx/spooler, on node 1
 
676
Printer: txt        (ready)
 
677
0000:     root  [job #1    ]   active 1146 bytes        /etc/profile
 
678
0001:     root  [job #2    ]    ready 2378 bytes        /etc/install
 
679
0002:     root  [job #3    ]    ready 1146 bytes        -- standard input --
 
680
****************************************************************************/
 
681
 
 
682
static bool parse_lpq_qnx(char *line,print_queue_struct *buf,bool first)
 
683
{
 
684
        char *tok[7];
 
685
        int count=0;
 
686
        const char *cline = line;
 
687
        TALLOC_CTX *frame = NULL;
 
688
 
 
689
        DEBUG(4,("antes [%s]\n", line));
 
690
 
 
691
        /* handle the case of "-- standard input --" as a filename */
 
692
        string_sub(line,"standard input","STDIN",0);
 
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));
 
697
 
 
698
        string_sub(line,"[job #","",0);
 
699
        string_sub(line,"]","",0);
 
700
        DEBUG(4,("despues 2 [%s]\n", line));
 
701
 
 
702
        frame = talloc_stackframe();
 
703
        for (count=0; count<7 &&
 
704
                        next_token_talloc(frame,&cline,&tok[count],NULL);
 
705
                        count++) {
 
706
                ;
 
707
        }
 
708
 
 
709
        /* we must get 7 tokens */
 
710
        if (count < 7) {
 
711
                TALLOC_FREE(frame);
 
712
                return False;
 
713
        }
 
714
 
 
715
        /* the 3rd and 5th columns must be integer */
 
716
        if (!isdigit((int)*tok[2]) || !isdigit((int)*tok[4])) {
 
717
                TALLOC_FREE(frame);
 
718
                return False;
 
719
        }
 
720
 
 
721
        /* only take the last part of the filename */
 
722
        {
 
723
                char *p = strrchr_m(tok[6],'/');
 
724
                if (p) {
 
725
                        tok[6] = p+1;
 
726
                }
 
727
        }
 
728
 
 
729
        buf->job = atoi(tok[2]);
 
730
        buf->size = atoi(tok[4]);
 
731
        buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED;
 
732
        buf->priority = 0;
 
733
        buf->time = time(NULL);
 
734
        fstrcpy(buf->fs_user,tok[1]);
 
735
        fstrcpy(buf->fs_file,tok[6]);
 
736
        TALLOC_FREE(frame);
 
737
        return True;
 
738
}
 
739
 
 
740
/****************************************************************************
 
741
  parse a lpq line for the plp printing system
 
742
  Bertrand Wallrich <Bertrand.Wallrich@loria.fr>
 
743
 
 
744
redone by tridge. Here is a sample queue:
 
745
 
 
746
Local  Printer 'lp2' (fjall):
 
747
  Printing (started at Jun 15 13:33:58, attempt 1).
 
748
    Rank Owner       Pr Opt  Job Host        Files           Size     Date
 
749
  active tridge      X  -    6   fjall       /etc/hosts      739      Jun 15 13:33
 
750
     3rd tridge      X  -    7   fjall       /etc/hosts      739      Jun 15 13:33
 
751
 
 
752
****************************************************************************/
 
753
 
 
754
static bool parse_lpq_plp(char *line,print_queue_struct *buf,bool first)
 
755
{
 
756
        char *tok[11];
 
757
        int count=0;
 
758
        const char *cline = line;
 
759
        TALLOC_CTX *frame = talloc_stackframe();
 
760
 
 
761
        /* handle the case of "(standard input)" as a filename */
 
762
        string_sub(line,"stdin","STDIN",0);
 
763
        all_string_sub(line,"(","\"",0);
 
764
        all_string_sub(line,")","\"",0);
 
765
 
 
766
        for (count=0; count<11 &&
 
767
                        next_token_talloc(frame,&cline,&tok[count],NULL);
 
768
                        count++) {
 
769
                ;
 
770
        }
 
771
 
 
772
        /* we must get 11 tokens */
 
773
        if (count < 11) {
 
774
                TALLOC_FREE(frame);
 
775
                return False;
 
776
        }
 
777
 
 
778
        /* the first must be "active" or begin with an integer */
 
779
        if (strcmp(tok[0],"active") && !isdigit((int)tok[0][0])) {
 
780
                TALLOC_FREE(frame);
 
781
                return False;
 
782
        }
 
783
 
 
784
        /* the 5th and 8th must be integer */
 
785
        if (!isdigit((int)*tok[4]) || !isdigit((int)*tok[7])) {
 
786
                TALLOC_FREE(frame);
 
787
                return False;
 
788
        }
 
789
 
 
790
        /* if the fname contains a space then use STDIN */
 
791
        if (strchr_m(tok[6],' ')) {
 
792
                tok[6] = talloc_strdup(frame, "STDIN");
 
793
                if (!tok[6]) {
 
794
                        TALLOC_FREE(frame);
 
795
                        return false;
 
796
                }
 
797
        }
 
798
 
 
799
        /* only take the last part of the filename */
 
800
        {
 
801
                fstring tmp;
 
802
                char *p = strrchr_m(tok[6],'/');
 
803
                if (p) {
 
804
                        fstrcpy(tmp,p+1);
 
805
                        fstrcpy(tok[6],tmp);
 
806
                }
 
807
        }
 
808
 
 
809
        buf->job = atoi(tok[4]);
 
810
 
 
811
        buf->size = atoi(tok[7]);
 
812
        if (strchr_m(tok[7],'K')) {
 
813
                buf->size *= 1024;
 
814
        }
 
815
        if (strchr_m(tok[7],'M')) {
 
816
                buf->size *= 1024*1024;
 
817
        }
 
818
 
 
819
        buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED;
 
820
        buf->priority = 0;
 
821
        buf->time = time(NULL);
 
822
        fstrcpy(buf->fs_user,tok[1]);
 
823
        fstrcpy(buf->fs_file,tok[6]);
 
824
        TALLOC_FREE(frame);
 
825
        return True;
 
826
}
 
827
 
 
828
/*******************************************************************
 
829
parse lpq on an NT system
 
830
 
 
831
                         Windows 2000 LPD Server
 
832
                              Printer \\10.0.0.2\NP17PCL (Paused)
 
833
 
 
834
Owner       Status         Jobname          Job-Id    Size   Pages  Priority
 
835
----------------------------------------------------------------------------
 
836
root (9.99. Printing  /usr/lib/rhs/rhs-pr      3       625      0      1
 
837
root (9.99. Paused    /usr/lib/rhs/rhs-pr      4       625      0      1
 
838
jmcd        Waiting   Re: Samba Open Sour     26     32476      1      1
 
839
 
 
840
********************************************************************/
 
841
 
 
842
static bool parse_lpq_nt(char *line,print_queue_struct *buf,bool first)
 
843
{
 
844
#define LPRNT_OWNSIZ 11
 
845
#define LPRNT_STATSIZ 9
 
846
#define LPRNT_JOBSIZ 19
 
847
#define LPRNT_IDSIZ 6
 
848
#define LPRNT_SIZSIZ 9
 
849
        typedef struct {
 
850
                char owner[LPRNT_OWNSIZ];
 
851
                char space1;
 
852
                char status[LPRNT_STATSIZ];
 
853
                char space2;
 
854
                char jobname[LPRNT_JOBSIZ];
 
855
                char space3;
 
856
                char jobid[LPRNT_IDSIZ];
 
857
                char space4;
 
858
                char size[LPRNT_SIZSIZ];
 
859
                char terminator;
 
860
        } nt_lpq_line;
 
861
 
 
862
        char parse_line_char[sizeof(nt_lpq_line)];
 
863
        nt_lpq_line *parse_line = (nt_lpq_line *)parse_line_char;
 
864
#define LPRNT_PRINTING "Printing"
 
865
#define LPRNT_WAITING "Waiting"
 
866
#define LPRNT_PAUSED "Paused"
 
867
 
 
868
        memset(parse_line_char, '\0', sizeof(parse_line_char));
 
869
        strncpy(parse_line_char, line, sizeof(parse_line_char) -1);
 
870
 
 
871
        if (strlen(parse_line_char) != sizeof(parse_line_char) - 1) {
 
872
                return False;
 
873
        }
 
874
 
 
875
        /* Just want the first word in the owner field - the username */
 
876
        if (strchr_m(parse_line->owner, ' ')) {
 
877
                *(strchr_m(parse_line->owner, ' ')) = '\0';
 
878
        } else {
 
879
                parse_line->space1 = '\0';
 
880
        }
 
881
 
 
882
        /* Make sure we have an owner */
 
883
        if (!strlen(parse_line->owner)) {
 
884
                return False;
 
885
        }
 
886
 
 
887
        /* Make sure the status is valid */
 
888
        parse_line->space2 = '\0';
 
889
        trim_char(parse_line->status, '\0', ' ');
 
890
        if (!strequal(parse_line->status, LPRNT_PRINTING) &&
 
891
                        !strequal(parse_line->status, LPRNT_PAUSED) &&
 
892
                        !strequal(parse_line->status, LPRNT_WAITING)) {
 
893
                return False;
 
894
        }
 
895
  
 
896
        parse_line->space3 = '\0';
 
897
        trim_char(parse_line->jobname, '\0', ' ');
 
898
 
 
899
        buf->job = atoi(parse_line->jobid);
 
900
        buf->priority = 0;
 
901
        buf->size = atoi(parse_line->size);
 
902
        buf->time = time(NULL);
 
903
        fstrcpy(buf->fs_user, parse_line->owner);
 
904
        fstrcpy(buf->fs_file, parse_line->jobname);
 
905
        if (strequal(parse_line->status, LPRNT_PRINTING)) {
 
906
                buf->status = LPQ_PRINTING;
 
907
        } else if (strequal(parse_line->status, LPRNT_PAUSED)) {
 
908
                buf->status = LPQ_PAUSED;
 
909
        } else {
 
910
                buf->status = LPQ_QUEUED;
 
911
        }
 
912
 
 
913
        return True;
 
914
}
 
915
 
 
916
/*******************************************************************
 
917
parse lpq on an OS2 system
 
918
 
 
919
JobID  File Name          Rank      Size        Status          Comment       
 
920
-----  ---------------    ------    --------    ------------    ------------  
 
921
    3  Control                 1          68    Queued          root@psflinu  
 
922
    4  /etc/motd               2       11666    Queued          root@psflinu  
 
923
 
 
924
********************************************************************/
 
925
 
 
926
static bool parse_lpq_os2(char *line,print_queue_struct *buf,bool first)
 
927
{
 
928
#define LPROS2_IDSIZ 5
 
929
#define LPROS2_JOBSIZ 15
 
930
#define LPROS2_SIZSIZ 8
 
931
#define LPROS2_STATSIZ 12
 
932
#define LPROS2_OWNSIZ 12
 
933
        typedef struct {
 
934
                char jobid[LPROS2_IDSIZ];
 
935
                char space1[2];
 
936
                char jobname[LPROS2_JOBSIZ];
 
937
                char space2[14];
 
938
                char size[LPROS2_SIZSIZ];
 
939
                char space3[4];
 
940
                char status[LPROS2_STATSIZ];
 
941
                char space4[4];
 
942
                char owner[LPROS2_OWNSIZ];
 
943
                char terminator;
 
944
        } os2_lpq_line;
 
945
 
 
946
        char parse_line_char[sizeof(os2_lpq_line)];
 
947
        os2_lpq_line *parse_line = (os2_lpq_line *)parse_line_char;
 
948
#define LPROS2_PRINTING "Printing"
 
949
#define LPROS2_WAITING "Queued"
 
950
#define LPROS2_PAUSED "Paused"
 
951
 
 
952
        memset(parse_line_char, '\0', sizeof(parse_line_char));
 
953
        strncpy(parse_line_char, line, sizeof(parse_line_char) -1);
 
954
 
 
955
        if (strlen(parse_line_char) != sizeof(parse_line_char) - 1) {
 
956
                return False;
 
957
        }
 
958
 
 
959
        /* Get the jobid */
 
960
        buf->job = atoi(parse_line->jobid);
 
961
 
 
962
        /* Get the job name */
 
963
        parse_line->space2[0] = '\0';
 
964
        trim_char(parse_line->jobname, '\0', ' ');
 
965
        fstrcpy(buf->fs_file, parse_line->jobname);
 
966
 
 
967
        buf->priority = 0;
 
968
        buf->size = atoi(parse_line->size);
 
969
        buf->time = time(NULL);
 
970
 
 
971
        /* Make sure we have an owner */
 
972
        if (!strlen(parse_line->owner)) {
 
973
                return False;
 
974
        }
 
975
 
 
976
        /* Make sure we have a valid status */
 
977
        parse_line->space4[0] = '\0';
 
978
        trim_char(parse_line->status, '\0', ' ');
 
979
        if (!strequal(parse_line->status, LPROS2_PRINTING) &&
 
980
                        !strequal(parse_line->status, LPROS2_PAUSED) &&
 
981
                        !strequal(parse_line->status, LPROS2_WAITING)) {
 
982
                return False;
 
983
        }
 
984
 
 
985
        fstrcpy(buf->fs_user, parse_line->owner);
 
986
        if (strequal(parse_line->status, LPROS2_PRINTING)) {
 
987
                buf->status = LPQ_PRINTING;
 
988
        } else if (strequal(parse_line->status, LPROS2_PAUSED)) {
 
989
                buf->status = LPQ_PAUSED;
 
990
        } else {
 
991
                buf->status = LPQ_QUEUED;
 
992
        }
 
993
 
 
994
        return True;
 
995
}
 
996
 
 
997
static const char *stat0_strings[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL };
 
998
static const char *stat1_strings[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL };
 
999
static const char *stat2_strings[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL };
 
1000
 
 
1001
#ifdef DEVELOPER
 
1002
 
 
1003
/****************************************************************************
 
1004
parse a vlp line
 
1005
****************************************************************************/
 
1006
 
 
1007
static bool parse_lpq_vlp(char *line,print_queue_struct *buf,bool first)
 
1008
{
 
1009
        int toknum = 0;
 
1010
        char *tok;
 
1011
        TALLOC_CTX *frame = talloc_stackframe();
 
1012
        const char *cline = line;
 
1013
 
 
1014
        /* First line is printer status */
 
1015
 
 
1016
        if (!isdigit(line[0])) {
 
1017
                TALLOC_FREE(frame);
 
1018
                return False;
 
1019
        }
 
1020
 
 
1021
        /* Parse a print job entry */
 
1022
 
 
1023
        while(next_token_talloc(frame, &cline, &tok, NULL)) {
 
1024
                switch (toknum) {
 
1025
                case 0:
 
1026
                        buf->job = atoi(tok);
 
1027
                        break;
 
1028
                case 1:
 
1029
                        buf->size = atoi(tok);
 
1030
                        break;
 
1031
                case 2:
 
1032
                        buf->status = atoi(tok);
 
1033
                        break;
 
1034
                case 3:
 
1035
                        buf->time = atoi(tok);
 
1036
                        break;
 
1037
                case 4:
 
1038
                        fstrcpy(buf->fs_user, tok);
 
1039
                        break;
 
1040
                case 5:
 
1041
                        fstrcpy(buf->fs_file, tok);
 
1042
                        break;
 
1043
                }
 
1044
                toknum++;
 
1045
        }
 
1046
 
 
1047
        TALLOC_FREE(frame);
 
1048
        return True;
 
1049
}
 
1050
 
 
1051
#endif /* DEVELOPER */
 
1052
 
 
1053
/****************************************************************************
 
1054
parse a lpq line. Choose printing style
 
1055
****************************************************************************/
 
1056
 
 
1057
bool parse_lpq_entry(enum printing_types printing_type,char *line,
 
1058
                     print_queue_struct *buf,
 
1059
                     print_status_struct *status,bool first)
 
1060
{
 
1061
        bool ret;
 
1062
 
 
1063
        switch (printing_type) {
 
1064
                case PRINT_SYSV:
 
1065
                        ret = parse_lpq_sysv(line,buf,first);
 
1066
                        break;
 
1067
                case PRINT_AIX:      
 
1068
                        ret = parse_lpq_aix(line,buf,first);
 
1069
                        break;
 
1070
                case PRINT_HPUX:
 
1071
                        ret = parse_lpq_hpux(line,buf,first);
 
1072
                        break;
 
1073
                case PRINT_QNX:
 
1074
                        ret = parse_lpq_qnx(line,buf,first);
 
1075
                        break;
 
1076
                case PRINT_LPRNG:
 
1077
                        ret = parse_lpq_lprng(line,buf,first);
 
1078
                        break;
 
1079
                case PRINT_PLP:
 
1080
                        ret = parse_lpq_plp(line,buf,first);
 
1081
                        break;
 
1082
                case PRINT_LPRNT:
 
1083
                        ret = parse_lpq_nt(line,buf,first);
 
1084
                        break;
 
1085
                case PRINT_LPROS2:
 
1086
                        ret = parse_lpq_os2(line,buf,first);
 
1087
                        break;
 
1088
#ifdef DEVELOPER
 
1089
                case PRINT_VLP:
 
1090
                case PRINT_TEST:
 
1091
                        ret = parse_lpq_vlp(line,buf,first);
 
1092
                        break;
 
1093
#endif /* DEVELOPER */
 
1094
                default:
 
1095
                        ret = parse_lpq_bsd(line,buf,first);
 
1096
                        break;
 
1097
        }
 
1098
 
 
1099
        /* We don't want the newline in the status message. */
 
1100
        {
 
1101
                char *p = strchr_m(line,'\n');
 
1102
                if (p) {
 
1103
                        *p = 0;
 
1104
                }
 
1105
        }
 
1106
 
 
1107
        /* in the LPRNG case, we skip lines starting by a space.*/
 
1108
        if (!ret && (printing_type==PRINT_LPRNG) ) {
 
1109
                if (line[0]==' ') {
 
1110
                        return ret;
 
1111
                }
 
1112
        }
 
1113
 
 
1114
        if (status && !ret) {
 
1115
                /* a few simple checks to see if the line might be a
 
1116
                        printer status line: 
 
1117
                        handle them so that most severe condition is shown */
 
1118
                int i;
 
1119
                strlower_m(line);
 
1120
      
 
1121
                switch (status->status) {
 
1122
                        case LPSTAT_OK:
 
1123
                                for (i=0; stat0_strings[i]; i++) {
 
1124
                                        if (strstr_m(line,stat0_strings[i])) {
 
1125
                                                fstrcpy(status->message,line);
 
1126
                                                status->status=LPSTAT_OK;
 
1127
                                                return ret;
 
1128
                                        }
 
1129
                                }
 
1130
                                /* fallthrough */
 
1131
                        case LPSTAT_STOPPED:
 
1132
                                for (i=0; stat1_strings[i]; i++) {
 
1133
                                        if (strstr_m(line,stat1_strings[i])) {
 
1134
                                                fstrcpy(status->message,line);
 
1135
                                                status->status=LPSTAT_STOPPED;
 
1136
                                                return ret;
 
1137
                                        }
 
1138
                                }
 
1139
                                /* fallthrough */
 
1140
                        case LPSTAT_ERROR:
 
1141
                                for (i=0; stat2_strings[i]; i++) {
 
1142
                                        if (strstr_m(line,stat2_strings[i])) {
 
1143
                                                fstrcpy(status->message,line);
 
1144
                                                status->status=LPSTAT_ERROR;
 
1145
                                                return ret;
 
1146
                                        }
 
1147
                                }
 
1148
                                break;
 
1149
                }
 
1150
        }
 
1151
 
 
1152
        return ret;
 
1153
}
 
1154
 
 
1155
/****************************************************************************
 
1156
 Parse a file name from the system spooler to generate a jobid.
 
1157
****************************************************************************/
 
1158
 
 
1159
uint32_t print_parse_jobid(const char *fname)
 
1160
{
 
1161
        int jobid;
 
1162
        const char *p = strstr_m(fname,PRINT_SPOOL_PREFIX);
 
1163
 
 
1164
        if (!p) {
 
1165
                return (uint32_t)-1;
 
1166
        }
 
1167
        p += strlen(PRINT_SPOOL_PREFIX);
 
1168
        jobid = atoi(p);
 
1169
        if (jobid <= 0) {
 
1170
                return (uint32_t)-1;
 
1171
        }
 
1172
        return (uint32_t)jobid;
 
1173
}