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

« back to all changes in this revision

Viewing changes to lpr/lpr.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: lpr.c,v 1.19 1997/07/25 20:12:13 mickey Exp $ */
 
2
/*      $NetBSD: lpr.c,v 1.10 1996/03/21 18:12:25 jtc Exp $     */
 
3
 
 
4
/*
 
5
 * Copyright (c) 1983, 1989, 1993
 
6
 *      The Regents of the University of California.  All rights reserved.
 
7
 * (c) UNIX System Laboratories, Inc.
 
8
 * All or some portions of this file are derived from material licensed
 
9
 * to the University of California by American Telephone and Telegraph
 
10
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 
11
 * the permission of UNIX System Laboratories, Inc.
 
12
 *
 
13
 *
 
14
 * Redistribution and use in source and binary forms, with or without
 
15
 * modification, are permitted provided that the following conditions
 
16
 * are met:
 
17
 * 1. Redistributions of source code must retain the above copyright
 
18
 *    notice, this list of conditions and the following disclaimer.
 
19
 * 2. Redistributions in binary form must reproduce the above copyright
 
20
 *    notice, this list of conditions and the following disclaimer in the
 
21
 *    documentation and/or other materials provided with the distribution.
 
22
 * 3. All advertising materials mentioning features or use of this software
 
23
 *    must display the following acknowledgement:
 
24
 *      This product includes software developed by the University of
 
25
 *      California, Berkeley and its contributors.
 
26
 * 4. Neither the name of the University nor the names of its contributors
 
27
 *    may be used to endorse or promote products derived from this software
 
28
 *    without specific prior written permission.
 
29
 *
 
30
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
31
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
32
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
33
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
34
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
35
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
36
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
37
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
38
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
39
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
40
 * SUCH DAMAGE.
 
41
 */
 
42
 
 
43
#ifndef lint
 
44
static char copyright[] =
 
45
"@(#) Copyright (c) 1983, 1989, 1993\n\
 
46
        The Regents of the University of California.  All rights reserved.\n";
 
47
#endif /* not lint */
 
48
 
 
49
#ifndef lint
 
50
#if 0
 
51
static char sccsid[] = "@(#)lpr.c       8.4 (Berkeley) 4/28/95";
 
52
#else
 
53
static char rcsid[] = "$OpenBSD: lpr.c,v 1.19 1997/07/25 20:12:13 mickey Exp $";
 
54
#endif
 
55
#endif /* not lint */
 
56
 
 
57
/*
 
58
 *      lpr -- off line print
 
59
 *
 
60
 * Allows multiple printers and printers on remote machines by
 
61
 * using information from a printer data base.
 
62
 */
 
63
 
 
64
#include <sys/param.h>
 
65
#include <sys/stat.h>
 
66
#include <sys/file.h>
 
67
 
 
68
#include <dirent.h>
 
69
#include <fcntl.h>
 
70
#include <a.out.h>
 
71
#include <signal.h>
 
72
#include <syslog.h>
 
73
#include <pwd.h>
 
74
#include <grp.h>
 
75
#include <unistd.h>
 
76
#include <stdlib.h>
 
77
#include <stdio.h>
 
78
#include <ctype.h>
 
79
#include <string.h>
 
80
#include "lp.h"
 
81
#include "lp.local.h"
 
82
#include "pathnames.h"
 
83
 
 
84
static char     *cfname;        /* daemon control files, linked from tf's */
 
85
static char     *class = host;  /* class title on header page */
 
86
static char     *dfname;        /* data files */
 
87
static char     *fonts[4];      /* troff font names */
 
88
static char      format = 'f';  /* format char for printing files */
 
89
static int       hdr = 1;       /* print header or not (default is yes) */
 
90
static int       iflag;         /* indentation wanted */
 
91
static int       inchar;        /* location to increment char in file names */
 
92
static int       indent;        /* amount to indent */
 
93
static char     *jobname;       /* job name on header page */
 
94
static int       mailflg;       /* send mail */
 
95
static int       nact;          /* number of jobs to act on */
 
96
static int       ncopies = 1;   /* # of copies to make */
 
97
static char     *person;        /* user name */
 
98
static int       qflag;         /* q job, but don't exec daemon */
 
99
static int       rflag;         /* remove files upon completion */      
 
100
static int       sflag;         /* symbolic link flag */
 
101
static int       tfd;           /* control file descriptor */
 
102
static char     *tfname;        /* tmp copy of cf before linking */
 
103
static char     *title;         /* pr'ing title */
 
104
static int       userid;        /* user id */
 
105
static char     *width;         /* width for versatec printing */
 
106
 
 
107
static struct stat statb;
 
108
 
 
109
static void      card __P((int, char *));
 
110
static void      chkprinter __P((char *));
 
111
static void      cleanup __P((int));
 
112
static void      copy __P((int, char []));
 
113
static void      fatal2 __P((const char *, ...));
 
114
static char     *linked __P((char *));
 
115
static char     *lmktemp __P((char *, int, int));
 
116
static void      mktemps __P((void));
 
117
static int       nfile __P((char *));
 
118
static int       test __P((char *));
 
119
static char     *itoa __P((int));
 
120
 
 
121
uid_t   uid, euid;
 
122
 
 
123
int
 
124
main(argc, argv)
 
125
        int argc;
 
126
        char *argv[];
 
127
{
 
128
        struct passwd *pw;
 
129
        struct group *gptr;
 
130
        register char *arg, *cp;
 
131
        char buf[BUFSIZ];
 
132
        int i, f;
 
133
        struct stat stb;
 
134
 
 
135
        euid = geteuid();
 
136
        uid = getuid();
 
137
        seteuid(uid);
 
138
        if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
 
139
                signal(SIGHUP, cleanup);
 
140
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 
141
                signal(SIGINT, cleanup);
 
142
        if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
 
143
                signal(SIGQUIT, cleanup);
 
144
        if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
 
145
                signal(SIGTERM, cleanup);
 
146
 
 
147
        name = argv[0];
 
148
        gethostname(host, sizeof (host));
 
149
        openlog("lpd", 0, LOG_LPR);
 
150
 
 
151
        while (argc > 1 && argv[1][0] == '-') {
 
152
                argc--;
 
153
                arg = *++argv;
 
154
                switch (arg[1]) {
 
155
 
 
156
                case 'P':               /* specifiy printer name */
 
157
                        if (arg[2])
 
158
                                printer = &arg[2];
 
159
                        else if (argc > 1) {
 
160
                                argc--;
 
161
                                printer = *++argv;
 
162
                        }
 
163
                        break;
 
164
 
 
165
                case 'C':               /* classification spec */
 
166
                        hdr++;
 
167
                        if (arg[2])
 
168
                                class = &arg[2];
 
169
                        else if (argc > 1) {
 
170
                                argc--;
 
171
                                class = *++argv;
 
172
                        }
 
173
                        break;
 
174
 
 
175
                case 'U':               /* user name */
 
176
                        hdr++;
 
177
                        if (arg[2])
 
178
                                person = &arg[2];
 
179
                        else if (argc > 1) {
 
180
                                argc--;
 
181
                                person = *++argv;
 
182
                        }
 
183
                        break;
 
184
 
 
185
                case 'J':               /* job name */
 
186
                        hdr++;
 
187
                        if (arg[2])
 
188
                                jobname = &arg[2];
 
189
                        else if (argc > 1) {
 
190
                                argc--;
 
191
                                jobname = *++argv;
 
192
                        }
 
193
                        break;
 
194
 
 
195
                case 'T':               /* pr's title line */
 
196
                        if (arg[2])
 
197
                                title = &arg[2];
 
198
                        else if (argc > 1) {
 
199
                                argc--;
 
200
                                title = *++argv;
 
201
                        }
 
202
                        break;
 
203
 
 
204
                case 'l':               /* literal output */
 
205
                case 'p':               /* print using ``pr'' */
 
206
                case 't':               /* print troff output (cat files) */
 
207
                case 'n':               /* print ditroff output */
 
208
                case 'd':               /* print tex output (dvi files) */
 
209
                case 'g':               /* print graph(1G) output */
 
210
                case 'c':               /* print cifplot output */
 
211
                case 'v':               /* print vplot output */
 
212
                        format = arg[1];
 
213
                        break;
 
214
 
 
215
                case 'f':               /* print fortran output */
 
216
                        format = 'r';
 
217
                        break;
 
218
 
 
219
                case '4':               /* troff fonts */
 
220
                case '3':
 
221
                case '2':
 
222
                case '1':
 
223
                        if (argc > 1) {
 
224
                                argc--;
 
225
                                fonts[arg[1] - '1'] = *++argv;
 
226
                        }
 
227
                        break;
 
228
 
 
229
                case 'w':               /* versatec page width */
 
230
                        width = arg+2;
 
231
                        break;
 
232
 
 
233
                case 'r':               /* remove file when done */
 
234
                        rflag++;
 
235
                        break;
 
236
 
 
237
                case 'm':               /* send mail when done */
 
238
                        mailflg++;
 
239
                        break;
 
240
 
 
241
                case 'h':               /* toggle want of header page */
 
242
                        hdr = !hdr;
 
243
                        break;
 
244
 
 
245
                case 's':               /* try to link files */
 
246
                        sflag++;
 
247
                        break;
 
248
 
 
249
                case 'q':               /* just q job */
 
250
                        qflag++;
 
251
                        break;
 
252
 
 
253
                case 'i':               /* indent output */
 
254
                        iflag++;
 
255
                        indent = arg[2] ? atoi(&arg[2]) : 8;
 
256
                        break;
 
257
 
 
258
                case '#':               /* n copies */
 
259
                        if (isdigit(arg[2])) {
 
260
                                i = atoi(&arg[2]);
 
261
                                if (i > 0)
 
262
                                        ncopies = i;
 
263
                        }
 
264
                }
 
265
        }
 
266
 
 
267
        if (printer == NULL) {
 
268
                char *p;
 
269
 
 
270
                printer = DEFLP;
 
271
                if ((p = getenv("PRINTER")) != NULL)
 
272
                        printer = p;
 
273
        }
 
274
        chkprinter(printer);
 
275
        if (SC && ncopies > 1)
 
276
                fatal2("multiple copies are not allowed");
 
277
        if (MC > 0 && ncopies > MC)
 
278
                fatal2("only %d copies are allowed", MC);
 
279
        /*
 
280
         * Get the identity of the person doing the lpr using the same
 
281
         * algorithm as lprm. 
 
282
         */
 
283
        userid = getuid();
 
284
        if (userid != DU || person == 0) {
 
285
                if ((pw = getpwuid(userid)) == NULL)
 
286
                        fatal2("Who are you?");
 
287
                person = pw->pw_name;
 
288
        }
 
289
        /*
 
290
         * Check for restricted group access.
 
291
         */
 
292
        if (RG != NULL && userid != DU) {
 
293
                if ((gptr = getgrnam(RG)) == NULL)
 
294
                        fatal2("Restricted group specified incorrectly");
 
295
                if (gptr->gr_gid != getgid()) {
 
296
                        while (*gptr->gr_mem != NULL) {
 
297
                                if ((strcmp(person, *gptr->gr_mem)) == 0)
 
298
                                        break;
 
299
                                gptr->gr_mem++;
 
300
                        }
 
301
                        if (*gptr->gr_mem == NULL)
 
302
                                fatal2("Not a member of the restricted group");
 
303
                }
 
304
        }
 
305
        /*
 
306
         * Check to make sure queuing is enabled if userid is not root.
 
307
         */
 
308
        (void) snprintf(buf, sizeof(buf), "%s/%s", SD, LO);
 
309
        if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010))
 
310
                fatal2("Printer queue is disabled");
 
311
        /*
 
312
         * Initialize the control file.
 
313
         */
 
314
        mktemps();
 
315
        tfd = nfile(tfname);
 
316
        seteuid(euid);
 
317
        (void) fchown(tfd, DU, -1);     /* owned by daemon for protection */
 
318
        seteuid(uid);
 
319
        card('H', host);
 
320
        card('P', person);
 
321
        if (hdr) {
 
322
                if (jobname == NULL) {
 
323
                        if (argc == 1)
 
324
                                jobname = "stdin";
 
325
                        else
 
326
                                jobname = (arg = strrchr(argv[1], '/')) ? arg+1 : argv[1];
 
327
                }
 
328
                card('J', jobname);
 
329
                card('C', class);
 
330
                card('L', person);
 
331
        }
 
332
        if (iflag)
 
333
                card('I', itoa(indent));
 
334
        if (mailflg)
 
335
                card('M', person);
 
336
        if (format == 't' || format == 'n' || format == 'd')
 
337
                for (i = 0; i < 4; i++)
 
338
                        if (fonts[i] != NULL)
 
339
                                card('1'+i, fonts[i]);
 
340
        if (width != NULL)
 
341
                card('W', width);
 
342
 
 
343
        /*
 
344
         * Read the files and spool them.
 
345
         */
 
346
        if (argc == 1)
 
347
                copy(0, " ");
 
348
        else while (--argc) {
 
349
                if ((f = test(arg = *++argv)) < 0)
 
350
                        continue;       /* file unreasonable */
 
351
 
 
352
                if (sflag && (cp = linked(arg)) != NULL) {
 
353
                        (void) snprintf(buf, sizeof(buf), "%d %d", statb.st_dev,
 
354
                                        statb.st_ino);
 
355
                        card('S', buf);
 
356
                        if (format == 'p')
 
357
                                card('T', title ? title : arg);
 
358
                        for (i = 0; i < ncopies; i++)
 
359
                                card(format, &dfname[inchar-2]);
 
360
                        card('U', &dfname[inchar-2]);
 
361
                        if (f)
 
362
                                card('U', cp);
 
363
                        card('N', arg);
 
364
                        dfname[inchar]++;
 
365
                        nact++;
 
366
                        continue;
 
367
                }
 
368
                if (sflag)
 
369
                        printf("%s: %s: not linked, copying instead\n", name, arg);
 
370
                if ((i = open(arg, O_RDONLY)) < 0) {
 
371
                        printf("%s: cannot open %s\n", name, arg);
 
372
                } else {
 
373
                        copy(i, arg);
 
374
                        (void) close(i);
 
375
                        if (f && unlink(arg) < 0)
 
376
                                printf("%s: %s: not removed\n", name, arg);
 
377
                }
 
378
        }
 
379
 
 
380
        if (nact) {
 
381
                (void) close(tfd);
 
382
                tfname[inchar]--;
 
383
                /*
 
384
                 * Touch the control file to fix position in the queue.
 
385
                 */
 
386
                seteuid(euid);
 
387
                if ((tfd = open(tfname, O_RDWR)) >= 0) {
 
388
                        char c;
 
389
 
 
390
                        if (read(tfd, &c, 1) == 1 &&
 
391
                            lseek(tfd, (off_t)0, 0) == 0 &&
 
392
                            write(tfd, &c, 1) != 1) {
 
393
                                printf("%s: cannot touch %s\n", name, tfname);
 
394
                                tfname[inchar]++;
 
395
                                cleanup(0);
 
396
                        }
 
397
                        (void) close(tfd);
 
398
                }
 
399
                if (link(tfname, cfname) < 0) {
 
400
                        printf("%s: cannot rename %s\n", name, cfname);
 
401
                        tfname[inchar]++;
 
402
                        cleanup(0);
 
403
                }
 
404
                unlink(tfname);
 
405
                seteuid(uid);
 
406
                if (qflag)              /* just q things up */
 
407
                        exit(0);
 
408
                if (!startdaemon(printer))
 
409
                        printf("jobs queued, but cannot start daemon.\n");
 
410
                exit(0);
 
411
        }
 
412
        cleanup(0);
 
413
        return (1);
 
414
        /* NOTREACHED */
 
415
}
 
416
 
 
417
/*
 
418
 * Create the file n and copy from file descriptor f.
 
419
 */
 
420
static void
 
421
copy(f, n)
 
422
        int f;
 
423
        char n[];
 
424
{
 
425
        register int fd, i, nr, nc;
 
426
        char buf[BUFSIZ];
 
427
 
 
428
        if (format == 'p')
 
429
                card('T', title ? title : n);
 
430
        for (i = 0; i < ncopies; i++)
 
431
                card(format, &dfname[inchar-2]);
 
432
        card('U', &dfname[inchar-2]);
 
433
        card('N', n);
 
434
        fd = nfile(dfname);
 
435
        nr = nc = 0;
 
436
        while ((i = read(f, buf, BUFSIZ)) > 0) {
 
437
                if (write(fd, buf, i) != i) {
 
438
                        printf("%s: %s: temp file write error\n", name, n);
 
439
                        break;
 
440
                }
 
441
                nc += i;
 
442
                if (nc >= BUFSIZ) {
 
443
                        nc -= BUFSIZ;
 
444
                        nr++;
 
445
                        if (MX > 0 && nr > MX) {
 
446
                                printf("%s: %s: copy file is too large\n",
 
447
                                       name, n);
 
448
                                break;
 
449
                        }
 
450
                }
 
451
        }
 
452
        (void) close(fd);
 
453
        if (nc==0 && nr==0) 
 
454
                printf("%s: %s: empty input file\n", name, f ? n : "stdin");
 
455
        else
 
456
                nact++;
 
457
}
 
458
 
 
459
/*
 
460
 * Try and link the file to dfname. Return a pointer to the full
 
461
 * path name if successful.
 
462
 */
 
463
static char *
 
464
linked(file)
 
465
        register char *file;
 
466
{
 
467
        register char *cp;
 
468
        static char nfile[MAXPATHLEN];
 
469
        register int ret;
 
470
 
 
471
        if (*file != '/') {
 
472
                if (getcwd(nfile, sizeof(nfile)) == NULL)
 
473
                        return(NULL);
 
474
 
 
475
                while (file[0] == '.') {
 
476
                        switch (file[1]) {
 
477
                        case '/':
 
478
                                file += 2;
 
479
                                continue;
 
480
                        case '.':
 
481
                                if (file[2] == '/') {
 
482
                                        if ((cp = strrchr(nfile, '/')) != NULL)
 
483
                                                *cp = '\0';
 
484
                                        file += 3;
 
485
                                        continue;
 
486
                                }
 
487
                        }
 
488
                        break;
 
489
                }
 
490
                strncat(nfile, "/", sizeof(nfile) - strlen(nfile) - 1);
 
491
                strncat(nfile, file, sizeof(nfile) - strlen(nfile) - 1);
 
492
                file = nfile;
 
493
        }
 
494
        seteuid(euid);
 
495
        ret = symlink(file, dfname);
 
496
        seteuid(uid);
 
497
        return(ret ? NULL : file);
 
498
}
 
499
 
 
500
/*
 
501
 * Put a line into the control file.
 
502
 */
 
503
static void
 
504
card(c, p2)
 
505
        register int c;
 
506
        register char *p2;
 
507
{
 
508
        char buf[BUFSIZ];
 
509
        register char *p1 = buf;
 
510
        register int len = 2;
 
511
 
 
512
        *p1++ = c;
 
513
        while ((c = *p2++) != '\0' && len < sizeof(buf)) {
 
514
                *p1++ = (c == '\n') ? ' ' : c;
 
515
                len++;
 
516
        }
 
517
        *p1++ = '\n';
 
518
        write(tfd, buf, len);
 
519
}
 
520
 
 
521
/*
 
522
 * Create a new file in the spool directory.
 
523
 */
 
524
static int
 
525
nfile(n)
 
526
        char *n;
 
527
{
 
528
        register int f;
 
529
        int oldumask = umask(0);                /* should block signals */
 
530
 
 
531
        seteuid(euid);
 
532
        f = open(n, O_WRONLY | O_EXCL | O_CREAT, FILMOD);
 
533
        (void) umask(oldumask);
 
534
        if (f < 0) {
 
535
                printf("%s: cannot create %s\n", name, n);
 
536
                cleanup(0);
 
537
        }
 
538
        if (fchown(f, userid, -1) < 0) {
 
539
                printf("%s: cannot chown %s\n", name, n);
 
540
                cleanup(0);     /* cleanup does exit */
 
541
        }
 
542
        seteuid(uid);
 
543
        if (++n[inchar] > 'z') {
 
544
                if (++n[inchar-2] == 't') {
 
545
                        printf("too many files - break up the job\n");
 
546
                        cleanup(0);
 
547
                }
 
548
                n[inchar] = 'A';
 
549
        } else if (n[inchar] == '[')
 
550
                n[inchar] = 'a';
 
551
        return(f);
 
552
}
 
553
 
 
554
/*
 
555
 * Cleanup after interrupts and errors.
 
556
 */
 
557
static void
 
558
cleanup(signo)
 
559
        int signo;
 
560
{
 
561
        register i;
 
562
 
 
563
        signal(SIGHUP, SIG_IGN);
 
564
        signal(SIGINT, SIG_IGN);
 
565
        signal(SIGQUIT, SIG_IGN);
 
566
        signal(SIGTERM, SIG_IGN);
 
567
        i = inchar;
 
568
        seteuid(euid);
 
569
        if (tfname)
 
570
                do
 
571
                        unlink(tfname);
 
572
                while (tfname[i]-- != 'A');
 
573
        if (cfname)
 
574
                do
 
575
                        unlink(cfname);
 
576
                while (cfname[i]-- != 'A');
 
577
        if (dfname)
 
578
                do {
 
579
                        do
 
580
                                unlink(dfname);
 
581
                        while (dfname[i]-- != 'A');
 
582
                        dfname[i] = 'z';
 
583
                } while (dfname[i-2]-- != 'd');
 
584
        exit(1);
 
585
}
 
586
 
 
587
/*
 
588
 * Test to see if this is a printable file.
 
589
 * Return -1 if it is not, 0 if its printable, and 1 if
 
590
 * we should remove it after printing.
 
591
 */
 
592
static int
 
593
test(file)
 
594
        char *file;
 
595
{
 
596
        struct exec execb;
 
597
        register int fd;
 
598
        register char *cp;
 
599
 
 
600
        if ((fd = open(file, O_RDONLY)) < 0) {
 
601
                printf("%s: cannot open %s\n", name, file);
 
602
                goto bad;
 
603
        }
 
604
        if (fstat(fd, &statb) < 0) {
 
605
                printf("%s: cannot stat %s\n", name, file);
 
606
                goto bad;
 
607
        }
 
608
        if ((statb.st_mode & S_IFMT) == S_IFDIR) {
 
609
                printf("%s: %s is a directory\n", name, file);
 
610
                goto bad;
 
611
        }
 
612
        if (statb.st_size == 0) {
 
613
                printf("%s: %s is an empty file\n", name, file);
 
614
                goto bad;
 
615
        }
 
616
        if (read(fd, &execb, sizeof(execb)) == sizeof(execb) &&
 
617
            !N_BADMAG(execb)) {
 
618
                        printf("%s: %s is an executable program and is unprintable",
 
619
                                name, file);
 
620
                        (void) close(fd);
 
621
                        goto bad;
 
622
        }
 
623
        (void) close(fd);
 
624
        if (rflag) {
 
625
                if ((cp = strrchr(file, '/')) == NULL) {
 
626
                        if (access(".", 2) == 0)
 
627
                                return(1);
 
628
                } else {
 
629
                        if (cp == file) {
 
630
                                fd = access("/", 2);
 
631
                        } else {
 
632
                                *cp = '\0';
 
633
                                fd = access(file, 2);
 
634
                                *cp = '/';
 
635
                        }
 
636
                        if (fd == 0)
 
637
                                return(1);
 
638
                }
 
639
                printf("%s: %s: is not removable by you\n", name, file);
 
640
        }
 
641
        return(0);
 
642
bad:
 
643
        return(-1);
 
644
}
 
645
 
 
646
/*
 
647
 * itoa - integer to string conversion
 
648
 */
 
649
static char *
 
650
itoa(i)
 
651
        register int i;
 
652
{
 
653
        static char b[10] = "########";
 
654
        register char *p;
 
655
 
 
656
        p = &b[8];
 
657
        do
 
658
                *p-- = i%10 + '0';
 
659
        while (i /= 10);
 
660
        return(++p);
 
661
}
 
662
 
 
663
/*
 
664
 * Perform lookup for printer name or abbreviation --
 
665
 */
 
666
static void
 
667
chkprinter(s)
 
668
        char *s;
 
669
{
 
670
        int status;
 
671
 
 
672
        if ((status = cgetent(&bp, printcapdb, s)) == -2)
 
673
                fatal2("cannot open printer description file");
 
674
        else if (status == -1)
 
675
                fatal2("%s: unknown printer", s);
 
676
        if (cgetstr(bp, "sd", &SD) == -1)
 
677
                SD = _PATH_DEFSPOOL;
 
678
        if (cgetstr(bp, "lo", &LO) == -1)
 
679
                LO = DEFLOCK;
 
680
        cgetstr(bp, "rg", &RG);
 
681
        if (cgetnum(bp, "mx", &MX) < 0)
 
682
                MX = DEFMX;
 
683
        if (cgetnum(bp,"mc", &MC) < 0)
 
684
                MC = DEFMAXCOPIES;
 
685
        if (cgetnum(bp, "du", &DU) < 0)
 
686
                DU = DEFUID;
 
687
        SC = (cgetcap(bp, "sc", ':') != NULL);
 
688
}
 
689
 
 
690
/*
 
691
 * Make the temp files.
 
692
 */
 
693
static void
 
694
mktemps()
 
695
{
 
696
        register int len, fd, n;
 
697
        register char *cp;
 
698
        char buf[BUFSIZ];
 
699
        char *lmktemp();
 
700
 
 
701
        (void) snprintf(buf, sizeof(buf), "%s/.seq", SD);
 
702
        seteuid(euid);
 
703
        if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) {
 
704
                printf("%s: cannot create %s\n", name, buf);
 
705
                exit(1);
 
706
        }
 
707
        if (flock(fd, LOCK_EX)) {
 
708
                printf("%s: cannot lock %s\n", name, buf);
 
709
                exit(1);
 
710
        }
 
711
        seteuid(uid);
 
712
        n = 0;
 
713
        if ((len = read(fd, buf, sizeof(buf))) > 0) {
 
714
                for (cp = buf; len--; ) {
 
715
                        if (*cp < '0' || *cp > '9')
 
716
                                break;
 
717
                        n = n * 10 + (*cp++ - '0');
 
718
                }
 
719
        }
 
720
        len = strlen(SD) + strlen(host) + 8;
 
721
        tfname = lmktemp("tf", n, len);
 
722
        cfname = lmktemp("cf", n, len);
 
723
        dfname = lmktemp("df", n, len);
 
724
        inchar = strlen(SD) + 3;
 
725
        n = (n + 1) % 1000;
 
726
        (void) lseek(fd, (off_t)0, 0);
 
727
        snprintf(buf, sizeof(buf), "%03d\n", n);
 
728
        (void) write(fd, buf, strlen(buf));
 
729
        (void) close(fd);       /* unlocks as well */
 
730
}
 
731
 
 
732
/*
 
733
 * Make a temp file name.
 
734
 */
 
735
static char *
 
736
lmktemp(id, num, len)
 
737
        char    *id;
 
738
        int     num, len;
 
739
{
 
740
        register char *s;
 
741
 
 
742
        if ((s = malloc(len)) == NULL)
 
743
                fatal2("out of memory");
 
744
        (void) snprintf(s, len, "%s/%sA%03d%s", SD, id, num, host);
 
745
        return(s);
 
746
}
 
747
 
 
748
#ifdef __STDC__
 
749
#include <stdarg.h>
 
750
#else
 
751
#include <varargs.h>
 
752
#endif
 
753
 
 
754
static void
 
755
#ifdef __STDC__
 
756
fatal2(const char *msg, ...)
 
757
#else
 
758
fatal2(msg, va_alist)
 
759
        char *msg;
 
760
        va_dcl
 
761
#endif
 
762
{
 
763
        va_list ap;
 
764
#ifdef __STDC__
 
765
        va_start(ap, msg);
 
766
#else
 
767
        va_start(ap);
 
768
#endif
 
769
        printf("%s: ", name);
 
770
        vprintf(msg, ap);
 
771
        putchar('\n');
 
772
        va_end(ap);
 
773
        exit(1);
 
774
}