⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recvjob.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
#ifndef lintstatic char *sccsid = "@(#)recvjob.c	4.1      ULTRIX 	7/2/90";#endif/************************************************************************ *									* *			Copyright (c) 1988 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * recvjob.c -- Receive printer jobs from the network, queue them and *	start the printer daemon. *//* * Modification History continues from Jan 1990 in reverse order * * 11-jan-90 -- thoms *	Fix buffer sizes for storing hostname. *//* * *************************************************************** *                -- Revision History -- * *************************************************************** *  * 01/11/83 -- sccs * date and time created 83/11/01 20:59:18 by sccs *  * *************************************************************** *  * 28/06/85 -- root * Comments taken from: /usr/src/usr.lib/lpr/SCCS/s.recvjob.c: *	1.2 85/06/24 08:36:14 williams 2 1	00001/00001/00203 * added argument to printjob to signify not initial condition. *  * *************************************************************** * * 19/07/88 -- thoms * Added copyright notice and modification history * * *************************************************************** *  * 14/09/89 -- Daren Seymour  * Fixed security hole. *  * *************************************************************** * * 17/09/89 -- Giles Atkinson * More security fixes - be very paranoid about the control file! * * PUT NEW MODIFICATION HISTORY IN REVERSE ORDER ABOVE */#include "lp.h"/* Default size for buffer to hold the names of the files (control and data) * which make up a job.   The names are needed to validate the control file * and clean up if there is a problem with the job or its transfer. */#define FNB_SIZE 2040/* Temporary buffers used to hold incoming file names and text of control file * with functions to handle them. */static struct tdbuf {	char *td_rdp;		/* Read data pointer */	char *td_wdp;		/* Write data pointer */	int   td_size;		/* Size of data storage */	char  td_data[1];	/* Data here */} *fnp, *cdp;static int find_td();static char *gets_td(), *puts_td();static struct tdbuf *init_td();static int onintr();recvjob(){	struct stat stb;	char *bp = pbuf;	int status;	/*	 * Perform lookup for printer name or abbreviation	 */	if ((status = pgetent(line, printer)) < 0)		fatal("cannot open printer description file");	else if (status == 0)		fatal("unknown printer");	if ((LF = pgetstr("lf", &bp)) == NULL)		LF = DEFLOGF;	if ((SD = pgetstr("sd", &bp)) == NULL)		SD = DEFSPOOL;	if ((LO = pgetstr("lo", &bp)) == NULL)		LO = DEFLOCK;	(void) close(2);	(void) open(LF, O_WRONLY|O_APPEND);	if (chdir(SD) < 0)		fatal("cannot chdir to %s", SD);	if (stat(LO, &stb) == 0 && (stb.st_mode & 010)) {		/* queue is disabled */		putchar('\1');		/* return error code */		exit(1);	}	signal(SIGHUP, onintr);	signal(SIGINT, onintr);	signal(SIGQUIT, onintr);	signal(SIGTERM, onintr);	signal(SIGCHLD, SIG_DFL);	if (readjob())		printjob(0);}char	*sp = "";#define ack()	(void) write(1, sp, 1);/* * Read printer jobs sent by lpd and copy them to the spooling directory. * Return the number of jobs successfully transfered. */staticreadjob() {	register int size, nfiles;	register char *cp;	fnp = init_td(fnp, FNB_SIZE);		/* Init filename buffer */	ack();	nfiles = 0;	for (;;) {		/*		 * Read a command to tell us what to do		 */		cp = line;		do {			if ((size = read(1, cp, 1)) != 1) {				if (size < 0)					fatal("Lost connection");				cleanup();				return(nfiles);			}		} while (*cp++ != '\n' && cp < &line[MAX_COML]);		if (cp >= &line[MAX_COML])			fatal("Command line too long");		*--cp = '\0';		cp = line;		switch (*cp++) {		case '\1':	/* cleanup because data sent was bad */			cleanup();			continue;		case '\2':	/* read cf file */			if (!read_control(cp))				break;			nfiles++;			continue;		case '\3':	/* read df file */			size = 0;			while (*cp >= '0' && *cp <= '9')				size = size * 10 + (*cp++ - '0');			if (*cp++ != ' ')				break;			(void) readfile(cp, size);			continue;		}		fatal("protocol screwup");	}}/* Handle a request to read a control file */static intread_control(fdat)char *fdat;	{	char tname[CFNAME_LEN+1], cfname[CFNAME_LEN+1];	char lname[MAX_COML];	FILE *cfile;	register char *cp;	register int size, n;	size = 0;	cp = fdat;	while (*cp >= '0' && *cp <= '9')		size = size * 10 + (*cp++ - '0');	if (*cp++ != ' ')		return 0;	fdat = cp;	if (index(fdat, '/'))		fatal("Illegal filename %s", fdat);	/* Allocate a buffer and read control file. */	ack();	cdp = init_td(cdp, size);	cp = cdp->td_data;	while (size) {		n = read(1, cp, size);		if (n <= 0)			fatal("Lost connection");		size -= n;		cp += n;	}	cdp->td_wdp = cp;	/* Now read it back and write a safe control file */	strncpy(cfname, fdat, sizeof cfname - 1);	cfname[sizeof cfname - 1] = '\0';	strcpy(tname, cfname);	tname[0] = (tname[0] == 't') ? 'T' : 't';	cp = puts_td(tname, &fnp);	if ((n = open(tname, O_WRONLY|O_CREAT|O_EXCL, FILMOD)) < 0 ||	    (cfile = fdopen(n, "w")) == NULL) {		if (n >= 0)			close(n);		else			fnp->td_wdp = cp;       /* To protect existing file */                fatal("cannot create %s", tname);	}	lname[0] = '\0';	while (cp = gets_td(cdp)) {		register int command_letter;		switch(command_letter = *cp) {		    case 'U':	/* Unlink command - dangerous, so ignore it */			continue;		    case 'H':	/* No spoofing allowed */			fprintf(cfile, "H%s\n", from);			continue;		    default:			break;		}		/* It would be nice to do something about the `M' and `E'		 * commands which can mail back on completion - rewriting the		 * node name would make them more reliable - do it later.		 *		 * In the meantime all other commands go through unchanged.		 */		fputs(cp, cfile);		putc('\n', cfile);		/* Lower case letters indicate a file to be printed.		 * Ensure that they are in the spool directory and are		 * part of this job.  If they pass we add a `U' line for		 * them so that they will be deleted after printing.		 * Only write one `U' line per file.		 */		if (command_letter >= 'a' && command_letter <= 'z') {			if (strcmp(++cp, lname)) {				strcpy(lname, cp);				if (index(cp, '/') || !find_td(cp, fnp)) {					fclose(cfile);					fatal("Illegal control file data: %s",					      --cp);				}				putc('U', cfile);				fputs(cp, cfile);				putc('\n', cfile);			}		}		    	}	if (ferror(cfile) || fclose(cfile) == EOF)		fatal("Error writing control file");	if (noresponse()) {		/* file sent had bad data in it */		return(0);	}	/* Use link/unlink rather than rename here for fear of destroying	 * existing file.	 */	cp = puts_td(fdat, &fnp);	if (link(tname, fdat) < 0) {		fnp->td_wdp = cp;		/* Protect existing file */		fatal("cannot rename %s", tname);	}	(void) unlink(tname);	fnp = init_td(fnp, FNB_SIZE);		/* Job succeeded, save files */	ack();	return 1;}/* * Read files send by lpd and copy them to the spooling directory. */staticreadfile(file, size)	char *file;	int size;{	register char *cp;	char buf[BUFSIZ];	register int i, j, amt;	int fd, err;	if (index(file, '/') !=0) {		fatal("%s illegal filename", file);	}	cp = puts_td(file, &fnp);	if ((fd = open(file, O_WRONLY|O_CREAT|O_EXCL, FILMOD)) < 0) {		fnp->td_wdp = cp;		/* Protect existing file */		fatal("cannot create %s", file);	}	ack();	err = 0;	for (i = 0; i < size; i += BUFSIZ) {		amt = BUFSIZ;		cp = buf;		if (i + amt > size)			amt = size - i;		do {			j = read(1, cp, amt);			if (j <= 0)				fatal("Lost connection");			amt -= j;			cp += j;		} while (amt > 0);		amt = BUFSIZ;		if (i + amt > size)			amt = size - i;		if (write(fd, buf, amt) != amt) {			err++;			break; 	    }	}	(void) close(fd);	if (err)		fatal("%s: write error", file);	if (noresponse()) {		/* file sent had bad data in it */		(void) unlink(file);		return(0);	}	ack();	return(1);}staticnoresponse(){	char resp;	if (read(1, &resp, 1) != 1)		fatal("Lost connection");	if (resp == '\0')		return(0);	return(1);}/* * Remove all the files associated with the current job being transfered. */staticcleanup(){	register char *cp;	fnp->td_rdp = fnp->td_data;		/* Rewind pseudo-file */	while (cp = gets_td(fnp))		unlink(cp);}staticfatal(msg, a1)	char *msg;{	cleanup();	log(msg, a1);	putchar('\1');		/* return error code */	exit(1);}/* Functions to handle temporary text storage. */static struct tdbuf *init_td(tdp, size)register struct tdbuf *tdp;int size;	{	if (tdp && tdp->td_size < size) {		free(tdp);		tdp = 0;	}	if (!tdp) {		tdp = (struct tdbuf *) malloc(sizeof (struct tdbuf) + size);		tdp->td_size = size;	}	tdp->td_rdp = tdp->td_wdp = tdp->td_data;	return tdp;}/* Put a null-terminated string into a buffer. * Notice that the second argument is a pointer to the buffer pointer - * this allows us to reallocate the buffer on overflow. * A pointer to the stored data is returned, this allows it to be erased * if necesary by restoring the write pointer. */static char *puts_td(cp, tdpp)char *cp;register struct tdbuf **tdpp;	{	register struct tdbuf *tdp;	register char *ip, *op, *ep;	tdp = *tdpp;				/* Point at buffer */	ip = cp;	op = tdp->td_wdp;again:	ep = tdp->td_data + tdp->td_size;	while (*ip && op < ep) {		*op++ = *ip++;	}	if (ip == cp && !*ip)			/* Nothing there */		return;	if (op == ep) {		/* Buffer overflowed */		register struct tdbuf *nbfp;		nbfp = (struct tdbuf *) realloc(tdp,				sizeof (struct tdbuf) + 2 * tdp->td_size);		nbfp->td_size = 2 * tdp->td_size;		nbfp->td_wdp += nbfp - tdp;		nbfp->td_rdp += nbfp - tdp;		op += nbfp - tdp;		*tdpp = tdp = nbfp;		goto again;	}	*op++ = '\0';	ep = tdp->td_wdp;	tdp->td_wdp = op;	return ep;}/* Read the next string out of a temporary buffer */static char *gets_td(tdp)register struct tdbuf *tdp;	{	register char *cp, *dp;	cp = dp = tdp->td_rdp;	if (dp < tdp->td_wdp) {		while (*cp && *cp != '\n' && cp < tdp->td_wdp)			++cp;		*cp++ = '\0';				tdp->td_rdp = cp;		return dp;	} else		return 0;}/* Find if a string is stored in a temporary data buffer. */static intfind_td(xp, tdp)register char *xp;register struct tdbuf *tdp;	{	register char *sp, *cp;	sp = tdp->td_rdp;			/* Save initial position */	while (cp = gets_td(tdp))		if (!strcmp(cp, xp))			return 1;	if (sp != tdp->td_data) {		/* Rewind pseudo-file */		tdp->td_rdp = tdp->td_data;		while (tdp->td_rdp < sp && (cp = gets_td(tdp)))        	        if (!strcmp(cp, xp))	                        return 1;	}	return 0;}static intonintr(){	fatal("Terminated by signal\n");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -