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

📄 queue.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
			syslog(LOG_INFO, "%s: dowork, pid=%d", CurEnv->e_id,			       getpid());# endif LOG		/* don't use the headers from sendmail.cf... */		CurEnv->e_header = NULL;		/* lock the control file during processing */		if (link(w->w_name, queuename(CurEnv, 'l')) < 0)		{			/* being processed by another queuer */# ifdef LOG			if (LogLevel > 4)				syslog(LOG_INFO, "%s: locked", CurEnv->e_id);# endif LOG			if (ForkQueueRuns)				exit(EX_OK);			else				return;		}		/* do basic system initialization */		initsys();		/* read the queue control file */		readqf(CurEnv, TRUE);		CurEnv->e_flags |= EF_INQUEUE;		eatheader(CurEnv);		/* do the delivery */		if (!bitset(EF_FATALERRS, CurEnv->e_flags))			sendall(CurEnv, SM_DELIVER);		/* finish up and exit */		if (ForkQueueRuns)			finis();		else			dropenvelope(CurEnv);	}	else	{		/*		**  Parent -- pick up results.		*/		errno = 0;		(void) waitfor(i);	}}/***  READQF -- read queue file and set up environment.****	Parameters:**		e -- the envelope of the job to run.**		full -- if set, read in all information.  Otherwise just**			read in info needed for a queue print.****	Returns:**		none.****	Side Effects:**		cf is read and created as the current job, as though**		we had been invoked by argument.*/readqf(e, full)	register ENVELOPE *e;	bool full;{	char *qf;	register FILE *qfp;	char buf[MAXFIELD];	extern char *fgetfolded(), *setctluser();	extern long atol();	/*	**  Read and process the file.	*/	qf = queuename(e, 'q');	qfp = fopen(qf, "r");	if (qfp == NULL)	{		syserr("readqf: no control file %s", qf);		return;	}	FileName = qf;	LineNumber = 0;	if (Verbose && full)		printf("\nRunning %s\n", e->e_id);	while (fgetfolded(buf, sizeof buf, qfp) != NULL)	{# ifdef DEBUG		if (tTd(40, 4))			printf("+++++ %s\n", buf);# endif DEBUG		switch (buf[0])		{		  case 'R':		/* specify recipient */			sendtolist(setctluser(&buf[1]), (ADDRESS *) NULL, &e->e_sendqueue);			clrctluser();			break;		  case 'E':		/* specify error recipient */			sendtolist(setctluser(&buf[1]), (ADDRESS *) NULL, &e->e_errorqueue);			clrctluser();			break;		  case 'H':		/* header */			if (full)				(void) chompheader(&buf[1], FALSE);			break;		  case 'M':		/* message */			e->e_message = newstr(&buf[1]);			break;		  case 'S':		/* sender */			setsender(newstr(&buf[1]));			break;		  case 'D':		/* data file name */			if (!full)				break;			e->e_df = newstr(&buf[1]);			e->e_dfp = fopen(e->e_df, "r");			if (e->e_dfp == NULL)				syserr("readqf: cannot open %s", e->e_df);			break;		  case 'T':		/* init time */			e->e_ctime = atol(&buf[1]);			break;		  case 'P':		/* message priority */			e->e_msgpriority = atol(&buf[1]) + WkTimeFact;			break;		  case '\0':		/* blank line; ignore */			break;		  default:			syserr("readqf(%s:%d): bad line \"%s\"", e->e_id,				LineNumber, buf);			break;		}	}	(void) fclose(qfp);	FileName = NULL;	/*	**  If we haven't read any lines, this queue file is empty.	**  Arrange to remove it without referencing any null pointers.	*/	if (LineNumber == 0)	{		errno = 0;		e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE;	}}/***  PRINTQUEUE -- print out a representation of the mail queue****	Parameters:**		none.****	Returns:**		none.****	Side Effects:**		Prints a listing of the mail queue on the standard output.*/printqueue(){	register WORK *w;	FILE *f;	int nrequests;	char buf[MAXLINE];	/*	**  Read and order the queue.	*/	nrequests = orderq(TRUE);	/*	**  Print the work list that we have read.	*/	/* first see if there is anything */	if (nrequests <= 0)	{		printf("Mail queue is empty\n");		return;	}	printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s");	if (nrequests > QUEUESIZE)		printf(", only %d printed", QUEUESIZE);	if (Verbose)		printf(")\n--QID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n");	else		printf(")\n--QID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n");	for (w = WorkQ; w != NULL; w = w->w_next)	{		struct stat st;		auto time_t submittime = 0;		long dfsize = -1;		char lf[20];		char message[MAXLINE];		extern bool shouldqueue();		f = fopen(w->w_name, "r");		if (f == NULL)		{			errno = 0;			continue;		}		printf("%7s", w->w_name + 2);		(void) strcpy(lf, w->w_name);		lf[0] = 'l';		if (stat(lf, &st) >= 0)			printf("*");		else if (shouldqueue(w->w_pri))			printf("X");		else			printf(" ");		errno = 0;		message[0] = '\0';		while (fgets(buf, sizeof buf, f) != NULL)		{			fixcrlf(buf, TRUE);			switch (buf[0])			{			  case 'M':	/* error message */				(void) strcpy(message, &buf[1]);				break;			  case 'S':	/* sender name */				if (Verbose)					printf("%8ld %10ld %.12s %.38s", dfsize,					    w->w_pri, ctime(&submittime) + 4,					    &buf[1]);				else					printf("%8ld %.16s %.45s", dfsize,					    ctime(&submittime), &buf[1]);				if (message[0] != '\0')					printf("\n\t\t (%.60s)", message);				break;			  case 'R':	/* recipient name */				if (Verbose)					printf("\n\t\t\t\t\t %.38s", &buf[1]);				else					printf("\n\t\t\t\t  %.45s", &buf[1]);				break;			  case 'T':	/* creation time */				submittime = atol(&buf[1]);				break;			  case 'D':	/* data file name */				if (stat(&buf[1], &st) >= 0)					dfsize = st.st_size;				break;			}		}		if (submittime == (time_t) 0)			printf(" (no control file)");		printf("\n");		(void) fclose(f);	}}# endif QUEUE/***  QUEUENAME -- build a file name in the queue directory for this envelope.****	Assigns an id code if one does not already exist.**	This code is very careful to avoid trashing existing files**	under any circumstances.**		We first create an nf file that is only used when**		assigning an id.  This file is always empty, so that**		we can never accidently truncate an lf file.****	Parameters:**		e -- envelope to build it in/from.**		type -- the file type, used as the first character**			of the file name.****	Returns:**		a pointer to the new file name (in a static buffer).****	Side Effects:**		Will create the lf and qf files if no id code is**		already assigned.  This will cause the envelope**		to be modified.*/char *queuename(e, type)	register ENVELOPE *e;	char type;{	static char buf[MAXNAME];	static int pid = -1;	char c1 = 'A';	char c2 = 'A';	if (e->e_id == NULL)	{		char qf[20];		char nf[20];		char lf[20];		/* find a unique id */		if (pid != getpid())		{			/* new process -- start back at "AA" */			pid = getpid();			c1 = 'A';			c2 = 'A' - 1;		}		(void) sprintf(qf, "qfAA%05d", pid);		(void) strcpy(lf, qf);		lf[0] = 'l';		(void) strcpy(nf, qf);		nf[0] = 'n';		while (c1 < '~' || c2 < 'Z')		{			int i;			if (c2 >= 'Z')			{				c1++;				c2 = 'A' - 1;			}			lf[2] = nf[2] = qf[2] = c1;			lf[3] = nf[3] = qf[3] = ++c2;# ifdef DEBUG			if (tTd(7, 20))				printf("queuename: trying \"%s\"\n", nf);# endif DEBUG# ifdef QUEUE			if (access(lf, 0) >= 0 || access(qf, 0) >= 0)				continue;			errno = 0;			i = creat(nf, FileMode);			if (i < 0)			{				(void) unlink(nf);	/* kernel bug */				continue;			}			(void) close(i);			i = link(nf, lf);			(void) unlink(nf);			if (i < 0)				continue;			if (link(lf, qf) >= 0)				break;			(void) unlink(lf);# else QUEUE			if (close(creat(qf, FileMode)) >= 0)				break;# endif QUEUE		}		if (c1 >= '~' && c2 >= 'Z')		{			syserr("queuename: Cannot create \"%s\" in \"%s\"",				qf, QueueDir);			exit(EX_OSERR);		}		e->e_id = newstr(&qf[2]);		define('i', e->e_id, e);# ifdef DEBUG		if (tTd(7, 1))			printf("queuename: assigned id %s, env=%x\n", e->e_id, e);# ifdef LOG		if (LogLevel > 16)			syslog(LOG_INFO, "%s: assigned id", e->e_id);# endif LOG# endif DEBUG	}	if (type == '\0')		return (NULL);	(void) sprintf(buf, "%cf%s", type, e->e_id);# ifdef DEBUG	if (tTd(7, 2))		printf("queuename: %s\n", buf);# endif DEBUG	return (buf);}/***  UNLOCKQUEUE -- unlock the queue entry for a specified envelope****	Parameters:**		e -- the envelope to unlock.****	Returns:**		none****	Side Effects:**		unlocks the queue for `e'.*/unlockqueue(e)	ENVELOPE *e;{	/* remove the transcript */#ifdef DEBUG# ifdef LOG	if (LogLevel > 19)		syslog(LOG_INFO, "%s: unlock", e->e_id);# endif LOG	if (!tTd(51, 4))#endif DEBUG		xunlink(queuename(e, 'x'));# ifdef QUEUE	/* last but not least, remove the lock */	xunlink(queuename(e, 'l'));# endif QUEUE}/***  GETCTLUSER -- return controlling user if mailing to prog or file****    Check for a "|" or "/" at the beginning of the address.  If**    found, return a controlling username.****    Parameters:**	    a - the address to check out****    Returns:**	    Either NULL, if we werent mailing to a program or file,**	    or a controlling user name (possibly in getpwuid's**	    static buffer).****    Side Effects:**	    none.****    Discussion:**	    Bugfix:  Mail to a file or program is occasionally**	    delivered with an inappropriate uid/gid.  Problem**	    arises usually because of a .forward file and the**	    fact the message got queued instead of immediately**	    delivered.  The proper Control Address info (and it's**	    uid/gid info) is usually lost irretrievably when a**	    program or file recipient is written into the queuefile.****	    It may be better to emit a controlling address in all**	    cases where a "ctladdr" can be found.  The use of a**	    new "C" record was considered, but would result in**	    non-backward-compatible queue files.****    Larry Parmelee 9-Mar-89	         Jeff Forys 25-Feb-90**    parmelee@cs.cornell.edu	         forys@cs.utah.edu*/char *getctluser(a)      ADDRESS *a;{      extern ADDRESS *getctladdr();      struct passwd *pw;      char *retstr, buf[MAXNAME];      /* get unquoted user for file, program or user.name check */      (void) strncpy(buf, a->q_paddr, MAXNAME);      buf[MAXNAME-1] = '\0';      stripquotes(buf, TRUE);      if (buf[0] != '|' && buf[0] != '/')	      return((char *)NULL);      a = getctladdr(a);	      /* find controlling address */      if (a != NULL && a->q_uid != 0 && (pw = getpwuid(a->q_uid)) != NULL)	      retstr = pw->pw_name;      else	                    /* use default user */	      retstr = DefUser;      if (tTd(40, 5))	      printf("Set controlling user for `%s' to `%s'\n",	             (a == NULL)? "<null>": a->q_paddr, retstr);      return(retstr);}static char CtlUser[MAXNAME];/***  SETCTLUSER - sets `CtlUser' to controlling user if appropriate**  CLRCTLUSER - clears controlling user (no params, nothing returned)****    These routines manipulate `CtlUser'.****    Parameters:**	    str  - string checked for a controlling user****    Returns:**	    If `str' is of the form "(user) anything", `CtlUser'**	    is set to "user", and "anything" is returned, otherwise**	    `str' is returned.****    Side Effects:**	    setctluser() may chop up `str' into two strings.**	    `CtlUser' is changed.****    Larry Parmelee 9-Mar-89	         Jeff Forys 25-Feb-90**    parmelee@cs.cornell.edu	         forys@cs.utah.edu*/char *setctluser(str)register char *str;{      register char *ectl;      int depth = 0, bslash = 0;      if (*str != '(')	/* no controlling user */	      return(str);      /*      **  Look thru the string for the matching right paren,      **  being careful about nesting and backslash escapes.      **  This is done to take care of any "weird" user names      **  which could conceivably show up between our paren.      */      for (ectl = str; *ectl; ectl++) {	      if (bslash == 0 && *ectl == '\\') {     /* escape */	              bslash = 1;	              continue;	      }	      if (bslash) {                           /* escaped char */	              bslash = 0;	              continue;	      }	      if (*ectl == '(')                       /* left paren */	              depth++;	      else if (*ectl == ')') {                /* right paren */	              if (--depth == 0)	                      break;	      }      }      if (depth)	      /* no controlling user */	      return(str);      /* we have a controlling user */      *ectl++ = '\0';      (void) strncpy(CtlUser, ++str, MAXNAME);      CtlUser[MAXNAME-1] = '\0';      return((*ectl == ' ')? ++ectl: ectl);}clrctluser(){      *CtlUser = '\0';}/***  SETCTLADDR -- create a controlling address****    If global variable `CtlUser' is set and we are given a valid**    address, make that address a controlling address; change the**    `q_uid', `q_gid', and `q_ruser' fields and set QGOODUID.****    Parameters:**	    a - address for which control uid/gid info may apply****    Returns:**	    None.****    Side Effects:**	    Fills in uid/gid fields in address and sets QGOODUID**	    flag if appropriate.****    Larry Parmelee 9-Mar-89	         Jeff Forys 25-Feb-90**    parmelee@cs.cornell.edu	         forys@cs.utah.edu*/setctladdr(a)      ADDRESS *a;{      struct passwd *pw;      if (*CtlUser == '\0' || a == NULL || a->q_ruser)	      return;      if ((pw = getpwnam(CtlUser)) != NULL) {	      if (a->q_home)	              free(a->q_home);	      a->q_home = newstr(pw->pw_dir);	      a->q_uid = pw->pw_uid;	      a->q_gid = pw->pw_gid;	      a->q_ruser = newstr(CtlUser);      } else {	      a->q_uid = DefUid;	      a->q_gid = DefGid;	      a->q_ruser = newstr(DefUser);      }      a->q_flags |= QGOODUID;	 /* flag as a "ctladdr"  */      if (tTd(40, 5))	      printf("Restored controlling user for `%s' to `%s'\n",	             (a == NULL)? "<null>": a->q_paddr, a->q_ruser);}/***  BADCTLADDR - ensure that an address does not look like "(user) xxx". EOL**    This is only a sanity check and is probably unnecessary, however**    being wrong could lead to another security hole so we do it!****    Parameters:**	    addr  - address to be checked****    Returns:**	    0 if the address is valid, 1 otherwise.****    Side Effects:**	    If `addr->q_paddr' looks like "(user) xxx", `addr->q_flags'**	    gets set to QBADADDR and `addr->q_paddr' gets chopped up.*/boolbadctladdr(addr)ADDRESS *addr;{      char *setctluser();      char *opaddr = addr->q_paddr;      if (setctluser(addr->q_paddr) != opaddr) {	      usrerr("Bad format for qf command: %s %s",	             CtlUser, addr->q_paddr);	      clrctluser();	      addr->q_flags |= QBADADDR;	      return(TRUE);      }      return(FALSE);}

⌨️ 快捷键说明

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