📄 dad.c
字号:
/* dad.c - "directory assistance" lightweight interface to the Directory Service */#ifndef lintstatic char *rcsid = "$Header: /xtel/isode/isode/others/quipu/uips/fred/RCS/dad.c,v 9.0 1992/06/16 12:44:30 isode Rel $";#endif/* * $Header: /xtel/isode/isode/others/quipu/uips/fred/RCS/dad.c,v 9.0 1992/06/16 12:44:30 isode Rel $ * * * $Log: dad.c,v $ * Revision 9.0 1992/06/16 12:44:30 isode * Release 8.0 * *//* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */#include <errno.h>#include <stdio.h>#include <signal.h>#include <varargs.h>#include <pwd.h>#include "config.h"#include "general.h"#include "sys.file.h"#ifdef BSD42#include <sys/wait.h>#endif#include "internet.h"#include "tailor.h"/* DATA */static int debug = 0;static int nbits = FD_SETSIZE;static int uid = 1;static int gid = 1;static int dishpid = NOTOK;static struct sockaddr_in dishsock;static int doomsday = 0;static LLog _pgm_log = { "dad.log", NULLCP, NULLCP, LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK}; LLog *pgm_log = &_pgm_log;static char *myname = "dad";static struct sockaddr_in lo_socket;void arginit (), envinit ();void advise (), adios ();static dadser ();#ifndef lintstatic int da_response ();static int _da_response ();#endifstatic int start_dish ();static rcfile ();static int rcpipe ();#ifdef SYS5struct passwd *getpwnam ();#endif/* MAIN *//* ARGSUSED */main (argc, argv, envp)int argc;char **argv, **envp;{ int nfds, fd, sd; fd_set sfds; struct sockaddr_in in_socket; register struct sockaddr_in *isock = &in_socket; arginit (argv); envinit (); if ((sd = start_tcp_server (&lo_socket, SOMAXCONN, debug ? SO_DEBUG : 0, 0)) == NOTOK) adios ("failed", "start_tcp_server");#ifdef FIOCLEX (void) ioctl (sd, FIOCLEX, NULLCP);#endif (void) setgid (gid); (void) setuid (uid); nfds = sd + 1; FD_ZERO (&sfds); FD_SET (sd, &sfds); for (;;) { fd_set ifds; if (dishpid == NOTOK || kill (dishpid, 0) == NOTOK) (void) start_dish (1); ifds = sfds; /* struct copy */ switch (xselect (nfds, &ifds, NULLFD, NULLFD, 5 * 60)) { case OK: continue; case NOTOK:#ifdef BSD42 if (errno == EINTR) continue;#endif adios ("failed", "xselect"); default: if (!FD_ISSET (sd, &ifds)) continue; break; } if ((fd = join_tcp_client (sd, isock)) == NOTOK) { advise (LLOG_EXCEPTIONS, "failed", "join_tcp_client"); continue; } advise (LLOG_NOTICE, NULLCP, "incoming connection from %s/%d", inet_ntoa (isock -> sin_addr), ntohs (isock -> sin_port)); if (debug) break; switch (fork ()) { case NOTOK: advise (LLOG_EXCEPTIONS, "failed", "fork"); (void) close_tcp_socket (fd); continue; case OK: /* child continues listening for new connections */ (void) close_tcp_socket (fd); isodexport (NULLCP); ll_hdinit (pgm_log, myname); dishpid = NOTOK; continue; default: /* parent handles request 'cause dish knows its pid */#ifdef BSD42 (void) signal (SIGCHLD, SIG_DFL);#else (void) signal (SIGCLD, SIG_DFL);#endif break; } break; } (void) close_tcp_socket (sd); (void) dadser (fd, isock); advise (LLOG_NOTICE, NULLCP, "terminating"); (void) close_tcp_socket (fd); _exit (0); return 0;}/* *//* ARGSUSED */#ifdef BSD42static SFD dishser (sig, code, sc)int sig;long code;struct sigcontext *sc;#elsestatic SFD dishser (i)int i;#endif{ int pid;#ifdef SVR4 int status;#else union wait status;#endif#ifndef BSD42 (void) signal (SIGCLD, dishser);#endif#ifdef SVR4 while ((pid = wait (&status)) != NOTOK#else while ((pid = wait (&status.w_status)) != NOTOK #endif && dishpid != pid) continue; if (pid == dishpid) { advise (LLOG_NOTICE, NULLCP, "dish has terminated"); doomsday++; }}/* *//* ARGSUSED */static dadser (fd, isock)int fd;struct sockaddr_in *isock;{ int i, nfds; char buffer[BUFSIZ], *vec[NVEC + NSLACK + 1]; fd_set sfds; if ((dishpid == NOTOK || kill (dishpid, 0) == NOTOK) && start_dish (0) == NOTOK) { da_response (fd, "-ERR unable to start service"); sleep (5); return; } da_response (fd, "+OK %s", getenv ("DISHPROC"));#ifdef BSD42 (void) signal (SIGCHLD, dishser);#else (void) signal (SIGCLD, dishser);#endif nfds = fd + 1; FD_ZERO (&sfds); FD_SET (fd, &sfds); for (;;) { int eof, n; register char *cp, *ep; fd_set ifds; ifds = sfds; /* struct copy */ switch (xselect (nfds, &ifds, NULLFD, NULLFD, doomsday ? 5 * 60 : NOTOK)) { case OK: if (doomsday) { da_response (fd, "-ERR time-out due to inactivity"); return; } continue; case NOTOK: if (errno == EINTR && doomsday) continue; adios ("failed", "xselect"); default: if (!FD_ISSET (fd, &ifds)) continue; break; } eof = 0; for (ep = (cp = buffer) + sizeof buffer - 1; cp < ep;) { switch (read_tcp_socket (fd, cp, sizeof *cp)) { case NOTOK: advise (LLOG_EXCEPTIONS, "failed", "read_tcp_socket on control connection"); goto were_history; case OK: advise (LLOG_NOTICE, NULLCP, "client closed control connection"); eof = 1; break; default: switch (*cp & 0xff) { case '\n': cp++; break; case 255: /* IAC */ if (read_tcp_socket (fd, cp, sizeof *cp) != 1) adios ("control connection", "eof or error reading"); continue; default: cp++; continue; } break; } break; } *cp = NULL; if (eof && (cp == buffer)) break; if (cp > buffer) cp--; if (*cp == '\n') { *cp = NULL; if (cp > buffer) cp--; } if (*cp == '\r') *cp = NULL; if (debug) (void) fprintf (stderr, "---> %s\n", buffer); if ((n = str2vec (buffer, vec)) < 1) cp = "-ERR null command"; else if (lexequ (vec[0], "intr") == 0 && n == 1) (void) kill (dishpid, SIGINT), cp = "+OK interrupted"; else if (lexequ (vec[0], "quit") == 0 && n == 1) eof = 1, cp = "+OK"; else if (lexequ (vec[0], "stat") == 0 && n == 1) cp = kill (dishpid, 0) != NOTOK ? "+OK" : "-ERR"; else cp = "-ERR command not understood"; da_response (fd, cp); if (eof) break; }#ifdef BSD42 (void) signal (SIGCHLD, SIG_DFL);#else (void) signal (SIGCLD, SIG_DFL);#endif advise (LLOG_NOTICE, NULLCP, "terminating dish"); (void) kill (dishpid, SIGHUP); for (i = 5; i-- > 0; sleep (1)) if (kill (dishpid, 0) == NOTOK) break;were_history: ; (void) kill (dishpid, SIGKILL);}/* */#ifndef lintstatic int da_response (va_alist)va_dcl{ int val; va_list ap; va_start (ap); val = _da_response (ap); va_end (ap); return val;}static int _da_response (ap)va_list ap;{ int cc, fd, len; char buffer[BUFSIZ]; fd = va_arg (ap, int); _asprintf (buffer, NULLCP, ap); if (debug) (void) fprintf (stderr, "<--- %s\n", buffer); (void) strcat (buffer, "\r\n"); len = strlen (buffer); if (write_tcp_socket (fd, buffer, len) != len) adios ("failed", "write_tcp_socket to control connection");}#else/* VARARGS1 */static da_response (fd, fmt)int fd;char *fmt;{ da_response (fd, fmt);}#endif/* */static int start_dish (binding)int binding;{ int ntries, vecp; char buffer[BUFSIZ], *vec[5]; if (dishpid != NOTOK) { (void) kill (dishpid, SIGKILL); dishpid = NOTOK; } (void) unsetenv ("DISHPROC"); (void) unsetenv ("DISHPARENT"); (void) unsetenv ("DISPLAY"); (void) unsetenv ("TERM"); (void) unsetenv ("TERMCAP"); if (get_dish_sock (&dishsock, getpid (), 0) == NOTOK) { advise (LLOG_EXCEPTIONS, NULLCP, "get_dish_sock failed"); return NOTOK; } (void) strcpy (buffer, _isodefile (isodebinpath, "dish"));fork_again: ; advise (LLOG_NOTICE, NULLCP, "starting %s on %s", buffer, getenv ("DISHPROC")); switch (dishpid = vfork ()) { case NOTOK: advise (LLOG_EXCEPTIONS, "fork", "unable to"); return NOTOK; case OK: vecp = 0; vec[vecp++] = "dish"; vec[vecp++] = "-pipe"; vec[vecp++] = "-dad"; vec[vecp++] = "-fast"; vec[vecp] = NULL; (void) execv (buffer, vec); advise (LLOG_FATAL, buffer, "unable to exec"); _exit (1); /* NOTREACHED */ default: for (ntries = 5; ntries-- > 0;) { int n, sd; if ((sd = start_tcp_client ((struct sockaddr_in *) 0, 0)) == NOTOK) break; n = join_tcp_server (sd, &dishsock); (void) close_tcp_socket (sd); if (n != NOTOK) break; sleep (5); if (kill (dishpid, 0) == NOTOK) { advise (LLOG_EXCEPTIONS, NULLCP, "dish not started"); goto fork_again; } } if (ntries <= 0) { advise (LLOG_EXCEPTIONS, NULLCP, "unable to start service"); (void) kill (dishpid, SIGKILL); dishpid = NOTOK; } if (dishpid != NOTOK && binding) rcfile (); break; } return (dishpid != NOTOK ? OK : NOTOK);}/* */static rcfile (){ register char *bp; char buffer[BUFSIZ], command[BUFSIZ], *vec[NVEC + 1]; FILE *fp; if ((fp = fopen (isodefile ("fredrc", 0), "r")) == NULL) return; while (fgets (buffer, sizeof buffer, fp)) { if (*buffer == '#') continue; if (bp = index (buffer, '\n')) *bp = NULL; bzero ((char *) vec, sizeof vec); switch (str2vec (buffer, vec)) { case 0: case 1: continue; default: if (lexequ (vec[0], "area") == 0) break; continue; } (void) sprintf (command, "moveto \"%s\"\n", vec[2] ? vec[2] : vec[1]); if (rcpipe (command) == NOTOK) {failed: ; advise (LLOG_EXCEPTIONS, NULLCP, "pre-caching failed!"); (void) kill (dishpid, SIGKILL); dishpid = NOTOK; break; } } (void) fclose (fp); if (rcpipe ("unbind -noquit\n") == NOTOK) goto failed;}/* */static int rcpipe (command)char *command;{ int cc, len, result, sd; char buffer[BUFSIZ]; if (debug) { (void) fprintf (stderr, "%s", command); (void) fflush (stderr); } if ((sd = start_tcp_client ((struct sockaddr_in *) 0, 0)) == NOTOK) return OK; result = NOTOK; if (join_tcp_server (sd, &dishsock) == NOTOK) { advise (LLOG_EXCEPTIONS, "failed", "join to dish"); goto done; } cc = send (sd, command, len = strlen (command), 0); if (cc != len) { if (cc == NOTOK) advise (LLOG_EXCEPTIONS, "failed", "write to dish"); else advise (LLOG_EXCEPTIONS, NULLCP, "write to dish truncated"); goto done; } for (;;) { if ((cc = recv (sd, buffer, sizeof buffer - 1, 0)) == NOTOK) { advise (LLOG_EXCEPTIONS, "failed", "read from dish"); goto done; } if (cc == 0) break; if (debug) { buffer[cc] = NULL; (void) fprintf (stderr, "%*.*s", cc, cc, buffer); } } if (debug) { (void) fprintf (stderr, "///////\n"); (void) fflush (stderr); } result = OK;done: ; (void) close_tcp_socket (sd); return result;}/* */#ifdef BSD42/* ARGSUSED */static SFD chldser (sig, code, sc)int sig;long code;struct sigcontext *sc;{ union wait status; while (wait3 (&status, WNOHANG, (struct rusage *) NULL) > 0) continue;}#endif/* */static void arginit (vec)char **vec;{ int port; register char *ap; register struct sockaddr_in *lsock = &lo_socket; register struct servent *sp; if (myname = rindex (*vec, '/')) myname++; if (myname == NULL || *myname == NULL) myname = *vec; isodetailor (myname, 0); ll_hdinit (pgm_log, myname); bzero ((char *) lsock, sizeof *lsock); lsock -> sin_family = AF_INET; if ((sp = getservbyname ("da", "tcp")) == NULL) { advise (LLOG_EXCEPTIONS, NULLCP, "%s/%s: unknown service", "tcp", "da"); lsock -> sin_port = htons ((u_short) 411); } else lsock -> sin_port = sp -> s_port; for (vec++; ap = *vec; vec++) { if (*ap == '-') switch (*++ap) { case 'd': debug++; continue; case 'p': if ((ap = *++vec) == NULL || *ap == '-' || (port = atoi (ap)) <= 0) adios (NULLCP, "usage: %s -p portno", myname); lsock -> sin_port = htons ((u_short) port); continue; default: adios (NULLCP, "-%s: unknown switch", ap); } adios (NULLCP, "usage: %s [switches]", myname); } { register struct passwd *pw = getpwnam ("fred"); if (pw && pw -> pw_uid) uid = pw -> pw_uid, gid = pw -> pw_gid; }}/* */static void envinit () { int i, sd; nbits = getdtablesize (); if (debug == 0 && !(debug = isatty (2))) { for (i = 0; i < 5; i++) { switch (fork ()) { case NOTOK: sleep (5); continue; case OK: break; default: _exit (0); } break; } (void) chdir ("/"); if ((sd = open ("/dev/null", O_RDWR)) == NOTOK) adios ("/dev/null", "unable to read"); if (sd != 0) (void) dup2 (sd, 0), (void) close (sd); (void) dup2 (0, 1); (void) dup2 (0, 2);#ifdef SETSID if (setsid () == NOTOK) advise (LLOG_EXCEPTIONS, "failed", "setsid");#endif#ifdef TIOCNOTTY if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) { (void) ioctl (sd, TIOCNOTTY, NULLCP); (void) close (sd); }#else#ifdef SYS5 (void) setpgrp (); (void) signal (SIGINT, SIG_IGN); (void) signal (SIGQUIT, SIG_IGN);#endif#endif#ifdef BSD42 (void) signal (SIGCHLD, chldser);#else (void) signal (SIGCLD, SIG_IGN);#endif } else ll_dbinit (pgm_log, myname);#ifndef sun /* damn YP... */ for (sd = 3; sd < nbits; sd++) if (pgm_log -> ll_fd != sd) (void) close (sd);#endif (void) signal (SIGPIPE, SIG_IGN); ll_hdinit (pgm_log, myname); advise (LLOG_NOTICE, NULLCP, "starting");}/* ERRORS */#ifndef lintvoid adios (va_alist)va_dcl{ va_list ap; va_start (ap); _ll_log (pgm_log, LLOG_FATAL, ap); va_end (ap); _exit (1);}#else/* VARARGS */void adios (what, fmt)char *what, *fmt;{ adios (what, fmt);}#endif#ifndef lintvoid advise (va_alist)va_dcl{ int code; va_list ap; va_start (ap); code = va_arg (ap, int); _ll_log (pgm_log, code, ap); va_end (ap);}#else/* VARARGS */void advise (code, what, fmt)char *what, *fmt;int code;{ advise (code, what, fmt);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -