📄 inetd.c
字号:
timingout = 1; alarm (RETRYTIME); } continue; } } pid = fork (); } if (pid < 0) { syslog (LOG_ERR, "fork: %m"); if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) close (ctrl);#ifdef HAVE_SIGACTION { sigset_t empty; sigemptyset (&empty); sigprocmask (SIG_SETMASK, &empty, 0); }#else sigsetmask (0L);#endif sleep (1); continue; } if (pid && sep->se_wait) { sep->se_wait = pid; if (sep->se_fd >= 0) { FD_CLR (sep->se_fd, &allsock); nsock--; } }#ifdef HAVE_SIGACTION { sigset_t empty; sigemptyset (&empty); sigprocmask (SIG_SETMASK, &empty, 0); }#else sigsetmask (0L);#endif if (pid == 0) { if (debug && dofork) setsid (); if (dofork) { int sock; if (debug) fprintf (stderr, "+ Closing from %d\n", maxsock); for (sock = maxsock; sock > 2; sock--) if (sock != ctrl) close (sock); } run_service (ctrl, sep); } if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) close (ctrl); } }}voidrun_service (int ctrl, struct servtab *sep){ struct passwd *pwd; char buf[50]; if (sep->se_bi) { (*sep->se_bi->bi_fn) (ctrl, sep); } else { if (debug) fprintf (stderr, "%d execl %s\n", getpid (), sep->se_server); dup2 (ctrl, 0); close (ctrl); dup2 (0, 1); dup2 (0, 2); if ((pwd = getpwnam (sep->se_user)) == NULL) { syslog (LOG_ERR, "%s/%s: %s: No such user", sep->se_service, sep->se_proto, sep->se_user); if (sep->se_socktype != SOCK_STREAM) recv (0, buf, sizeof buf, 0); _exit (1); } if (pwd->pw_uid) { if (setgid (pwd->pw_gid) < 0) { syslog (LOG_ERR, "%s: can't set gid %d: %m", sep->se_service, pwd->pw_gid); _exit (1); }#ifdef HAVE_INITGROUPS (void) initgroups (pwd->pw_name, pwd->pw_gid);#endif if (setuid (pwd->pw_uid) < 0) { syslog (LOG_ERR, "%s: can't set uid %d: %m", sep->se_service, pwd->pw_uid); _exit (1); } } execv (sep->se_server, sep->se_argv); if (sep->se_socktype != SOCK_STREAM) recv (0, buf, sizeof buf, 0); syslog (LOG_ERR, "cannot execute %s: %m", sep->se_server); _exit (1); }}voidreapchild (int signo){ int status; pid_t pid; struct servtab *sep; (void)signo; /* shutup gcc */ for (;;) {#ifdef HAVE_WAIT3 pid = wait3 (&status, WNOHANG, (struct rusage *)0);#else pid = wait (&status);#endif if (pid <= 0) break; if (debug) fprintf (stderr, "%d reaped, status %#x\n", pid, status); for (sep = servtab; sep; sep = sep->se_next) if (sep->se_wait == pid) { if (status) syslog (LOG_WARNING, "%s: exit status 0x%x", sep->se_server, status); if (debug) fprintf (stderr, "restored %s, fd %d\n", sep->se_service, sep->se_fd); FD_SET (sep->se_fd, &allsock); nsock++; sep->se_wait = 1; } }}voidconfig (int signo){ int i; struct stat stats; struct servtab *sep; (void)signo; /* Shutup gcc. */ for (sep = servtab; sep; sep = sep->se_next) sep->se_checked = 0; for (i = 0; config_files[i]; i++) { struct stat statbuf; if (stat (config_files[i], &statbuf) == 0) { if (S_ISDIR (statbuf.st_mode)) { DIR *dirp = opendir (config_files[i]); if (dirp) { struct dirent *dp; while ((dp = readdir (dirp)) != NULL) { char *path = calloc (strlen (config_files[i]) + strlen (dp->d_name) + 2, 1); if (path) { sprintf (path,"%s/%s", config_files[i], dp->d_name); if (stat (path, &stats) == 0 && S_ISREG(stats.st_mode)) { nextconfig (path); } free (path); } } closedir (dirp); } } else if (S_ISREG (statbuf.st_mode)) { nextconfig (config_files[i]); } } else { if (signo == 0) fprintf (stderr, "inetd: %s, %s\n", config_files[i], strerror(errno)); else syslog (LOG_ERR, "%s: %m", config_files[i]); } }}voidnextconfig (const char *file){ struct servtab *sep, *cp, **sepp; struct passwd *pwd; FILE * fconfig;#ifdef HAVE_SIGACTION sigset_t sigs, osigs;#else long omask;#endif fconfig = setconfig (file); if (!fconfig) { syslog (LOG_ERR, "%s: %m", file); return; } while ((cp = getconfigent (fconfig, file))) { if ((pwd = getpwnam (cp->se_user)) == NULL) { syslog(LOG_ERR, "%s/%s: No such user '%s', service ignored", cp->se_service, cp->se_proto, cp->se_user); continue; } /* Checking/Removing duplicates */ for (sep = servtab; sep; sep = sep->se_next) if (strcmp (sep->se_service, cp->se_service) == 0 && strcmp (sep->se_proto, cp->se_proto) == 0 && ISMUX(sep) == ISMUX (cp)) break; if (sep != 0) { int i;#ifdef HAVE_SIGACTION sigemptyset (&sigs); sigaddset (&sigs, SIGCHLD); sigaddset (&sigs, SIGHUP); sigaddset (&sigs, SIGALRM); sigprocmask (SIG_BLOCK, &sigs, &osigs);#else omask = sigblock (SIGBLOCK);#endif /* * sep->se_wait may be holding the pid of a daemon * that we're waiting for. If so, don't overwrite * it unless the config file explicitly says don't * wait. */ if (cp->se_bi == 0 && (sep->se_wait == 1 || cp->se_wait == 0)) sep->se_wait = cp->se_wait;#define SWAP(a, b) { char *c = a; a = b; b = c; } if (cp->se_user) SWAP(sep->se_user, cp->se_user); if (cp->se_server) SWAP(sep->se_server, cp->se_server); for (i = 0; i < MAXARGV; i++) SWAP(sep->se_argv[i], cp->se_argv[i]);#ifdef HAVE_SIGACTION sigprocmask (SIG_SETMASK, &osigs, 0);#else sigsetmask (omask);#endif freeconfig (cp); if (debug) print_service (file, "REDO", sep); } else { sep = enter (cp); if (debug) print_service (file, "ADD ", sep); } sep->se_checked = 1; if (ISMUX (sep)) { sep->se_fd = -1; continue; } sp = getservbyname (sep->se_service, sep->se_proto); if (sp == 0) { syslog (LOG_ERR, "%s/%s: unknown service", sep->se_service, sep->se_proto); sep->se_checked = 0; continue; } if (sp->s_port != sep->se_ctrladdr.sin_port) { sep->se_ctrladdr.sin_family = AF_INET; sep->se_ctrladdr.sin_port = sp->s_port; if (sep->se_fd >= 0) close_sep (sep); } if (sep->se_fd == -1) setup (sep); } endconfig (fconfig); /* * Purge anything not looked at above. */#ifdef HAVE_SIGACTION sigemptyset (&sigs); sigaddset (&sigs, SIGCHLD); sigaddset (&sigs, SIGHUP); sigaddset (&sigs, SIGALRM); sigprocmask (SIG_BLOCK, &sigs, &osigs);#else omask = sigblock (SIGBLOCK);#endif sepp = &servtab; while ((sep = *sepp)) { if (sep->se_checked) { sepp = &sep->se_next; continue; } *sepp = sep->se_next; if (sep->se_fd >= 0) close_sep (sep); if (debug) print_service (file, "FREE", sep); freeconfig (sep); free ((char *)sep); }#ifdef HAVE_SIGACTION sigprocmask (SIG_SETMASK, &osigs, 0);#else (void) sigsetmask (omask);#endif}voidretry (int signo){ struct servtab *sep; (void)signo; /* shutup gcc */ timingout = 0; for (sep = servtab; sep; sep = sep->se_next) if (sep->se_fd == -1 && !ISMUX (sep)) setup (sep);}voidsetup (struct servtab *sep){ int on = 1; if ((sep->se_fd = socket (AF_INET, sep->se_socktype, 0)) < 0) { if (debug) fprintf (stderr, "socket failed on %s/%s: %s\n", sep->se_service, sep->se_proto, strerror (errno)); syslog(LOG_ERR, "%s/%s: socket: %m", sep->se_service, sep->se_proto); return; }#define turnon(fd, opt) \setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) if (strcmp (sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && turnon(sep->se_fd, SO_DEBUG) < 0) syslog (LOG_ERR, "setsockopt (SO_DEBUG): %m"); if (turnon (sep->se_fd, SO_REUSEADDR) < 0) syslog (LOG_ERR, "setsockopt (SO_REUSEADDR): %m");#undef turnon if (bind (sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr, sizeof (sep->se_ctrladdr)) < 0) { if (debug) fprintf (stderr, "bind failed on %s/%s: %s\n", sep->se_service, sep->se_proto, strerror (errno)); syslog(LOG_ERR, "%s/%s: bind: %m", sep->se_service, sep->se_proto); (void) close (sep->se_fd); sep->se_fd = -1; if (!timingout) { timingout = 1; alarm (RETRYTIME); } 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 (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 (struct servtab *cp){ struct servtab *sep;#ifdef HAVE_SIGACTION sigset_t sigs, osigs;#else long omask;#endif 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;#ifdef HAVE_SIGACTION sigemptyset (&sigs); sigaddset (&sigs, SIGCHLD); sigaddset (&sigs, SIGHUP); sigaddset (&sigs, SIGALRM); sigprocmask (SIG_BLOCK, &sigs, &osigs);#else omask = sigblock (SIGBLOCK);#endif sep->se_next = servtab; servtab = sep;#ifdef HAVE_SIGACTION sigprocmask (SIG_SETMASK, &osigs, 0);#else sigsetmask (omask);#endif return sep;}struct servtab serv;#ifdef LINE_MAXchar line[LINE_MAX];#elsechar line[2048];#endifFILE *setconfig (const char *file){ return fopen (file, "r");}voidendconfig (FILE *fconfig){ if (fconfig) { (void) fclose (fconfig); }}struct servtab *getconfigent (FILE *fconfig, const char *file){ 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, fconfig); 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++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -