int main(int argc,char **argv,char **envp) { int piin[2]; int piout[2]; pid[fmt_ulong(pid,getpid())] = 0; if (argc < 2) strerr_die1x(100,"recordio: usage: recordio program [ arg ... ]"); if (pipe(piin) == -1) strerr_die2sys(111,FATAL,"unable to create pipe: "); if (pipe(piout) == -1) strerr_die2sys(111,FATAL,"unable to create pipe: "); switch(fork()) { case -1: strerr_die2sys(111,FATAL,"unable to fork: "); case 0: sig_ignore(sig_pipe); close(piin[0]); close(piout[1]); doit(piin[1],piout[0]); } close(piin[1]); close(piout[0]); if (fd_move(0,piin[0]) == -1) strerr_die2sys(111,FATAL,"unable to move descriptors: "); if (fd_move(1,piout[1]) == -1) strerr_die2sys(111,FATAL,"unable to move descriptors: "); pathexec_run(argv[1],argv + 1,envp); strerr_die4sys(111,FATAL,"unable to run ",argv[1],": "); }
void startprocessor(struct cyclog *d) { const char *args[4]; int fd; sig_uncatch(sig_term); sig_uncatch(sig_alarm); sig_unblock(sig_term); sig_unblock(sig_alarm); fd = open_read("previous"); if (fd == -1) return; if (fd_move(0,fd) == -1) return; fd = open_trunc("processed"); if (fd == -1) return; if (fd_move(1,fd) == -1) return; fd = open_read("state"); if (fd == -1) return; if (fd_move(4,fd) == -1) return; fd = open_trunc("newstate"); if (fd == -1) return; if (fd_move(5,fd) == -1) return; args[0] = "sh"; args[1] = "-c"; args[2] = d->processor; args[3] = 0; execve("/bin/sh",args,environ); }
int main(int argc,char **argv,char **envp) { int piin[2]; int piout[2]; if (argc < 2) errint(EINVAL,"usage: fixcrio program [ arg ... ]"); if (pipe(piin) == -1) errint(errno,"unable to create pipe"); if (pipe(piout) == -1) errint(errno,"unable to create pipe"); switch(fork()) { case -1: errint(errno,"unable to fork"); case 0: sig_ignore(sig_pipe); close(piin[0]); close(piout[1]); doit(piin[1],piout[0]); } close(piin[1]); close(piout[0]); if (fd_move(0,piin[0]) == -1) errint(errno,"unable to move descriptors"); if (fd_move(1,piout[1]) == -1) errint(errno,"unable to move descriptors"); pathexec_run(argv[1],argv + 1,envp); errsys(errno); return(0); }
pid_t child_spawn1_internal (char const *prog, char const *const *argv, char const *const *envp, int *p, int to) { int e ; int syncp[2] ; pid_t pid ; if (coe(p[0]) < 0 || pipecoe(syncp) < 0) { e = errno ; fd_close(p[1]) ; fd_close(p[0]) ; errno = e ; return 0 ; } pid = fork() ; if (pid < 0) { e = errno ; fd_close(syncp[1]) ; fd_close(syncp[0]) ; fd_close(p[1]) ; fd_close(p[0]) ; errno = e ; return 0 ; } if (!pid) { fd_close(syncp[0]) ; fd_close(p[!(to & 1)]) ; if (fd_move(to & 1, p[to & 1]) < 0) goto err ; if ((to & 2) && (fd_copy(!(to & 1), to & 1) < 0)) goto err ; sig_blocknone() ; pathexec_run(prog, argv, envp) ; err: e = errno ; fd_write(syncp[1], (char *)&e, sizeof(e)) ; _exit(127) ; } fd_close(syncp[1]) ; fd_close(p[to & 1]) ; syncp[1] = fd_read(syncp[0], (char *)&e, sizeof(e)) ; if (syncp[1] < 0) { e = errno ; fd_close(syncp[0]) ; fd_close(p[!(to & 1)]) ; errno = e ; return 0 ; } fd_close(syncp[0]) ; if (syncp[1] == sizeof(e)) { fd_close(p[!(to & 1)]) ; wait_pid(pid, &syncp[1]) ; errno = e ; return 0 ; } return pid ; }
int main (int argc, char const *const *argv, char const *const *envp) { int fd, fd2 ; unsigned int flags = 0 ; int what = -1 ; int changemode = 0 ; PROG = "redirfd" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { register int opt = subgetopt_r(argc, argv, "rwuacxnb", &l) ; if (opt == -1) break ; switch (opt) { case 'r' : what = O_RDONLY ; flags &= ~(O_APPEND|O_CREAT|O_TRUNC|O_EXCL) ; break ; case 'w' : what = O_WRONLY ; flags |= O_CREAT|O_TRUNC ; flags &= ~(O_APPEND|O_EXCL) ; break ; case 'u' : what = O_RDWR ; flags &= ~(O_APPEND|O_CREAT|O_TRUNC|O_EXCL) ; break ; case 'a' : what = O_WRONLY ; flags |= O_CREAT|O_APPEND ; flags &= ~(O_TRUNC|O_EXCL) ; break ; case 'c' : what = O_WRONLY ; flags |= O_APPEND ; flags &= ~(O_CREAT|O_TRUNC|O_EXCL) ; break ; case 'x' : what = O_WRONLY ; flags |= O_CREAT|O_EXCL ; flags &= ~(O_APPEND|O_TRUNC) ; break ; case 'n' : flags |= O_NONBLOCK ; break ; case 'b' : changemode = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if ((argc < 3) || (what == -1)) dieusage() ; if (!uint0_scan(argv[0], (unsigned int *)&fd)) dieusage() ; flags |= what ; fd2 = open3(argv[1], flags, 0666) ; if ((fd2 == -1) && (what == O_WRONLY) && (errno == ENXIO)) { register int e ; int fdr = open_read(argv[1]) ; if (fdr == -1) strerr_diefu2sys(111, "open_read ", argv[1]) ; fd2 = open3(argv[1], flags, 0666) ; e = errno ; fd_close(fdr) ; errno = e ; } if (fd2 == -1) strerr_diefu2sys(111, "open ", argv[1]) ; if (fd_move(fd, fd2) == -1) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, fd2)] = 0 ; strerr_diefu4sys(111, "move fd ", fmt, " to fd ", argv[0]) ; } if (changemode) { if (((flags & O_NONBLOCK) ? ndelay_off(fd) : ndelay_on(fd)) < 0) strerr_diefu1sys(111, "change blocking mode") ; } pathexec_run(argv[2], argv+2, envp) ; strerr_dieexec(111, argv[2]) ; }
int call_open(struct call *cc, const char *prog, int timeout, int flagstar) { int pit[2]; int pif[2]; const char *(args[2]); args[0] = prog; args[1] = 0; if (pipe(pit) == -1) return -1; if (pipe(pif) == -1) { close(pit[0]); close(pit[1]); return -1; } switch(cc->pid = vfork()) { case -1: close(pit[0]); close(pit[1]); close(pif[0]); close(pif[1]); return -1; case 0: close(pit[1]); close(pif[0]); if (fd_move(0,pit[0]) == -1) _exit(120); if (fd_move(1,pif[1]) == -1) _exit(120); if (chdir(auto_qmail) == -1) _exit(61); execv(*args,(char **)args); _exit(120); } if (timeout != 0) mytimeout = timeout; cc->flagerr = 0; cc->flagabort = 0; cc->flagstar = flagstar; cc->tofd = pit[1]; close(pit[0]); cc->fromfd = pif[0]; close(pif[1]); coe(cc->tofd); coe(cc->fromfd); substdio_fdbuf(&cc->ssto, mywrite, cc->tofd, cc->tobuf, sizeof(cc->tobuf)); substdio_fdbuf(&cc->ssfrom, myread, cc->fromfd, cc->frombuf, sizeof(cc->frombuf)); return 0; }
int main (int argc, char const *const *argv, char const *const *envp) { char const *s = env_get2(envp, VAR) ; unsigned int fd = 1 ; unsigned int timeout = 0 ; int df = 1, keep = 0 ; PROG = "sdnotify-wrapper" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { register int opt = subgetopt_r(argc, argv, "d:ft:k", &l) ; if (opt == -1) break ; switch (opt) { case 'd' : if (!uint0_scan(l.arg, &fd)) dieusage() ; break ; case 'f' : df = 0 ; break ; case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; case 'k' : keep = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (!argc) dieusage() ; if (!s) xpathexec_run(argv[0], argv, envp) ; else { pid_t parent = getpid() ; pid_t child ; int p[2] ; if (pipe(p) < 0) strerr_diefu1sys(111, "pipe") ; child = df ? doublefork() : fork() ; if (child < 0) strerr_diefu1sys(111, df ? "doublefork" : "fork") ; else if (!child) { PROG = "sdnotify-wrapper (child)" ; close(p[1]) ; return run_child(p[0], timeout, parent, s) ; } close(p[0]) ; if (fd_move((int)fd, p[1]) < 0) strerr_diefu1sys(111, "move descriptor") ; if (keep) xpathexec_run(argv[0], argv, envp) ; else xpathexec_r(argv, envp, env_len(envp), VAR, sizeof(VAR)) ; } }
int main (int argc, char const *const *argv, char const *const *envp) { int df = 0 ; PROG = "heredoc" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { register int opt = subgetopt_r(argc, argv, "d", &l) ; if (opt == -1) break ; switch (opt) { case 'd' : df = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 3) dieusage() ; { int fd[2] ; unsigned int fdr ; int pid ; if (!uint0_scan(argv[0], &fdr)) strerr_dieusage(100, USAGE) ; if (pipe(fd) < 0) strerr_diefu1sys(111, "pipe") ; pid = df ? doublefork() : fork() ; switch (pid) { case -1: strerr_diefu2sys(111, df ? "double" : "", "fork") ; case 0: { unsigned int len = str_len(argv[1]) ; PROG = "heredoc (child)" ; fd_close(fd[0]) ; if (allwrite(fd[1], argv[1], len) < len) strerr_diefu1sys(111, "allwrite") ; return 0 ; } } fd_close(fd[1]) ; if (fd_move((int)fdr, fd[0]) == -1) strerr_diefu2sys(111, "read on fd ", argv[0]) ; } pathexec_run(argv[2], argv+2, envp) ; strerr_dieexec(111, argv[2]) ; }
int fd_ensure_open (int fd, int w) { int dummy ; if (fcntl(fd, F_GETFD, &dummy) < 0) { int newfd ; if (errno != EBADF) return 0 ; newfd = open2("/dev/null", w ? O_WRONLY : O_RDONLY) ; if (newfd < 0) return 0 ; if (fd_move(fd, newfd) < 0) { register int e = errno ; fd_close(newfd) ; errno = e ; return 0 ; } } return 1 ; }
static void trystart (unsigned int i, char const *name, int islog) { int pid = fork() ; switch (pid) { case -1 : tain_addsec_g(&services[i].restartafter[islog], CHECK_RETRY_TIMEOUT) ; strerr_warnwu2sys("fork for ", name) ; return ; case 0 : { char const *cargv[3] = { "s6-supervise", name, 0 } ; PROG = "s6-svscan (child)" ; selfpipe_finish() ; if (services[i].flaglog) if (fd_move(!islog, services[i].p[!islog]) == -1) strerr_diefu2sys(111, "set fds for ", name) ; pathexec_run(S6_BINPREFIX "s6-supervise", cargv, (char const **)environ) ; strerr_dieexec(111, S6_BINPREFIX "s6-supervise") ; } } services[i].pid[islog] = pid ; }
int main(int argc,char **argv) { if (chdir("/") == -1) die(errno); umask(077); if (prot_gid(auto_gidq) == -1) die(errno); if (fd_copy(2,0) == -1) die(errno); if (fd_copy(3,0) == -1) die(errno); if (fd_copy(4,0) == -1) die(errno); if (fd_copy(5,0) == -1) die(errno); if (fd_copy(6,0) == -1) die(errno); if (argv[1]) { qlargs[1] = argv[1]; ++argv; } if (argv[1]) { if (pipe(pi0) == -1) die(errno); switch(fork()) { case -1: die(errno); case 0: if (prot_gid(auto_gidn) == -1) die(errno); if (prot_uid(auto_uidl) == -1) die(errno); close(pi0[1]); if (fd_move(0,pi0[0]) == -1) die(errno); close23456(); execvp(argv[1],argv + 1); die(errno); } close(pi0[0]); if (fd_move(1,pi0[1]) == -1) die(errno); } if (pipe(pi1) == -1) die(errno); if (pipe(pi2) == -1) die(errno); if (pipe(pi3) == -1) die(errno); if (pipe(pi4) == -1) die(errno); if (pipe(pi5) == -1) die(errno); if (pipe(pi6) == -1) die(errno); /* start qmail-lspawn */ switch(fork()) { case -1: die(errno); case 0: if (fd_copy(0,pi1[0]) == -1) die(errno); if (fd_copy(1,pi2[1]) == -1) die(errno); close23456(); closepipes(); execvp(*qlargs,qlargs); die(errno); } /* start qmail-rspawn */ switch(fork()) { case -1: die(errno); case 0: if (prot_uid(auto_uidr) == -1) die(errno); if (fd_copy(0,pi3[0]) == -1) die(errno); if (fd_copy(1,pi4[1]) == -1) die(errno); close23456(); closepipes(); execvp(*qrargs,qrargs); die(errno); } /* start qmail-clean */ switch(fork()) { case -1: die(errno); case 0: if (prot_uid(auto_uidq) == -1) die(errno); if (fd_copy(0,pi5[0]) == -1) die(errno); if (fd_copy(1,pi6[1]) == -1) die(errno); close23456(); closepipes(); execvp(*qcargs,qcargs); die(errno); } if (prot_uid(auto_uids) == -1) die(errno); if (fd_copy(0,1) == -1) die(errno); if (fd_copy(1,pi1[1]) == -1) die(errno); if (fd_copy(2,pi2[0]) == -1) die(errno); if (fd_copy(3,pi3[1]) == -1) die(errno); if (fd_copy(4,pi4[0]) == -1) die(errno); if (fd_copy(5,pi5[1]) == -1) die(errno); if (fd_copy(6,pi6[0]) == -1) die(errno); closepipes(); execvp(*qsargs,qsargs); /* start qmail-send */ die(errno); return(0); /* never reached */ }
/* * Attempt to save the player in a savefile */ bool save_player(void) { int result = FALSE; char safe[1024]; // in final deployment versions, you cannot save in the tutorial if (DEPLOYMENT && p_ptr->game_type != 0) { return (FALSE); } /* New savefile */ my_strcpy(safe, savefile, sizeof(safe)); my_strcat(safe, ".new", sizeof(safe)); #ifdef VM /* Hack -- support "flat directory" usage on VM/ESA */ my_strcpy(safe, savefile, sizeof(safe)); my_strcat(safe, "n", sizeof(safe)); #endif /* VM */ /* Grab permissions */ safe_setuid_grab(); /* Remove it */ fd_kill(safe); /* Drop permissions */ safe_setuid_drop(); /* Attempt to save the player */ if (save_player_aux(safe)) { char temp[1024]; /* Old savefile */ my_strcpy(temp, savefile, sizeof(temp)); my_strcat(temp, ".old", sizeof(temp)); #ifdef VM /* Hack -- support "flat directory" usage on VM/ESA */ my_strcpy(temp, savefile, sizeof(temp)); my_strcat(temp, "o", sizeof(temp)); #endif /* VM */ /* Grab permissions */ safe_setuid_grab(); /* Remove it */ fd_kill(temp); /* Preserve old savefile */ fd_move(savefile, temp); /* Activate new savefile */ fd_move(safe, savefile); /* Remove preserved savefile */ fd_kill(temp); /* Drop permissions */ safe_setuid_drop(); /* Hack -- Pretend the character was loaded */ character_loaded = TRUE; #ifdef VERIFY_SAVEFILE /* Lock on savefile */ my_strcpy(temp, savefile, sizeof(temp)); my_strcat(temp, ".lok", sizeof(temp)); /* Grab permissions */ safe_setuid_grab(); /* Remove lock file */ fd_kill(temp); /* Drop permissions */ safe_setuid_drop(); #endif /* VERIFY_SAVEFILE */ /* Success */ result = TRUE; } /* Return the result */ return (result); }
void doit(int t) { int fakev4=0; int j; SSL *ssl; int wstat; uint32 scope_id; int sslctl[2]; char *s; unsigned long tmp_long; char sslctl_cmd; stralloc ssl_env = { 0 }; buffer ssl_env_buf; if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); if (socketpair(AF_UNIX, SOCK_STREAM, 0, sslctl) == -1) strerr_die2sys(111,DROP,"unable to create socketpair: "); switch(fork()) { case -1: strerr_die2sys(111,DROP,"unable to fork: "); case 0: /* Child */ break; default: /* Parent */ close(pi[0]); close(po[1]); close(sslctl[1]); if ((s=env_get("SSL_CHROOT"))) if (chroot(s) == -1) strerr_die2x(111,DROPSSL,"unable to chroot"); if ((s=env_get("SSL_GID"))) { scan_ulong(s,&tmp_long); gid = tmp_long; } if (gid) if (prot_gid(gid) == -1) strerr_die2sys(111,DROPSSL,"unable to set gid: "); if ((s=env_get("SSL_UID"))) { scan_ulong(s,&tmp_long); uid = tmp_long; } if (uid) if (prot_uid(uid) == -1) strerr_die2sys(111,DROPSSL,"unable to set uid: "); /* This will exit on a fatal error or if the client quits * without activating SSL */ sslctl_cmd = ucspitls_master_wait_for_activation(sslctl[0]); /* If we got here, SSL must have been activated */ ssl = ssl_new(ctx,t); if (!ssl) strerr_die2x(111,DROP,"unable to create SSL instance"); if (ndelay_on(t) == -1) strerr_die2sys(111,DROP,"unable to set socket options: "); if (ssl_timeoutaccept(ssl,ssltimeout) == -1) strerr_die3x(111,DROP,"unable to accept SSL: ",ssl_error_str(ssl_errno)); if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; strerr_warn3("sslserver: ssl ",strnum," accept ",0); } if (flagclientcert) { switch(ssl_verify(ssl,verifyhost)) { case -1: strerr_die2x(111,DROP,"unable to verify client certificate"); case -2: strerr_die2x(111,DROP,"no client certificate"); case -3: strerr_die2x(111,DROP,"client name does not match certificate"); default: break; } } if (sslctl_cmd == 'Y') { ssl_server_env(ssl, &ssl_env); stralloc_0(&ssl_env); /* Add another NUL */ buffer_init(&ssl_env_buf,buffer_unixwrite,sslctl[0],NULL,0); if (buffer_putflush(&ssl_env_buf, ssl_env.s, ssl_env.len) == -1) { strerr_die2sys(111, FATAL, "unable to write SSL environment: "); } } else if (sslctl_cmd != 'y') { strerr_die2x(111,DROP,"Protocol error on SSL control descriptor: invalid command character read"); } if (close(sslctl[0]) != 0) { strerr_die2sys(111, DROP, "Error closing SSL control socket: "); } if (ssl_io(ssl,pi[1],po[0],io_opt) != 0) strerr_die3x(111,DROP,"unable to speak SSL: ",ssl_error_str(ssl_errno)); if (wait_nohang(&wstat) > 0) _exit(wait_exitcode(wstat)); ssl_close(ssl); _exit(0); } /* Child-only below this point */ if (close(sslctl[0]) != 0) { strerr_die2sys(111, DROP, "Error closing SSL control socket: "); } if (!forcev6 && ip6_isv4mapped(remoteip)) fakev4=1; if (fakev4) remoteipstr[ip4_fmt(remoteipstr,remoteip+12)] = 0; else remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0; if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; strerr_warn4("sslserver: pid ",strnum," from ",remoteipstr,0); } if (socket_local6(t,localip,&localport,&scope_id) == -1) strerr_die2sys(111,DROP,"unable to get local address: "); if (fakev4) localipstr[ip4_fmt(localipstr,localip+12)] = 0; else localipstr[ip6_fmt(localipstr,localip)] = 0; remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0; if (!localhost) if (dns_name6(&localhostsa,localip) == 0) if (localhostsa.len) { if (!stralloc_0(&localhostsa)) drop_nomem(); localhost = localhostsa.s; } env("PROTO",fakev4?"SSL":"SSL6"); env("SSLLOCALIP",localipstr); env("SSL6LOCALIP",localipstr); env("SSLLOCALPORT",localportstr); env("SSL6LOCALPORT",localportstr); env("SSLLOCALHOST",localhost); env("SSL6LOCALHOST",localhost); if (!fakev4 && scope_id) env("SSL6INTERFACE",socket_getifname(scope_id)); if (flagtcpenv) { env("TCPLOCALIP",localipstr); env("TCP6LOCALIP",localipstr); env("TCPLOCALPORT",localportstr); env("TCP6LOCALPORT",localportstr); env("TCPLOCALHOST",localhost); env("TCP6LOCALHOST",localhost); if (!fakev4 && scope_id) env("TCP6INTERFACE",socket_getifname(scope_id)); } if (flagremotehost) if (dns_name6(&remotehostsa,remoteip) == 0) if (remotehostsa.len) { if (flagparanoid) { verifyhost = remoteipstr; if (dns_ip6(&tmp,&remotehostsa) == 0) for (j = 0;j + 16 <= tmp.len;j += 16) if (byte_equal(remoteip,16,tmp.s + j)) { flagparanoid = 0; break; } } if (!flagparanoid) { if (!stralloc_0(&remotehostsa)) drop_nomem(); remotehost = remotehostsa.s; verifyhost = remotehostsa.s; } } env("SSLREMOTEIP",remoteipstr); env("SSL6REMOTEIP",remoteipstr); remoteipstr[ip6_fmt(remoteipstr,remoteip)]=0; env("SSLREMOTEPORT",remoteportstr); env("SSL6REMOTEPORT",remoteportstr); env("SSLREMOTEHOST",remotehost); env("SSL6REMOTEHOST",remotehost); if (flagtcpenv) { env("TCPREMOTEIP",remoteipstr); env("TCP6REMOTEIP",remoteipstr); env("TCPREMOTEPORT",remoteportstr); env("TCP6REMOTEPORT",remoteportstr); env("TCPREMOTEHOST",remotehost); env("TCP6REMOTEHOST",remotehost); } if (flagremoteinfo) { if (remoteinfo6(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1) flagremoteinfo = 0; if (!stralloc_0(&tcpremoteinfo)) drop_nomem(); } env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); env("SSL6REMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); if (flagtcpenv) { env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); env("TCP6REMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); } if (fnrules) { int fdrules; fdrules = open_read(fnrules); if (fdrules == -1) { if (errno != error_noent) drop_rules(); if (!flagallownorules) drop_rules(); } else { int fakev4=0; char* temp; if (!forcev6 && ip6_isv4mapped(remoteip)) fakev4=1; if (fakev4) temp=remoteipstr+7; else temp=remoteipstr; if (rules(found,fdrules,temp,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules(); close(fdrules); } } if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; if (!stralloc_copys(&tmp,"sslserver: ")) drop_nomem(); safecats(flagdeny ? "deny" : "ok"); cats(" "); safecats(strnum); cats(" "); if (localhost) safecats(localhost); cats(":"); safecats(localipstr); cats(":"); safecats(localportstr); cats(" "); if (remotehost) safecats(remotehost); cats(":"); safecats(remoteipstr); cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s); cats(":"); safecats(remoteportstr); cats("\n"); buffer_putflush(buffer_2,tmp.s,tmp.len); } if (flagdeny) _exit(100); if (gid) if (prot_gid(gid) == -1) strerr_die2sys(111,FATAL,"unable to set gid: "); if (uid) if (prot_uid(uid) == -1) strerr_die2sys(111,FATAL,"unable to set uid: "); close(pi[1]); close(po[0]); sig_uncatch(sig_child); sig_unblock(sig_child); sig_uncatch(sig_term); sig_uncatch(sig_pipe); if (fcntl(sslctl[1],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,sslctl[1])]=0; setenv("SSLCTLFD",strnum,1); if (fcntl(pi[0],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,pi[0])]=0; setenv("SSLREADFD",strnum,1); if (fcntl(po[1],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,po[1])]=0; setenv("SSLWRITEFD",strnum,1); if (flagsslwait) { if (fd_copy(0,t) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); if (fd_copy(1,t) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); } else { if (fd_move(0,pi[0]) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); if (fd_move(1,po[1]) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); } if (flagkillopts) socket_ipoptionskill(t); if (!flagdelay) socket_tcpnodelay(t); if (*banner) { buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace); if (buffer_putsflush(&b,banner) == -1) strerr_die2sys(111,DROP,"unable to print banner: "); } if (!flagsslwait) { strnum[fmt_ulong(strnum,flagsslenv)] = 0; strerr_warn2("flagsslenv: ", strnum, 0); ucspitls(flagsslenv,0,1); } pathexec(prog); strerr_die4sys(111,DROP,"unable to run ",*prog,": "); }
void doit(int t) { int j; SSL *ssl; int wstat; int sslctl[2]; char *s; unsigned long tmp_long; char ssl_cmd; stralloc ssl_env = { 0 }; int bytesleft; char envbuf[8192]; int childpid; if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); if (socketpair(AF_UNIX, SOCK_STREAM, 0, sslctl) == -1) strerr_die2sys(111,DROP,"unable to create socketpair: "); if ((j = ip_fmt(&remoteipsa,&remoteaddr))) strerr_die3x(111,DROP,"unable to print remote ip",gai_strerror(j)); if (flagremotehost) { if (dns_name(&remotehostsa,&remoteaddr) == 0) if (remotehostsa.len) { if (flagparanoid) { struct addrinfo *reverse, hints = {0}; verifyhost = remoteipsa.s; hints.ai_family = remoteaddr.sa4.sin_family; if (remoteaddr.sa6.sin6_family == AF_INET6) { hints.ai_flags = AI_V4MAPPED | AI_ALL; } if (getaddrinfo(remotehostsa.s, NULL, &hints, &reverse) == 0) { hints.ai_next = reverse; while (hints.ai_next) { if (hints.ai_next->ai_family == AF_INET && remoteaddr.sa4.sin_family == AF_INET && byte_equal(&remoteaddr.sa4.sin_addr, 4, &((struct sockaddr_in*) hints.ai_next->ai_addr)->sin_addr) || hints.ai_next->ai_family == AF_INET6 && remoteaddr.sa6.sin6_family == AF_INET6 && byte_equal(remoteaddr.sa6.sin6_addr.s6_addr, 16, &((struct sockaddr_in6*) hints.ai_next->ai_addr)->sin6_addr.s6_addr)) { flagparanoid = 0; break; } hints.ai_next = hints.ai_next->ai_next; } freeaddrinfo(reverse); } } if (!flagparanoid) { remotehost = remotehostsa.s; verifyhost = remotehostsa.s; } } } switch(childpid=fork()) { case -1: strerr_die2sys(111,DROP,"unable to fork: "); case 0: /* Child */ close(sslctl[0]); break; default: /* Parent */ close(pi[0]); close(po[1]); close(sslctl[1]); if ((s=env_get("SSL_CHROOT"))) if (chroot(s) == -1) { kill(childpid, SIGTERM); strerr_die2x(111,DROP,"unable to chroot"); } if ((s=env_get("SSL_GID"))) { scan_ulong(s,&tmp_long); gid = tmp_long; } if (gid) if (prot_gid(gid) == -1) { kill(childpid, SIGTERM); strerr_die2sys(111,FATAL,"unable to set gid: "); } if ((s=env_get("SSL_UID"))) { scan_ulong(s,&tmp_long); uid = tmp_long; } if (uid) if (prot_uid(uid) == -1) { kill(childpid, SIGTERM); strerr_die2sys(111,FATAL,"unable to set uid: "); } /* Read the TLS command socket. This will block until/unless * TLS is requested. */ if (read(sslctl[0],&ssl_cmd,1) == 1) { ssl = ssl_new(ctx,t); if (!ssl) { kill(childpid, SIGTERM); strerr_die2x(111,DROP,"unable to create SSL instance"); } if (ndelay_on(t) == -1) { kill(childpid, SIGTERM); strerr_die2sys(111,DROP,"unable to set socket options: "); } if (ssl_timeoutaccept(ssl,ssltimeout) == -1) { kill(childpid, SIGTERM); strerr_die3x(111,DROP,"unable to accept SSL: ",ssl_error_str(ssl_errno)); } } if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; strerr_warn3("sslserver: ssl ",strnum," accept ",0); } if (flagclientcert) { switch(ssl_verify(ssl,verifyhost)) { case -1: kill(childpid, SIGTERM); strerr_die2x(111,DROP,"unable to verify client certificate"); case -2: kill(childpid, SIGTERM); strerr_die2x(111,DROP,"no client certificate"); case -3: kill(childpid, SIGTERM); strerr_die3x(111,DROP,"certificate name does not match client fqdn: ",verifyhost); default: break; } } if (ssl_cmd == 'Y') { ssl_server_env(ssl, &ssl_env); if(!stralloc_0(&ssl_env)) drop_nomem(); /* Add another NUL */ env("SSLCTL",ssl_env.s); for(bytesleft = ssl_env.len; bytesleft>0; bytesleft-=j) if ( (j=write(sslctl[0], ssl_env.s, bytesleft)) < 0) { kill(childpid, SIGTERM); strerr_die2sys(111, FATAL, "unable to write SSL environment: "); } } if (ssl_cmd == 'Y' || ssl_cmd == 'y') { if (ssl_io(ssl,pi[1],po[0],progtimeout) != 0) { kill(childpid, SIGTERM); strerr_die3x(111,DROP,"unable to speak SSL: ",ssl_error_str(ssl_errno)); } if (wait_nohang(&wstat) > 0) _exit(wait_exitcode(wstat)); ssl_close(ssl); } kill(childpid, SIGTERM); _exit(0); } /* Child-only below this point */ if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; strerr_warn4("sslserver: pid ",strnum," from ",remoteipsa.s,0); } if (socket_local(t,&localaddr,&localport) == -1) strerr_die2sys(111,DROP,"unable to get local address: "); if ((j = ip_fmt(&localipsa,&localaddr))) strerr_die3x(111,DROP,"unable to print local address: ",gai_strerror(j)); remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0; if (!localhost) if (dns_name(&localhostsa,&localaddr) == 0) if (localhostsa.len) { if (!stralloc_0(&localhostsa)) drop_nomem(); localhost = localhostsa.s; } /* If remoteipsa.s contain ':' colon character will assume it is IPv6 */ if (byte_chr(remoteipsa.s, remoteipsa.len, ':') < remoteipsa.len) env("PROTO","SSL6"); else env("PROTO","SSL"); env("SSLLOCALIP",localipsa.s); env("SSLLOCALPORT",localportstr); env("SSLLOCALHOST",localhost); if (flagtcpenv) { env("TCPLOCALIP",localipsa.s); env("TCPLOCALPORT",localportstr); env("TCPLOCALHOST",localhost); } env("SSLREMOTEIP",remoteipsa.s); env("SSLREMOTEPORT",remoteportstr); env("SSLREMOTEHOST",remotehost); if (flagtcpenv) { env("TCPREMOTEIP",remoteipsa.s); env("TCPREMOTEPORT",remoteportstr); env("TCPREMOTEHOST",remotehost); } if (flagremoteinfo) { if (remoteinfo(&tcpremoteinfo,&remoteaddr,&localaddr,timeout) == -1) flagremoteinfo = 0; if (!stralloc_0(&tcpremoteinfo)) drop_nomem(); } env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); if (flagtcpenv) env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); if (fnrules) { int fdrules; fdrules = open_read(fnrules); if (fdrules == -1) { if (errno != error_noent) drop_rules(); if (!flagallownorules) drop_rules(); } else { if (rules(found,fdrules,&remoteaddr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules(); close(fdrules); } } if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; if (!stralloc_copys(&tmp,"sslserver: ")) drop_nomem(); safecats(flagdeny ? "deny" : "ok"); cats(" "); safecats(strnum); cats(" "); if (localhost) safecats(localhost); cats(":"); safecats(localipsa.s); cats(":"); safecats(localportstr); cats(" "); if (remotehost) safecats(remotehost); cats(":"); safecats(remoteipsa.s); cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s); cats(":"); safecats(remoteportstr); cats("\n"); buffer_putflush(buffer_2,tmp.s,tmp.len); } if (flagdeny) _exit(100); if (gid) if (prot_gid(gid) == -1) strerr_die2sys(111,FATAL,"unable to set gid: "); if (uid) if (prot_uid(uid) == -1) strerr_die2sys(111,FATAL,"unable to set uid: "); close(pi[1]); close(po[0]); close(sslctl[0]); sig_uncatch(sig_child); sig_unblock(sig_child); sig_uncatch(sig_term); sig_uncatch(sig_pipe); if (fcntl(sslctl[1],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,sslctl[1])]=0; env("SSLCTLFD",strnum); if (fcntl(pi[0],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,pi[0])]=0; env("SSLREADFD",strnum); if (fcntl(po[1],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,po[1])]=0; env("SSLWRITEFD",strnum); if (flagsslwait) { if (fd_copy(0,t) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); if (fd_copy(1,t) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); } else { if (fd_move(0,pi[0]) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); if (fd_move(1,po[1]) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); } if (flagkillopts) socket_ipoptionskill(t); if (!flagdelay) socket_tcpnodelay(t); if (*banner) { buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace); if (buffer_putsflush(&b,banner) == -1) strerr_die2sys(111,DROP,"unable to print banner: "); } if (!flagsslwait) { ssl_cmd = flagsslenv ? 'Y' : 'y'; if (write(sslctl[1], &ssl_cmd, 1) < 1) strerr_die2sys(111,DROP,"unable to start SSL: "); if (flagsslenv) { while ((j=read(sslctl[1],envbuf,8192)) > 0) { stralloc_catb(&ssl_env,envbuf,j); if (ssl_env.len >= 2 && ssl_env.s[ssl_env.len-2]==0 && ssl_env.s[ssl_env.len-1]==0) break; } if (j < 0) strerr_die2sys(111,DROP,"unable to read SSL environment: "); pathexec_multienv(&ssl_env); } } pathexec(prog); strerr_die4sys(111,DROP,"unable to run ",*prog,": "); }
int main(int argc,char **argv) { char *hostname; // char *portname; int opt; struct servent *se; char *x; unsigned long u; int s; int t; while ((opt = getopt(argc,argv,"4dDvqQhHrR1UXx:t:u:g:l:b:B:c:I:pPoO")) != opteof) switch(opt) { case 'b': scan_ulong(optarg,&backlog); break; case 'c': scan_ulong(optarg,&limit); break; case 'X': flagallownorules = 1; break; case 'x': fnrules = optarg; break; case 'B': banner = optarg; break; case 'd': flagdelay = 1; break; case 'D': flagdelay = 0; break; case 'v': verbosity = 2; break; case 'q': verbosity = 0; break; case 'Q': verbosity = 1; break; case 'P': flagparanoid = 0; break; case 'p': flagparanoid = 1; break; case 'O': flagkillopts = 1; break; case 'o': flagkillopts = 0; break; case 'H': flagremotehost = 0; break; case 'h': flagremotehost = 1; break; // case 'R': flagremoteinfo = 0; break; case 'r': flagremoteinfo = 1; break; case 't': scan_ulong(optarg,&timeout); break; case 'U': x = env_get("UID"); if (x) scan_ulong(x,&uid); x = env_get("GID"); if (x) scan_ulong(x,&gid); break; case 'u': scan_ulong(optarg,&uid); break; case 'g': scan_ulong(optarg,&gid); break; case 'I': netif=socket_getifidx(optarg); break; case '1': flag1 = 1; break; // case '4': noipv6 = 1; break; case '4': ipv4socket = 1; break; // case '6': forcev6 = 1; break; case 'l': localhost = optarg; break; default: usage(); } argc -= optind; argv += optind; if (!verbosity) buffer_2->fd = -1; hostname = *argv++; if (!hostname) usage(); if (str_equal(hostname,"")) hostname = "0"; x = *argv++; if (!x) usage(); if (!x[scan_ulong(x,&u)]) localport = u; else { se = getservbyname(x,"tcp"); if (!se) errint(EHARD,B("unable to figure out port number for ",x)); uint16_unpack_big((char*)&se->s_port,&localport); } if (!*argv) usage(); sig_block(sig_child); sig_catch(sig_child,sigchld); sig_catch(sig_term,sigterm); sig_ignore(sig_pipe); if (str_equal(hostname,"0")) { byte_zero(localip,sizeof localip); } else { if (!stralloc_copys(&tmp,hostname)) errmem; if (dns_ip6_qualify(&addresses,&fqdn,&tmp) == -1) errint(EHARD,B("temporarily unable to figure out IP address for ",hostname,": ")); if (addresses.len < 16) errint(EHARD,B("no IP address for ",hostname)); byte_copy(localip,16,addresses.s); if (ip6_isv4mapped(localip)) ipv4socket = 1; } s = socket_tcp(); if (s == -1) errint(EHARD,"unable to create socket: "); if (socket_bind_reuse(s,localip,localport,netif) == -1) errint(EHARD,"unable to bind: "); if (!ipv4socket) ipv4socket = ip6_isv4mapped(localip); if (socket_local(s,localip,&localport,&netif) == -1) errint(EHARD,"unable to get local address: "); if (socket_listen(s,backlog) == -1) errint(EHARD,"unable to listen: "); ndelay_off(s); if (gid) if (prot_gid(gid) == -1) errint(EHARD,"unable to set gid: "); if (uid) if (prot_uid(uid) == -1) errint(EHARD,"unable to set uid: "); localportstr[fmt_ulong(localportstr,localport)] = 0; if (flag1) { buffer_init(&b,write,1,bspace,sizeof bspace); buffer_puts(&b,localportstr); buffer_puts(&b,"\n"); buffer_flush(&b); } close(0); close(1); printstatus(); for (;;) { while (numchildren >= limit) sig_pause(); sig_unblock(sig_child); t = socket_accept(s,remoteip,&remoteport,&netif); sig_block(sig_child); if (t == -1) continue; ++numchildren; printstatus(); switch(fork()) { case 0: close(s); doit(t); if ((fd_move(0,t) == -1) || (fd_copy(1,0) == -1)) errint(EHARD,"unable to set up descriptors: "); sig_uncatch(sig_child); sig_unblock(sig_child); sig_uncatch(sig_term); sig_uncatch(sig_pipe); pathexec(argv); errint(EHARD,B("unable to run ",*argv,": ")); case -1: errlog(ESOFT,NOTICE,"unable to fork: "); --numchildren; printstatus(); } close(t); } }
/*! * @brief セーブデータ書き込みのメインルーチン / * Attempt to save the player in a savefile * @return 成功すればtrue */ bool save_player(void) { int result = FALSE; char safe[1024]; #ifdef SET_UID # ifdef SECURE /* Get "games" permissions */ beGames(); # endif #endif /* New savefile */ strcpy(safe, savefile); strcat(safe, ".new"); #ifdef VM /* Hack -- support "flat directory" usage on VM/ESA */ strcpy(safe, savefile); strcat(safe, "n"); #endif /* VM */ /* Grab permissions */ safe_setuid_grab(); /* Remove it */ fd_kill(safe); /* Drop permissions */ safe_setuid_drop(); update_playtime(); /* Attempt to save the player */ if (save_player_aux(safe)) { char temp[1024]; /* Old savefile */ strcpy(temp, savefile); strcat(temp, ".old"); #ifdef VM /* Hack -- support "flat directory" usage on VM/ESA */ strcpy(temp, savefile); strcat(temp, "o"); #endif /* VM */ /* Grab permissions */ safe_setuid_grab(); /* Remove it */ fd_kill(temp); /* Preserve old savefile */ fd_move(savefile, temp); /* Activate new savefile */ fd_move(safe, savefile); /* Remove preserved savefile */ fd_kill(temp); /* Drop permissions */ safe_setuid_drop(); /* Hack -- Pretend the character was loaded */ character_loaded = TRUE; #ifdef VERIFY_SAVEFILE /* Lock on savefile */ strcpy(temp, savefile); strcat(temp, ".lok"); /* Grab permissions */ safe_setuid_grab(); /* Remove lock file */ fd_kill(temp); /* Drop permissions */ safe_setuid_drop(); #endif /* Success */ result = TRUE; } #ifdef SET_UID # ifdef SECURE /* Drop "games" permissions */ bePlayer(); # endif #endif /* Return the result */ return (result); }
int ssl_io(unsigned int newsession, const char **prog) { if (client) { fdstdin =6; fdstdou =7; } bad_certificate = env_get("SSLIO_BAD_CERTIFICATE"); if ((s =env_get("SSLIO_BUFIN"))) scan_ulong(s, &bufsizein); if ((s =env_get("SSLIO_BUFOU"))) scan_ulong(s, &bufsizeou); if (bufsizein < 64) bufsizein =64; if (bufsizeou < 64) bufsizeou =64; if ((s =env_get("SSLIO_HANDSHAKE_TIMEOUT"))) scan_ulong(s, &handshake_timeout); if (handshake_timeout < 1) handshake_timeout =1; if (pipe(encpipe) == -1) fatalm("unable to create pipe for encoding"); if (pipe(decpipe) == -1) fatalm("unable to create pipe for decoding"); if ((pid =fork()) == -1) fatalm("unable to fork"); if (pid == 0) { if (close(encpipe[1]) == -1) fatalm("unable to close encoding pipe output"); if (close(decpipe[0]) == -1) fatalm("unable to close decoding pipe input"); if (newsession) if (matrixSslOpen() < 0) fatalm("unable to initialize ssl"); if (root) { if (chdir(root) == -1) fatalm("unable to change to new root directory"); if (chroot(".") == -1) fatalm("unable to chroot"); } if (ssluser) { /* drop permissions */ if (setgroups(sslugid.gids, sslugid.gid) == -1) fatal("unable to set groups"); if (setgid(*sslugid.gid) == -1) fatal("unable to set gid"); if (prot_uid(sslugid.uid) == -1) fatalm("unable to set uid"); } if (newsession) { if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) { if (client) fatalm("unable to read cert, key, or ca file"); fatalm("unable to read cert or key file"); } if (matrixSslNewSession(&ssl, keys, 0, client?0:SSL_FLAGS_SERVER) < 0) fatalmx("unable to create ssl session"); } if (client) if (ca || bad_certificate) matrixSslSetCertValidator(ssl, &validate, 0); sig_catch(sig_term, sig_term_handler); sig_ignore(sig_pipe); doio(); finish(); _exit(0); } if (close(encpipe[0]) == -1) fatalm("unable to close encoding pipe input"); if (close(decpipe[1]) == -1) fatalm("unable to close decoding pipe output"); if (fd_move(fdstdin, decpipe[0]) == -1) fatalm("unable to setup filedescriptor for decoding"); if (fd_move(fdstdou, encpipe[1]) == -1) fatalm("unable to setup filedescriptor for encoding"); sslCloseOsdep(); if (svuser) { if (setgroups(ugid.gids, ugid.gid) == -1) fatal("unable to set groups for prog"); if (setgid(*ugid.gid) == -1) fatal("unable to set gid for prog"); if (prot_uid(ugid.uid) == -1) fatalm("unable to set uid for prog"); } pathexec(prog); fatalm("unable to run prog"); return(111); }
unsigned int NAME (char const *prog, char const *const *argv, char const *const *envp, unsigned int uid, unsigned int gid, int *fds) { int p[NPIPES][2] ; int syncpipe[2] ; int pid ; int e ; if (pipe(p[0]) < 0) return 0 ; if (pipe(p[1]) < 0) { e = errno ; goto errp0 ; } #ifdef _CHILD_SPAWN2_ if (pipe(p[2]) < 0) { e = errno ; goto errp1 ; } #endif if (pipe(syncpipe) < 0) { e = errno ; goto errp2 ; } if (coe(syncpipe[1]) < 0) { e = errno ; goto errsp ; } pid = fork() ; if (pid < 0) { e = errno ; goto errsp ; } else if (!pid) { unsigned int m = 25 ; unsigned int n = str_len(PROG) ; char fmt[25 + UINT_FMT] = "SKACLIENT2_ADDITIONAL_FD" ; char name[n + 9] ; byte_copy(name, n, PROG) ; byte_copy(name + n, 9, " (child)") ; PROG = name ; #ifdef _CHILD_SPAWN2_ fmt[m-1] = '=' ; m += uint_fmt(fmt + m, p[2][1]) ; fmt[m++] = 0 ; fd_close(p[2][0]) ; #endif fd_close(syncpipe[0]) ; fd_close(p[1][1]) ; fd_close(p[0][0]) ; if ((fd_move(0, p[1][0]) < 0) || (fd_move(1, p[0][1]) < 0)) goto syncdie ; if (gid && (prot_gid(gid) < 0)) goto syncdie ; if (uid && (prot_uid(uid) < 0)) goto syncdie ; /* XXX: we should unignore signals here, but there's a compromise to be XXX: found between bloat, API complexity, and theoretical correctness. XXX: Not sure what The Right Thing is; just not unignoring atm. XXX: 20130326 edit: The Right Thing is probably to leave the ignore XXX: status alone, because programs that do actual signal handling XXX: are likely to use a selfpipe, and selfpipe_finish() restores XXX: old signal handlers - it knows what to do and we don't. So, XXX: leave that work to selfpipe_finish(). */ sig_blocknone() ; /* empty sigprocmask in the child, always */ pathexec_r_name(prog, argv, envp, env_len(envp), fmt, m) ; syncdie: { char c = errno ; fd_write(syncpipe[1], &c, 1) ; } _exit(111) ; } { char c ; fd_close(syncpipe[1]) ; #ifdef _CHILD_SPAWN2_ fd_close(p[2][1]) ; #endif fd_close(p[1][0]) ; fd_close(p[0][1]) ; p[1][0] = fd_read(syncpipe[0], &c, 1) ; if (p[1][0] < 0) goto killclosewait ; else if (p[1][0]) { e = c ; goto closewait ; } } fd_close(syncpipe[0]) ; if ((ndelay_on(p[0][0]) < 0) || (coe(p[0][0]) < 0) || (ndelay_on(p[1][1]) < 0) || (coe(p[1][1]) < 0)) goto killclosewait ; #ifdef _CHILD_SPAWN2_ if ((ndelay_on(p[2][0]) < 0) || (coe(p[2][0]) < 0)) goto killclosewait ; fds[2] = p[2][0] ; #endif fds[0] = p[0][0] ; fds[1] = p[1][1] ; return (unsigned int)pid ; errsp: fd_close(syncpipe[1]) ; fd_close(syncpipe[0]) ; errp2: #ifdef _CHILD_SPAWN2_ fd_close(p[2][1]) ; fd_close(p[2][0]) ; errp1: #endif fd_close(p[1][1]) ; fd_close(p[1][0]) ; errp0: fd_close(p[0][1]) ; fd_close(p[0][0]) ; errno = e ; return 0 ; killclosewait: e = errno ; kill(pid, SIGKILL) ; closewait: #ifdef _CHILD_SPAWN2_ fd_close(p[2][0]) ; #endif fd_close(p[1][1]) ; fd_close(p[0][0]) ; wait_pid(&syncpipe[1], pid) ; errno = e ; return 0 ; }
int main(int argc,char **argv) { char *hostname, *x; int c, s, t; unsigned int u; unsigned int cpid = 0; opterr = 0; while ((c = getopt(argc, argv, "dDoOC:k:c:")) != -1) switch (c) { case 'c': limit = atoi(optarg); if (limit == 0) usage(); break; case 'd': flagdelay = 1; break; case 'D': flagdelay = 0; break; case 'O': flagkillopts = 1; break; case 'o': flagkillopts = 0; break; case 'C': cacheprogram = 1; break; case 'k': autokill = atoi(optarg); if (autokill == 0) usage(); break; default: abort(); } argc -= optind; argv += optind; hostname = *argv++; if (!hostname) usage(); x = *argv++; if (!x) usage(); u = 0; u = atoi(x); if (u != 0) localport = u; else usage(); if (!*argv) usage(); sig_block(sig_child); sig_catch(sig_child,sigchld); sig_catch(sig_term,sigterm); sig_catch(sig_int,sigint); sig_ignore(sig_pipe); inet_aton(hostname, (struct in_addr *) &localip); if (autokill != 0) pt = ptable_init(limit); s = socket_tcp(); if (s == -1) die(111, "unable to create socket"); if (socket_bind4_reuse(s,localip,localport) == -1) die(111, "unable to bind"); if (socket_local4(s,localip,&localport) == -1) die(111, "unable to get local address"); if (socket_listen(s,20) == -1) die(111, "unable to listen"); ndelay_off(s); fprintf(stderr, "bind: %s:%d\n", hostname, localport); close(0); close(1); printstatus(); if (cacheprogram) { FILE *fp1; int fp2; char path[1024]; ssize_t n; fp1 = popen(*argv, "r"); if (fp1 == NULL) { fprintf(stderr, "Failed to run command\n"); exit(1); } fp2 = open("/var/tmp/tcpd.cache", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fp2 == -1) { fprintf(stderr, "Can't open cache file\n"); exit(1); } while ((n = fgets(path, sizeof(path)-1, fp1)) != NULL) { if (write(fp2, path, n) == n) { fprintf(stderr, "Error occured while creating cache\n"); exit(1); } } /* close */ pclose(fp1); close(fp2); // read cache file into memory FILE *f = fopen("/var/tmp/tcpd.cache", "rb"); fseek(f, 0, SEEK_END); cachesize = ftell(f); fseek(f, 0, SEEK_SET); //same as rewind(f); cache = malloc(cachesize + 1); n = fread(cache, cachesize, 1, f); fclose(f); cache[cachesize] = 0; } for (;;) { while (numchildren >= limit) { if (autokill != 0) ptable_autokill(pt, limit, autokill); sig_pause(); } sig_unblock(sig_child); t = socket_accept4(s,remoteip,&remoteport); sig_block(sig_child); if (t == -1) continue; ++numchildren; printstatus(); fprintf(stderr, "inbound connection from %d.%d.%d.%d:%d\n", (unsigned char) remoteip[0], (unsigned char) remoteip[1], (unsigned char) remoteip[2], (unsigned char) remoteip[3], remoteport); if (autokill != 0) ptable_autokill(pt,limit,autokill); cpid = fork(); switch(cpid) { case 0: close(s); if(flagkillopts) socket_ipoptionskill(t); if(!flagdelay) socket_tcpnodelay(t); if((fd_move(0,t) == -1) || (fd_copy(1,0) == -1)) die(111,"unable to setup descriptors"); sig_uncatch(sig_child); sig_unblock(sig_child); sig_uncatch(sig_term); sig_uncatch(sig_int); sig_uncatch(sig_pipe); if (cacheprogram) { printf("%s", cache); close(t); exit(0); } else { if(execve(*argv,argv,NULL) == 0) { close(t); exit(0); } else { die(111, "unable to run argv"); } } break; case -1: // unable to fork eprint(P_WARN,"unable to fork"); --numchildren; printstatus(); break; default: fprintf(stderr, "fork: child pid %d\n", cpid); if (autokill != 0) ptable_set(pt, limit, cpid, time(NULL)); break; } close(t); } }
int main(int argc, char **argv) { liao_log("liao_server", LOG_PID|LOG_NDELAY, LOG_MAIL); if (argc != 3) { usage(argv[0]); exit(0); } if (chdir(LIAO_HOME) == -1) { log_alert("cannot start: unable to switch to home directory"); exit(0); } snprintf(msg_id, sizeof(msg_id), "00000000"); char cfg_file[MAX_LINE] = CFG_FILE; int c; const char *args = "c:h"; while ((c = getopt(argc, argv, args)) != -1) { switch (c) { case 'c': snprintf(cfg_file, sizeof(cfg_file), "%s", optarg); break; case 'h': default: usage(argv[0]); exit(0); } } // 处理配置文件 if (conf_init(cfg_file)) { fprintf(stderr, "Unable to read control files:%s\n", cfg_file); log_error("Unable to read control files:%s", cfg_file); exit(1); } /* // 检查队列目录 if (strlen(config_st.queue_path) <= 0) { fprintf(stderr, "Unable to read queue path.\n"); log_error("Unable to read queue path."); exit(1); } if ( access(config_st.queue_path, F_OK) ) { fprintf(stderr, "Queue path:%s not exists:%s, so create it.\n", config_st.queue_path, strerror(errno)); log_error("Queue path:%s not exists:%s, so create it.", config_st.queue_path, strerror(errno)); umask(0); mkdir(config_st.queue_path, 0777); }*/ online_d = dictionary_new(atoi(config_st.max_works) + 1); child_st = (struct childs *)malloc((atoi(config_st.max_works) + 1) * sizeof(struct childs)); if (!child_st) { log_error("malloc childs [%d] failed:[%d]%s", (atoi(config_st.max_works) + 1), errno, strerror(errno)); exit(1); } int i = 0; for (i=0; i<(atoi(config_st.max_works) + 1); i++) { child_st[i].used = 0; child_st[i].pid = -1; child_st[i].client_fd = -1; child_st[i].pipe_r_in = -1; child_st[i].pipe_r_out = -1; child_st[i].pipe_w_in = -1; child_st[i].pipe_w_out = -1; memset(child_st[i].mid, 0, sizeof(child_st[i].mid)); child_st[i].mfp_out = NULL; } // 开始服务 int connfd, epfd, sockfd, n, nread; struct sockaddr_in local, remote; socklen_t addrlen; // 初始化buffer char buf[BUF_SIZE]; size_t pbuf_len = 0; size_t pbuf_size = BUF_SIZE + 1; char *pbuf = (char *)calloc(1, pbuf_size); if (pbuf == NULL) { log_error("calloc fail: size[%d]", pbuf_size); exit(1); } // 创建listen socket int bind_port = atoi(config_st.bind_port); if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { log_error("socket failed:[%d]:%s", errno, strerror(errno)); exit(1); } if (setnonblocking(listenfd) > 0) { exit(1); } bzero(&local, sizeof(local)); local.sin_family = AF_INET; local.sin_addr.s_addr = htonl(INADDR_ANY); local.sin_port = htons(bind_port); if (bind(listenfd, (struct sockaddr *)&local, sizeof(local)) < 0) { log_error("bind local %d failed:[%d]%s", bind_port, errno, strerror(errno)); exit(1); } log_info("bind local %d succ", bind_port); if (listen(listenfd, atoi(config_st.max_works)) != 0) { log_error("listen fd[%d] max_number[%d] failed:[%d]%s", listenfd, atoi(config_st.max_works), errno, strerror(errno)); exit(1); } // 忽略pipe信号 sig_pipeignore(); // 捕抓子进程退出信号 sig_catch(SIGCHLD, sigchld); // epoll create fd epoll_event_num = atoi(config_st.max_works) + 1; epoll_evts = NULL; epoll_fd = -1; epoll_nfds = -1; int epoll_i = 0; epoll_evts = (struct epoll_event *)malloc(epoll_event_num * sizeof(struct epoll_event)); if (epoll_evts == NULL) { log_error("alloc epoll event failed"); _exit(111); } epoll_fd = epoll_create(epoll_event_num); if (epoll_fd == -1) { log_error("epoll_create max_number[%d] failed:[%d]%s", epoll_event_num, errno, strerror(errno)); exit(1); } struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = listenfd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) { log_error("epoll_ctl: listen_socket failed:[%d]%s", errno, strerror(errno)); exit(1); } epoll_num_running = 1; for (;;) { epoll_nfds = epoll_wait(epoll_fd, epoll_evts, epoll_event_num, -1); if (epoll_nfds == -1) { if (errno == EINTR) { // 收到中断信号 log_info("epoll_wait recive EINTR signal, continue"); continue; } _exit(111); } log_debug("epoll_num_running:%d nfds:%d", epoll_num_running, epoll_nfds); for (epoll_i = 0; epoll_i < epoll_nfds; epoll_i++) { sig_childblock(); int evt_fd = epoll_evts[epoll_i].data.fd; if (evt_fd == listenfd) { if ((connfd = accept(listenfd, (struct sockaddr *) &remote, &addrlen)) > 0) { char *ipaddr = inet_ntoa(remote.sin_addr); log_info("accept client:%s", ipaddr); char greetting[512] = {0}; char hostname[1024] = {0}; if (gethostname(hostname, sizeof(hostname)) != 0) { snprintf(hostname, sizeof(hostname), "unknown"); } // 取客户端IP,Port char client_ip[20] = {0}; char client_port[20] = {0}; struct sockaddr_in sa; int len = sizeof(sa); if (!getpeername(connfd, (struct sockaddr *)&sa, &len)) { snprintf(client_ip, sizeof(client_ip), "%s", inet_ntoa(sa.sin_addr)); snprintf(client_port, sizeof(client_port), "%d", ntohs(sa.sin_port)); } // 取一个新的client int i = new_idx_from_child_st(); if (i == -1) { log_error("new_idx_from_client_st fail: maybe client queue is full."); // send error snprintf(greetting, sizeof(greetting), "%s ERR %s%s", TAG_GREET, hostname, DATA_END); write(connfd, greetting, strlen(greetting)); log_debug("send fd[%d]:%s", connfd, greetting); continue; } child_st[i].used = 1; int pir[2]; int piw[2]; if (pipe(pir) == -1) { log_error("unable to create pipe:%s", strerror(errno)); // send error snprintf(greetting, sizeof(greetting), "%s ERR %s%s", TAG_GREET, hostname, DATA_END); write(connfd, greetting, strlen(greetting)); log_debug("send fd[%d]:%s", connfd, greetting); continue; } if (pipe(piw) == -1) { log_error("unable to create pipe:%s", strerror(errno)); close(pir[0]); close(pir[1]); pir[0] = -1; pir[1] = -1; // send error snprintf(greetting, sizeof(greetting), "%s ERR %s%s", TAG_GREET, hostname, DATA_END); write(connfd, greetting, strlen(greetting)); log_debug("send fd[%d]:%s", connfd, greetting); continue; } log_debug("create pir[0]:%d pir[1]:%d", pir[0], pir[1]); log_debug("create piw[0]:%d piw[1]:%d", piw[0], piw[1]); // 当程序执行exec函数时本fd将被系统自动关闭,表示不传递给exec创建的新进程 //fcntl(pir[0], F_SETFD, FD_CLOEXEC); //fcntl(piw[1], F_SETFD, FD_CLOEXEC); int f = fork(); if (f < 0) { log_error("fork fail:%s", strerror(errno)); close(pir[0]); close(pir[1]); pir[0] = -1; pir[1] = -1; close(piw[0]); close(piw[1]); piw[0] = -1; piw[1] = -1; child_st[i].used = 0; // send error snprintf(greetting, sizeof(greetting), "%s ERR %s%s", TAG_GREET, hostname, DATA_END); write(connfd, greetting, strlen(greetting)); log_debug("send fd[%d]:%s", connfd, greetting); continue; } struct timeval tm; gettimeofday(&tm, NULL); snprintf(child_st[i].mid, sizeof(child_st[i].mid), "%05u%u", (uint32_t)tm.tv_usec, (uint32_t)f); snprintf(msg_id, sizeof(msg_id), "%s", child_st[i].mid); if (f == 0) { // 子进程 close(pir[0]); close(piw[1]); close(listenfd); char _cmid[512] = {0}; char _cchild_st[512] = {0}; char _ccip[20] = {0}; char _ccport[20] = {0}; snprintf(_cmid, sizeof(_cmid), "-m%s", child_st[i].mid); snprintf(_cchild_st, sizeof(_cchild_st), "-c%s", config_st.child_cf); snprintf(_ccip, sizeof(_ccip), "-i%s", client_ip); snprintf(_ccport, sizeof(_ccport), "-p%s", client_port); char *args[6]; args[0] = "./liao_command"; args[1] = _cmid; args[2] = _cchild_st; args[3] = _ccip; args[4] = _ccport; args[5] = 0; if (fd_move(0, connfd) == -1) { log_info("%s fd_move(0, %d) failed:%d %s", child_st[i].mid, connfd, errno, strerror(errno)); _exit(111); } if (fd_move(1, pir[1]) == -1) { log_info("%s fd_move(pipe_w, %d) failed:%d %s", child_st[i].mid, pir[1], errno, strerror(errno)); _exit(111); } if (fd_move(2, piw[0]) == -1) { log_info("%s fd_move(pipe_r, %d) failed:%d %s", child_st[i].mid, piw[0], errno, strerror(errno)); _exit(111); } if (execvp(*args, args) == -1) { log_error("execp fail:%s", strerror(errno)); _exit(111); } //if (error_temp(errno)) // _exit(111); log_debug("execp succ"); _exit(100); } close(connfd); child_st[i].pipe_r_in = pir[0]; close(pir[1]); pir[1] = -1; child_st[i].pipe_r_out = -1; child_st[i].pipe_w_out = piw[1]; close(piw[0]); piw[0] = -1; child_st[i].pipe_w_in = -1; child_st[i].pid = f; if (setnonblocking(child_st[i].pipe_r_in) != 0) { log_error("setnonblocking fd[%d] failed", child_st[i].pipe_r_in); } struct epoll_event pipe_in_ev; pipe_in_ev.events = EPOLLIN | EPOLLET; pipe_in_ev.data.fd = child_st[i].pipe_r_in; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pipe_in_ev.data.fd, &pipe_in_ev) == -1) { log_error("epoll_ctl client fd[%d] EPOLL_CTL_ADD failed:[%d]%s", pipe_in_ev.data.fd, errno, strerror(errno)); } log_debug("epoll_add fd[%d]", pipe_in_ev.data.fd); } else if (connfd == -1) { if (errno != EAGAIN && errno != ECONNABORTED && errno != EPROTO && errno != EINTR) { log_error("accept failed:[%d]%s", errno, strerror(errno)); } continue; } } else if (epoll_evts[epoll_i].events & EPOLLIN) { int ci = get_idx_with_sockfd(evt_fd); if (ci < 0) { log_error("socket fd[%d] get_idx_with_sockfd fail", evt_fd); continue; } log_debug("%s get event EPOLLIN: epoll_i[%d] fd[%d] get d_i[%d] fd[%d], used[%d]", child_st[ci].mid, epoll_i, epoll_evts[epoll_i].data.fd, child_st[ci].pipe_r_in, child_st[ci].used); // 读取内容 ---------------------- char inbuf[BUF_SIZE] = {0}; char *pinbuf = inbuf; int inbuf_size = BUF_SIZE; int inbuf_len = 0; char ch; do { i = 0; nread = read(child_st[ci].pipe_r_in, inbuf, inbuf_size); log_debug("%s read from liao_command:[%d]", child_st[ci].mid, nread); if (nread == -1) { // read error on a readable pipe? be serious //log_error("it is failed from fd[%d] read. error:%d %s", child_st[ci].fd_in, errno, strerror(errno)); //log_debug("it is failed from fd[%d] read. error:%d %s", child_st[ci].pipe_r_in, errno, strerror(errno)); break; } else if (nread > 0) { if (child_st[ci].mfp_out == NULL) { child_st[ci].mfp_out = mopen(MAX_BLOCK_SIZE, NULL, NULL); if (child_st[ci].mfp_out == NULL) { log_debug("%s mopen for body fail", child_st[ci].mid); break; } } while (i < nread) { ch = inbuf[i]; if ((inbuf_size - inbuf_len) < 2) { int r = fast_write(child_st[ci].mfp_out, inbuf, inbuf_len); if (r == 0) { log_error("%s fast_write fail", child_st[ci].mid); break; } memset(inbuf, 0, inbuf_size); inbuf_len = 0; } mybyte_copy(pinbuf + inbuf_len, 1, &ch); inbuf_len++; if (ch == '\n') { if (inbuf_len > 0) { int r = fast_write(child_st[ci].mfp_out, inbuf, inbuf_len); if (r == 0) { log_error("%s fast_write fail", child_st[ci].mid); break; } memset(inbuf, 0, inbuf_size); inbuf_len = 0; } // 处理当前指令 // ... process_system(&child_st[ci]); // ... // 处理完成后 if (child_st[ci].mfp_out != NULL) { mclose(child_st[ci].mfp_out); child_st[ci].mfp_out = NULL; child_st[ci].mfp_out = mopen(MAX_BLOCK_SIZE, NULL, NULL); if (child_st[ci].mfp_out == NULL) { log_error("mopen fail for mfp_out"); break; } } pinbuf = inbuf + 0; } i++; } } else { break; } } while (1); } else if ((epoll_evts[epoll_i].events & EPOLLHUP) && (epoll_evts[epoll_i].data.fd != listenfd)) { int ci = get_idx_with_sockfd(evt_fd); if ( ci < 0 ) { log_error("get_idx_with_sockfd(%d) fail, so not write", evt_fd); continue; } log_debug("%s get event EPOLLHUP: epoll_i[%d] fd[%d] get d_i[%d] fd[%d], used[%d]", child_st[ci].mid, epoll_i, epoll_evts[epoll_i].data.fd, child_st[ci].pipe_r_in, child_st[ci].used); epoll_delete_evt(epoll_fd, child_st[ci].pipe_r_in); continue; } } sig_childunblock(); } close(epoll_fd); close(listenfd); log_info("i'm finish"); return 0; }
void connection_accept(int c) { int ac; const char **run; const char *args[4]; char *ip =(char*)&socka.sin_addr; remote_ip[ipsvd_fmt_ip(remote_ip, ip)] =0; if (verbose) { out(INFO); out("pid "); bufnum[fmt_ulong(bufnum, getpid())] =0; out(bufnum); out(" from "); outfix(remote_ip); flush("\n"); } remote_port[ipsvd_fmt_port(remote_port, (char*)&socka.sin_port)] =0; if (lookuphost) { if (ipsvd_hostname(&remote_hostname, ip, paranoid) == -1) warn2("unable to look up hostname", remote_ip); if (! stralloc_0(&remote_hostname)) drop_nomem(); } socka_size =sizeof(socka); if (getsockname(c, (struct sockaddr*)&socka, &socka_size) == -1) drop("unable to get local address"); if (! local_hostname.len) { if (dns_name4(&local_hostname, (char*)&socka.sin_addr) == -1) drop("unable to look up local hostname"); if (! stralloc_0(&local_hostname)) die_nomem(); } local_ip[ipsvd_fmt_ip(local_ip, (char*)&socka.sin_addr)] =0; if (ucspi) ucspi_env(); if (instructs) { ac =ipsvd_check(iscdb, &inst, &match, (char*)instructs, remote_ip, remote_hostname.s, timeout); if (ac == -1) drop2("unable to check inst", remote_ip); if (ac == IPSVD_ERR) drop2("unable to read", (char*)instructs); } else ac =IPSVD_DEFAULT; if (phccmax) { if (phcc > phccmax) { ac =IPSVD_DENY; if (phccmsg) { ndelay_on(c); if (write(c, phccmsg, str_len(phccmsg)) == -1) warn("unable to write concurrency message"); } } if (verbose) { bufnum[fmt_ulong(bufnum, getpid())] =0; out(INFO); out("concurrency "); out(bufnum); out(" "); outfix(remote_ip); out(" "); bufnum[fmt_ulong(bufnum, phcc)] =0; out(bufnum); out("/"); bufnum[fmt_ulong(bufnum, phccmax)] =0; out(bufnum); out("\n"); } } if (verbose) { out(INFO); switch(ac) { case IPSVD_DENY: out("deny "); break; case IPSVD_DEFAULT: case IPSVD_INSTRUCT: out("start "); break; case IPSVD_EXEC: out("exec "); break; } bufnum[fmt_ulong(bufnum, getpid())] =0; out(bufnum); out(" "); outfix(local_hostname.s); out(":"); out(local_ip); out(" :"); outfix(remote_hostname.s); out(":"); outfix(remote_ip); out(":"); outfix(remote_port); if (instructs) { out(" "); if (iscdb) { out((char*)instructs); out("/"); } outfix(match.s); if(inst.s && inst.len && (verbose > 1)) { out(": "); outinst(&inst); } } flush("\n"); } if (ac == IPSVD_DENY) { close(c); _exit(100); } if (ac == IPSVD_EXEC) { args[0] ="/bin/sh"; args[1] ="-c"; args[2] =inst.s; args[3] =0; run =args; } else run =prog; if ((fd_move(0, c) == -1) || (fd_copy(1, 0) == -1)) drop("unable to set filedescriptor"); sig_uncatch(sig_term); sig_uncatch(sig_pipe); sig_uncatch(sig_child); sig_unblock(sig_child); #ifdef SSLSVD pid =getpid(); id[fmt_ulong(id, pid)] =0; ssl_io(0, run); #else pathexec(run); #endif drop2("unable to run", (char *)*prog); }
int ltTcpDoSRequest(lt_shmHead *lt_MMHead,int confd) { int i; int errint; uint32 lFunCode; ltMsgHead *psMsgHead; char **binqqargs; int (*op)(); psMsgHead = (ltMsgHead *)lt_TcpMsgRead(confd,&errint); if(psMsgHead == NULL) { return 0; } /*msg包的其他处理*/ psMsgHead->lMaxBytes = psMsgHead->lBytes; lFunCode=0; lFunCode=psMsgHead->lFunCode; /*later will be hash table and more funtion control*/ /*serach funtion*/ //ltMsgPrintMsg(psMsgHead); i=nasFindFun(lFunCode); if(i==-1){ ltsSysCheck(confd,psMsgHead,lt_MMHead); close(confd); return 0; } if(_ltfunList[i].maxruntime>0){ alarm(_ltfunList[i].maxruntime); } /*检查激活问题*/ //printf("1111111111:%d\n",_ltPubInfo->sysActive); // if(_ltPubInfo->sysActive==0){ // // if(_ltfunList[i].activeflag==1){ // ltactivesys(confd,psMsgHead,lt_MMHead); // close(confd); // return 0; // } // } /*检查权限问题*/ // if(_ltfunList[i].rightflag!=0){ // if(checkRight(confd,psMsgHead,_ltfunList[i].rightflag,lt_MMHead)==-1){ // close(confd); // return -1; // } // } if(_ltfunList[i].funFlag==0){ op=_ltfunList[i].op; op(confd,psMsgHead,lt_MMHead); close(confd); return 0; }else if(_ltfunList[i].funFlag==1){ void *handle; handle = dlopen (_ltfunList[i].strFunUrl, RTLD_LAZY); op = dlsym (handle, _ltfunList[i].strFunName); op(confd,psMsgHead,lt_MMHead); close(confd); dlclose (handle); return 0; }else if(_ltfunList[i].funFlag==3){/*app*/ int pim[2]; int pie[2]; if (pipe(pim) == -1) return -1; if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; } switch(vfork()) { case -1: close(pim[0]); close(pim[1]); close(pie[0]); close(pie[1]); return -1; case 0:/*child process*/ close(pim[1]); close(pie[0]); /* pim[0] read; pie[1] write */ if (fd_move(0,pim[0]) == -1) _exit(120); if (fd_move(1,pie[1]) == -1) _exit(120); binqqargs = (char **) malloc(2 * sizeof(char *)); binqqargs[0]=_ltfunList[i].strFunUrl; binqqargs[1]= 0; execv(*binqqargs,binqqargs); _exit(120); } /* pim[1] write; pie[0] read */ close(pim[0]); close(pie[1]); //fd_move(confd,pie[0]); lt_TcpMsgSend(pim[1],psMsgHead); psMsgHead = (ltMsgHead *)lt_TcpMsgRead(confd,&errint); if(psMsgHead != NULL) { lt_TcpMsgSend(pim[1],psMsgHead); } close(confd); return 0; }else{ ltsSysCheck(confd,psMsgHead,lt_MMHead); close(confd); return 0; } close(confd); return 0; }
int main(int argc, char **argv) { if (argc != 3 && argc != 4) { usage(argv[0]); exit(0); } char cfg_file[MAX_LINE] = {0}; int make_deamon = 0; int ch; const char *args = "c:dh"; while ((ch = getopt(argc, argv, args)) != -1) { switch (ch) { case 'c': snprintf(cfg_file, sizeof(cfg_file), "%s", optarg); break; case 'd': make_deamon = 1; break; case 'h': default: usage(argv[0]); exit(0); break; } } if (make_deamon == 1) { // create deamon create_daemon(config_st.chdir_path); } // init log ctlog("ctserver", LOG_PID|LOG_NDELAY, LOG_MAIL); // read config dict_conf = open_config(cfg_file); if (dict_conf == NULL) { printf("parse config fail"); return 1; } if (read_config(dict_conf) != 0) { return 1; } log_level = atoi(config_st.log_level); if (chdir(config_st.chdir_path) == -1) { log_error("can not start: unable to change directory:%s", config_st.chdir_path); return 1; } log_debug("bind_port:%s", config_st.bind_port); log_debug("log_level:%s", config_st.log_level); log_debug("chdir_path:%s", config_st.chdir_path); log_debug("max_childs:%s", config_st.max_childs); log_debug("child_prog:%s", config_st.child_prog); log_debug("child_cf:%s", config_st.child_cf); // Get Local Host Name char local_hostname[MAX_LINE] = {0}; if (gethostname(local_hostname, sizeof(local_hostname)) != 0) { snprintf(local_hostname, sizeof(local_hostname), "unknown"); } log_debug("local_hostname:%s", local_hostname); // ---------- ---------- childs_st = (struct childs_t *)malloc((atoi(config_st.max_childs) + 1) * sizeof(struct childs_t)); if (childs_st == NULL) { log_error("malloc childs [%d] faild:[%d]:%s", (atoi(config_st.max_childs) + 1), errno, strerror(errno)); exit(1); } int i = 0; for (i=0; i<(atoi(config_st.max_childs) +1); i++) { init_child_with_idx(i); } // Start Server int connfd, epfd, sockfd, n, nread, nwrite; struct sockaddr_in local, remote; socklen_t addrlen; // Create Listen Socket int bind_port = atoi(config_st.bind_port); if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { log_error("socket fail:[%d]:%s", errno, strerror(errno)); exit(1); } // 设置套接字选项避免地址使用错误,解决: Address already in use int on = 1; if ((setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) { log_error("setsockopt failed"); exit(1); } // Set Listen FD Nonblock if (set_nonblocking(listen_fd) != 0) { exit(1); } bzero(&local, sizeof(local)); local.sin_family = AF_INET; local.sin_addr.s_addr = htonl(INADDR_ANY); local.sin_port = htons(bind_port); if (bind(listen_fd, (struct sockaddr *)&local, sizeof(local)) < 0) { log_error("bind local %d failed:[%d]%s", bind_port, errno, strerror(errno)); exit(1); } log_info("bind local %d succ", bind_port); if (listen(listen_fd, atoi(config_st.max_childs)) != 0) { log_error("listen fd[%d] max_number[%d] failed:[%d]%s", listen_fd, atoi(config_st.max_childs), errno, strerror(errno)); exit(1); } // Ignore pipe signal sig_pipeignore(); // Catch signal which is child program exit sig_catch(SIGCHLD, sigchld_exit); // epoll create fd epoll_event_num = atoi(config_st.max_childs) + 1; epoll_evts = NULL; epoll_fd = -1; epoll_nfds = -1; int epoll_i = 0; epoll_evts = (struct epoll_event *)malloc(epoll_event_num * sizeof(struct epoll_event)); if (epoll_evts == NULL) { log_error("malloc for epoll event fail"); exit(1); } epoll_fd = epoll_create(epoll_event_num); if (epoll_fd == -1) { log_error("epoll_create max_number[%d] failed:[%d]%s", epoll_event_num, errno, strerror(errno)); exit(1); } struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = listen_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) { log_error("epoll_ctl: listen_socket failed:[%d]%s", errno, strerror(errno)); exit(1); } epoll_num_running = 0; for (;;) { epoll_nfds = epoll_wait(epoll_fd, epoll_evts, epoll_event_num, -1); if (epoll_nfds == -1) { if (errno == EINTR) { // 收到中断信号 log_info("epoll_wait recive EINTR signal, continue"); continue; } exit(1); } log_debug("epoll_num_running:%d nfds:%d", epoll_num_running, epoll_nfds); for (epoll_i = 0; epoll_i < epoll_nfds; epoll_i++) { sig_childblock(); int evt_fd = epoll_evts[epoll_i].data.fd; if (evt_fd == listen_fd) { // new connect if ((connfd = accept(listen_fd, (struct sockaddr *)&remote, &addrlen)) > 0) { char *ipaddr = inet_ntoa(remote.sin_addr); log_debug("accept client:%s", ipaddr); char greet_buf[MAX_LINE] = {0}; // get a new index from child list int i = get_idle_idx_from_childs(); if (i == -1) { log_error("get_idle_idx_from_childs_t fail: maybe client queue is full."); // send to client error information n = snprintf(greet_buf, sizeof(greet_buf), "%s ERR %s%s", FAIL_CODE, local_hostname, DATA_END); nwrite = write(connfd, greet_buf, n); log_debug("send client fd[%d]:[%d]%s", connfd, nwrite, greet_buf); continue; } childs_st[i].used = 1; // get client ip and port. struct sockaddr_in sa; int len = sizeof(sa); if (!getpeername(connfd, (struct sockaddr *)&sa, &len)) { n = snprintf(childs_st[i].client_info.ip, sizeof(childs_st[i].client_info.ip), "%s", inet_ntoa(sa.sin_addr)); n = snprintf(childs_st[i].client_info.port, sizeof(childs_st[i].client_info.port), "%d", ntohs(sa.sin_port)); log_info("accept client:%s:%s", childs_st[i].client_info.ip, childs_st[i].client_info.port); } int pi1[2]; int pi2[2]; if (pipe(pi1) == -1) { log_error("unable to create pipe:[%d]%s", errno, strerror(errno)); // send to client error information n = snprintf(greet_buf, sizeof(greet_buf), "%s ERR %s%s", FAIL_CODE, local_hostname, DATA_END); nwrite = write(connfd, greet_buf, n); log_debug("send client fd[%d]:[%d]%s", connfd, nwrite, greet_buf); continue; } if (pipe(pi2) == -1) { log_error("unable to create pipe:[%d]%s", errno, strerror(errno)); close(pi1[0]); close(pi1[1]); pi1[0] = -1; pi1[1] = -1; // send to client error information n = snprintf(greet_buf, sizeof(greet_buf), "%s ERR %s%s", FAIL_CODE, local_hostname, DATA_END); nwrite = write(connfd, greet_buf, n); log_debug("send client fd[%d]:[%d]%s", connfd, nwrite, greet_buf); continue; } log_debug("create pi1[0]:%d pi1[1]:%d", pi1[0], pi1[1]); log_debug("create pi2[0]:%d pi2[1]:%d", pi2[0], pi2[1]); // create unique id n = create_unique_id(childs_st[i].sid, sizeof(childs_st[i].sid)); if (n != 16) { log_error("create unique id fail"); close(pi1[0]); close(pi1[1]); close(pi2[0]); close(pi2[1]); // send to client error information n = snprintf(greet_buf, sizeof(greet_buf), "%s SYSTEM ERR %s%s", FAIL_CODE, local_hostname, DATA_END); nwrite = write(connfd, greet_buf, n); log_debug("send client fd[%d]:[%d]%s", connfd, nwrite, greet_buf); continue; } log_debug("create mid:%s", childs_st[i].sid); // 当程序执行exec函数时本fd将被系统自动关闭,表示不传递给exec创建的新进程 fcntl(pi1[1], F_SETFD, FD_CLOEXEC); fcntl(pi2[0], F_SETFD, FD_CLOEXEC); fcntl(listen_fd, F_SETFD, FD_CLOEXEC); int f = fork(); if (f < 0) { log_error("fork fail:[%d]%s", errno, strerror(errno)); close(pi1[0]); close(pi1[1]); pi1[0] = -1; pi1[1] = -1; close(pi2[0]); close(pi2[1]); pi2[0] = -1; pi2[1] = -1; // send to client error information n = snprintf(greet_buf, sizeof(greet_buf), "%s SYSTEM ERR %s%s", FAIL_CODE, local_hostname, DATA_END); nwrite = write(connfd, greet_buf, n); log_debug("send client fd[%d]:[%d]%s", connfd, nwrite, greet_buf); continue; } else if (f == 0) { // 子进程 close(pi1[1]); close(pi2[0]); pi1[1] = -1; pi2[0] = -1; close(listen_fd); listen_fd = -1; if (fd_move(2, connfd) == -1) { log_error("%s fd_move(2, %d) failed:[%d]%s", childs_st[i].sid, connfd, errno, strerror(errno)); _exit(111); } // read from 0 if (fd_move(0, pi1[0])) { log_error("%s fd_move(0, %d) failed:[%d]%s", childs_st[i].sid, pi1[0], errno, strerror(errno)); _exit(111); } // write to 1 if (fd_move(1, pi2[1])) { log_error("%s fd_move(1, %d) failed:[%d]%s", childs_st[i].sid, pi2[1], errno, strerror(errno)); _exit(111); } // lunach child program char exe_sid[MAX_LINE] = {0}; char exe_cfg[MAX_LINE] = {0}; char exe_remote[MAX_LINE] = {0}; snprintf(exe_sid, sizeof(exe_sid), "-m%s", childs_st[i].sid); snprintf(exe_cfg, sizeof(exe_cfg), "-c%s", config_st.child_cf); snprintf(exe_remote, sizeof(exe_remote), "-r%s:%s", childs_st[i].client_info.ip, childs_st[i].client_info.port); char *args[5]; args[0] = config_st.child_prog; args[1] = exe_sid; args[2] = exe_cfg; args[3] = exe_remote; args[4] = 0; char log_exec[MAX_LINE*3] = {0}; char *plog_exec = log_exec; int len = 0; int i=0; while (args[i] != 0) { int n = snprintf(plog_exec + len, sizeof(log_exec) - len, "%s ", args[i]); len += n; i++; } log_info("Exec:[%s]", log_exec); if (execvp(*args, args) == -1) { log_error("execvp fail:[%d]%s", errno, strerror(errno)); _exit(111); } _exit(100); } // 父进程 log_debug("add child index:%d pid:%lu", i, f); childs_st[i].pid = f; close(pi1[0]); close(pi2[1]); pi1[0] = -1; pi2[1] = -1; close(connfd); connfd = -1; childs_st[i].pfd_r = pi2[0]; childs_st[i].pfd_w = pi1[1]; if (set_nonblocking(childs_st[i].pfd_r)) { log_error("set nonblocking fd[%d] fail", childs_st[i].pfd_r); } struct epoll_event pipe_r_ev; pipe_r_ev.events = EPOLLIN | EPOLLET; pipe_r_ev.data.fd = childs_st[i].pfd_r; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pipe_r_ev.data.fd, &pipe_r_ev) == -1) { log_error("epoll_ctl client fd[%d] EPOLL_CTL_ADD failed:[%d]%s", pipe_r_ev.data.fd, errno, strerror(errno)); } log_debug("epoll_add fd[%d]", pipe_r_ev.data.fd); epoll_num_running++; } else if (connfd == -1) { if (errno != EAGAIN && errno != ECONNABORTED && errno != EPROTO && errno != EINTR) { log_error("accept failed:[%d]%s", errno, strerror(errno)); } continue; } } else if (epoll_evts[epoll_i].events & EPOLLIN) { // 有可读事件从子进程过来 int idx = get_idx_with_sockfd(evt_fd); if (idx < 0) { log_error("get_idx_with_sockfd(%d) fail, so not process", evt_fd); continue; } log_debug("%s get event EPOLLIN: epoll_i[%d] fd[%d] get fd[%d], used[%d]", childs_st[idx].sid, epoll_i, epoll_evts[epoll_i].data.fd, childs_st[idx].pfd_r, childs_st[idx].used); // 读取内容 char cbuf[MAX_LINE] = {0}; nread = read(childs_st[idx].pfd_r, cbuf, sizeof(cbuf)); log_debug("read buf:'[%d]%s' from child", n, cbuf); } else if ((epoll_evts[epoll_i].events & EPOLLHUP) && (epoll_evts[epoll_i].data.fd != listen_fd)) { // 有子进程退出 int idx = get_idx_with_sockfd(evt_fd); if (idx < 0) { log_error("get_idx_with_sockfd(%d) fail, so not process", evt_fd); continue; } log_debug("%s get event EPOLLHUP: epoll_i[%d] fd[%d] get fd[%d], used[%d]", childs_st[idx].sid, epoll_i, epoll_evts[epoll_i].data.fd, childs_st[idx].pfd_r, childs_st[idx].used); epoll_delete_evt(epoll_fd, childs_st[idx].pfd_r); // 子进程清理 clean_child_with_idx(idx); continue; } } sig_childunblock(); } close(epoll_fd); close(listen_fd); epoll_fd = -1; listen_fd = -1; if (childs_st != NULL) { free(childs_st); childs_st = NULL; } if (epoll_evts != NULL) { free(epoll_evts); epoll_evts = NULL; } log_info("I'm finish"); return 0; }
main(int argc,char **argv) { int fakev4=0; unsigned long u; int opt; char *x; int j; int s; int cloop; dns_random_init(seed); close(6); close(7); sig_ignore(sig_pipe); while ((opt = getopt(argc,argv,"46dDvqQhHrRi:p:t:T:l:I:")) != opteof) switch(opt) { case '4': noipv6 = 1; break; case '6': forcev6 = 1; break; case 'd': flagdelay = 1; break; case 'D': flagdelay = 0; break; case 'v': verbosity = 2; break; case 'q': verbosity = 0; break; case 'Q': verbosity = 1; break; case 'l': forcelocal = optarg; break; case 'H': flagremotehost = 0; break; case 'h': flagremotehost = 1; break; case 'R': flagremoteinfo = 0; break; case 'r': flagremoteinfo = 1; break; case 't': scan_ulong(optarg,&itimeout); break; case 'T': j = scan_ulong(optarg,&ctimeout[0]); if (optarg[j] == '+') ++j; scan_ulong(optarg + j,&ctimeout[1]); break; case 'i': if (!scan_ip6(optarg,iplocal)) usage(); break; case 'I': netif=socket_getifidx(optarg); break; case 'p': scan_ulong(optarg,&u); portlocal = u; break; default: usage(); } argv += optind; if (!verbosity) buffer_2->fd = -1; hostname = *argv; if (!hostname) usage(); if (!hostname[0] || str_equal(hostname,"0")) hostname = (noipv6?"127.0.0.1":"::1"); x = *++argv; if (!x) usage(); if (!x[scan_ulong(x,&u)]) portremote = u; else { struct servent *se; se = getservbyname(x,"tcp"); if (!se) strerr_die3x(111,FATAL,"unable to figure out port number for ",x); portremote = ntohs(se->s_port); /* i continue to be amazed at the stupidity of the s_port interface */ } if (!*++argv) usage(); if (!stralloc_copys(&tmp,hostname)) nomem(); if (dns_ip6_qualify(&addresses,&fqdn,&tmp) == -1) strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": "); if (addresses.len < 16) strerr_die3x(111,FATAL,"no IP address for ",hostname); if (addresses.len == 16) { ctimeout[0] += ctimeout[1]; ctimeout[1] = 0; } for (cloop = 0;cloop < 2;++cloop) { if (!stralloc_copys(&moreaddresses,"")) nomem(); for (j = 0;j + 16 <= addresses.len;j += 4) { s = socket_tcp6(); if (s == -1) strerr_die2sys(111,FATAL,"unable to create socket: "); if (socket_bind6(s,iplocal,portlocal,netif) == -1) strerr_die2sys(111,FATAL,"unable to bind socket: "); if (timeoutconn6(s,addresses.s + j,portremote,ctimeout[cloop],netif) == 0) goto CONNECTED; close(s); if (!cloop && ctimeout[1] && (errno == error_timeout)) { if (!stralloc_catb(&moreaddresses,addresses.s + j,16)) nomem(); } else { strnum[fmt_ulong(strnum,portremote)] = 0; if (ip6_isv4mapped(addresses.s+j)) ipstr[ip4_fmt(ipstr,addresses.s + j + 12)] = 0; else ipstr[ip6_fmt(ipstr,addresses.s + j)] = 0; strerr_warn5(CONNECT,ipstr," port ",strnum,": ",&strerr_sys); } } if (!stralloc_copy(&addresses,&moreaddresses)) nomem(); } _exit(111); CONNECTED: if (!flagdelay) socket_tcpnodelay(s); /* if it fails, bummer */ if (socket_local6(s,iplocal,&portlocal,&netif) == -1) strerr_die2sys(111,FATAL,"unable to get local address: "); if (!forcev6 && (ip6_isv4mapped(iplocal) || byte_equal(iplocal,16,V6any))) fakev4=1; if (!pathexec_env("PROTO",fakev4?"TCP":"TCP6")) nomem(); strnum[fmt_ulong(strnum,portlocal)] = 0; if (!pathexec_env("TCPLOCALPORT",strnum)) nomem(); if (fakev4) ipstr[ip4_fmt(ipstr,iplocal+12)] = 0; else ipstr[ip6_fmt(ipstr,iplocal)] = 0; if (!pathexec_env("TCPLOCALIP",ipstr)) nomem(); x = forcelocal; if (!x) if (dns_name6(&tmp,iplocal) == 0) { if (!stralloc_0(&tmp)) nomem(); x = tmp.s; } if (!pathexec_env("TCPLOCALHOST",x)) nomem(); if (socket_remote6(s,ipremote,&portremote,&netif) == -1) strerr_die2sys(111,FATAL,"unable to get remote address: "); strnum[fmt_ulong(strnum,portremote)] = 0; if (!pathexec_env("TCPREMOTEPORT",strnum)) nomem(); if (fakev4) ipstr[ip4_fmt(ipstr,ipremote+12)] = 0; else ipstr[ip6_fmt(ipstr,ipremote)] = 0; if (!pathexec_env("TCPREMOTEIP",ipstr)) nomem(); if (verbosity >= 2) strerr_warn4("tcpclient: connected to ",ipstr," port ",strnum,0); x = 0; if (flagremotehost) if (dns_name6(&tmp,ipremote) == 0) { if (!stralloc_0(&tmp)) nomem(); x = tmp.s; } if (!pathexec_env("TCPREMOTEHOST",x)) nomem(); x = 0; if (flagremoteinfo) if (remoteinfo6(&tmp,ipremote,portremote,iplocal,portlocal,itimeout,netif) == 0) { if (!stralloc_0(&tmp)) nomem(); x = tmp.s; } if (!pathexec_env("TCPREMOTEINFO",x)) nomem(); if (fd_move(6,s) == -1) strerr_die2sys(111,FATAL,"unable to set up descriptor 6: "); if (fd_copy(7,6) == -1) strerr_die2sys(111,FATAL,"unable to set up descriptor 7: "); sig_uncatch(sig_pipe); pathexec(argv); strerr_die4sys(111,FATAL,"unable to run ",*argv,": "); }