inetd.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 646 行 · 第 1/2 页

C
646
字号
#ifndef lintstatic	char sccsid[] = "@(#)inetd.c	4.3	(ULTRIX)	9/11/90";#endif/************************************************************************ *									* *			Copyright (c) 1985 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.	* *									* ************************************************************************//*----------------------------------------------------------------------- *	Modification History * *	 *	09/04/89 - lp *		Add 4.3bsd style inetd.conf to allow setting *		of uid/gid of executed process. This allows some *		internet tasks to run a something other than root *		(like maybe daemon or something). The compatibility *		shows up by looking to see if the 5th argument on * 		a line looks like a path. If it does then its the *		Ultrix style of file in use. If not then we assume its * 		a username and use the 6th argument as the command to  *		execute. FIXES a possible security problem as it  *		allows user started daemons to run a non-root. * *	05/06/89 -- jsd *		Allow invocation by super-user only * *	06/09/88 -- map *		Changed signal handlers to void. * *	04/29/85 -- jrs *		Update to handle greater than 32 fd's * *	4/10/85 -- jrs *		Clean up little nits in code.  Also add timer to select *		call so we can momentarily ignore multithreaded datagram *		connections in order to give the server time to pick up *		the initial packet before we try to listen to the socket again. * *	Based on 4.2BSD labeled: *		inetd.c	4.2	84/05/18 * *----------------------------------------------------------------------- *//* * Inetd - Internet super-server * * This program invokes all internet services as needed. * connection-oriented services are invoked each time a * connection is made, by creating a process.  This process * is passed the connection as file descriptor 0 and is * expected to do a getpeername to find out the source host * and port. * * Datagram oriented services are invoked when a datagram * arrives; a process is created and passed a pending message * on file descriptor 0.  Datagram servers may either connect * to their peer, freeing up the original socket for inetd * to receive further messages on, or ``take over the socket'', * processing all arriving datagrams and, eventually, timing * out.	 The first type of server is said to be ``multi-threaded''; * the second type of server ``single-threaded''.  * * Inetd uses a configuration file which is read at startup * and, possibly, at some later time in response to a hangup signal. * The configuration file is ``free format'' with fields given in the * order shown below.  Continuation lines for an entry must being with * a space or tab.  All fields must be present in each entry. * *	service name			must be in /etc/services *	socket type			stream/dgram/raw/rdm/seqpacket *	protocol			must be in /etc/protocols *	wait/nowait			single-threaded/multi-threaded *	user (optional)			user to run program as *	server program			full path name *	server program arguments	maximum of MAXARGS (5) * * Comment lines are indicated by a `#' in column 1. */#include <sys/param.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/file.h>#include <sys/time.h>#include <sys/wait.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <stdio.h>#include <signal.h>#include <netdb.h>#include <syslog.h>#include <pwd.h>#define	MAXARGV	5			/* number of arguments to subdaemon */#define	CONFIG	"/etc/inetd.conf"	/* default configuration file name */#define	FDWORDS	((NOFILE+(NBBY*NBPW)-1)/(NBBY*NBPW))					/* number of words of bit mask */extern	int errno;void	reapchild();char	*index();char	*malloc();int	debug = 0;int	allsock[FDWORDS];int	delaysock[FDWORDS];int	sockndx;struct	timeval deltime = { 1, 0 };struct	timeval *seltimer = NULL;int	options;struct	servent *sp;char	*conffile = CONFIG;void	config();struct	servtab {	char	*se_service;		/* name of service */	int	se_socktype;		/* type of socket to use */	char	*se_proto;		/* protocol used */	short	se_wait;		/* single threaded server */	short	se_checked;		/* looked at during merge */	char 	*se_user;		/* user if present */	char	*se_server;		/* server program */	char	*se_argv[MAXARGV+1];	/* program arguments */	int	se_fd;			/* open descriptor */	struct	sockaddr_in se_ctrladdr;/* bound address */	struct	servtab *se_next;} *servtab;main(argc, argv)	int argc;	char *argv[];{	register struct servtab *sep;	register struct passwd *pwd;	char *cp, buf[50];	int pid, i;	if (getuid()) {		fprintf(stderr, "%s: not super user\n", argv[0]);		exit(1);	}	argc--, argv++;	while (argc > 0 && *argv[0] == '-') {		for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {		case 'd':			debug = 1;			options |= SO_DEBUG;			break;		default:			fprintf(stderr,			    "inetd: Unknown flag -%c ignored.\n", *cp);			break;		}		argc--, argv++;	}	if (argc > 0) {		conffile = argv[0];	}#ifndef DEBUG	if (fork())		exit(0);	{ int s;	for (s = 0; s < 10; s++)		(void) close(s);	}	(void) open("/", O_RDONLY);	(void) dup2(0, 1);	(void) dup2(0, 2);	{ int tt = open("/dev/tty", O_RDWR);	  if (tt > 0) {		(void) ioctl(tt, TIOCNOTTY, 0);		(void) close(tt);	  }	}#endif	for (sockndx = 0; sockndx < FDWORDS; sockndx++) {		delaysock[sockndx] = 0;	}	openlog("inetd", LOG_PID, 0);	config();	(void) signal(SIGHUP, config);	(void) signal(SIGCHLD, reapchild);	for (;;) {		int readable[FDWORDS], s, ctrl;		while (anybit(allsock, FDWORDS) == 0) {			sigpause(0);		}		for (sockndx = 0; sockndx < FDWORDS; sockndx++) {			readable[sockndx] = allsock[sockndx];		}		if (select(NOFILE, readable, 0, 0, seltimer) <= 0) {			if (anybit(readable, FDWORDS) == 0 && seltimer != NULL) {				for (sockndx = 0; sockndx < FDWORDS; sockndx++) {					allsock[sockndx] |= delaysock[sockndx];					delaysock[sockndx] = 0;				}				seltimer = NULL;			}			continue;		}		for (sockndx = 0; sockndx < FDWORDS; sockndx++) {			s = ffs(readable[sockndx])-1;			if (s >= 0) {				s += NBBY * NBPW * sockndx;				break;			}		}		if (s < 0)			continue;		for (sep = servtab; sep; sep = sep->se_next)			if (s == sep->se_fd)				goto found;		abort();	found:		if (debug)			fprintf(stderr, "someone wants %s\n", sep->se_service);		if (sep->se_socktype == SOCK_STREAM) {			ctrl = accept(s, 0, 0);			if (debug)				fprintf(stderr, "accept, ctrl %d\n", ctrl);			if (ctrl < 0) {				if (errno == EINTR)					continue;				syslog(LOG_WARNING, "accept: %m");				continue;			}		} else			ctrl = sep->se_fd;#define mask(sig)	(1 << (sig - 1))		(void) sigblock(mask(SIGCHLD)|mask(SIGHUP));		pid = fork();		if (pid < 0) {			if (sep->se_socktype == SOCK_STREAM)				(void) close(ctrl);			sleep(1);			continue;		}		if (sep->se_wait) {			sep->se_wait = pid;			clearbit(allsock, s);		} else {			if (sep->se_socktype == SOCK_DGRAM) {				pickbit(delaysock, s);				clearbit(allsock, s);				seltimer = &deltime;			}		}		(void) sigsetmask(0);		if (pid == 0) {#ifdef	DEBUG			int tt = open("/dev/tty", O_RDWR);			if (tt > 0) {				(void) ioctl(tt, TIOCNOTTY, 0);				(void) close(tt);			}#endif			(void) dup2(ctrl, 0);			(void) close(ctrl);			(void) dup2(0, 1);			for (i = getdtablesize(); --i > 2; )				(void) close(i);			if (debug)				fprintf(stderr, "%d execl %s\n",				    getpid(), sep->se_server);			if(sep->se_user != NULL) {				if ((pwd = getpwnam(sep->se_user)) == NULL) {					syslog(LOG_ERR, "Invalid user name to run command -  %s: No such user", sep->se_user);					if(sep->se_socktype != SOCK_STREAM)						recv(0, buf, sizeof(buf), 0);					_exit(1);				}				if(pwd->pw_uid) {					(void) setgid((gid_t)pwd->pw_gid);					initgroups(pwd->pw_name, pwd->pw_gid);					(void) setuid((uid_t)pwd->pw_uid);				}			}			execv(sep->se_server, sep->se_argv);			if (sep->se_socktype != SOCK_STREAM)				(void) recv(0, buf, sizeof (buf), 0);			syslog(LOG_ERR, "execv %s: %m", sep->se_server);			_exit(1);		}		if (sep->se_socktype == SOCK_STREAM)			(void) close(ctrl);	}}

⌨️ 快捷键说明

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