file reorg, pathnames.h, paths.h
[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[] =
3b5e183c 77"@(#) Copyright (c) 1983, 1989 Regents of the University of California.\n\
d0aeaf5a 78 All rights reserved.\n";
9d85c861 79#endif /* not lint */
d0aeaf5a 80
5f84f8f0 81#ifndef lint
7abf8d65 82static char sccsid[] = "@(#)lpr.c 5.6 (Berkeley) %G%";
9d85c861 83#endif /* not lint */
51d1035a
BJ
84/*
85 * lpr -- off line print
fdaeefb7
BJ
86 *
87 * Allows multiple printers and printers on remote machines by
88 * using information from a printer data base.
51d1035a
BJ
89 */
90
8fed920b
RC
91#include <stdio.h>
92#include <sys/types.h>
93#include <sys/file.h>
94#include <sys/stat.h>
95#include <pwd.h>
5b9885a9 96#include <grp.h>
8fed920b
RC
97#include <signal.h>
98#include <ctype.h>
126fc76f 99#include <syslog.h>
8fed920b 100#include "lp.local.h"
7abf8d65 101#include "pathnames.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
3b5e183c
KS
195 case 'U': /* user name */
196 hdr++;
197 if (arg[2])
198 person = &arg[2];
199 else if (argc > 1) {
200 argc--;
201 person = *++argv;
202 }
203 break;
204
fdaeefb7
BJ
205 case 'J': /* job name */
206 hdr++;
207 if (arg[2])
51d1035a 208 jobname = &arg[2];
878a0818 209 else if (argc > 1) {
51d1035a 210 argc--;
fdaeefb7 211 jobname = *++argv;
51d1035a
BJ
212 }
213 break;
214
fdaeefb7
BJ
215 case 'T': /* pr's title line */
216 if (arg[2])
217 title = &arg[2];
878a0818 218 else if (argc > 1) {
fdaeefb7
BJ
219 argc--;
220 title = *++argv;
221 }
51d1035a
BJ
222 break;
223
878a0818
RC
224 case 'l': /* literal output */
225 case 'p': /* print using ``pr'' */
dfc1084e 226 case 't': /* print troff output (cat files) */
a4f59913 227 case 'n': /* print ditroff output */
dfc1084e
RC
228 case 'd': /* print tex output (dvi files) */
229 case 'g': /* print graph(1G) output */
878a0818
RC
230 case 'c': /* print cifplot output */
231 case 'v': /* print vplot output */
232 format = arg[1];
233 break;
234
dfc1084e
RC
235 case 'f': /* print fortran output */
236 format = 'r';
237 break;
238
878a0818
RC
239 case '4': /* troff fonts */
240 case '3':
241 case '2':
242 case '1':
243 if (argc > 1) {
244 argc--;
245 fonts[arg[1] - '1'] = *++argv;
878a0818
RC
246 }
247 break;
248
249 case 'w': /* versatec page width */
250 width = arg+2;
51d1035a
BJ
251 break;
252
fdaeefb7
BJ
253 case 'r': /* remove file when done */
254 rflag++;
51d1035a
BJ
255 break;
256
fdaeefb7
BJ
257 case 'm': /* send mail when done */
258 mailflg++;
51d1035a
BJ
259 break;
260
fdaeefb7 261 case 'h': /* toggle want of header page */
51d1035a
BJ
262 hdr = !hdr;
263 break;
264
878a0818 265 case 's': /* try to link files */
dfc1084e 266 sflag++;
fdaeefb7
BJ
267 break;
268
269 case 'q': /* just q job */
270 qflag++;
271 break;
272
273 case 'i': /* indent output */
274 iflag++;
275 indent = arg[2] ? atoi(&arg[2]) : 8;
276 break;
277
af807caa 278 case '#': /* n copies */
eee484be
RC
279 if (isdigit(arg[2])) {
280 i = atoi(&arg[2]);
281 if (i > 0)
282 ncopies = i;
283 }
51d1035a 284 }
51d1035a 285 }
fdaeefb7
BJ
286 if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
287 printer = DEFLP;
dfc1084e 288 chkprinter(printer);
eee484be
RC
289 if (SC && ncopies > 1)
290 fatal("multiple copies are not allowed");
291 if (MC > 0 && ncopies > MC)
292 fatal("only %d copies are allowed", MC);
878a0818 293 /*
dfc1084e
RC
294 * Get the identity of the person doing the lpr using the same
295 * algorithm as lprm.
878a0818
RC
296 */
297 userid = getuid();
3b5e183c
KS
298 if (userid != DU || person == 0) {
299 if ((pw = getpwuid(userid)) == NULL)
300 fatal("Who are you?");
301 person = pw->pw_name;
302 }
5b9885a9
MAN
303 /*
304 * Check for restricted group access.
305 */
3b5e183c 306 if (RG != NULL && userid != DU) {
5b9885a9
MAN
307 if ((gptr = getgrnam(RG)) == NULL)
308 fatal("Restricted group specified incorrectly");
ca1ba714
RC
309 if (gptr->gr_gid != getgid()) {
310 while (*gptr->gr_mem != NULL) {
311 if ((strcmp(person, *gptr->gr_mem)) == 0)
312 break;
313 gptr->gr_mem++;
314 }
315 if (*gptr->gr_mem == NULL)
316 fatal("Not a member of the restricted group");
5b9885a9 317 }
5b9885a9 318 }
eee484be
RC
319 /*
320 * Check to make sure queuing is enabled if userid is not root.
321 */
8fed920b
RC
322 (void) sprintf(buf, "%s/%s", SD, LO);
323 if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010))
eee484be 324 fatal("Printer queue is disabled");
dfc1084e
RC
325 /*
326 * Initialize the control file.
327 */
fdaeefb7
BJ
328 mktemps();
329 tfd = nfile(tfname);
fa211baf 330 (void) fchown(tfd, DU, -1); /* owned by daemon for protection */
878a0818
RC
331 card('H', host);
332 card('P', person);
333 if (hdr) {
334 if (jobname == NULL) {
335 if (argc == 1)
af807caa 336 jobname = "stdin";
878a0818 337 else
dfc1084e 338 jobname = (arg = rindex(argv[1], '/')) ? arg+1 : argv[1];
878a0818
RC
339 }
340 card('J', jobname);
341 card('C', class);
342 card('L', person);
51d1035a 343 }
878a0818
RC
344 if (iflag)
345 card('I', itoa(indent));
346 if (mailflg)
347 card('M', person);
a4f59913 348 if (format == 't' || format == 'n' || format == 'd')
878a0818
RC
349 for (i = 0; i < 4; i++)
350 if (fonts[i] != NULL)
351 card('1'+i, fonts[i]);
af807caa 352 if (width != NULL)
878a0818 353 card('W', width);
51d1035a 354
dfc1084e
RC
355 /*
356 * Read the files and spool them.
357 */
6f038d7b 358 if (argc == 1)
51d1035a 359 copy(0, " ");
6f038d7b 360 else while (--argc) {
af807caa 361 if ((f = test(arg = *++argv)) < 0)
fdaeefb7
BJ
362 continue; /* file unreasonable */
363
4d4caa50 364 if (sflag && (cp = linked(arg)) != NULL) {
98d189de
RC
365 (void) sprintf(buf, "%d %d", statb.st_dev, statb.st_ino);
366 card('S', buf);
878a0818 367 if (format == 'p')
fdaeefb7 368 card('T', title ? title : arg);
878a0818
RC
369 for (i = 0; i < ncopies; i++)
370 card(format, &dfname[inchar-2]);
fdaeefb7 371 card('U', &dfname[inchar-2]);
4d4caa50 372 if (f)
af807caa 373 card('U', cp);
fdaeefb7
BJ
374 card('N', arg);
375 dfname[inchar]++;
51d1035a 376 nact++;
4d4caa50
RC
377 continue;
378 }
379 if (sflag)
380 printf("%s: %s: not linked, copying instead\n", name, arg);
adec4d9e 381 if ((i = open(arg, O_RDONLY)) < 0) {
4d4caa50
RC
382 printf("%s: cannot open %s\n", name, arg);
383 continue;
51d1035a 384 }
4d4caa50
RC
385 copy(i, arg);
386 (void) close(i);
387 if (f && unlink(arg) < 0)
388 printf("%s: %s: not removed\n", name, arg);
51d1035a
BJ
389 }
390
6f038d7b 391 if (nact) {
5c0abf7f 392 (void) close(tfd);
51d1035a 393 tfname[inchar]--;
5c0abf7f
RC
394 /*
395 * Touch the control file to fix position in the queue.
396 */
adec4d9e 397 if ((tfd = open(tfname, O_RDWR)) >= 0) {
5c0abf7f
RC
398 char c;
399
400 if (read(tfd, &c, 1) == 1 && lseek(tfd, 0L, 0) == 0 &&
401 write(tfd, &c, 1) != 1) {
402 printf("%s: cannot touch %s\n", name, tfname);
403 tfname[inchar]++;
dfc1084e 404 cleanup();
5c0abf7f
RC
405 }
406 (void) close(tfd);
407 }
fdaeefb7
BJ
408 if (link(tfname, cfname) < 0) {
409 printf("%s: cannot rename %s\n", name, cfname);
51d1035a 410 tfname[inchar]++;
dfc1084e 411 cleanup();
51d1035a
BJ
412 }
413 unlink(tfname);
fdaeefb7 414 if (qflag) /* just q things up */
51d1035a 415 exit(0);
8fed920b 416 if (!startdaemon(printer))
dfc1084e 417 printf("jobs queued, but cannot start daemon.\n");
fdaeefb7 418 exit(0);
51d1035a 419 }
dfc1084e
RC
420 cleanup();
421 /* NOTREACHED */
51d1035a
BJ
422}
423
fdaeefb7
BJ
424/*
425 * Create the file n and copy from file descriptor f.
426 */
51d1035a 427copy(f, n)
6f038d7b
RC
428 int f;
429 char n[];
51d1035a 430{
fdaeefb7 431 register int fd, i, nr, nc;
98d189de 432 char buf[BUFSIZ];
51d1035a 433
878a0818 434 if (format == 'p')
fdaeefb7
BJ
435 card('T', title ? title : n);
436 for (i = 0; i < ncopies; i++)
878a0818 437 card(format, &dfname[inchar-2]);
fdaeefb7
BJ
438 card('U', &dfname[inchar-2]);
439 card('N', n);
440 fd = nfile(dfname);
51d1035a 441 nr = nc = 0;
6f038d7b 442 while ((i = read(f, buf, BUFSIZ)) > 0) {
fdaeefb7 443 if (write(fd, buf, i) != i) {
51d1035a
BJ
444 printf("%s: %s: temp file write error\n", name, n);
445 break;
446 }
447 nc += i;
6f038d7b 448 if (nc >= BUFSIZ) {
51d1035a 449 nc -= BUFSIZ;
c9f75218
RC
450 nr++;
451 if (MX > 0 && nr > MX) {
51d1035a
BJ
452 printf("%s: %s: copy file is too large\n", name, n);
453 break;
454 }
455 }
456 }
fdaeefb7 457 (void) close(fd);
bdddb896
RC
458 if (nc==0 && nr==0)
459 printf("%s: %s: empty input file\n", name, f ? n : "stdin");
460 else
461 nact++;
51d1035a
BJ
462}
463
fdaeefb7 464/*
af807caa
RC
465 * Try and link the file to dfname. Return a pointer to the full
466 * path name if successful.
fdaeefb7 467 */
af807caa 468char *
fdaeefb7
BJ
469linked(file)
470 register char *file;
471{
472 register char *cp;
4d4caa50 473 static char buf[BUFSIZ];
fdaeefb7 474
fdaeefb7
BJ
475 if (*file != '/') {
476 if (getwd(buf) == NULL)
af807caa 477 return(NULL);
fdaeefb7
BJ
478 while (file[0] == '.') {
479 switch (file[1]) {
480 case '/':
481 file += 2;
482 continue;
483 case '.':
484 if (file[2] == '/') {
485 if ((cp = rindex(buf, '/')) != NULL)
486 *cp = '\0';
487 file += 3;
488 continue;
489 }
490 }
491 break;
492 }
493 strcat(buf, "/");
494 strcat(buf, file);
495 file = buf;
496 }
af807caa 497 return(symlink(file, dfname) ? NULL : file);
fdaeefb7
BJ
498}
499
500/*
501 * Put a line into the control file.
502 */
51d1035a 503card(c, p2)
6f038d7b 504 register char c, *p2;
51d1035a 505{
98d189de 506 char buf[BUFSIZ];
51d1035a 507 register char *p1 = buf;
fdaeefb7 508 register int len = 2;
51d1035a
BJ
509
510 *p1++ = c;
6f038d7b 511 while ((c = *p2++) != '\0') {
51d1035a 512 *p1++ = c;
fdaeefb7 513 len++;
51d1035a
BJ
514 }
515 *p1++ = '\n';
fdaeefb7 516 write(tfd, buf, len);
51d1035a
BJ
517}
518
fdaeefb7
BJ
519/*
520 * Create a new file in the spool directory.
521 */
51d1035a 522nfile(n)
6f038d7b 523 char *n;
51d1035a
BJ
524{
525 register f;
fdaeefb7 526 int oldumask = umask(0); /* should block signals */
51d1035a 527
6f038d7b
RC
528 f = creat(n, FILMOD);
529 (void) umask(oldumask);
530 if (f < 0) {
51d1035a 531 printf("%s: cannot create %s\n", name, n);
dfc1084e 532 cleanup();
51d1035a 533 }
fa211baf
RC
534 if (fchown(f, userid, -1) < 0) {
535 printf("%s: cannot chown %s\n", name, n);
536 cleanup();
537 }
5c0abf7f
RC
538 if (++n[inchar] > 'z') {
539 if (++n[inchar-2] == 't') {
540 printf("too many files - break up the job\n");
dfc1084e 541 cleanup();
5c0abf7f
RC
542 }
543 n[inchar] = 'A';
544 } else if (n[inchar] == '[')
545 n[inchar] = 'a';
fdaeefb7 546 return(f);
51d1035a
BJ
547}
548
fdaeefb7
BJ
549/*
550 * Cleanup after interrupts and errors.
551 */
dfc1084e 552cleanup()
51d1035a
BJ
553{
554 register i;
555
556 signal(SIGHUP, SIG_IGN);
557 signal(SIGINT, SIG_IGN);
558 signal(SIGQUIT, SIG_IGN);
559 signal(SIGTERM, SIG_IGN);
560 i = inchar;
561 if (tfname)
c9f75218 562 do
51d1035a 563 unlink(tfname);
c9f75218 564 while (tfname[i]-- != 'A');
51d1035a 565 if (cfname)
c9f75218 566 do
51d1035a 567 unlink(cfname);
c9f75218 568 while (cfname[i]-- != 'A');
51d1035a 569 if (dfname)
c9f75218
RC
570 do {
571 do
5c0abf7f 572 unlink(dfname);
c9f75218
RC
573 while (dfname[i]-- != 'A');
574 dfname[i] = 'z';
575 } while (dfname[i-2]-- != 'd');
5c3a8db4 576 exit(1);
51d1035a
BJ
577}
578
fdaeefb7
BJ
579/*
580 * Test to see if this is a printable file.
4d4caa50 581 * Return -1 if it is not, 0 if its printable, and 1 if
af807caa 582 * we should remove it after printing.
fdaeefb7 583 */
51d1035a 584test(file)
6f038d7b 585 char *file;
51d1035a 586{
fdaeefb7 587 struct exec execb;
af807caa
RC
588 register int fd;
589 register char *cp;
51d1035a
BJ
590
591 if (access(file, 4) < 0) {
592 printf("%s: cannot access %s\n", name, file);
fdaeefb7 593 return(-1);
51d1035a 594 }
fdaeefb7 595 if (stat(file, &statb) < 0) {
51d1035a 596 printf("%s: cannot stat %s\n", name, file);
fdaeefb7 597 return(-1);
51d1035a 598 }
fdaeefb7 599 if ((statb.st_mode & S_IFMT) == S_IFDIR) {
51d1035a 600 printf("%s: %s is a directory\n", name, file);
fdaeefb7 601 return(-1);
51d1035a 602 }
bdddb896
RC
603 if (statb.st_size == 0) {
604 printf("%s: %s is an empty file\n", name, file);
605 return(-1);
606 }
adec4d9e 607 if ((fd = open(file, O_RDONLY)) < 0) {
51d1035a 608 printf("%s: cannot open %s\n", name, file);
fdaeefb7 609 return(-1);
51d1035a 610 }
fdaeefb7
BJ
611 if (read(fd, &execb, sizeof(execb)) == sizeof(execb))
612 switch(execb.a_magic) {
51d1035a
BJ
613 case A_MAGIC1:
614 case A_MAGIC2:
615 case A_MAGIC3:
616#ifdef A_MAGIC4
617 case A_MAGIC4:
618#endif
619 printf("%s: %s is an executable program", name, file);
620 goto error1;
621
622 case ARMAG:
623 printf("%s: %s is an archive file", name, file);
624 goto error1;
625 }
fdaeefb7 626 (void) close(fd);
af807caa
RC
627 if (rflag) {
628 if ((cp = rindex(file, '/')) == NULL) {
629 if (access(".", 2) == 0)
4d4caa50 630 return(1);
af807caa 631 } else {
fdaeefb7 632 *cp = '\0';
4d4caa50 633 fd = access(file, 2);
fdaeefb7 634 *cp = '/';
4d4caa50
RC
635 if (fd == 0)
636 return(1);
878a0818 637 }
4d4caa50 638 printf("%s: %s: is not removable by you\n", name, file);
fdaeefb7 639 }
4d4caa50 640 return(0);
51d1035a 641
51d1035a
BJ
642error1:
643 printf(" and is unprintable\n");
fdaeefb7
BJ
644 (void) close(fd);
645 return(-1);
51d1035a
BJ
646}
647
648/*
649 * itoa - integer to string conversion
650 */
651char *
652itoa(i)
6f038d7b 653 register int i;
51d1035a
BJ
654{
655 static char b[10] = "########";
656 register char *p;
657
658 p = &b[8];
659 do
660 *p-- = i%10 + '0';
661 while (i /= 10);
fdaeefb7 662 return(++p);
51d1035a
BJ
663}
664
665/*
666 * Perform lookup for printer name or abbreviation --
51d1035a
BJ
667 */
668chkprinter(s)
8fed920b 669 char *s;
51d1035a 670{
dfc1084e 671 int status;
98d189de 672 char buf[BUFSIZ];
8fed920b
RC
673 static char pbuf[BUFSIZ/2];
674 char *bp = pbuf;
675 extern char *pgetstr();
dfc1084e 676
8fed920b 677 if ((status = pgetent(buf, s)) < 0)
dfc1084e
RC
678 fatal("cannot open printer description file");
679 else if (status == 0)
8fed920b 680 fatal("%s: unknown printer", s);
fdaeefb7 681 if ((SD = pgetstr("sd", &bp)) == NULL)
7abf8d65 682 SD = _PATH_DEFSPOOL;
4d4caa50
RC
683 if ((LO = pgetstr("lo", &bp)) == NULL)
684 LO = DEFLOCK;
ca1ba714 685 RG = pgetstr("rg", &bp);
51d1035a
BJ
686 if ((MX = pgetnum("mx")) < 0)
687 MX = DEFMX;
eee484be
RC
688 if ((MC = pgetnum("mc")) < 0)
689 MC = DEFMAXCOPIES;
fa211baf
RC
690 if ((DU = pgetnum("du")) < 0)
691 DU = DEFUID;
eee484be 692 SC = pgetflag("sc");
fdaeefb7
BJ
693}
694
695/*
696 * Make the temp files.
697 */
698mktemps()
699{
eee484be
RC
700 register int c, len, fd, n;
701 register char *cp;
98d189de 702 char buf[BUFSIZ];
8fed920b 703 char *mktemp();
fdaeefb7
BJ
704
705 (void) sprintf(buf, "%s/.seq", SD);
eee484be
RC
706 if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) {
707 printf("%s: cannot create %s\n", name, buf);
708 exit(1);
709 }
710 if (flock(fd, LOCK_EX)) {
711 printf("%s: cannot lock %s\n", name, buf);
712 exit(1);
713 }
714 n = 0;
715 if ((len = read(fd, buf, sizeof(buf))) > 0) {
716 for (cp = buf; len--; ) {
717 if (*cp < '0' || *cp > '9')
718 break;
719 n = n * 10 + (*cp++ - '0');
fdaeefb7 720 }
fdaeefb7
BJ
721 }
722 len = strlen(SD) + strlen(host) + 8;
723 tfname = mktemp("tf", n, len);
724 cfname = mktemp("cf", n, len);
725 dfname = mktemp("df", n, len);
726 inchar = strlen(SD) + 3;
727 n = (n + 1) % 1000;
eee484be
RC
728 (void) lseek(fd, 0L, 0);
729 sprintf(buf, "%03d\n", n);
730 (void) write(fd, buf, strlen(buf));
731 (void) close(fd); /* unlocks as well */
51d1035a
BJ
732}
733
734/*
fdaeefb7 735 * Make a temp file name.
51d1035a
BJ
736 */
737char *
fdaeefb7
BJ
738mktemp(id, num, len)
739 char *id;
740 int num, len;
51d1035a
BJ
741{
742 register char *s;
8fed920b 743 extern char *malloc();
51d1035a 744
dfc1084e
RC
745 if ((s = malloc(len)) == NULL)
746 fatal("out of memory");
fdaeefb7
BJ
747 (void) sprintf(s, "%s/%sA%03d%s", SD, id, num, host);
748 return(s);
51d1035a 749}
8fed920b
RC
750
751/*VARARGS1*/
752fatal(msg, a1, a2, a3)
753 char *msg;
754{
755 printf("%s: ", name);
756 printf(msg, a1, a2, a3);
757 putchar('\n');
758 exit(1);
759}