DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦741930213⟧ TextFile

    Length: 5032 (0x13a8)
    Types: TextFile
    Notes: UNIX file
    Names: »lpr.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦f4b8d8c84⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »cmd/lpr/lpr.c« 

TextFile

/*
 * Submit a listing to the local line
 * printer spooler.
 */

#include <stdio.h>
#include <pwd.h>
#include <signal.h>
#ifndef	TYPES_H
#include <types.h>
#endif

/* Schizo is missing so -r doesn't check access privileges */
#define	NBAN	6		/* Maximum number of banners */
#define	NFNAME	400		/* Longest filename allowed */

char	*banners[NBAN];

char	tfspace[20];
char	cfname[20];
char	dfname[20];
char	*tfname;		/* Control file during lpr */
char	*wd;
char	*myuname;
FILE	*cfp;			/* Control file stream */
char	spooldir[] = "/usr/spool/lpd";
char	lpd[] = "/usr/lib/lpd";
char	tmb[] = "Too many banners, `%s' ignored";

int	cflag;		/* Generate a copy */
int	mflag;		/* Send notification */
int	rflag;		/* Remove when done */
int	banno = 4;	/* Current banner number */
int	myuid;

long	unique();
char	*absname();
char	*getwd();
char	*ctime();
char	*getlogin();
int	rmexit();

main(argc, argv)
char *argv[];
{
	register char *ap;
	register int i, j;

	signal(SIGINT, rmexit);
	signal(SIGHUP, rmexit);
	for (i=1; i<argc; i++) {
		if (*argv[i] != '-')
			break;
		for (ap = &argv[i][1]; *ap != '\0'; ap++)
			switch (*ap) {
			case 'b':
				if (++i >= argc)
					lperr("Missing banner");
				if (banno >= NBAN)
					fprintf(stderr, tmb, argv[i]);
				else
					banners[banno++] = argv[i];
				break;

			case 'c':
				cflag = 1;
				break;

			case 'm':
				mflag = 1;
				break;

			case 'n':
				mflag = 0;
				break;

			case 'r':
				cflag = rflag = 1;
				break;

			default:
				usage();
			}
	}
	lprinit(argc, argv);
	for (j=i; j<argc; j++)
		if (banno < NBAN)
			banners[banno++] = argv[j];
		else
			break;
	for (j=0; j<banno; j++)
		fprintf(cfp, "L%s\n", banners[j]);
	if (i == argc)
		lpr(NULL);
	else
		for (; i<argc; i++)
			lpr(argv[i]);
	lprterm();
	for (i=3; i<_NFILE; i++)
		close(i);
	close(0);
	execl(lpd, lpd, NULL);
	lperr("Cannot find daemon `%s'", lpd);
}

/*
 * Initialise the control file.
 * Set up the banners.
 */
lprinit(ac, av)
char **av;
{
	time_t time(), xtime;
	register int i;
	register struct passwd *pwp;
	register char *s;

	myuid = getuid();
	wd = getwd();
	if (chdir(spooldir) < 0)
		lperr("bad directory `%s'", spooldir);
	tfname = tfspace;
	sprintf(tfname, "tf%D", unique());
	strcpy(cfname, tfname);
	cfname[0] = 'c';
	if ((cfp = fopen(tfname, "w")) == NULL)
		lperr("cannot create control file");
	putc('D', cfp);
	for (i=0; i<ac; i++)
		fprintf(cfp, "%s%c", av[i], i==ac-1 ? '\n' : ' ');
	banners[0] = "\35\36\37";
	banners[1] = "Coherent";		/* Mark Williams logo */
	xtime = time(NULL);
	s = ctime(&xtime);
	s[16] = '\0';
	banners[2] = s;
	if ((myuname = getlogin()) == NULL)
		if ((pwp = getpwuid(myuid))==NULL)
			myuname = "Guess who?";
	if (myuname == NULL)
		banners[3] = "Guess who?"; else
		banners[3] = myuname;
}

/*
 * Called for each file to put
 * an entry for it in the control
 * file and do any copies to the
 * spool area.
 * The NULL `file' is stdin.
 */
lpr(file)
char *file;
{
	FILE *ifp;
	char *abfile;

	if (file == NULL)
		ifp = stdin;
	else {
		abfile = absname(file);
		if ((ifp = fopen(abfile, "r")) == NULL)
			lperr("cannot open %s", file);
	}
	if (cflag || file==NULL) {
		copy(ifp);
		fprintf(cfp, "A%s\nU%s\n", dfname, dfname);
		dfname[0] = '\0';
	} else
		fprintf(cfp, "A%s\n", abfile);
	if (rflag && file!=NULL) {
		if (unperm(abfile)<0 || unlink(abfile)<0)
			lperr("Cannot unlink %s", file);
	}
	if (file != NULL)
		fclose(ifp);
}

/*
 * Given a file, see if we have permissions to unlink it.
 */
unperm(np)
register char *np;
{
	register char *cp;
	char name[NFNAME];

	cp = name;
	while ((*cp++=*np++) != '\0')
		;
	while (*--cp != '/') {
		if (cp == name) {
			*cp = '.';
			break;
		}
	}
	cp[1] = '\0';
	return (access(name, 2));
}

/*
 * Clean up and close out
 * control file.
 */
lprterm()
{
	if (mflag)
		if (myuname == NULL)
			fprintf(cfp, "M%d\n", myuid); else
			fprintf(cfp, "M%s\n", myuname);
	fflush(cfp);
	if (ferror(cfp))
		lperr("Control file I/O error");
	fclose(cfp);
	link(tfname, cfname);
	unlink(tfname);
	tfname = NULL;
}

/*
 * Copy the data to a data file
 * in the spool directory.
 */
copy(inf)
register FILE *inf;
{
	register int c;
	register FILE *outf;

	sprintf(dfname, "df%D", unique());
	if ((outf = fopen(dfname, "w")) == NULL)
		lperr("cannot create data file");
	while ((c = getc(inf)) != EOF)
		putc(c, outf);
	fflush(outf);
	if (ferror(outf))
		lperr("data file I/O error");
	fclose(outf);
}

/*
 * Return an absolute pathname
 * for the given filename.
 * (Uses the variable `wd' which
 * contains the process's working
 * directory.)
 */
char *
absname(fn)
char *fn;
{
	static char name[NFNAME];

	if (*fn == '/')
		return (fn);
	sprintf(name, "%s/%s", wd, fn);
	return (name);
}

usage()
{
	lperr("Usage: lpr [-cmrn] [-b banner] [file ...]");
}

/* VARARGS */
lperr(x)
{
	fprintf(stderr, "lpr: %r", &x);
	putc('\n', stderr);
	rmexit(1);
}

/*
 * Exit, removing any files that
 * are left lying around.
 */
rmexit(s)
{
	if (tfname != NULL)
		unlink(tfname);
	if (dfname[0] != '\0')
		unlink(dfname);
	exit(s);
}