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

📄 servtab.c

📁 netkit-base-0.17.tar.gz linux嵌入式开发使用!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983, 1991 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include <sys/types.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/un.h>#include <netdb.h>#include <syslog.h>#include <signal.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include "inetd.h"#include "servtab.h"#include "builtins.h"#include "sig.h"#include "mysleep.h"char servtab_rcsid[] =   "$Id: servtab.c,v 1.6 2000/07/22 20:20:50 dholland Exp $";static struct biltin biltins[] = {	/* service	socktype	fork,wait   function */	/* Echo received data */	{ "echo",	SOCK_STREAM,	1, 0,	echo_stream, },	{ "echo",	SOCK_DGRAM,	0, 0,	echo_dg, },	/* Internet /dev/null */	{ "discard",	SOCK_STREAM,	1, 0,	discard_stream, },	{ "discard",	SOCK_DGRAM,	0, 0,	discard_dg, },	/* Return 32 bit time since 1900 */	{ "time",	SOCK_STREAM,	0, 0,	machtime_stream, },	{ "time",	SOCK_DGRAM,	0, 0,	machtime_dg,     },	/* Return human-readable time */	{ "daytime",	SOCK_STREAM,	0, 0,	daytime_stream,     },	{ "daytime",	SOCK_DGRAM,	0, 0,	daytime_dg,     },	/* Familiar character generator */	{ "chargen",	SOCK_STREAM,	1, 0,	chargen_stream,     },	{ "chargen",	SOCK_DGRAM,	0, 0,	chargen_dg,     },	{ NULL, 	0, 		0, 0, 	NULL }};struct servtab *find_service_by_fd(int fd){	struct servtab *sep;	for (sep = servtab; sep; sep = sep->se_next) {		if (sep->se_fd == fd) return sep;	}	return NULL;}struct servtab *find_service_by_pid(pid_t pid){	struct servtab *sep;	for (sep = servtab; sep; sep = sep->se_next) {		if (sep->se_wait == pid) return sep;	}	return NULL;}staticstruct servtab *find_same_service(struct servtab *cp){	struct servtab *sep;	for (sep = servtab; sep; sep = sep->se_next) {		if (strcmp(sep->se_service, cp->se_service)) continue;		if (strcmp(sep->se_proto, cp->se_proto)) continue;		/* 		 * At this point they're the same up to bind address.		 * Catch 1: se_address can be null.		 * Catch 2: two different se_addresses can give the same IP.		 * Catch 3: contents of se_ctrladdr_in.sin_addr are undefined		 *          if they're unix sockets. But we do know that this		 *          isn't the case if se_address isn't null.		 */		/* Easy case: both null (cannot point to the same string) */		if (sep->se_address == cp->se_address) return sep;		/* Now, if one is null, the other isn't */		if (sep->se_address==NULL || cp->se_address==NULL) continue;		/* Don't bother to compare the hostnames, just the IPs */		if (sep->se_ctrladdr_in.sin_addr.s_addr ==		    cp->se_ctrladdr_in.sin_addr.s_addr) return sep;	}	return NULL;}const char *service_name(struct servtab *sep){	static char rv[256];	if (sep->se_address) {		snprintf(rv, sizeof(rv), "%s/%s@%s", sep->se_service, 			 sep->se_proto, sep->se_address);	}	else {		snprintf(rv, sizeof(rv), "%s/%s", sep->se_service, 			 sep->se_proto);	}	return rv;}/********* exit-resistant malloc ************************//* * On many systems, including presently Linux, this is bloat because * malloc never returns null - if the system runs out of swap, it  * panics or randomly starts killing processes or does other weird  * stuff. However, it doesn't hurt to be prepared. This is the only * place inetd can actually exit due to failure, now. */void *domalloc(size_t len){	static int retries[] = { 2, 10, 60, 600, -1 };	void *p;	int try = 0;	while (retries[try]>0) {		p = malloc(len);		if (p != NULL) {		    	return p;		}			syslog(LOG_ERR, "Out of memory - retrying in %d seconds.",		       retries[try]);		mysleep(retries[try]);		try++;	}	/* Should this be LOG_EMERG? */	syslog(LOG_ALERT, "Out of memory - GIVING UP!");	exit(100);	return NULL;  /* unreachable */}char *dostrdup(const char *cp){	char *x = domalloc(strlen(cp)+1);	strcpy(x, cp);	return x;}/********* config parser ********************************/static void loadconfigent(struct servtab *cp);static FILE *fconfig = NULL;#if 0 /* old version */static struct servtab serv;static char line[256];staticchar *nextline(FILE *fd){	char *cp;	if (fgets(line, sizeof (line), fd) == NULL)		return ((char *)0);	cp = strchr(line, '\n');	if (cp)		*cp = '\0';	return (line);}static char *skip(char **cpp){	register char *cp = *cpp;	char *start;	if (*cpp == NULL)		return ((char *)0);again:	while (*cp == ' ' || *cp == '\t')		cp++;	if (*cp == '\0') {		int c;		c = getc(fconfig);		(void) ungetc(c, fconfig);		if (c == ' ' || c == '\t')			if ((cp = nextline(fconfig))!=NULL)				goto again;		*cpp = NULL;		return NULL;	}	start = cp;	while (*cp && *cp != ' ' && *cp != '\t')		cp++;	if (*cp != '\0')		*cp++ = '\0';	*cpp = cp;	return (start);}staticstruct servtab *getconfigent(void){	register struct servtab *sep = &serv;	int argc;	char *cp, *arg;more:	while ((cp = nextline(fconfig)) && *cp == '#')		;	if (cp == NULL) {		return NULL;	}	memset(sep, 0, sizeof(*sep));	sep->se_service = dostrdup(skip(&cp));	arg = skip(&cp);	if (arg == NULL)		goto more;	if (strcmp(arg, "stream") == 0)		sep->se_socktype = SOCK_STREAM;	else if (strcmp(arg, "dgram") == 0)		sep->se_socktype = SOCK_DGRAM;	else if (strcmp(arg, "rdm") == 0)		sep->se_socktype = SOCK_RDM;	else if (strcmp(arg, "seqpacket") == 0)		sep->se_socktype = SOCK_SEQPACKET;	else if (strcmp(arg, "raw") == 0)		sep->se_socktype = SOCK_RAW;	else		sep->se_socktype = -1;	sep->se_proto = dostrdup(skip(&cp));	if (strcmp(sep->se_proto, "unix") == 0) {		sep->se_family = AF_UNIX;	} else {		sep->se_family = AF_INET;		if (strncmp(sep->se_proto, "rpc/", 4) == 0) {#ifdef RPC			char *cp1, *ccp;			cp1 = index(sep->se_service, '/');			if (cp1 == NULL) {				syslog(LOG_ERR, "%s: no rpc version",				    sep->se_service);				goto more;			}			*cp1++ = '\0';			sep->se_rpcversl =				sep->se_rpcversh = strtol(cp1, &ccp, 0);			if (ccp == cp1) {		badafterall:				syslog(LOG_ERR, "%s/%s: bad rpc version",				    sep->se_service, cp1);				goto more;			}			if (*ccp == '-') {				cp1 = ccp + 1;				sep->se_rpcversh = strtol(cp1, &ccp, 0); 				if (ccp == cp1)					goto badafterall;			}#else			syslog(LOG_ERR, "%s: rpc services not supported",			    sep->se_service);			goto more;#endif /* RPC */		}	}	arg = skip(&cp);	if (arg == NULL)		goto more;	{		char	*s = index(arg, '.');		if (s) {			*s++ = '\0';			sep->se_max = atoi(s);		} else			sep->se_max = TOOMANY;	}	sep->se_wait = strcmp(arg, "wait") == 0;	sep->se_user = dostrdup(skip(&cp));	sep->se_group = strchr(sep->se_user, '.');	if (sep->se_group) {		*sep->se_group++ = '\0';	}	sep->se_server = dostrdup(skip(&cp));	if (strcmp(sep->se_server, "internal") == 0) {		register struct biltin *bi;		for (bi = biltins; bi->bi_service; bi++)			if (bi->bi_socktype == sep->se_socktype &&			    strcmp(bi->bi_service, sep->se_service) == 0)				break;		if (bi->bi_service == 0) {			syslog(LOG_ERR, "internal service %s unknown\n",				sep->se_service);			goto more;		}		sep->se_bi = bi;		sep->se_wait = bi->bi_wait;	} else		sep->se_bi = NULL;	argc = 0;	for (arg = skip(&cp); cp; arg = skip(&cp)) {#if MULOG		char *colon, *rindex();		if (argc == 0 && (colon = rindex(arg, ':'))) {			while (arg < colon) {				int	x;				char	*ccp;				switch (*arg++) {				case 'l':					x = 1;					if (isdigit(*arg)) {						x = strtol(arg, &ccp, 0);						if (ccp == arg)							break;						arg = ccp;					}					sep->se_log &= ~MULOG_RFC931;					sep->se_log |= x;					break;				case 'a':					sep->se_log |= MULOG_RFC931;					break;				default:					break;				}			}			arg = colon + 1;		}#endif		if (argc < MAXARGV)			sep->se_argv[argc++] = dostrdup(arg);	}	while (argc <= MAXARGV)		sep->se_argv[argc++] = NULL;	return (sep);}#else /* new version begins here */struct wordmap {	const char *word;	int val;};static struct wordmap socket_types[] = {	{ "stream",    SOCK_STREAM    },	{ "dgram",     SOCK_DGRAM     },	{ "rdm",       SOCK_RDM       },	{ "seqpacket", SOCK_SEQPACKET },	{ "raw",       SOCK_RAW       },	{ NULL,        -1 }};staticintmap_word(struct wordmap *wm, const char *word){	int i;	for (i=0; wm[i].word!=NULL; i++) {		if (!strcmp(wm[i].word, word)) return wm[i].val;	}	return -1;}staticstruct biltin *find_builtin(int socktype, const char *service){	int i;	for (i=0; biltins[i].bi_service; i++) {		if (biltins[i].bi_socktype != socktype) continue;		if (strcmp(biltins[i].bi_service, service)) continue;		return &biltins[i];	}		return NULL;}staticconst char *assemble_entry(struct servtab *sep, int nfields, char **fields){	struct in_addr service_home;	struct hostent *hp;	char *s, *t;	int i;	if (nfields < 6) {		return "Incomplete config entry";	}	memset(sep, 0, sizeof(*sep));	s = strchr(fields[0], '@');	if (s) {		*s++ = 0;		sep->se_address = s;		hp = gethostbyname(s);		if (hp==NULL) return "Service hostname/address not found";		memcpy(&service_home, hp->h_addr, sizeof(service_home));	}	else {		service_home.s_addr = INADDR_ANY;	}	sep->se_service = fields[0];	sep->se_socktype = map_word(socket_types, fields[1]);	free(fields[1]);	sep->se_proto = fields[2];	if (!strcmp(sep->se_proto, "unix")) {		sep->se_family = AF_UNIX;		if (sep->se_address!=NULL) {			return "@host given for unix socket";		}	}	else {		sep->se_family = AF_INET;		sep->se_ctrladdr_in.sin_addr = service_home;		if (!strncmp(sep->se_proto, "rpc/", 4)) {#ifdef RPC

⌨️ 快捷键说明

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