checkpoint working version with variable size sockaddr changes
[unix-history] / usr / src / usr.sbin / lpr / lpr / lpr.c
CommitLineData
51d1035a
BJ
1/*
2 *
3 * 1.1 mike 5/77 - all files copied to spooler space
4 * (see note below)
5 *
6 * 1.2 dlm 26 Sep 1977
7 * fix for allowing variable indents (-i flag)
8 *
9 * 1.3 dlm/njl 12 Dec 1977
10 * fix for open pipe when spawning progess (affects lpd)
11 *
12 * 1.4 dlm 24 Feb 1978
13 * test for data files; add -C option for classification
14 * and change format of $L card; reversed 1.1 on copies
15 *
16 * 1.5 dlm 27 Mar 1978
17 * add job name and -h option
18 *
19 * 2.0 was 21 Dec 1978
20 * -h option changed to -J
21 * added -H option to cause header page to be
22 * printed, default is no header page
23 * added -p option to cause files to be printed
24 * using pr
25 * default for classification changed
26 *
27 * 2.1 was 14 Mar 1979
28 * multiple printer logic changed,
29 * printer number sent to daemon.
30 *
31 * 3.0 sjl 6 May 1980
32 * Mods for Version 7, plus portability
33 * (in preparation for UNIX/24V)
34 *
35 * 3.1 sjl Oct 28 1980
36 * Mods for protected spooling area, see note below
37 *
38 * 3.2 sjl Mar 13 1981
39 * Add N card for file names to help out sq
40 *
41 * 3.3 sjl Mar 27 1981 from decvax!shannon
42 * Mods and cleanup for 4bsd.
43 * Send mail option added.
44 *
45 * 4.0 sjl Mar 28 1981
46 * Support multiple printers and daemons through termcap-like
47 * data base
48 *
49 * 4.1 sjl Apr 28 1981
50 * Check for printer being down (mode 0 on device)
51 *
52 * 4.2 was May 1 1981
53 * Clean up handling of printcap database, add more defaults
54 */
55
56char lpr_id[] = "~|^`lpr.c:\t4.2\t1 May 1981\n";
57
d0aeaf5a
DF
58/*
59 * Copyright (c) 1983 Regents of the University of California.
9d85c861
KB
60 * All rights reserved.
61 *
62 * Redistribution and use in source and binary forms are permitted
a399f6c8
KB
63 * provided that the above copyright notice and this paragraph are
64 * duplicated in all such forms and that any documentation,
65 * advertising materials, and other materials related to such
66 * distribution and use acknowledge that the software was developed
67 * by the University of California, Berkeley. The name of the
68 * University may not be used to endorse or promote products derived
69 * from this software without specific prior written permission.
70 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
71 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
72 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
d0aeaf5a
DF
73 */
74
75#ifndef lint
76char copyright[] =
77"@(#) Copyright (c) 1983 Regents of the University of California.\n\
78 All rights reserved.\n";
9d85c861 79#endif /* not lint */
d0aeaf5a 80
5f84f8f0 81#ifndef lint
a399f6c8 82static char sccsid[] = "@(#)lpr.c 5.4 (Berkeley) %G%";
9d85c861 83#endif /* not lint */
5f84f8f0 84
51d1035a
BJ
85/*
86 * lpr -- off line print
fdaeefb7
BJ
87 *
88 * Allows multiple printers and printers on remote machines by
89 * using information from a printer data base.
51d1035a
BJ
90 */
91
8fed920b
RC
92#include <stdio.h>
93#include <sys/types.h>
94#include <sys/file.h>
95#include <sys/stat.h>
96#include <pwd.h>
5b9885a9 97#include <grp.h>
8fed920b
RC
98#include <signal.h>
99#include <ctype.h>
126fc76f 100#include <syslog.h>
8fed920b 101#include "lp.local.h"
51d1035a 102
fdaeefb7
BJ
103char *tfname; /* tmp copy of cf before linking */
104char *cfname; /* daemon control files, linked from tf's */
105char *dfname; /* data files */
51d1035a
BJ
106
107int nact; /* number of jobs to act on */
fdaeefb7 108int tfd; /* control file descriptor */
51d1035a 109int mailflg; /* send mail */
fdaeefb7 110int qflag; /* q job, but don't exec daemon */
878a0818 111char format = 'f'; /* format char for printing files */
fdaeefb7 112int rflag; /* remove files upon completion */
dfc1084e 113int sflag; /* symbolic link flag */
51d1035a
BJ
114int inchar; /* location to increment char in file names */
115int ncopies = 1; /* # of copies to make */
116int iflag; /* indentation wanted */
117int indent; /* amount to indent */
fdaeefb7 118int hdr = 1; /* print header or not (default is yes) */
878a0818 119int userid; /* user id */
dfc1084e 120char *person; /* user name */
51d1035a 121char *title; /* pr'ing title */
878a0818
RC
122char *fonts[4]; /* troff font names */
123char *width; /* width for versatec printing */
8fed920b 124char host[32]; /* host name */
fdaeefb7 125char *class = host; /* class title on header page */
51d1035a 126char *jobname; /* job name on header page */
8fed920b
RC
127char *name; /* program name */
128char *printer; /* printer name */
98d189de 129struct stat statb;
8fed920b
RC
130
131int MX; /* maximum number of blocks to copy */
132int MC; /* maximum number of copies allowed */
fa211baf 133int DU; /* daemon user-id */
8fed920b
RC
134char *SD; /* spool directory */
135char *LO; /* lock file name */
5b9885a9 136char *RG; /* restrict group */
8fed920b
RC
137short SC; /* suppress multiple copies */
138
139char *getenv();
140char *rindex();
af807caa 141char *linked();
dfc1084e 142int cleanup();
51d1035a 143
fdaeefb7 144/*ARGSUSED*/
51d1035a 145main(argc, argv)
6f038d7b
RC
146 int argc;
147 char *argv[];
51d1035a 148{
dfc1084e 149 extern struct passwd *getpwuid();
878a0818 150 struct passwd *pw;
5b9885a9 151 struct group *gptr;
878a0818 152 extern char *itoa();
af807caa 153 register char *arg, *cp;
98d189de 154 char buf[BUFSIZ];
dfc1084e 155 int i, f;
fdaeefb7 156 struct stat stb;
51d1035a 157
6f038d7b 158 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
dfc1084e 159 signal(SIGHUP, cleanup);
6f038d7b 160 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
dfc1084e 161 signal(SIGINT, cleanup);
6f038d7b 162 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
dfc1084e 163 signal(SIGQUIT, cleanup);
6f038d7b 164 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
dfc1084e 165 signal(SIGTERM, cleanup);
fdaeefb7 166
51d1035a 167 name = argv[0];
4d4caa50 168 gethostname(host, sizeof (host));
126fc76f 169 openlog("lpd", 0, LOG_LPR);
51d1035a 170
dfc1084e 171 while (argc > 1 && argv[1][0] == '-') {
fdaeefb7 172 argc--;
dfc1084e 173 arg = *++argv;
51d1035a
BJ
174 switch (arg[1]) {
175
fdaeefb7 176 case 'P': /* specifiy printer name */
e5be50e6
RC
177 if (arg[2])
178 printer = &arg[2];
179 else if (argc > 1) {
180 argc--;
181 printer = *++argv;
182 }
51d1035a
BJ
183 break;
184
185 case 'C': /* classification spec */
186 hdr++;
187 if (arg[2])
188 class = &arg[2];
878a0818 189 else if (argc > 1) {
51d1035a 190 argc--;
fdaeefb7 191 class = *++argv;
51d1035a
BJ
192 }
193 break;
194
fdaeefb7
BJ
195 case 'J': /* job name */
196 hdr++;
197 if (arg[2])
51d1035a 198 jobname = &arg[2];
878a0818 199 else if (argc > 1) {
51d1035a 200 argc--;
fdaeefb7 201 jobname = *++argv;
51d1035a
BJ
202 }
203 break;
204
fdaeefb7
BJ
205 case 'T': /* pr's title line */
206 if (arg[2])
207 title = &arg[2];
878a0818 208 else if (argc > 1) {
fdaeefb7
BJ
209 argc--;
210 title = *++argv;
211 }
51d1035a
BJ
212 break;
213
878a0818
RC
214 case 'l': /* literal output */
215 case 'p': /* print using ``pr'' */
dfc1084e 216 case 't': /* print troff output (cat files) */
a4f59913 217 case 'n': /* print ditroff output */
dfc1084e
RC
218 case 'd': /* print tex output (dvi files) */
219 case 'g': /* print graph(1G) output */
878a0818
RC
220 case 'c': /* print cifplot output */
221 case 'v': /* print vplot output */
222 format = arg[1];
223 break;
224
dfc1084e
RC
225 case 'f': /* print fortran output */
226 format = 'r';
227 break;
228
878a0818
RC
229 case '4': /* troff fonts */
230 case '3':
231 case '2':
232 case '1':
233 if (argc > 1) {
234 argc--;
235 fonts[arg[1] - '1'] = *++argv;
878a0818
RC
236 }
237 break;
238
239 case 'w': /* versatec page width */
240 width = arg+2;
51d1035a
BJ
241 break;
242
fdaeefb7
BJ
243 case 'r': /* remove file when done */
244 rflag++;
51d1035a
BJ
245 break;
246
fdaeefb7
BJ
247 case 'm': /* send mail when done */
248 mailflg++;
51d1035a
BJ
249 break;
250
fdaeefb7 251 case 'h': /* toggle want of header page */
51d1035a
BJ
252 hdr = !hdr;
253 break;
254
878a0818 255 case 's': /* try to link files */
dfc1084e 256 sflag++;
fdaeefb7
BJ
257 break;
258
259 case 'q': /* just q job */
260 qflag++;
261 break;
262
263 case 'i': /* indent output */
264 iflag++;
265 indent = arg[2] ? atoi(&arg[2]) : 8;
266 break;
267
af807caa 268 case '#': /* n copies */
eee484be
RC
269 if (isdigit(arg[2])) {
270 i = atoi(&arg[2]);
271 if (i > 0)
272 ncopies = i;
273 }
51d1035a 274 }
51d1035a 275 }
fdaeefb7
BJ
276 if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
277 printer = DEFLP;
dfc1084e 278 chkprinter(printer);
eee484be
RC
279 if (SC && ncopies > 1)
280 fatal("multiple copies are not allowed");
281 if (MC > 0 && ncopies > MC)
282 fatal("only %d copies are allowed", MC);
878a0818 283 /*
dfc1084e
RC
284 * Get the identity of the person doing the lpr using the same
285 * algorithm as lprm.
878a0818
RC
286 */
287 userid = getuid();
dfc1084e
RC
288 if ((pw = getpwuid(userid)) == NULL)
289 fatal("Who are you?");
290 person = pw->pw_name;
5b9885a9
MAN
291 /*
292 * Check for restricted group access.
293 */
ca1ba714 294 if (RG != NULL) {
5b9885a9
MAN
295 if ((gptr = getgrnam(RG)) == NULL)
296 fatal("Restricted group specified incorrectly");
ca1ba714
RC
297 if (gptr->gr_gid != getgid()) {
298 while (*gptr->gr_mem != NULL) {
299 if ((strcmp(person, *gptr->gr_mem)) == 0)
300 break;
301 gptr->gr_mem++;
302 }
303 if (*gptr->gr_mem == NULL)
304 fatal("Not a member of the restricted group");
5b9885a9 305 }
5b9885a9 306 }
eee484be
RC
307 /*
308 * Check to make sure queuing is enabled if userid is not root.
309 */
8fed920b
RC
310 (void) sprintf(buf, "%s/%s", SD, LO);
311 if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010))
eee484be 312 fatal("Printer queue is disabled");
dfc1084e
RC
313 /*
314 * Initialize the control file.
315 */
fdaeefb7
BJ
316 mktemps();
317 tfd = nfile(tfname);
fa211baf 318 (void) fchown(tfd, DU, -1); /* owned by daemon for protection */
878a0818
RC
319 card('H', host);
320 card('P', person);
321 if (hdr) {
322 if (jobname == NULL) {
323 if (argc == 1)
af807caa 324 jobname = "stdin";
878a0818 325 else
dfc1084e 326 jobname = (arg = rindex(argv[1], '/')) ? arg+1 : argv[1];
878a0818
RC
327 }
328 card('J', jobname);
329 card('C', class);
330 card('L', person);
51d1035a 331 }
878a0818
RC
332 if (iflag)
333 card('I', itoa(indent));
334 if (mailflg)
335 card('M', person);
a4f59913 336 if (format == 't' || format == 'n' || format == 'd')
878a0818
RC
337 for (i = 0; i < 4; i++)
338 if (fonts[i] != NULL)
339 card('1'+i, fonts[i]);
af807caa 340 if (width != NULL)
878a0818 341 card('W', width);
51d1035a 342
dfc1084e
RC
343 /*
344 * Read the files and spool them.
345 */
6f038d7b 346 if (argc == 1)
51d1035a 347 copy(0, " ");
6f038d7b 348 else while (--argc) {
af807caa 349 if ((f = test(arg = *++argv)) < 0)
fdaeefb7
BJ
350 continue; /* file unreasonable */
351
4d4caa50 352 if (sflag && (cp = linked(arg)) != NULL) {
98d189de
RC
353 (void) sprintf(buf, "%d %d", statb.st_dev, statb.st_ino);
354 card('S', buf);
878a0818 355 if (format == 'p')
fdaeefb7 356 card('T', title ? title : arg);
878a0818
RC
357 for (i = 0; i < ncopies; i++)
358 card(format, &dfname[inchar-2]);
fdaeefb7 359 card('U', &dfname[inchar-2]);
4d4caa50 360 if (f)
af807caa 361 card('U', cp);
fdaeefb7
BJ
362 card('N', arg);
363 dfname[inchar]++;
51d1035a 364 nact++;
4d4caa50
RC
365 continue;
366 }
367 if (sflag)
368 printf("%s: %s: not linked, copying instead\n", name, arg);
adec4d9e 369 if ((i = open(arg, O_RDONLY)) < 0) {
4d4caa50
RC
370 printf("%s: cannot open %s\n", name, arg);
371 continue;
51d1035a 372 }
4d4caa50
RC
373 copy(i, arg);
374 (void) close(i);
375 if (f && unlink(arg) < 0)
376 printf("%s: %s: not removed\n", name, arg);
51d1035a
BJ
377 }
378
6f038d7b 379 if (nact) {
5c0abf7f 380 (void) close(tfd);
51d1035a 381 tfname[inchar]--;
5c0abf7f
RC
382 /*
383 * Touch the control file to fix position in the queue.
384 */
adec4d9e 385 if ((tfd = open(tfname, O_RDWR)) >= 0) {
5c0abf7f
RC
386 char c;
387
388 if (read(tfd, &c, 1) == 1 && lseek(tfd, 0L, 0) == 0 &&
389 write(tfd, &c, 1) != 1) {
390 printf("%s: cannot touch %s\n", name, tfname);
391 tfname[inchar]++;
dfc1084e 392 cleanup();
5c0abf7f
RC
393 }
394 (void) close(tfd);
395 }
fdaeefb7
BJ
396 if (link(tfname, cfname) < 0) {
397 printf("%s: cannot rename %s\n", name, cfname);
51d1035a 398 tfname[inchar]++;
dfc1084e 399 cleanup();
51d1035a
BJ
400 }
401 unlink(tfname);
fdaeefb7 402 if (qflag) /* just q things up */
51d1035a 403 exit(0);
8fed920b 404 if (!startdaemon(printer))
dfc1084e 405 printf("jobs queued, but cannot start daemon.\n");
fdaeefb7 406 exit(0);
51d1035a 407 }
dfc1084e
RC
408 cleanup();
409 /* NOTREACHED */
51d1035a
BJ
410}
411
fdaeefb7
BJ
412/*
413 * Create the file n and copy from file descriptor f.
414 */
51d1035a 415copy(f, n)
6f038d7b
RC
416 int f;
417 char n[];
51d1035a 418{
fdaeefb7 419 register int fd, i, nr, nc;
98d189de 420 char buf[BUFSIZ];
51d1035a 421
878a0818 422 if (format == 'p')
fdaeefb7
BJ
423 card('T', title ? title : n);
424 for (i = 0; i < ncopies; i++)
878a0818 425 card(format, &dfname[inchar-2]);
fdaeefb7
BJ
426 card('U', &dfname[inchar-2]);
427 card('N', n);
428 fd = nfile(dfname);
51d1035a 429 nr = nc = 0;
6f038d7b 430 while ((i = read(f, buf, BUFSIZ)) > 0) {
fdaeefb7 431 if (write(fd, buf, i) != i) {
51d1035a
BJ
432 printf("%s: %s: temp file write error\n", name, n);
433 break;
434 }
435 nc += i;
6f038d7b 436 if (nc >= BUFSIZ) {
51d1035a 437 nc -= BUFSIZ;
c9f75218
RC
438 nr++;
439 if (MX > 0 && nr > MX) {
51d1035a
BJ
440 printf("%s: %s: copy file is too large\n", name, n);
441 break;
442 }
443 }
444 }
fdaeefb7 445 (void) close(fd);
bdddb896
RC
446 if (nc==0 && nr==0)
447 printf("%s: %s: empty input file\n", name, f ? n : "stdin");
448 else
449 nact++;
51d1035a
BJ
450}
451
fdaeefb7 452/*
af807caa
RC
453 * Try and link the file to dfname. Return a pointer to the full
454 * path name if successful.
fdaeefb7 455 */
af807caa 456char *
fdaeefb7
BJ
457linked(file)
458 register char *file;
459{
460 register char *cp;
4d4caa50 461 static char buf[BUFSIZ];
fdaeefb7 462
fdaeefb7
BJ
463 if (*file != '/') {
464 if (getwd(buf) == NULL)
af807caa 465 return(NULL);
fdaeefb7
BJ
466 while (file[0] == '.') {
467 switch (file[1]) {
468 case '/':
469 file += 2;
470 continue;
471 case '.':
472 if (file[2] == '/') {
473 if ((cp = rindex(buf, '/')) != NULL)
474 *cp = '\0';
475 file += 3;
476 continue;
477 }
478 }
479 break;
480 }
481 strcat(buf, "/");
482 strcat(buf, file);
483 file = buf;
484 }
af807caa 485 return(symlink(file, dfname) ? NULL : file);
fdaeefb7
BJ
486}
487
488/*
489 * Put a line into the control file.
490 */
51d1035a 491card(c, p2)
6f038d7b 492 register char c, *p2;
51d1035a 493{
98d189de 494 char buf[BUFSIZ];
51d1035a 495 register char *p1 = buf;
fdaeefb7 496 register int len = 2;
51d1035a
BJ
497
498 *p1++ = c;
6f038d7b 499 while ((c = *p2++) != '\0') {
51d1035a 500 *p1++ = c;
fdaeefb7 501 len++;
51d1035a
BJ
502 }
503 *p1++ = '\n';
fdaeefb7 504 write(tfd, buf, len);
51d1035a
BJ
505}
506
fdaeefb7
BJ
507/*
508 * Create a new file in the spool directory.
509 */
51d1035a 510nfile(n)
6f038d7b 511 char *n;
51d1035a
BJ
512{
513 register f;
fdaeefb7 514 int oldumask = umask(0); /* should block signals */
51d1035a 515
6f038d7b
RC
516 f = creat(n, FILMOD);
517 (void) umask(oldumask);
518 if (f < 0) {
51d1035a 519 printf("%s: cannot create %s\n", name, n);
dfc1084e 520 cleanup();
51d1035a 521 }
fa211baf
RC
522 if (fchown(f, userid, -1) < 0) {
523 printf("%s: cannot chown %s\n", name, n);
524 cleanup();
525 }
5c0abf7f
RC
526 if (++n[inchar] > 'z') {
527 if (++n[inchar-2] == 't') {
528 printf("too many files - break up the job\n");
dfc1084e 529 cleanup();
5c0abf7f
RC
530 }
531 n[inchar] = 'A';
532 } else if (n[inchar] == '[')
533 n[inchar] = 'a';
fdaeefb7 534 return(f);
51d1035a
BJ
535}
536
fdaeefb7
BJ
537/*
538 * Cleanup after interrupts and errors.
539 */
dfc1084e 540cleanup()
51d1035a
BJ
541{
542 register i;
543
544 signal(SIGHUP, SIG_IGN);
545 signal(SIGINT, SIG_IGN);
546 signal(SIGQUIT, SIG_IGN);
547 signal(SIGTERM, SIG_IGN);
548 i = inchar;
549 if (tfname)
c9f75218 550 do
51d1035a 551 unlink(tfname);
c9f75218 552 while (tfname[i]-- != 'A');
51d1035a 553 if (cfname)
c9f75218 554 do
51d1035a 555 unlink(cfname);
c9f75218 556 while (cfname[i]-- != 'A');
51d1035a 557 if (dfname)
c9f75218
RC
558 do {
559 do
5c0abf7f 560 unlink(dfname);
c9f75218
RC
561 while (dfname[i]-- != 'A');
562 dfname[i] = 'z';
563 } while (dfname[i-2]-- != 'd');
5c3a8db4 564 exit(1);
51d1035a
BJ
565}
566
fdaeefb7
BJ
567/*
568 * Test to see if this is a printable file.
4d4caa50 569 * Return -1 if it is not, 0 if its printable, and 1 if
af807caa 570 * we should remove it after printing.
fdaeefb7 571 */
51d1035a 572test(file)
6f038d7b 573 char *file;
51d1035a 574{
fdaeefb7 575 struct exec execb;
af807caa
RC
576 register int fd;
577 register char *cp;
51d1035a
BJ
578
579 if (access(file, 4) < 0) {
580 printf("%s: cannot access %s\n", name, file);
fdaeefb7 581 return(-1);
51d1035a 582 }
fdaeefb7 583 if (stat(file, &statb) < 0) {
51d1035a 584 printf("%s: cannot stat %s\n", name, file);
fdaeefb7 585 return(-1);
51d1035a 586 }
fdaeefb7 587 if ((statb.st_mode & S_IFMT) == S_IFDIR) {
51d1035a 588 printf("%s: %s is a directory\n", name, file);
fdaeefb7 589 return(-1);
51d1035a 590 }
bdddb896
RC
591 if (statb.st_size == 0) {
592 printf("%s: %s is an empty file\n", name, file);
593 return(-1);
594 }
adec4d9e 595 if ((fd = open(file, O_RDONLY)) < 0) {
51d1035a 596 printf("%s: cannot open %s\n", name, file);
fdaeefb7 597 return(-1);
51d1035a 598 }
fdaeefb7
BJ
599 if (read(fd, &execb, sizeof(execb)) == sizeof(execb))
600 switch(execb.a_magic) {
51d1035a
BJ
601 case A_MAGIC1:
602 case A_MAGIC2:
603 case A_MAGIC3:
604#ifdef A_MAGIC4
605 case A_MAGIC4:
606#endif
607 printf("%s: %s is an executable program", name, file);
608 goto error1;
609
610 case ARMAG:
611 printf("%s: %s is an archive file", name, file);
612 goto error1;
613 }
fdaeefb7 614 (void) close(fd);
af807caa
RC
615 if (rflag) {
616 if ((cp = rindex(file, '/')) == NULL) {
617 if (access(".", 2) == 0)
4d4caa50 618 return(1);
af807caa 619 } else {
fdaeefb7 620 *cp = '\0';
4d4caa50 621 fd = access(file, 2);
fdaeefb7 622 *cp = '/';
4d4caa50
RC
623 if (fd == 0)
624 return(1);
878a0818 625 }
4d4caa50 626 printf("%s: %s: is not removable by you\n", name, file);
fdaeefb7 627 }
4d4caa50 628 return(0);
51d1035a 629
51d1035a
BJ
630error1:
631 printf(" and is unprintable\n");
fdaeefb7
BJ
632 (void) close(fd);
633 return(-1);
51d1035a
BJ
634}
635
636/*
637 * itoa - integer to string conversion
638 */
639char *
640itoa(i)
6f038d7b 641 register int i;
51d1035a
BJ
642{
643 static char b[10] = "########";
644 register char *p;
645
646 p = &b[8];
647 do
648 *p-- = i%10 + '0';
649 while (i /= 10);
fdaeefb7 650 return(++p);
51d1035a
BJ
651}
652
653/*
654 * Perform lookup for printer name or abbreviation --
51d1035a
BJ
655 */
656chkprinter(s)
8fed920b 657 char *s;
51d1035a 658{
dfc1084e 659 int status;
98d189de 660 char buf[BUFSIZ];
8fed920b
RC
661 static char pbuf[BUFSIZ/2];
662 char *bp = pbuf;
663 extern char *pgetstr();
dfc1084e 664
8fed920b 665 if ((status = pgetent(buf, s)) < 0)
dfc1084e
RC
666 fatal("cannot open printer description file");
667 else if (status == 0)
8fed920b 668 fatal("%s: unknown printer", s);
fdaeefb7
BJ
669 if ((SD = pgetstr("sd", &bp)) == NULL)
670 SD = DEFSPOOL;
4d4caa50
RC
671 if ((LO = pgetstr("lo", &bp)) == NULL)
672 LO = DEFLOCK;
ca1ba714 673 RG = pgetstr("rg", &bp);
51d1035a
BJ
674 if ((MX = pgetnum("mx")) < 0)
675 MX = DEFMX;
eee484be
RC
676 if ((MC = pgetnum("mc")) < 0)
677 MC = DEFMAXCOPIES;
fa211baf
RC
678 if ((DU = pgetnum("du")) < 0)
679 DU = DEFUID;
eee484be 680 SC = pgetflag("sc");
fdaeefb7
BJ
681}
682
683/*
684 * Make the temp files.
685 */
686mktemps()
687{
eee484be
RC
688 register int c, len, fd, n;
689 register char *cp;
98d189de 690 char buf[BUFSIZ];
8fed920b 691 char *mktemp();
fdaeefb7
BJ
692
693 (void) sprintf(buf, "%s/.seq", SD);
eee484be
RC
694 if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) {
695 printf("%s: cannot create %s\n", name, buf);
696 exit(1);
697 }
698 if (flock(fd, LOCK_EX)) {
699 printf("%s: cannot lock %s\n", name, buf);
700 exit(1);
701 }
702 n = 0;
703 if ((len = read(fd, buf, sizeof(buf))) > 0) {
704 for (cp = buf; len--; ) {
705 if (*cp < '0' || *cp > '9')
706 break;
707 n = n * 10 + (*cp++ - '0');
fdaeefb7 708 }
fdaeefb7
BJ
709 }
710 len = strlen(SD) + strlen(host) + 8;
711 tfname = mktemp("tf", n, len);
712 cfname = mktemp("cf", n, len);
713 dfname = mktemp("df", n, len);
714 inchar = strlen(SD) + 3;
715 n = (n + 1) % 1000;
eee484be
RC
716 (void) lseek(fd, 0L, 0);
717 sprintf(buf, "%03d\n", n);
718 (void) write(fd, buf, strlen(buf));
719 (void) close(fd); /* unlocks as well */
51d1035a
BJ
720}
721
722/*
fdaeefb7 723 * Make a temp file name.
51d1035a
BJ
724 */
725char *
fdaeefb7
BJ
726mktemp(id, num, len)
727 char *id;
728 int num, len;
51d1035a
BJ
729{
730 register char *s;
8fed920b 731 extern char *malloc();
51d1035a 732
dfc1084e
RC
733 if ((s = malloc(len)) == NULL)
734 fatal("out of memory");
fdaeefb7
BJ
735 (void) sprintf(s, "%s/%sA%03d%s", SD, id, num, host);
736 return(s);
51d1035a 737}
8fed920b
RC
738
739/*VARARGS1*/
740fatal(msg, a1, a2, a3)
741 char *msg;
742{
743 printf("%s: ", name);
744 printf(msg, a1, a2, a3);
745 putchar('\n');
746 exit(1);
747}