📄 listen.c
字号:
sprintf(scratch, nlsunknown, svc_code_p); logmessage(scratch); nls_reply(NLSUNKNOWN, scratch); } } else error(E_BAD_FORMAT, CONTINUE); /* if we're still here, server didn't get exec'ed */ return(-1);}/* * nls_chkmsg: validate message and return fields to caller. * returns: TRUE == good format * FALSE== bad format */nls_chkmsg(bp, size, lowp, highp, svc_code_p)char *bp, *svc_code_p;int size, *lowp, *highp;{ /* first, make sure bp is null terminated */ if ((*(bp + size - 1)) != (char)0) return(0); /* scanf returns number of "matched and assigned items" */ return(sscanf(bp, "%*4c:%3d:%3d:%s", lowp, highp, svc_code_p) == 3);}/* * nls_reply: send the "service request response message" * when appropriate. (Valid if running version 2 or greater). * Must use write(2) since unknown modules may be pushed. * * Message format: * protocol_verion_# : message_code_# : message_text */static char *srrpprot = "%d:%d:%s";nls_reply(code, text)register code;register char *text;{ char scratch[256]; /* Nlsversion = -1 for login service */ if (Nlsversion >= 2) { DEBUG((7, "nls_reply: sending response message")); sprintf(scratch, srrpprot, Nlsversion, code, text); t_snd(0, scratch, strlen(scratch)+1, 0); }}/* * common code to start a server process (for any service) * if optional argv is given, info comes from o_argv, else pointer * to dbf struct is used. In either case, first argument in argv is * full pathname of server. Before exec-ing the server, the caller's * logical address, opt and udata are addded to the environment. */start_server(netfd, dbp, o_argv, call)int netfd;register dbf_t *dbp;register char **o_argv;struct t_call *call;{ char *path; char **argvp; extern char **environ; extern struct passwd *getpwnam(); extern void endpwent(); extern struct group *getgrgid(); register struct passwd *pwdp; struct group *grpp; char msgbuf[256]; register dbf_t *wdbp = dbp; /* * o_argv is set during SMB service setup only, in * which case dbp is NULL. */ if (o_argv) { argvp = o_argv; if ((wdbp = getdbfentry(DBF_SMB_CODE)) == NULL) { /* this shouldn't happen because at this point we've already found it once */ logmessage("SMB message, missing data base entry"); exit(2); /* server, don't log */ } } else argvp = mkdbfargv(dbp); path = *argvp; /* set up stdout and stderr before pushing optional modules */ (void) close(1); (void) close(2); if (dup(0) != 1 || dup(0) != 2) { logmessage("Dup of fd 0 failed"); exit(2); /* server, don't log */ } sprintf(msgbuf,"Starting server (%s)",path); nls_reply(NLSSTART, msgbuf); logmessage(msgbuf); /* after pushmod, tli calls are questionable? */ if (dbp && pushmod(netfd, dbp->dbf_modules)) { logmessage("Can't push server's modules: exit"); exit(2); /* server, don't log */ } rst_signals(); if (wdbp == NULL) { logmessage("No database entry"); exit(2); /* server, don't log */ }/* if ((pwdp = getpwnam(wdbp->dbf_id)) == NULL) { sprintf(msgbuf, "Missing or bad passwd entry for <%s>", wdbp->dbf_id); logmessage(msgbuf); exit(2); */ /* server, don't log *//* } if (setgid(pwdp->pw_gid)) { if ((grpp = getgrgid(pwdp->pw_gid)) == NULL) { sprintf(msgbuf, "No group entry for %d", pwdp->pw_gid); logmessage(msgbuf); exit(2); */ /* server, don't log *//* } sprintf(msgbuf, "Cannot set group id to %s", grpp->gr_name); logmessage(msgbuf); exit(2); */ /* server, don't log *//* } if (setuid(pwdp->pw_uid)) { sprintf(msgbuf, "Cannot set user id to %s", wdbp->dbf_id); logmessage(msgbuf); exit(2); */ /* server, don't log *//* } if (chdir(pwdp->pw_dir)) { sprintf(msgbuf, "Cannot chdir to %s", pwdp->pw_dir); logmessage(msgbuf); exit(2); */ /* server, don't log *//* } DEBUG((9, "New uid %d New gid %d", getuid(), getgid())); if (senviron(call, pwdp->pw_dir)) { logmessage("Can't expand server's environment"); } endpwent();*/ execve(path, argvp, environ); /* exec returns only on failure! */ logmessage("listener could not exec server"); sys_error(E_SYS_ERROR, CONTINUE); return(-1);}/* * senviron: Update environment before exec-ing the server: * The callers logical address is placed in the * environment in hex/ascii character representation. * * Note: no need to free the malloc'ed buffers since this process * will either exec or exit. */static char provenv[2*PATHSIZE];static char homeenv[BUFSIZ];static char tzenv[BUFSIZ];#define TIMEZONE "/etc/TIMEZONE"#define TZSTR "TZ="intsenviron(call, home)register struct t_call *call;register char *home;{ register char *p; char scratch[BUFSIZ]; extern void nlsaddr2c(); extern char *getenv(); char *parse(); FILE *fp; sprintf(homeenv, "HOME=%s", home); putenv(homeenv);/* * The following code handles the case where the listener was started with * no environment. If so, supply a reasonable default path and find out * what timezone we're in so the log file is consistent. */ if (getenv("PATH") == NULL) putenv("PATH=/bin:/etc:/usr/bin"); if (getenv("TZ") == NULL) { fp = fopen(TIMEZONE, "r"); if (fp) { while (fgets(tzenv, BUFSIZ, fp)) { if (scratch[strlen(tzenv) - 1] == '\n') tzenv[strlen(tzenv) - 1] = '\0'; if (!strncmp(TZSTR, tzenv, strlen(TZSTR))) { putenv(parse(tzenv)); break; } } fclose(fp); } else { sprintf(scratch, "couldn't open %s, default to GMT", TIMEZONE); logmessage(scratch); } } if ((p = (char *)malloc(((call->addr.len)<<1) + 18)) == NULL) return(-1); strcpy(p, NLSADDR); strcat(p, "="); nlsaddr2c(p + strlen(p), call->addr.buf, call->addr.len); DEBUG((7, "Adding %s to server's environment", p)); putenv(p); if ((p = (char *)malloc(((call->opt.len)<<1) + 16)) == NULL) return(-1); strcpy(p, NLSOPT); strcat(p, "="); nlsaddr2c(p + strlen(p), call->opt.buf, call->opt.len); DEBUG((7, "Adding %s to server's environment", p)); putenv(p); p = provenv; strcpy(p, NLSPROVIDER); strcat(p, "="); strcat(p, Netspec); DEBUG((7, "Adding %s to environment", p)); putenv(p); if ((p = (char *)malloc(((call->udata.len)<<1) + 20)) == NULL) return(-1); strcpy(p, NLSUDATA); strcat(p, "="); if ((int)call->udata.len >= 0) nlsaddr2c(p + strlen(p), call->udata.buf, call->udata.len); DEBUG((7, "Adding %s to server's environment", p)); putenv(p); return (0);}/* * parse: Parse TZ= string like init does for consistency * Work on string in place since result will * either be the same or shorter. */char *parse(s)char *s;{ register char *p; register char *tp; char scratch[BUFSIZ]; int delim; tp = p = s + strlen("TZ="); /* skip TZ= in parsing */ if ((*p == '"') || (*p == '\'')) { /* it is quoted */ delim = *p++; for (;;) { if (*p == '\0') { /* etc/TIMEZONE ill-formed, go without TZ */ sprintf(scratch, "%s ill-formed", TIMEZONE); logmessage(scratch); strcpy(s, "TZ="); return(s); } if (*p == delim) { *tp = '\0'; return(s); } else { *tp++ = *p++; } } } else { /* look for comment or trailing whitespace */ for ( ; *p && !isspace(*p) && *p != '#'; ++p) ; /* if a comment or trailing whitespace, trash it */ if (*p) { *p = '\0'; } return(s); }}/* * login: Start the intermediary process that handles * pseudo-tty getty/login service. */login(fd, call)register fd;struct t_call *call;{ register dbf_t *dbp; DEBUG((9,"in login (request for intermediary)")); if (!(dbp = getdbfentry(DBF_INT_CODE)) || (dbp->dbf_flags & DBF_OFF)) { log( E_NOINTERMEDIARY ); return(-1); } start_server(fd, dbp, (char **)0, call); /* returns only on failure! */ logmessage("listener could not exec the intermediary process"); sys_error(E_SYS_ERROR, CONTINUE); return(-1);}/* * isdigits: string version of isdigit. (See ctype(3)) */intisdigits(p)register char *p;{ register int flag = 1; if (!strlen(p)) return(0); while (*p) if (!isdigit(*p++)) flag = 0; return(flag);}/* * pushmod: push modules if defined in the data base entry. * * NOTE: there are no modules to push in WTLI. * so this code is a noop on the S4. However, * the data base file is compatible. * * WARNING: This routine writes into the in-memory copy * of the database file. Therefore, after it is called, * the incore copy of the database file will no longer be valid. */intpushmod(fd, mp)int fd;register char *mp;{#ifndef S4 register char *cp = mp; register int pflag = 0; char name[32]; DEBUG((9,"in pushmod:")); if (!mp) { DEBUG((9,"NULL list: exiting pushmod")); return(0); } while (*cp) { if (*cp == ',') { *cp = (char)0; if (*mp && strcmp(mp, "NULL")) { /* * if first time thru, pop off TIMOD if it is on top of stream */ if (!pflag) { pflag++; if (ioctl(fd, I_LOOK, name) >= 0) { if (strcmp(name, "timod") == 0) { if (ioctl(fd, I_POP) < 0) DEBUG((9,"pushmod: I_POP failed")); } } } DEBUG((9,"pushmod: about to push %s",mp)); if (ioctl(fd, I_PUSH, mp) < 0) { DEBUG((9,"pushmod: ioctl failed, errno = %d",errno)); return(1); } } /* if */ mp = ++cp; continue; } /* if */ cp++; } /* while */ DEBUG((9,"exiting pushmod:"));#endif return(0);}intl_rcv(fd, bufp, bytes, flagp)int fd;char *bufp;int bytes;int *flagp;{ register int n; register int count = bytes; register char *bp = bufp; DEBUG((9, "in l_rcv")); do { *flagp = 0; n = t_rcv(fd, bp, count, flagp); if (n < 0) { DEBUG((9, "l_rcv, t_errno is %d", t_errno));#ifdef DEBUGMODE if (t_errno == TLOOK) { DEBUG((9, "l_rcv, t_look returns %d", t_look(fd))); }#endif return(n); } count -= n; bp += n; } while (count > 0); return(bp - bufp);}/* * clr_call: clear out a call structure */clr_call(call)struct t_call *call;{ call->sequence = 0; call->addr.len = 0; call->opt.len = 0; call->udata.len = 0; memset(call->addr.buf, 0, call->addr.maxlen); memset(call->opt.buf, 0, call->opt.maxlen); memset(call->udata.buf, 0, call->udata.maxlen);}/* * pitchcall: remove call from pending list */pitchcall(free, pending, disc)struct call_list *free;struct call_list *pending;struct t_discon *disc;{ register struct callsave *p, *oldp; DEBUG((9, "pitching call, sequence # is %d", disc->sequence)); if (EMPTY(pending)) { disc->sequence = -1; return; } p = pending->cl_head; oldp = (struct callsave *) NULL; while (p) { if (p->c_cp->sequence == disc->sequence) { if (oldp == (struct callsave *) NULL) { pending->cl_head = p->c_np; if (pending->cl_head == (struct callsave *) NULL) { pending->cl_tail = (struct callsave *) NULL; } } else if (p == pending->cl_tail) { oldp->c_np = p->c_np; pending->cl_tail = oldp; } else { oldp->c_np = p->c_np; } clr_call(p->c_cp); queue(free, p); disc->sequence = -1; return; } oldp = p; p = p->c_np; } logmessage("received disconnect with no pending call"); disc->sequence = -1; return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -