~ubuntu-branches/ubuntu/hoary/lpr/hoary

« back to all changes in this revision

Viewing changes to lpc/cmds.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-03-15 14:54:38 UTC
  • Revision ID: james.westby@ubuntu.com-20030315145438-3n1sxzrmv1g34n4t
Tags: upstream-2000.05.07
ImportĀ upstreamĀ versionĀ 2000.05.07

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $OpenBSD: cmds.c,v 1.9 1997/07/25 18:57:24 grr Exp $    */
 
2
 
 
3
/*
 
4
 * Copyright (c) 1983, 1993
 
5
 *      The Regents of the University of California.  All rights reserved.
 
6
 *
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions
 
10
 * are met:
 
11
 * 1. Redistributions of source code must retain the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer.
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in the
 
15
 *    documentation and/or other materials provided with the distribution.
 
16
 * 3. All advertising materials mentioning features or use of this software
 
17
 *    must display the following acknowledgement:
 
18
 *      This product includes software developed by the University of
 
19
 *      California, Berkeley and its contributors.
 
20
 * 4. Neither the name of the University nor the names of its contributors
 
21
 *    may be used to endorse or promote products derived from this software
 
22
 *    without specific prior written permission.
 
23
 *
 
24
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
25
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
27
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
28
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
29
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
30
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
31
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
33
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
34
 * SUCH DAMAGE.
 
35
 */
 
36
 
 
37
#ifndef lint
 
38
static char copyright[] =
 
39
"@(#) Copyright (c) 1983, 1993\n\
 
40
        The Regents of the University of California.  All rights reserved.\n";
 
41
#endif /* not lint */
 
42
 
 
43
#ifndef lint
 
44
#if 0
 
45
static char sccsid[] = "@(#)cmds.c      8.2 (Berkeley) 4/28/95";
 
46
#else
 
47
static char rcsid[] = "$OpenBSD: cmds.c,v 1.9 1997/07/25 18:57:24 grr Exp $";
 
48
#endif
 
49
#endif /* not lint */
 
50
 
 
51
/*
 
52
 * lpc -- line printer control program -- commands:
 
53
 */
 
54
 
 
55
#include <sys/param.h>
 
56
#include <sys/time.h>
 
57
#include <sys/stat.h>
 
58
#include <sys/file.h>
 
59
 
 
60
#include <signal.h>
 
61
#include <fcntl.h>
 
62
#include <errno.h>
 
63
#include <dirent.h>
 
64
#include <unistd.h>
 
65
#include <stdlib.h>
 
66
#include <stdio.h>
 
67
#include <ctype.h>
 
68
#include <string.h>
 
69
#include "lp.h"
 
70
#include "lp.local.h"
 
71
#include "lpc.h"
 
72
#include "extern.h"
 
73
#include "pathnames.h"
 
74
 
 
75
extern uid_t    uid, euid;
 
76
 
 
77
static void     abortpr __P((int));
 
78
static void     cleanpr __P((void));
 
79
static void     disablepr __P((void));
 
80
static int      doarg __P((char *));
 
81
static int      doselect __P((struct dirent *));
 
82
static void     enablepr __P((void));
 
83
static void     prstat __P((void));
 
84
static void     putmsg __P((int, char **));
 
85
static int      sortq __P((const void *, const void *));
 
86
static void     startpr __P((int));
 
87
static void     stoppr __P((void));
 
88
static int      touch __P((struct queue *));
 
89
static void     unlinkf __P((char *));
 
90
static void     upstat __P((char *));
 
91
 
 
92
/*
 
93
 * kill an existing daemon and disable printing.
 
94
 */
 
95
void
 
96
doabort(argc, argv)
 
97
        int argc;
 
98
        char *argv[];
 
99
{
 
100
        register int c, status;
 
101
        register char *cp1, *cp2;
 
102
        char prbuf[100];
 
103
 
 
104
        if (argc == 1) {
 
105
                printf("Usage: abort {all | printer ...}\n");
 
106
                return;
 
107
        }
 
108
        if (argc == 2 && !strcmp(argv[1], "all")) {
 
109
                printer = prbuf;
 
110
                while (cgetnext(&bp, printcapdb) > 0) {
 
111
                        cp1 = prbuf;
 
112
                        cp2 = bp;
 
113
                        while ((c = *cp2++) && c != '|' && c != ':' &&
 
114
                            (cp1 - prbuf) < sizeof(prbuf))
 
115
                                *cp1++ = c;
 
116
                        *cp1 = '\0';
 
117
                        abortpr(1);
 
118
                }
 
119
                return;
 
120
        }
 
121
        while (--argc) {
 
122
                printer = *++argv;
 
123
                if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
 
124
                        printf("cannot open printer description file\n");
 
125
                        continue;
 
126
                } else if (status == -1) {
 
127
                        printf("unknown printer %s\n", printer);
 
128
                        continue;
 
129
                } else if (status == -3)
 
130
                        fatal("potential reference loop detected in printcap file");
 
131
                abortpr(1);
 
132
        }
 
133
}
 
134
 
 
135
static void
 
136
abortpr(dis)
 
137
        int dis;
 
138
{
 
139
        register FILE *fp;
 
140
        struct stat stbuf;
 
141
        int pid, fd;
 
142
 
 
143
        if (cgetstr(bp, "sd", &SD) == -1)
 
144
                SD = _PATH_DEFSPOOL;
 
145
        if (cgetstr(bp, "lo", &LO) == -1)
 
146
                LO = DEFLOCK;
 
147
        (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
 
148
        printf("%s:\n", printer);
 
149
 
 
150
        /*
 
151
         * Turn on the owner execute bit of the lock file to disable printing.
 
152
         */
 
153
        if (dis) {
 
154
                seteuid(euid);
 
155
                if (stat(line, &stbuf) >= 0) {
 
156
                        if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
 
157
                                printf("\tcannot disable printing\n");
 
158
                        else {
 
159
                                upstat("printing disabled\n");
 
160
                                printf("\tprinting disabled\n");
 
161
                        }
 
162
                } else if (errno == ENOENT) {
 
163
                        if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
 
164
                                printf("\tcannot create lock file\n");
 
165
                        else {
 
166
                                (void) close(fd);
 
167
                                upstat("printing disabled\n");
 
168
                                printf("\tprinting disabled\n");
 
169
                                printf("\tno daemon to abort\n");
 
170
                        }
 
171
                        goto out;
 
172
                } else {
 
173
                        printf("\tcannot stat lock file\n");
 
174
                        goto out;
 
175
                }
 
176
        }
 
177
        /*
 
178
         * Kill the current daemon to stop printing now.
 
179
         */
 
180
        if ((fp = fopen(line, "r")) == NULL) {
 
181
                printf("\tcannot open lock file\n");
 
182
                goto out;
 
183
        }
 
184
        if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) {
 
185
                (void) fclose(fp);      /* unlocks as well */
 
186
                printf("\tno daemon to abort\n");
 
187
                goto out;
 
188
        }
 
189
        (void) fclose(fp);
 
190
        if (kill(pid = atoi(line), SIGTERM) < 0) {
 
191
                if (errno == ESRCH)
 
192
                        printf("\tno daemon to abort\n");
 
193
                else
 
194
                        printf("\tWarning: daemon (pid %d) not killed\n", pid);
 
195
        } else
 
196
                printf("\tdaemon (pid %d) killed\n", pid);
 
197
out:
 
198
        seteuid(uid);
 
199
}
 
200
 
 
201
/*
 
202
 * Write a message into the status file.
 
203
 */
 
204
static void
 
205
upstat(msg)
 
206
        char *msg;
 
207
{
 
208
        register int fd;
 
209
        char statfile[MAXPATHLEN];
 
210
 
 
211
        if (cgetstr(bp, "st", &ST) == -1)
 
212
                ST = DEFSTAT;
 
213
        (void) snprintf(statfile, sizeof(statfile), "%s/%s", SD, ST);
 
214
        umask(0);
 
215
        fd = open(statfile, O_WRONLY|O_CREAT, 0664);
 
216
        if (fd < 0 || flock(fd, LOCK_EX) < 0) {
 
217
                printf("\tcannot create status file\n");
 
218
                return;
 
219
        }
 
220
        (void) ftruncate(fd, 0);
 
221
        if (msg == (char *)NULL)
 
222
                (void) write(fd, "\n", 1);
 
223
        else
 
224
                (void) write(fd, msg, strlen(msg));
 
225
        (void) close(fd);
 
226
}
 
227
 
 
228
/*
 
229
 * Remove all spool files and temporaries from the spooling area.
 
230
 */
 
231
void
 
232
clean(argc, argv)
 
233
        int argc;
 
234
        char *argv[];
 
235
{
 
236
        register int c, status;
 
237
        register char *cp1, *cp2;
 
238
        char prbuf[100];
 
239
 
 
240
        if (argc == 1) {
 
241
                printf("Usage: clean {all | printer ...}\n");
 
242
                return;
 
243
        }
 
244
        if (argc == 2 && !strcmp(argv[1], "all")) {
 
245
                printer = prbuf;
 
246
                while (cgetnext(&bp, printcapdb) > 0) {
 
247
                        cp1 = prbuf;
 
248
                        cp2 = bp;
 
249
                        while ((c = *cp2++) && c != '|' && c != ':' &&
 
250
                            (cp1 - prbuf) < sizeof(prbuf))
 
251
                                *cp1++ = c;
 
252
                        *cp1 = '\0';
 
253
                        cleanpr();
 
254
                }
 
255
                return;
 
256
        }
 
257
        while (--argc) {
 
258
                printer = *++argv;
 
259
                if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
 
260
                        printf("cannot open printer description file\n");
 
261
                        continue;
 
262
                } else if (status == -1) {
 
263
                        printf("unknown printer %s\n", printer);
 
264
                        continue;
 
265
                } else if (status == -3)
 
266
                        fatal("potential reference loop detected in printcap file");
 
267
 
 
268
                cleanpr();
 
269
        }
 
270
}
 
271
 
 
272
static int
 
273
doselect(d)
 
274
        struct dirent *d;
 
275
{
 
276
        int c = d->d_name[0];
 
277
 
 
278
        if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f')
 
279
                return(1);
 
280
        return(0);
 
281
}
 
282
 
 
283
/*
 
284
 * Comparison routine for scandir. Sort by job number and machine, then
 
285
 * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z.
 
286
 */
 
287
static int
 
288
sortq(a, b)
 
289
        const void *a, *b;
 
290
{
 
291
        struct dirent **d1, **d2;
 
292
        int c1, c2;
 
293
 
 
294
        d1 = (struct dirent **)a;
 
295
        d2 = (struct dirent **)b;
 
296
        if ((c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)))
 
297
                return(c1);
 
298
        c1 = (*d1)->d_name[0];
 
299
        c2 = (*d2)->d_name[0];
 
300
        if (c1 == c2)
 
301
                return((*d1)->d_name[2] - (*d2)->d_name[2]);
 
302
        if (c1 == 'c')
 
303
                return(-1);
 
304
        if (c1 == 'd' || c2 == 'c')
 
305
                return(1);
 
306
        return(-1);
 
307
}
 
308
 
 
309
/*
 
310
 * Remove incomplete jobs from spooling area.
 
311
 */
 
312
static void
 
313
cleanpr()
 
314
{
 
315
        register int i, n;
 
316
        register char *cp, *cp1, *lp;
 
317
        struct dirent **queue;
 
318
        int nitems;
 
319
 
 
320
        if (cgetstr(bp, "sd", &SD) == -1)
 
321
                SD = _PATH_DEFSPOOL;
 
322
        printf("%s:\n", printer);
 
323
 
 
324
        for (lp = line, cp = SD; (lp - line) < sizeof(line) && (*lp++ = *cp++);)
 
325
                ;
 
326
        lp[-1] = '/';
 
327
 
 
328
        seteuid(euid);
 
329
        nitems = scandir(SD, &queue, doselect, sortq);
 
330
        seteuid(uid);
 
331
        if (nitems < 0) {
 
332
                printf("\tcannot examine spool directory\n");
 
333
                return;
 
334
        }
 
335
        if (nitems == 0)
 
336
                return;
 
337
        i = 0;
 
338
        do {
 
339
                cp = queue[i]->d_name;
 
340
                if (*cp == 'c') {
 
341
                        n = 0;
 
342
                        while (i + 1 < nitems) {
 
343
                                cp1 = queue[i + 1]->d_name;
 
344
                                if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3))
 
345
                                        break;
 
346
                                i++;
 
347
                                n++;
 
348
                        }
 
349
                        if (n == 0) {
 
350
                                strncpy(lp, cp, sizeof(line) - strlen(line) - 1);
 
351
                                line[sizeof(line) - 1] = '\0';
 
352
                                unlinkf(line);
 
353
                        }
 
354
                } else {
 
355
                        /*
 
356
                         * Must be a df with no cf (otherwise, it would have
 
357
                         * been skipped above) or a tf file (which can always
 
358
                         * be removed).
 
359
                         */
 
360
                        strncpy(lp, cp, sizeof(line) - strlen(line) - 1);
 
361
                        line[sizeof(line) - 1] = '\0';
 
362
                        unlinkf(line);
 
363
                }
 
364
        } while (++i < nitems);
 
365
}
 
366
 
 
367
static void
 
368
unlinkf(name)
 
369
        char    *name;
 
370
{
 
371
        seteuid(euid);
 
372
        if (unlink(name) < 0)
 
373
                printf("\tcannot remove %s\n", name);
 
374
        else
 
375
                printf("\tremoved %s\n", name);
 
376
        seteuid(uid);
 
377
}
 
378
 
 
379
/*
 
380
 * Enable queuing to the printer (allow lpr's).
 
381
 */
 
382
void
 
383
enable(argc, argv)
 
384
        int argc;
 
385
        char *argv[];
 
386
{
 
387
        register int c, status;
 
388
        register char *cp1, *cp2;
 
389
        char prbuf[100];
 
390
 
 
391
        if (argc == 1) {
 
392
                printf("Usage: enable {all | printer ...}\n");
 
393
                return;
 
394
        }
 
395
        if (argc == 2 && !strcmp(argv[1], "all")) {
 
396
                printer = prbuf;
 
397
                while (cgetnext(&bp, printcapdb) > 0) {
 
398
                        cp1 = prbuf;
 
399
                        cp2 = bp;
 
400
                        while ((c = *cp2++) && c != '|' && c != ':' &&
 
401
                            (cp1 - prbuf) < sizeof(prbuf))
 
402
                                *cp1++ = c;
 
403
                        *cp1 = '\0';
 
404
                        enablepr();
 
405
                }
 
406
                return;
 
407
        }
 
408
        while (--argc) {
 
409
                printer = *++argv;
 
410
                if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
 
411
                        printf("cannot open printer description file\n");
 
412
                        continue;
 
413
                } else if (status == -1) {
 
414
                        printf("unknown printer %s\n", printer);
 
415
                        continue;
 
416
                } else if (status == -3)
 
417
                        fatal("potential reference loop detected in printcap file");
 
418
 
 
419
                enablepr();
 
420
        }
 
421
}
 
422
 
 
423
static void
 
424
enablepr()
 
425
{
 
426
        struct stat stbuf;
 
427
 
 
428
        if (cgetstr(bp, "sd", &SD) == -1)
 
429
                SD = _PATH_DEFSPOOL;
 
430
        if (cgetstr(bp, "lo", &LO) == -1)
 
431
                LO = DEFLOCK;
 
432
        (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
 
433
        printf("%s:\n", printer);
 
434
 
 
435
        /*
 
436
         * Turn off the group execute bit of the lock file to enable queuing.
 
437
         */
 
438
        seteuid(euid);
 
439
        if (stat(line, &stbuf) >= 0) {
 
440
                if (chmod(line, stbuf.st_mode & 0767) < 0)
 
441
                        printf("\tcannot enable queuing\n");
 
442
                else
 
443
                        printf("\tqueuing enabled\n");
 
444
        }
 
445
        seteuid(uid);
 
446
}
 
447
 
 
448
/*
 
449
 * Disable queuing.
 
450
 */
 
451
void
 
452
disable(argc, argv)
 
453
        int argc;
 
454
        char *argv[];
 
455
{
 
456
        register int c, status;
 
457
        register char *cp1, *cp2;
 
458
        char prbuf[100];
 
459
 
 
460
        if (argc == 1) {
 
461
                printf("Usage: disable {all | printer ...}\n");
 
462
                return;
 
463
        }
 
464
        if (argc == 2 && !strcmp(argv[1], "all")) {
 
465
                printer = prbuf;
 
466
                while (cgetnext(&bp, printcapdb) > 0) {
 
467
                        cp1 = prbuf;
 
468
                        cp2 = bp;
 
469
                        while ((c = *cp2++) && c != '|' && c != ':' &&
 
470
                            (cp1 - prbuf) < sizeof(prbuf))
 
471
                                *cp1++ = c;
 
472
                        *cp1 = '\0';
 
473
                        disablepr();
 
474
                }
 
475
                return;
 
476
        }
 
477
        while (--argc) {
 
478
                printer = *++argv;
 
479
                if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
 
480
                        printf("cannot open printer description file\n");
 
481
                        continue;
 
482
                } else if (status == -1) {
 
483
                        printf("unknown printer %s\n", printer);
 
484
                        continue;
 
485
                } else if (status == -3)
 
486
                        fatal("potential reference loop detected in printcap file");
 
487
 
 
488
                disablepr();
 
489
        }
 
490
}
 
491
 
 
492
static void
 
493
disablepr()
 
494
{
 
495
        register int fd;
 
496
        struct stat stbuf;
 
497
 
 
498
        if (cgetstr(bp, "sd", &SD) == -1)
 
499
                SD = _PATH_DEFSPOOL;
 
500
        if (cgetstr(bp, "lo", &LO) == -1)
 
501
                LO = DEFLOCK;
 
502
        (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
 
503
        printf("%s:\n", printer);
 
504
        /*
 
505
         * Turn on the group execute bit of the lock file to disable queuing.
 
506
         */
 
507
        seteuid(euid);
 
508
        if (stat(line, &stbuf) >= 0) {
 
509
                if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
 
510
                        printf("\tcannot disable queuing\n");
 
511
                else
 
512
                        printf("\tqueuing disabled\n");
 
513
        } else if (errno == ENOENT) {
 
514
                if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0)
 
515
                        printf("\tcannot create lock file\n");
 
516
                else {
 
517
                        (void) close(fd);
 
518
                        printf("\tqueuing disabled\n");
 
519
                }
 
520
        } else
 
521
                printf("\tcannot stat lock file\n");
 
522
        seteuid(uid);
 
523
}
 
524
 
 
525
/*
 
526
 * Disable queuing and printing and put a message into the status file
 
527
 * (reason for being down).
 
528
 */
 
529
void
 
530
down(argc, argv)
 
531
        int argc;
 
532
        char *argv[];
 
533
{
 
534
        register int c, status;
 
535
        register char *cp1, *cp2;
 
536
        char prbuf[100];
 
537
 
 
538
        if (argc == 1) {
 
539
                printf("Usage: down {all | printer} [message ...]\n");
 
540
                return;
 
541
        }
 
542
        if (!strcmp(argv[1], "all")) {
 
543
                printer = prbuf;
 
544
                while (cgetnext(&bp, printcapdb) > 0) {
 
545
                        cp1 = prbuf;
 
546
                        cp2 = bp;
 
547
                        while ((c = *cp2++) && c != '|' && c != ':' &&
 
548
                            (cp1 - prbuf) < sizeof(prbuf))
 
549
                                *cp1++ = c;
 
550
                        *cp1 = '\0';
 
551
                        putmsg(argc - 2, argv + 2);
 
552
                }
 
553
                return;
 
554
        }
 
555
        printer = argv[1];
 
556
        if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
 
557
                printf("cannot open printer description file\n");
 
558
                return;
 
559
        } else if (status == -1) {
 
560
                printf("unknown printer %s\n", printer);
 
561
                return;
 
562
        } else if (status == -3)
 
563
                        fatal("potential reference loop detected in printcap file");
 
564
 
 
565
        putmsg(argc - 2, argv + 2);
 
566
}
 
567
 
 
568
static void
 
569
putmsg(argc, argv)
 
570
        int argc;
 
571
        char **argv;
 
572
{
 
573
        register int fd;
 
574
        register char *cp1, *cp2;
 
575
        char buf[1024];
 
576
        struct stat stbuf;
 
577
 
 
578
        if (cgetstr(bp, "sd", &SD) == -1)
 
579
                SD = _PATH_DEFSPOOL;
 
580
        if (cgetstr(bp, "lo", &LO) == -1)
 
581
                LO = DEFLOCK;
 
582
        if (cgetstr(bp, "st", &ST) == -1)
 
583
                ST = DEFSTAT;
 
584
        printf("%s:\n", printer);
 
585
        /*
 
586
         * Turn on the group execute bit of the lock file to disable queuing and
 
587
         * turn on the owner execute bit of the lock file to disable printing.
 
588
         */
 
589
        (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
 
590
        seteuid(euid);
 
591
        if (stat(line, &stbuf) >= 0) {
 
592
                if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0)
 
593
                        printf("\tcannot disable queuing\n");
 
594
                else
 
595
                        printf("\tprinter and queuing disabled\n");
 
596
        } else if (errno == ENOENT) {
 
597
                if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0)
 
598
                        printf("\tcannot create lock file\n");
 
599
                else {
 
600
                        (void) close(fd);
 
601
                        printf("\tprinter and queuing disabled\n");
 
602
                }
 
603
                seteuid(uid);
 
604
                return;
 
605
        } else
 
606
                printf("\tcannot stat lock file\n");
 
607
        /*
 
608
         * Write the message into the status file.
 
609
         */
 
610
        (void) snprintf(line, sizeof(line), "%s/%s", SD, ST);
 
611
        fd = open(line, O_WRONLY|O_CREAT, 0664);
 
612
        if (fd < 0 || flock(fd, LOCK_EX) < 0) {
 
613
                printf("\tcannot create status file\n");
 
614
                seteuid(uid);
 
615
                return;
 
616
        }
 
617
        seteuid(uid);
 
618
        (void) ftruncate(fd, 0);
 
619
        if (argc <= 0) {
 
620
                (void) write(fd, "\n", 1);
 
621
                (void) close(fd);
 
622
                return;
 
623
        }
 
624
        cp1 = buf;
 
625
        while (--argc >= 0) {
 
626
                cp2 = *argv++;
 
627
                while ((cp1 - buf) < sizeof(buf) && (*cp1++ = *cp2++))
 
628
                        ;
 
629
                cp1[-1] = ' ';
 
630
        }
 
631
        cp1[-1] = '\n';
 
632
        *cp1 = '\0';
 
633
        (void) write(fd, buf, strlen(buf));
 
634
        (void) close(fd);
 
635
}
 
636
 
 
637
/*
 
638
 * Exit lpc
 
639
 */
 
640
void
 
641
quit(argc, argv)
 
642
        int argc;
 
643
        char *argv[];
 
644
{
 
645
        exit(0);
 
646
}
 
647
 
 
648
/*
 
649
 * Kill and restart the daemon.
 
650
 */
 
651
void
 
652
restart(argc, argv)
 
653
        int argc;
 
654
        char *argv[];
 
655
{
 
656
        register int c, status;
 
657
        register char *cp1, *cp2;
 
658
        char prbuf[100];
 
659
 
 
660
        if (argc == 1) {
 
661
                printf("Usage: restart {all | printer ...}\n");
 
662
                return;
 
663
        }
 
664
        if (argc == 2 && !strcmp(argv[1], "all")) {
 
665
                printer = prbuf;
 
666
                while (cgetnext(&bp, printcapdb) > 0) {
 
667
                        cp1 = prbuf;
 
668
                        cp2 = bp;
 
669
                        while ((c = *cp2++) && c != '|' && c != ':' &&
 
670
                            (cp1 - prbuf) < sizeof(prbuf))
 
671
                                *cp1++ = c;
 
672
                        *cp1 = '\0';
 
673
                        abortpr(0);
 
674
                        startpr(0);
 
675
                }
 
676
                return;
 
677
        }
 
678
        while (--argc) {
 
679
                printer = *++argv;
 
680
                if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
 
681
                        printf("cannot open printer description file\n");
 
682
                        continue;
 
683
                } else if (status == -1) {
 
684
                        printf("unknown printer %s\n", printer);
 
685
                        continue;
 
686
                } else if (status == -3)
 
687
                        fatal("potential reference loop detected in printcap file");
 
688
 
 
689
                abortpr(0);
 
690
                startpr(0);
 
691
        }
 
692
}
 
693
 
 
694
/*
 
695
 * Enable printing on the specified printer and startup the daemon.
 
696
 */
 
697
void
 
698
startcmd(argc, argv)
 
699
        int argc;
 
700
        char *argv[];
 
701
{
 
702
        register int c, status;
 
703
        register char *cp1, *cp2;
 
704
        char prbuf[100];
 
705
 
 
706
        if (argc == 1) {
 
707
                printf("Usage: start {all | printer ...}\n");
 
708
                return;
 
709
        }
 
710
        if (argc == 2 && !strcmp(argv[1], "all")) {
 
711
                printer = prbuf;
 
712
                while (cgetnext(&bp, printcapdb) > 0) {
 
713
                        cp1 = prbuf;
 
714
                        cp2 = bp;
 
715
                        while ((c = *cp2++) && c != '|' && c != ':' &&
 
716
                            (cp1 - prbuf) < sizeof(prbuf))
 
717
                                *cp1++ = c;
 
718
                        *cp1 = '\0';
 
719
                        startpr(1);
 
720
                }
 
721
                return;
 
722
        }
 
723
        while (--argc) {
 
724
                printer = *++argv;
 
725
                if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
 
726
                        printf("cannot open printer description file\n");
 
727
                        continue;
 
728
                } else if (status == -1) {
 
729
                        printf("unknown printer %s\n", printer);
 
730
                        continue;
 
731
                } else if (status == -3)
 
732
                        fatal("potential reference loop detected in printcap file");
 
733
 
 
734
                startpr(1);
 
735
        }
 
736
}
 
737
 
 
738
static void
 
739
startpr(enable)
 
740
        int enable;
 
741
{
 
742
        struct stat stbuf;
 
743
 
 
744
        if (cgetstr(bp, "sd", &SD) == -1)
 
745
                SD = _PATH_DEFSPOOL;
 
746
        if (cgetstr(bp, "lo", &LO) == -1)
 
747
                LO = DEFLOCK;
 
748
        (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
 
749
        printf("%s:\n", printer);
 
750
 
 
751
        /*
 
752
         * Turn off the owner execute bit of the lock file to enable printing.
 
753
         */
 
754
        seteuid(euid);
 
755
        if (enable && stat(line, &stbuf) >= 0) {
 
756
                if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0)
 
757
                        printf("\tcannot enable printing\n");
 
758
                else
 
759
                        printf("\tprinting enabled\n");
 
760
        }
 
761
        if (!startdaemon(printer))
 
762
                printf("\tcouldn't start daemon\n");
 
763
        else
 
764
                printf("\tdaemon started\n");
 
765
        seteuid(uid);
 
766
}
 
767
 
 
768
/*
 
769
 * Print the status of each queue listed or all the queues.
 
770
 */
 
771
void
 
772
status(argc, argv)
 
773
        int argc;
 
774
        char *argv[];
 
775
{
 
776
        register int c, status;
 
777
        register char *cp1, *cp2;
 
778
        char prbuf[100];
 
779
 
 
780
        if (argc == 1 || argc == 2 && !strcmp(argv[1], "all")) {
 
781
                printer = prbuf;
 
782
                while (cgetnext(&bp, printcapdb) > 0) {
 
783
                        cp1 = prbuf;
 
784
                        cp2 = bp;
 
785
                        while ((c = *cp2++) && c != '|' && c != ':' &&
 
786
                            (cp1 - prbuf) < sizeof(prbuf))
 
787
                                *cp1++ = c;
 
788
                        *cp1 = '\0';
 
789
                        prstat();
 
790
                }
 
791
                return;
 
792
        }
 
793
        while (--argc) {
 
794
                printer = *++argv;
 
795
                if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
 
796
                        printf("cannot open printer description file\n");
 
797
                        continue;
 
798
                } else if (status == -1) {
 
799
                        printf("unknown printer %s\n", printer);
 
800
                        continue;
 
801
                } else if (status == -3)
 
802
                        fatal("potential reference loop detected in printcap file");
 
803
 
 
804
                prstat();
 
805
        }
 
806
}
 
807
 
 
808
/*
 
809
 * Print the status of the printer queue.
 
810
 */
 
811
static void
 
812
prstat()
 
813
{
 
814
        struct stat stbuf;
 
815
        register int fd, i;
 
816
        register struct dirent *dp;
 
817
        DIR *dirp;
 
818
 
 
819
        if (cgetstr(bp, "sd", &SD) == -1)
 
820
                SD = _PATH_DEFSPOOL;
 
821
        if (cgetstr(bp, "lo", &LO) == -1)
 
822
                LO = DEFLOCK;
 
823
        if (cgetstr(bp, "st", &ST) == -1)
 
824
                ST = DEFSTAT;
 
825
        printf("%s:\n", printer);
 
826
        (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
 
827
        if (stat(line, &stbuf) >= 0) {
 
828
                printf("\tqueuing is %s\n",
 
829
                        (stbuf.st_mode & 010) ? "disabled" : "enabled");
 
830
                printf("\tprinting is %s\n",
 
831
                        (stbuf.st_mode & 0100) ? "disabled" : "enabled");
 
832
        } else {
 
833
                printf("\tqueuing is enabled\n");
 
834
                printf("\tprinting is enabled\n");
 
835
        }
 
836
        if ((dirp = opendir(SD)) == NULL) {
 
837
                printf("\tcannot examine spool directory\n");
 
838
                return;
 
839
        }
 
840
        i = 0;
 
841
        while ((dp = readdir(dirp)) != NULL) {
 
842
                if (*dp->d_name == 'c' && dp->d_name[1] == 'f')
 
843
                        i++;
 
844
        }
 
845
        closedir(dirp);
 
846
        if (i == 0)
 
847
                printf("\tno entries\n");
 
848
        else if (i == 1)
 
849
                printf("\t1 entry in spool area\n");
 
850
        else
 
851
                printf("\t%d entries in spool area\n", i);
 
852
        fd = open(line, O_RDONLY);
 
853
        if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
 
854
                (void) close(fd);       /* unlocks as well */
 
855
                printf("\tprinter idle\n");
 
856
                return;
 
857
        }
 
858
        (void) close(fd);
 
859
        putchar('\t');
 
860
        (void) snprintf(line, sizeof(line), "%s/%s", SD, ST);
 
861
        fd = open(line, O_RDONLY);
 
862
        if (fd >= 0) {
 
863
                (void) flock(fd, LOCK_SH);
 
864
                while ((i = read(fd, line, sizeof(line))) > 0)
 
865
                        (void) fwrite(line, 1, i, stdout);
 
866
                (void) close(fd);       /* unlocks as well */
 
867
        }
 
868
}
 
869
 
 
870
/*
 
871
 * Stop the specified daemon after completing the current job and disable
 
872
 * printing.
 
873
 */
 
874
void
 
875
stop(argc, argv)
 
876
        int argc;
 
877
        char *argv[];
 
878
{
 
879
        register int c, status;
 
880
        register char *cp1, *cp2;
 
881
        char prbuf[100];
 
882
 
 
883
        if (argc == 1) {
 
884
                printf("Usage: stop {all | printer ...}\n");
 
885
                return;
 
886
        }
 
887
        if (argc == 2 && !strcmp(argv[1], "all")) {
 
888
                printer = prbuf;
 
889
                while (cgetnext(&bp, printcapdb) > 0) {
 
890
                        cp1 = prbuf;
 
891
                        cp2 = bp;
 
892
                        while ((c = *cp2++) && c != '|' && c != ':' &&
 
893
                            (cp1 - prbuf) < sizeof(prbuf))
 
894
                                *cp1++ = c;
 
895
                        *cp1 = '\0';
 
896
                        stoppr();
 
897
                }
 
898
                return;
 
899
        }
 
900
        while (--argc) {
 
901
                printer = *++argv;
 
902
                if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
 
903
                        printf("cannot open printer description file\n");
 
904
                        continue;
 
905
                } else if (status == -1) {
 
906
                        printf("unknown printer %s\n", printer);
 
907
                        continue;
 
908
                } else if (status == -3)
 
909
                        fatal("potential reference loop detected in printcap file");
 
910
 
 
911
                stoppr();
 
912
        }
 
913
}
 
914
 
 
915
static void
 
916
stoppr()
 
917
{
 
918
        register int fd;
 
919
        struct stat stbuf;
 
920
 
 
921
        if (cgetstr(bp, "sd", &SD) == -1)
 
922
                SD = _PATH_DEFSPOOL;
 
923
        if (cgetstr(bp, "lo", &LO) == -1)
 
924
                LO = DEFLOCK;
 
925
        (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
 
926
        printf("%s:\n", printer);
 
927
 
 
928
        /*
 
929
         * Turn on the owner execute bit of the lock file to disable printing.
 
930
         */
 
931
        seteuid(euid);
 
932
        if (stat(line, &stbuf) >= 0) {
 
933
                if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
 
934
                        printf("\tcannot disable printing\n");
 
935
                else {
 
936
                        upstat("printing disabled\n");
 
937
                        printf("\tprinting disabled\n");
 
938
                }
 
939
        } else if (errno == ENOENT) {
 
940
                if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
 
941
                        printf("\tcannot create lock file\n");
 
942
                else {
 
943
                        (void) close(fd);
 
944
                        upstat("printing disabled\n");
 
945
                        printf("\tprinting disabled\n");
 
946
                }
 
947
        } else
 
948
                printf("\tcannot stat lock file\n");
 
949
        seteuid(uid);
 
950
}
 
951
 
 
952
struct  queue **queue;
 
953
int     nitems;
 
954
time_t  mtime;
 
955
 
 
956
/*
 
957
 * Put the specified jobs at the top of printer queue.
 
958
 */
 
959
void
 
960
topq(argc, argv)
 
961
        int argc;
 
962
        char *argv[];
 
963
{
 
964
        register int i;
 
965
        struct stat stbuf;
 
966
        int status, changed;
 
967
 
 
968
        if (argc < 3) {
 
969
                printf("Usage: topq printer [jobnum ...] [user ...]\n");
 
970
                return;
 
971
        }
 
972
 
 
973
        --argc;
 
974
        printer = *++argv;
 
975
        status = cgetent(&bp, printcapdb, printer);
 
976
        if (status == -2) {
 
977
                printf("cannot open printer description file\n");
 
978
                return;
 
979
        } else if (status == -1) {
 
980
                printf("%s: unknown printer\n", printer);
 
981
                return;
 
982
        } else if (status == -3)
 
983
                fatal("potential reference loop detected in printcap file");
 
984
 
 
985
        if (cgetstr(bp, "sd", &SD) == -1)
 
986
                SD = _PATH_DEFSPOOL;
 
987
        if (cgetstr(bp, "lo", &LO) == -1)
 
988
                LO = DEFLOCK;
 
989
        printf("%s:\n", printer);
 
990
 
 
991
        seteuid(euid);
 
992
        if (chdir(SD) < 0) {
 
993
                printf("\tcannot chdir to %s\n", SD);
 
994
                goto out;
 
995
        }
 
996
        seteuid(uid);
 
997
        nitems = getq(&queue);
 
998
        if (nitems == 0)
 
999
                return;
 
1000
        changed = 0;
 
1001
        mtime = queue[0]->q_time;
 
1002
        for (i = argc; --i; ) {
 
1003
                if (doarg(argv[i]) == 0) {
 
1004
                        printf("\tjob %s is not in the queue\n", argv[i]);
 
1005
                        continue;
 
1006
                } else
 
1007
                        changed++;
 
1008
        }
 
1009
        for (i = 0; i < nitems; i++)
 
1010
                free(queue[i]);
 
1011
        free(queue);
 
1012
        if (!changed) {
 
1013
                printf("\tqueue order unchanged\n");
 
1014
                return;
 
1015
        }
 
1016
        /*
 
1017
         * Turn on the public execute bit of the lock file to
 
1018
         * get lpd to rebuild the queue after the current job.
 
1019
         */
 
1020
        seteuid(euid);
 
1021
        if (changed && stat(LO, &stbuf) >= 0)
 
1022
                (void) chmod(LO, (stbuf.st_mode & 0777) | 01);
 
1023
 
 
1024
out:
 
1025
        seteuid(uid);
 
1026
 
1027
 
 
1028
/*
 
1029
 * Reposition the job by changing the modification time of
 
1030
 * the control file.
 
1031
 */
 
1032
static int
 
1033
touch(q)
 
1034
        struct queue *q;
 
1035
{
 
1036
        struct timeval tvp[2];
 
1037
        int ret;
 
1038
 
 
1039
        tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
 
1040
        tvp[0].tv_usec = tvp[1].tv_usec = 0;
 
1041
        seteuid(euid);
 
1042
        ret = utimes(q->q_name, tvp);
 
1043
        seteuid(uid);
 
1044
        return (ret);
 
1045
}
 
1046
 
 
1047
/*
 
1048
 * Checks if specified job name is in the printer's queue.
 
1049
 * Returns:  negative (-1) if argument name is not in the queue.
 
1050
 */
 
1051
static int
 
1052
doarg(job)
 
1053
        char *job;
 
1054
{
 
1055
        register struct queue **qq;
 
1056
        register int jobnum, n;
 
1057
        register char *cp, *machine;
 
1058
        int cnt = 0;
 
1059
        FILE *fp;
 
1060
 
 
1061
        /*
 
1062
         * Look for a job item consisting of system name, colon, number 
 
1063
         * (example: ucbarpa:114)  
 
1064
         */
 
1065
        if ((cp = strchr(job, ':')) != NULL) {
 
1066
                machine = job;
 
1067
                *cp++ = '\0';
 
1068
                job = cp;
 
1069
        } else
 
1070
                machine = NULL;
 
1071
 
 
1072
        /*
 
1073
         * Check for job specified by number (example: 112 or 235ucbarpa).
 
1074
         */
 
1075
        if (isdigit(*job)) {
 
1076
                jobnum = 0;
 
1077
                do
 
1078
                        jobnum = jobnum * 10 + (*job++ - '0');
 
1079
                while (isdigit(*job));
 
1080
                for (qq = queue + nitems; --qq >= queue; ) {
 
1081
                        n = 0;
 
1082
                        for (cp = (*qq)->q_name+3; isdigit(*cp); )
 
1083
                                n = n * 10 + (*cp++ - '0');
 
1084
                        if (jobnum != n)
 
1085
                                continue;
 
1086
                        if (*job && strcmp(job, cp) != 0)
 
1087
                                continue;
 
1088
                        if (machine != NULL && strcmp(machine, cp) != 0)
 
1089
                                continue;
 
1090
                        if (touch(*qq) == 0) {
 
1091
                                printf("\tmoved %s\n", (*qq)->q_name);
 
1092
                                cnt++;
 
1093
                        }
 
1094
                }
 
1095
                return(cnt);
 
1096
        }
 
1097
        /*
 
1098
         * Process item consisting of owner's name (example: henry).
 
1099
         */
 
1100
        for (qq = queue + nitems; --qq >= queue; ) {
 
1101
                seteuid(euid);
 
1102
                fp = fopen((*qq)->q_name, "r");
 
1103
                seteuid(uid);
 
1104
                if (fp == NULL)
 
1105
                        continue;
 
1106
                while (getline(fp) > 0)
 
1107
                        if (line[0] == 'P')
 
1108
                                break;
 
1109
                (void) fclose(fp);
 
1110
                if (line[0] != 'P' || strcmp(job, line+1) != 0)
 
1111
                        continue;
 
1112
                if (touch(*qq) == 0) {
 
1113
                        printf("\tmoved %s\n", (*qq)->q_name);
 
1114
                        cnt++;
 
1115
                }
 
1116
        }
 
1117
        return(cnt);
 
1118
}
 
1119
 
 
1120
/*
 
1121
 * Enable everything and start printer (undo `down').
 
1122
 */
 
1123
void
 
1124
up(argc, argv)
 
1125
        int argc;
 
1126
        char *argv[];
 
1127
{
 
1128
        register int c, status;
 
1129
        register char *cp1, *cp2;
 
1130
        char prbuf[100];
 
1131
 
 
1132
        if (argc == 1) {
 
1133
                printf("Usage: up {all | printer ...}\n");
 
1134
                return;
 
1135
        }
 
1136
        if (argc == 2 && !strcmp(argv[1], "all")) {
 
1137
                printer = prbuf;
 
1138
                while (cgetnext(&bp, printcapdb) > 0) {
 
1139
                        cp1 = prbuf;
 
1140
                        cp2 = bp;
 
1141
                        while ((c = *cp2++) && c != '|' && c != ':' &&
 
1142
                            (cp1 - prbuf) < sizeof(prbuf))
 
1143
                                *cp1++ = c;
 
1144
                        *cp1 = '\0';
 
1145
                        startpr(2);
 
1146
                }
 
1147
                return;
 
1148
        }
 
1149
        while (--argc) {
 
1150
                printer = *++argv;
 
1151
                if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
 
1152
                        printf("cannot open printer description file\n");
 
1153
                        continue;
 
1154
                } else if (status == -1) {
 
1155
                        printf("unknown printer %s\n", printer);
 
1156
                        continue;
 
1157
                } else if (status == -3)
 
1158
                        fatal("potential reference loop detected in printcap file");
 
1159
 
 
1160
                startpr(2);
 
1161
        }
 
1162
}