📄 servtab.c
字号:
s = strchr(sep->se_service, '/'); if (!s) return "No RPC version"; *s++ = 0; sep->se_rpcversl = strtol(s, &t, 0); if (t==s) return "Invalid RPC version"; if (*t=='-') { s = t+1; sep->se_rpcversh = strtol(s, &t, 0); if (t==s) return "Invalid RPC high version"; } else { sep->se_rpcversh = sep->se_rpcversl; }#else return "No support for RPC services compiled in";#endif } } s = strchr(fields[3], '.'); if (s) { *s++ = 0; sep->se_max = atoi(s); } else { sep->se_max = TOOMANY; } sep->se_wait = !strcmp(fields[3], "wait"); free(fields[3]); s = strchr(fields[4], '.'); if (s) { *s++ = 0; sep->se_group = s; } else { sep->se_group = NULL; } sep->se_user = fields[4]; sep->se_server = fields[5]; if (!strcmp(fields[5], "internal")) { sep->se_bi = find_builtin(sep->se_socktype, sep->se_service); if (sep->se_bi==NULL) { return "Invalid internal service"; } sep->se_wait = sep->se_bi->bi_wait; } else { sep->se_bi = NULL; } /* The rest are argv[]. */ for (i=6; i<nfields; i++) { sep->se_argv[i-6] = fields[i]; } /* Most programs core if argv[0] is null. */ if (!sep->se_argv[0]) { sep->se_argv[0] = dostrdup(sep->se_server); } return NULL;}staticconst char *nexttoken(void){ static char linebuf[256]; char *s; /* * Hack: linebuf[0-1] is not read into; it is always "Q ". This permits * us to initialize strtok so that it will return the first word on * the line on the _next_ call if we so choose. */ linebuf[0] = 'Q'; linebuf[1] = ' '; s = strtok(NULL, " \t\n"); if (s!=NULL) return s; do { if (fgets(linebuf+2, sizeof(linebuf)-2, fconfig)==NULL) { return NULL; } } while (linebuf[2]=='#'); if (!strchr(" \t", linebuf[2])) { /* Not a continuation line - send back EOL */ strtok(linebuf, " \t\n"); /* returns Q */ return ""; } s = strtok(linebuf+2, " \t\n"); if (!s) return ""; /* empty line -> send EOL */ return s;}staticvoidloadconfigfile(void (*sendents)(struct servtab *)){ /* 6 fields plus argv, but the last entry of argv[] must remain null */ char *fields[MAXARGV+6-1]; int nfields=0; int warned=0; const char *s; int eof=0; struct servtab assm; /* assemble entries into here */ char junk[4]; /* * Insure strtok() will start at EOL. */ junk[0] = 'Q' ; junk[1] = 0; strtok(junk, " \t\n"); while (!eof) { s = nexttoken(); if (!s&& nfields<1) { eof = 1; } else if (!s || (!*s && nfields>0)) { const char *errmsg; errmsg = assemble_entry(&assm, nfields, fields); if (errmsg) { syslog(LOG_WARNING, "Bad config for %s: %s" " (skipped)", fields[0], errmsg); } else { sendents(&assm); } if (!s) { eof = 1; } else { nfields = 0; warned = 0; } } else if (!*s) { /* blank line */ } else if (nfields < MAXARGV+6) { fields[nfields++] = dostrdup(s); } else if (!warned) { syslog(LOG_WARNING, "%s: too many arguments, max %d", fields[0], MAXARGV); warned = 1; } }}#endif/********* config loading ****************************************/static intsetconfig(void){ if (fconfig != NULL) { fseek(fconfig, 0L, SEEK_SET); return (1); } fconfig = fopen(configfile, "r"); return (fconfig != NULL);}static voidendconfig(void){ if (fconfig) { (void) fclose(fconfig); fconfig = NULL; }}static voidfreeconfig(struct servtab *cp){ int i; if (cp->se_service) free(cp->se_service); cp->se_service = NULL; cp->se_address = NULL; /* points into se_service */ if (cp->se_proto) free(cp->se_proto); cp->se_proto = NULL; if (cp->se_user) free(cp->se_user); cp->se_user = NULL; cp->se_group = NULL; /* points into se_user */ if (cp->se_server) free(cp->se_server); cp->se_server = NULL; for (i = 0; i < MAXARGV; i++) { if (cp->se_argv[i]) free(cp->se_argv[i]); cp->se_argv[i] = NULL; }}/* * print_service: * Dump relevant information to stderr */static voidprint_service(const char *action, struct servtab *sep){ if (isrpcservice(sep)) fprintf(stderr, "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%lx server=%s\n", action, sep->se_service, sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto, sep->se_wait, sep->se_max, sep->se_user, sep->se_group, (unsigned long)sep->se_bi, sep->se_server); else fprintf(stderr, "%s: %s proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%lx server=%s\n", action, sep->se_service, sep->se_proto, sep->se_wait, sep->se_max, sep->se_user, sep->se_group, (unsigned long)sep->se_bi, sep->se_server);}staticvoidloadconfigent(struct servtab *cp){ struct servtab *sep; unsigned n; /* * dholland 7/14/1997: always use the canonical service * name to protect against silly configs that list a * service twice under different aliases. This has been * observed in the wild thanks to Slackware... * Note: this is a patch, not a fix. The real fix is * to key the table by port and protocol, not service name * and protocol. */ if (cp->se_family==AF_INET && !isrpcservice(cp)) { u_short port = htons(atoi(cp->se_service)); if (!port) { struct servent *sp; sp = getservbyname(cp->se_service, cp->se_proto); if (sp != NULL) { /* bogus services are caught later */ if (strcmp(cp->se_service, sp->s_name)) { /* * Ugh. Since se_address points into * se_service, we need to copy both * together. Ew. */ char *tmp, *tmp2 = NULL; const char *addr = cp->se_address; size_t len = strlen(sp->s_name)+1; if (addr==NULL) addr = ""; len += strlen(addr)+1; tmp = domalloc(len); strcpy(tmp, cp->se_service); if (cp->se_address) { tmp2 = tmp+strlen(tmp)+1; strcpy(tmp2, cp->se_address); } free(cp->se_service); cp->se_service = tmp; cp->se_address = tmp2; } } } } /* End silly patch */ sep = find_same_service(cp); if (sep != NULL) { int i; if (sep->se_checked) { syslog(LOG_WARNING, "extra conf for service %s (skipped)\n", service_name(sep)); return; } #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;} /* * 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; if (cp->se_max != sep->se_max) SWAP(int, cp->se_max, sep->se_max); if (cp->se_user) SWAP(char *, sep->se_user, cp->se_user); if (cp->se_group) SWAP(char *, sep->se_group, cp->se_group); if (cp->se_server) SWAP(char *, sep->se_server, cp->se_server); if (cp->se_address) { /* must swap se_service; se_address points into it */ SWAP(char *, sep->se_service, cp->se_service); SWAP(char *, sep->se_address, cp->se_address); } for (i = 0; i < MAXARGV; i++) SWAP(char *, sep->se_argv[i], cp->se_argv[i]);#undef SWAP if (isrpcservice(sep)) unregister_rpc(sep); sep->se_rpcversl = cp->se_rpcversl; sep->se_rpcversh = cp->se_rpcversh; freeconfig(cp); if (debug) { print_service("REDO", sep); } } else { sep = enter(cp); if (debug) print_service("ADD ", sep); } sep->se_checked = 1; switch (sep->se_family) { case AF_UNIX: if (sep->se_fd != -1) break; (void)unlink(sep->se_service); n = strlen(sep->se_service); if (n > sizeof(sep->se_ctrladdr_un.sun_path) - 1) n = sizeof(sep->se_ctrladdr_un.sun_path) - 1; strncpy(sep->se_ctrladdr_un.sun_path, sep->se_service, n); sep->se_ctrladdr_un.sun_path[n] = 0; sep->se_ctrladdr_un.sun_family = AF_UNIX; sep->se_ctrladdr_size = n + sizeof sep->se_ctrladdr_un.sun_family; setup(sep); break; case AF_INET: sep->se_ctrladdr_in.sin_family = AF_INET; sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in; if (isrpcservice(sep)) { struct rpcent *rp; sep->se_rpcprog = atoi(sep->se_service); if (sep->se_rpcprog == 0) { rp = getrpcbyname(sep->se_service); if (rp == 0) { syslog(LOG_ERR, "%s: unknown service", sep->se_service); return; } sep->se_rpcprog = rp->r_number; } if (sep->se_fd == -1) setup(sep); if (sep->se_fd != -1) register_rpc(sep); } else { u_short port = htons(atoi(sep->se_service)); if (!port) { struct servent *sp; sp = getservbyname(sep->se_service, sep->se_proto); if (sp == 0) { syslog(LOG_ERR, "%s: unknown service", service_name(sep)); return; } port = sp->s_port; } if (port != sep->se_ctrladdr_in.sin_port) { sep->se_ctrladdr_in.sin_port = port; if (sep->se_fd != -1) { closeit(sep); } } if (sep->se_fd == -1) setup(sep); } }}voidconfig(int signum){ register struct servtab *sep, **sepp; (void)signum; if (!setconfig()) { syslog(LOG_ERR, "%s: %m", configfile); return; } for (sep = servtab; sep; sep = sep->se_next) sep->se_checked = 0;#if 0 /* old version */ while ((cp = getconfigent())!=NULL) { loadconfigent(cp); }#else loadconfigfile(loadconfigent);#endif endconfig(); /* * Purge anything not looked at above. */ sepp = &servtab; while ((sep = *sepp) != NULL) { if (sep->se_checked) { sepp = &sep->se_next; continue; } *sepp = sep->se_next; if (sep->se_fd != -1) { closeit(sep); } if (isrpcservice(sep)) unregister_rpc(sep); if (sep->se_family == AF_UNIX) (void)unlink(sep->se_service); if (debug) print_service("FREE", sep); freeconfig(sep); free((char *)sep); }}/********* SIGALRM handler ******************************/voidrestart_services(void){ struct servtab *sep; for (sep = servtab; sep; sep = sep->se_next) { if (sep->se_fd == -1) { switch (sep->se_family) { case AF_UNIX: case AF_INET: setup(sep); if (sep->se_fd != -1 && isrpcservice(sep)) register_rpc(sep); break; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -