📄 listen.c
字号:
/* @(#)listen.c 1.1 92/07/30 SMI *//* Copyright (c) 1984 AT&T *//* All Rights Reserved *//* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T *//* The copyright notice above does not evidence any *//* actual or intended publication of such source code. */#ident "@(#)listen:listen.c 1.19.4.4"/* * Network Listener Process * * data base version: * * accepts the following message to start servers: * * NLPS:000:001:svc_code where svc_code is a null terminated * char string ( <= SVC_CODE_SZ bytes) * * command line: * * listen [ -n netspec ] [ -r external_addr ] [ -l external_addr ] * all options take appropriate defaults for STARLAN NETWORK. * -r: address to listen for remote login requests. * -l: address to listen for listener service requests. * *//* system include files */#include <fcntl.h>#include <signal.h>#include <stdio.h>#include <varargs.h>#include <string.h>#include <errno.h>#include <memory.h>#include <sys/ioctl.h>#include <sys/utsname.h>#include <tiuser.h>#include <sys/param.h>#include <sys/types.h>#include <sys/stat.h>#include <values.h>#include <ctype.h>#include <pwd.h>#include <grp.h>#include <sys/poll.h>#include <sys/dir.h>#include <sys/stropts.h>/* S4 status manager interface */#ifdef S4#include <status.h>#endif/* listener include files */#include "lsparam.h" /* listener parameters */#include "lsfiles.h" /* listener files info */#include "lserror.h" /* listener error codes */#include "lsnlsmsg.h" /* NLPS listener protocol */#include "lssmbmsg.h" /* MS_NET identifier */#include "lsdbf.h" /* data base file stuff */#include "nlsenv.h" /* environ variable names */#include "listen.h"/* defines */#define NAMESIZE (NAMEBUFSZ-1)#define SPLhi() Splflag = 1#define SPLlo() Splflag = 0#define GEN 1#define LOGIN 0/* global variables */int Child; /* set if process is a listener child (worker bee) */int Pid; /* listener's process ID (original listener's child) */char *Progname; /* listener's basename (from argv[0]) */static char Provbuf[PATHSIZE];char *Provider = Provbuf; /* name of transport provider */char *Netspec = NETSPEC;int Nfd1 = -1; /* Net fd's, init to illegal */int Nfd2 = -1;int Nfd3 = -1;char _rlbuf[NAMEBUFSZ]; /* remote login name */char _lsbuf[NAMEBUFSZ]; /* listener service name */char *Nodename = _rlbuf; /* my normalized name (login svc)*/char *Pnodename = _lsbuf; /* my permuted name (listener svc) */char *Rxname = NULL; /* remote login external name */char *Lxname = NULL; /* listener svc external name */int Rlen = NAMEBUFSZ;int Llen = NAMEBUFSZ;struct call_list Lfree; /* network call save free list */struct call_list Lpend; /* network call save pending list */unsigned int Lmaxcon; /* maximum # of connections for gen. listen */struct call_list Rfree; /* rem login call save free list */struct call_list Rpend; /* rem login call save pending list */unsigned int Rmaxcon; /* maximum # of connections for remote login */char *Basedir = BASEDIR; /* base dir */char *Home; /* listener's home directory */char Homebuf[BUFSIZ];FILE *Debugfp = stderr;FILE *Logfp;int Pidfd;int Background; /* are we in background? */char Lastmsg[BUFSIZ]; /* contains last msg logged (by stampbuf) */int Logmax = LOGMAX;int Validate; /* from -v flag: validate data base only */int Lckfd;int Sigusr1; /* data base file changed */int Splflag; /* logfile critical region flag */static char *badnspmsg = "Bad netspec on command line ( Pathname too long )\n";static char *badstart = "Listener failed to start properly\n";main(argc, argv)int argc;char **argv;{ register char **av; struct stat buf; int ret; extern void exit(), logexit(); /* * pre-initialization: */ if (geteuid() != 0) { fprintf(stderr, "Must be root to start listener\n"); logexit(1, badstart); } /* * quickly, find -n [ and -v ] argument on command line */ av = argv; ++av; /* skip argv[0] */ while(*av) { if (!strncmp(*av,"-n", 2)) { if (*(*av + 2) == NULL) Netspec = *++av; else Netspec = (*av + 2); } else { if (!strcmp(*av, "-v")) ++Validate; } ++av; } if (strlen(Netspec) > PATHSIZE) { fprintf(stderr, badnspmsg); logexit(1, badstart); } strcat(Homebuf,Basedir); strcat(Homebuf,"/"); strcat(Homebuf,Netspec); Home = Homebuf; strcpy(Provbuf, "/dev/"); strcat(Provbuf, Netspec); if (chdir(Home)) { fprintf(stderr,"Cannot change directory to %s\n",Home); logexit(1, badstart); } /* * -v flag tells listener to validate the data base only */ if (Validate) { Logfp = stderr;#ifdef DEBUGMODE umask(022); if (!(Debugfp = fopen(VDBGNAME, "w"))) { fprintf(stderr,"Can't create debug file: %s in %s\n", VDBGNAME, Home); exit(1); /* don't log validation exits */ }#endif ret = init_dbf(); logmessage(ret ? "Bad data base file": "Good data base file"); exit(ret); /* don't log validation exits */ } umask(0); if (((Lckfd = open(LCKNAME, O_WRONLY | O_CREAT, 0666 )) == -1) || (locking(Lckfd, 2, 0L) == -1)) { fprintf(stderr, "Errno %d opening lock file %s/%s.\n", errno, Home, LCKNAME); fprintf(stderr, "Listener may already be running!\n"); logexit(1, badstart); } write(Lckfd, "lock", 4); if (locking(Lckfd, 1, 0L) == -1) { fprintf(stderr, "Errno %d while locking lock file\n", errno); logexit(1, badstart); } umask(022); if (stat(LOGNAME, &buf) == 0) { /* file exists, try and save it but if we can't don't worry */ unlink(OLOGNAME); if (link(LOGNAME, OLOGNAME)) { fprintf(stderr, "Lost old log file\n"); } unlink(LOGNAME); }/* * At this point, either it didn't exist, we successfully saved it * or we couldn't save it. In any case, just open and continue. */ Logfp = fopen(LOGNAME, "w");#ifdef DEBUGMODE Debugfp = fopen(DBGNAME, "w");#endif#ifdef DEBUGMODE if ((!Logfp) || (!Debugfp)) {#else if (!Logfp) {#endif fprintf(stderr,"listener cannot create file(s) in %s\n",Home); logexit(1, badstart); } logmessage("@(#)listen:listen.c 1.19.4.4");#ifdef DEBUGMODE logmessage("Listener process with DEBUG capability");#endif initialize(argv, argc); listen();}initialize(argv, argc)int argc;char **argv;{ /* try to get my "basename" */ DEBUG((9,"in initialize")); Progname = strrchr(argv[0], '/'); if (Progname && Progname[1]) ++Progname; else Progname = argv[0]; cmd_line_args(argv,argc); init_dbf(); pid_open(); /* create pid file */ net_open(); /* init, open, bind names */ catch_signals(); divorce_parent(); logmessage("Initialization Complete");}/* * cmd_line_args uses getopt(3) to read command line arguments. */static char *Optflags = "n:r:l:L:";cmd_line_args(argv,argc)int argc;char **argv;{ register i; extern char *optarg; extern int optind, opterr; extern int isdigits(); int errflag = 0; DEBUG((9,"in cmd_line_args"));#ifdef DEBUGMODE DEBUG((9,"cmd_line_args: argc = %d",argc)); for (i=0; i < argc; i++) DEBUG((9,"argv[%d] = %s",i,argv[i]));#else opterr = 1; /* disable getopt's stderr output */#endif /* DEBUGMODE */ while ( (i = getopt(argc, argv, Optflags)) != EOF ) switch (i) { case 'n': /* netspec */ break; /* (read previously) */ case 'r': /* remote login external addr */ Rxname = optarg; break; case 'l': /* listener svc external addr */ Lxname = optarg; break; case 'L': /* max log entries */ if (isdigits(optarg)) { Logmax = atoi( optarg ); if (Logmax < LOGMIN) Logmax = LOGMIN; DEBUG((5, "Logmax = %d", Logmax)); } else ++errflag; break; case '?': ++errflag; break; }#ifndef S4 if (!Lxname) ++errflag;#endif if (errflag) error(E_CMDLINE, EXIT | NOCORE);}/* * pid_open: * * open pidfile with specified oflags and modes * */static char *pidopenmsg ="Can't create process ID file in home directory";pid_open(){ int pid; int ret; unsigned i; char pidstring[20]; DEBUG((9,"in pid_open()")); if ((Pidfd = open(PIDNAME, PIDOFLAG, PIDMODE)) == -1) { logmessage(pidopenmsg); error(E_CREAT, EXIT | NOCORE | NO_MSG); } pid = getpid(); i = sprintf(pidstring, "%d", pid) + 1; if ((ret = write(Pidfd, pidstring, i)) != i) { if (ret < 0) sys_error(E_PIDWRITE, EXIT); else error(E_PIDWRITE, EXIT); } (void) lseek(Pidfd, 0L, 0);}/* * net_open: open and bind communications channels * The name generation code in net_open, open_bind and bind is, * for the most part, specific to STARLAN NETWORK. * This name generation code is included in the listener * as a developer debugging aid. */net_open(){ extern char *memcpy(); extern char *t_alloc(); extern int nlsc2addr(); void queue();#ifdef S4 register char *p; extern char *getnodename(); extern char *nlsname(); /* STARLAN specific */#endif#ifdef CHARADDR char pbuf[NAMEBUFSZ + 1];#endif register int i; register struct callsave *tmp; char scratch[BUFSIZ]; DEBUG((9,"in net_open")); DEBUG((3, "Rxname = %s", Rxname)); DEBUG((3, "Lxname = %s", Lxname)); if (Rxname) { /* -r cmd line argument */ DEBUG((3, "Decoding remote login address")); if ((Rlen = nlsc2addr(Nodename, NAMEBUFSZ, Rxname)) < 0) { logmessage("Error decoding remote login name"); error(E_CMDLINE, EXIT | NOCORE | NO_MSG); } }#ifdef S4 else { p = getnodename(); DEBUG((3, "machine nodename = %s", p)); Rlen = strlen(p); (void)memcpy(Nodename, p, Rlen); }#endif /* S4 */ if (Lxname) { /* -l cmd line argument */ DEBUG((3, "Decoding listener service address")); if ((Llen = nlsc2addr(Pnodename, NAMEBUFSZ, Lxname)) < 0) { logmessage("Error decoding listener service name"); error(E_CMDLINE, EXIT | NOCORE | NO_MSG); } }#ifdef S4 else { p = getnodename(); DEBUG((3, "machine nodename = %s", p)); p = nlsname(p); Llen = strlen(p); (void)memcpy(Pnodename,p,Llen); DEBUG((3,"nlsname = %s, Pnodename = %s, Llen = %d", p, Pnodename, Llen)); }#endif /* S4 */#ifdef CHARADDR /* this debug code assumes addresses are printable characters */ /* not necessarily null terminated. */ if (Rxname) { (void)memcpy(pbuf, Nodename, Rlen); *(pbuf+Rlen) = (char)0; DEBUG((3, "Nodename = %s, length = %d", pbuf, Rlen)); } (void)memcpy(pbuf, Pnodename, Llen); *(pbuf+Llen) = (char)0; DEBUG((3, "Pnodename = %s, length = %d", pbuf, Llen));#endif /* CHARADDR */ if (Rxname) { Nfd1 = open_bind(Nodename, MAXCON, Rlen, &Rmaxcon); sprintf(scratch, "Rmaxcon is %d", Rmaxcon); logmessage(scratch); }/* * set up call save list for remote login service */ if (Rxname) { Rfree.cl_head = (struct callsave *) NULL; Rfree.cl_tail = (struct callsave *) NULL; for (i = 0; i < Rmaxcon; ++i) { if ((tmp = (struct callsave *) malloc(sizeof(struct callsave))) == NULL) { error(E_MALLOC, NOCORE | EXIT); } if ((tmp->c_cp = (struct t_call *) t_alloc(Nfd1, T_CALL, T_ALL)) == NULL) { tli_error(E_T_ALLOC, EXIT); } queue(&Rfree, tmp); } } Nfd2 = open_bind(Pnodename, MAXCON, Llen, &Lmaxcon); sprintf(scratch, "Lmaxcon is %d", Lmaxcon); logmessage(scratch);/* * set up call save list for general network listen service */ Lfree.cl_head = (struct callsave *) NULL; Lfree.cl_tail = (struct callsave *) NULL; for (i = 0; i < Lmaxcon; ++i) { if ((tmp = (struct callsave *) malloc(sizeof(struct callsave))) == NULL) { error(E_MALLOC, NOCORE | EXIT); } if ((tmp->c_cp = (struct t_call *) t_alloc(Nfd2, T_CALL, T_ALL)) == NULL) { tli_error(E_T_ALLOC, EXIT); } queue(&Lfree, tmp); } if ( ((Nfd1 == -1) && Rxname) || (Nfd2 == -1) ) error(E_OPENBIND, EXIT); logmessage("Net opened, names bound");}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -