📄 inetd.c
字号:
return; } if (sep->se_socktype == SOCK_STREAM) listen(sep->se_fd, 10); FD_SET(sep->se_fd, &allsock); nsock++; if (sep->se_fd > maxsock) maxsock = sep->se_fd; if (debug) { fprintf(stderr, "registered %s on %d\n", sep->se_server, sep->se_fd); }}/* * Finish with a service and its socket. */voidclose_sep(sep) struct servtab *sep;{ if (sep->se_fd >= 0) { nsock--; FD_CLR(sep->se_fd, &allsock); (void) close(sep->se_fd); sep->se_fd = -1; } sep->se_count = 0; /* * Don't keep the pid of this running deamon: when reapchild() * reaps this pid, it would erroneously increment nsock. */ if (sep->se_wait > 1) sep->se_wait = 1;}struct servtab *enter(cp) struct servtab *cp;{ struct servtab *sep; long omask; sep = (struct servtab *)malloc(sizeof (*sep)); if (sep == (struct servtab *)0) { syslog(LOG_ERR, "Out of memory."); exit(-1); } *sep = *cp; sep->se_fd = -1; omask = sigblock(SIGBLOCK); sep->se_next = servtab; servtab = sep; sigsetmask(omask); return (sep);}FILE *fconfig = NULL;struct servtab serv;char line[LINE_MAX];intsetconfig(){ if (fconfig != NULL) { fseek(fconfig, 0L, SEEK_SET); return (1); } fconfig = fopen(CONFIG, "r"); return (fconfig != NULL);}voidendconfig(){ if (fconfig) { (void) fclose(fconfig); fconfig = NULL; }}struct servtab *getconfigent(){ struct servtab *sep = &serv; int argc; char *cp, *arg; static char TCPMUX_TOKEN[] = "tcpmux/";#define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)more: while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0')) ; if (cp == NULL) return ((struct servtab *)0); /* * clear the static buffer, since some fields (se_ctrladdr, * for example) don't get initialized here. */ memset((caddr_t)sep, 0, sizeof *sep); arg = skip(&cp); if (cp == NULL) { /* got an empty line containing just blanks/tabs. */ goto more; } if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { char *c = arg + MUX_LEN; if (*c == '+') { sep->se_type = MUXPLUS_TYPE; c++; } else sep->se_type = MUX_TYPE; sep->se_service = newstr(c); } else { sep->se_service = newstr(arg); sep->se_type = NORM_TYPE; } arg = sskip(&cp); 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 = newstr(sskip(&cp)); arg = sskip(&cp); sep->se_wait = strcmp(arg, "wait") == 0; if (ISMUX(sep)) { /* * Silently enforce "nowait" for TCPMUX services since * they don't have an assigned port to listen on. */ sep->se_wait = 0; if (strcmp(sep->se_proto, "tcp")) { syslog(LOG_ERR, "%s: bad protocol for tcpmux service %s", CONFIG, sep->se_service); goto more; } if (sep->se_socktype != SOCK_STREAM) { syslog(LOG_ERR, "%s: bad socket type for tcpmux service %s", CONFIG, sep->se_service); goto more; } } sep->se_user = newstr(sskip(&cp)); sep->se_server = newstr(sskip(&cp)); if (strcmp(sep->se_server, "internal") == 0) { 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", 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 (argc < MAXARGV) sep->se_argv[argc++] = newstr(arg); while (argc <= MAXARGV) sep->se_argv[argc++] = NULL; return (sep);}voidfreeconfig(cp) struct servtab *cp;{ int i; if (cp->se_service) free(cp->se_service); if (cp->se_proto) free(cp->se_proto); if (cp->se_user) free(cp->se_user); if (cp->se_server) free(cp->se_server); for (i = 0; i < MAXARGV; i++) if (cp->se_argv[i]) free(cp->se_argv[i]);}/* * Safe skip - if skip returns null, log a syntax error in the * configuration file and exit. */char *sskip(cpp) char **cpp;{ char *cp; cp = skip(cpp); if (cp == NULL) { syslog(LOG_ERR, "%s: syntax error", CONFIG); exit(-1); } return (cp);}char *skip(cpp) char **cpp;{ char *cp = *cpp; char *start;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)) goto again; *cpp = (char *)0; return ((char *)0); } start = cp; while (*cp && *cp != ' ' && *cp != '\t') cp++; if (*cp != '\0') *cp++ = '\0'; *cpp = cp; return (start);}char *nextline(fd) FILE *fd;{ char *cp; if (fgets(line, sizeof (line), fd) == NULL) return ((char *)0); cp = strchr(line, '\n'); if (cp) *cp = '\0'; return (line);}char *newstr(cp) char *cp;{ if (cp = strdup(cp ? cp : "")) return (cp); syslog(LOG_ERR, "strdup: %m"); exit(-1);}voidsetproctitle(a, s) char *a; int s;{ int size; char *cp; struct sockaddr_in sin; char buf[80]; cp = Argv[0]; size = sizeof(sin); if (getpeername(s, (struct sockaddr *)&sin, &size) == 0) (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); else (void) sprintf(buf, "-%s", a); strncpy(cp, buf, LastArg - cp); cp += strlen(cp); while (cp < LastArg) *cp++ = ' ';}/* * Internet services provided internally by inetd: */#define BUFSIZE 8192/* ARGSUSED */voidecho_stream(s, sep) /* Echo service -- echo data back */ int s; struct servtab *sep;{ char buffer[BUFSIZE]; int i; setproctitle(sep->se_service, s); while ((i = read(s, buffer, sizeof(buffer))) > 0 && write(s, buffer, i) > 0) ; exit(0);}/* ARGSUSED */voidecho_dg(s, sep) /* Echo service -- echo data back */ int s; struct servtab *sep;{ char buffer[BUFSIZE]; int i, size; struct sockaddr sa; size = sizeof(sa); if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) return; (void) sendto(s, buffer, i, 0, &sa, sizeof(sa));}/* ARGSUSED */voiddiscard_stream(s, sep) /* Discard service -- ignore data */ int s; struct servtab *sep;{ int ret; char buffer[BUFSIZE]; setproctitle(sep->se_service, s); while (1) { while ((ret = read(s, buffer, sizeof(buffer))) > 0) ; if (ret == 0 || errno != EINTR) break; } exit(0);}/* ARGSUSED */voiddiscard_dg(s, sep) /* Discard service -- ignore data */ int s; struct servtab *sep;{ char buffer[BUFSIZE]; (void) read(s, buffer, sizeof(buffer));}#include <ctype.h>#define LINESIZ 72char ring[128];char *endring;voidinitring(){ int i; endring = ring; for (i = 0; i <= 128; ++i) if (isprint(i)) *endring++ = i;}/* ARGSUSED */voidchargen_stream(s, sep) /* Character generator */ int s; struct servtab *sep;{ int len; char *rs, text[LINESIZ+2]; setproctitle(sep->se_service, s); if (!endring) { initring(); rs = ring; } text[LINESIZ] = '\r'; text[LINESIZ + 1] = '\n'; for (rs = ring;;) { if ((len = endring - rs) >= LINESIZ) memmove(text, rs, LINESIZ); else { memmove(text, rs, len); memmove(text + len, ring, LINESIZ - len); } if (++rs == endring) rs = ring; if (write(s, text, sizeof(text)) != sizeof(text)) break; } exit(0);}/* ARGSUSED */voidchargen_dg(s, sep) /* Character generator */ int s; struct servtab *sep;{ struct sockaddr sa; static char *rs; int len, size; char text[LINESIZ+2]; if (endring == 0) { initring(); rs = ring; } size = sizeof(sa); if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) return; if ((len = endring - rs) >= LINESIZ) memmove(text, rs, LINESIZ); else { memmove(text, rs, len); memmove(text + len, ring, LINESIZ - len); } if (++rs == endring) rs = ring; text[LINESIZ] = '\r'; text[LINESIZ + 1] = '\n'; (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));}/* * Return a machine readable date and time, in the form of the * number of seconds since midnight, Jan 1, 1900. Since gettimeofday * returns the number of seconds since midnight, Jan 1, 1970, * we must add 2208988800 seconds to this figure to make up for * some seventy years Bell Labs was asleep. */longmachtime(){ struct timeval tv; if (gettimeofday(&tv, (struct timezone *)0) < 0) { if (debug) fprintf(stderr, "Unable to get time of day\n"); return (0L); }#define OFFSET ((u_long)25567 * 24*60*60) return (htonl((long)(tv.tv_sec + OFFSET)));#undef OFFSET}/* ARGSUSED */voidmachtime_stream(s, sep) int s; struct servtab *sep;{ long result; result = machtime(); (void) write(s, (char *) &result, sizeof(result));}/* ARGSUSED */voidmachtime_dg(s, sep) int s; struct servtab *sep;{ long result; struct sockaddr sa; int size; size = sizeof(sa); if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0) return; result = machtime(); (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));}/* ARGSUSED */voiddaytime_stream(s, sep) /* Return human-readable time of day */ int s; struct servtab *sep;{ char buffer[256]; time_t clock; clock = time((time_t *) 0); (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); (void) write(s, buffer, strlen(buffer));}/* ARGSUSED */voiddaytime_dg(s, sep) /* Return human-readable time of day */ int s; struct servtab *sep;{ char buffer[256]; time_t clock; struct sockaddr sa; int size; clock = time((time_t *) 0); size = sizeof(sa); if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) return; (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa));}/* * print_service: * Dump relevant information to stderr */voidprint_service(action, sep) char *action; struct servtab *sep;{ fprintf(stderr, "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n", action, sep->se_service, sep->se_proto, sep->se_wait, sep->se_user, (int)sep->se_bi, sep->se_server);}/* * Based on TCPMUX.C by Mark K. Lottor November 1988 * sri-nic::ps:<mkl>tcpmux.c */static int /* # of characters upto \r,\n or \0 */getline(fd, buf, len) int fd; char *buf; int len;{ int count = 0, n; do { n = read(fd, buf, len-count); if (n == 0) return (count); if (n < 0) return (-1); while (--n >= 0) { if (*buf == '\r' || *buf == '\n' || *buf == '\0') return (count); count++; buf++; } } while (count < len); return (count);}#define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */#define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1)struct servtab *tcpmux(s) int s;{ struct servtab *sep; char service[MAX_SERV_LEN+1]; int len; /* Get requested service name */ if ((len = getline(s, service, MAX_SERV_LEN)) < 0) { strwrite(s, "-Error reading service name\r\n"); return (NULL); } service[len] = '\0'; if (debug) fprintf(stderr, "tcpmux: someone wants %s\n", service); /* * Help is a required command, and lists available services, * one per line. */ if (!strcasecmp(service, "help")) { for (sep = servtab; sep; sep = sep->se_next) { if (!ISMUX(sep)) continue; (void)write(s,sep->se_service,strlen(sep->se_service)); strwrite(s, "\r\n"); } return (NULL); } /* Try matching a service in inetd.conf with the request */ for (sep = servtab; sep; sep = sep->se_next) { if (!ISMUX(sep)) continue; if (!strcasecmp(service, sep->se_service)) { if (ISMUXPLUS(sep)) { strwrite(s, "+Go\r\n"); } return (sep); } } strwrite(s, "-Service not available\r\n"); return (NULL);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -