Esempio n. 1
0
int
main(int argc, char *argv[])
{
    pid_t pid = fork();
    if(pid != 0) {
        exit(EXIT_SUCCESS);
    }
    if(setsid() == -1) {
        exit(EXIT_FAILURE);
    }
    lock_check("mlock");
	cmdline_parse(argc, argv);
    bzero(&procs, sizeof(procs));
    sig_catch(SIGCHLD, sigchld_handler); 
    while(1) {
        int i, ret;
        for (i = 1; i <= proc_num; i++) {
            if (procs.agents[i].flag == 0) {
                ret = start_process(i);
                if (ret != 0) {
                    // start process failed
                    log_error("start process failed");
                    exit(EXIT_FAILURE);
                }
            }
        }
        sleep(5); 
    }
	return 0;
}
Esempio n. 2
0
void sig_all_catch(signalfn fn)
{
  int i;
  for (i = 1; i < SIGMAX; i++)
    if (i != SIGPROF || i != SIGSEGV)
      sig_catch(i, fn);
}
Esempio n. 3
0
int main(int argc,char **argv)
{
  struct stat st;

  dir = argv[1];
  if (!dir || argv[2])
    strerr_die1x(100,"supervise: usage: supervise dir");

  if (pipe(selfpipe) == -1)
    strerr_die4sys(111,FATAL,"unable to create pipe for ",dir,": ");
  coe(selfpipe[0]);
  coe(selfpipe[1]);
  ndelay_on(selfpipe[0]);
  ndelay_on(selfpipe[1]);

  sig_block(sig_child);
  sig_catch(sig_child,trigger);

  if (chdir(dir) == -1)
    strerr_die4sys(111,FATAL,"unable to chdir to ",dir,": ");

  if (stat("down",&st) != -1)
    flagwantup = 0;
  else
    if (errno != error_noent)
      strerr_die4sys(111,FATAL,"unable to stat ",dir,"/down: ");

  mkdir("supervise",0700);
  fdlock = open_append("supervise/lock");
  if ((fdlock == -1) || (lock_exnb(fdlock) == -1))
    strerr_die4sys(111,FATAL,"unable to acquire ",dir,"/supervise/lock: ");
  coe(fdlock);

  fifo_make("supervise/control",0600);
  fdcontrol = open_read("supervise/control");
  if (fdcontrol == -1)
    strerr_die4sys(111,FATAL,"unable to read ",dir,"/supervise/control: ");
  coe(fdcontrol);
  ndelay_on(fdcontrol); /* shouldn't be necessary */
  fdcontrolwrite = open_write("supervise/control");
  if (fdcontrolwrite == -1)
    strerr_die4sys(111,FATAL,"unable to write ",dir,"/supervise/control: ");
  coe(fdcontrolwrite);

  pidchange();
  announce();

  fifo_make("supervise/ok",0600);
  fdok = open_read("supervise/ok");
  if (fdok == -1)
    strerr_die4sys(111,FATAL,"unable to read ",dir,"/supervise/ok: ");
  coe(fdok);

  if (!flagwant || flagwantup) trystart();

  doit();
  announce();
  _exit(0);
}
Esempio n. 4
0
int main(int argc,char **argv)
{
  umask(022);

  fdstartdir = open_read(".");
  if (fdstartdir == -1)
    strerr_die2sys(111,FATAL,"unable to switch to current directory: ");
  coe(fdstartdir);

  sig_block(sig_term);
  sig_block(sig_alarm);
  sig_catch(sig_term,exitasap);
  sig_catch(sig_alarm,forcerotate);

  ++argv;
  f_init(argv);
  c_init(argv);
  doit(argv);
  c_quit();
  _exit(0);
}
Esempio n. 5
0
int main() {
  int i;
  
  sig_catch(SIGUSR1, sigusr1_handler);
  sig_block(SIGUSR1);
  sig_unblock(SIGUSR1);
  
  for (i = 0; i < 3; i++)
    sleep(3);
    
  return 1;
}
Esempio n. 6
0
static
void
setup(void)
{
  int  i = 0;

  if(pipe(my_sigpipe) == -1){
      fatal_syserr("failure setting up selfpipe");
  }

  for(i = 0; i < 2; ++i){
      fd_cloexec(my_sigpipe[i]);
      fd_nonblock(my_sigpipe[i]);
  }

  if(pipe(my_logpipe) == -1){
      fatal_syserr("failure creating logpipe");
  }

  sigset_fill(&my_sigset);
  sigset_block(&my_sigset);

  sig_catch(SIGTERM, &sigtrap);
  sig_catch(SIGINT, &sigtrap);
  sig_catch(SIGCHLD, &sigtrap);

  /* catching these signals to pass to program: */
  sig_catch(SIGALRM, &sigtrap);
  sig_catch(SIGCONT, &sigtrap);
  sig_catch(SIGHUP, &sigtrap);
  sig_catch(SIGQUIT, &sigtrap);
  sig_catch(SIGTSTP, &sigtrap);
  sig_catch(SIGUSR1, &sigtrap);
  sig_catch(SIGUSR2, &sigtrap);

  sig_ignore(SIGPIPE);
  return;
}    
Esempio n. 7
0
void encode(void) {
  if ((len =read(encpipe[0], encinbuf.s, encin.size)) < 0)
    fatal("unable to read from prog");
  if (len == 0) {
    if (verbose > 2) info("eof reading from proc");
    if (quit == 0) {
      finish();
      _exit(0);
    } else {
      close(encpipe[0]); encpipe[0] = -1;
      if (shutdown(fdstdou, SHUT_WR) == 0) {
	fdstdou =-1;
	if (verbose > 2) info("shutdown network");
      } else {
	if (verbose > 2) info("close network");
	close(fdstdou); fdstdou =-1;
      }
      sig_catch(sig_alarm, quit_handler);
      alarm(quit);
      return;
    }
  }
  for (;;) {
    rc =matrixSslEncode(ssl, encin.buf, len, &encou);
    if (rc == SSL_ERROR) {
      close(fdstdou); fdstdou =-1;
      fatalx("unable to encode data");
    }
    if (rc == SSL_FULL) {
      if (! blowup(&encou, &encoubuf, bufsizeou)) die_nomem();
      if (verbose > 1) infou("encode output buffer size: ", encou.size);
      continue;
    }
    if (write(fdstdou, encou.start, encou.end -encou.start)
        != encou.end -encou.start) fatal("unable to write to network");
    if (verbose > 2) infou("write bytes: ", encou.end -encou.start);
    bytesou +=encou.end -encou.start;
    encou.start =encou.end =encou.buf =encoubuf.s;
    return;
  }
}
Esempio n. 8
0
void sig_pipedefault(void) { sig_catch(SIGPIPE,SIG_DFL); }
Esempio n. 9
0
void sig_pipeignore(void) { sig_catch(SIGPIPE,SIG_IGN); }
Esempio n. 10
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;
    
}
Esempio n. 11
0
int main(int argc, char **argv)
{
  int fdfifo, fdfifowrite;
  char *x;
  unsigned long id;

  VERSIONINFO;

  x = env_get("WORKDIR");
  if (!x)
    strerr_die2x(111, FATAL, "$WORKDIR not set");
  if (chdir(x) == -1)
    strerr_die4sys(111, FATAL, "unable to chdir to ", x, ": ");

  x = env_get("GID");
  if (!x)
    strerr_die2x(111, FATAL, "$GID not set");
  scan_ulong(x,&id);
  if (prot_gid((int) id) == -1)
    strerr_die2sys(111, FATAL, "unable to setgid: ");

  x = env_get("UID");
  if (!x)
    strerr_die2x(111, FATAL, "$UID not set");
  scan_ulong(x,&id);

  /* undocumented feature */
  if(id == 0)
    if(!env_get("IWANTTORUNASROOTANDKNOWWHATIDO"))
      strerr_die2x(111, FATAL, "unable to run under uid 0: please change $UID");

  if (prot_uid((int) id) == -1)
    strerr_die2sys(111, FATAL, "unable to setuid: ");

  buffer_putsflush(buffer_2, ARGV0 "starting\n");

  if(fifo_make(FIFONAME, 0620) == -1)
    strerr_warn4(ARGV0, "unable to create fifo ", FIFONAME, " ", &strerr_sys);

  fdfifo = open_read(FIFONAME);
  if(fdfifo == -1)
    strerr_die4sys(111, FATAL, "unable to open for read ", FIFONAME, " ");
  coe(fdfifo);
  ndelay_on(fdfifo); /* DJB says: shouldn't be necessary */

  /* we need this to keep the fifo from beeing closed */
  fdfifowrite = open_write(FIFONAME);
  if (fdfifowrite == -1)
    strerr_die4sys(111, FATAL, "unable to open for write ", FIFONAME, " ");
  coe(fdfifowrite);

  /* init a buffer for nonblocking reading */
  buffer_init(&wr, waitread, fdfifo, waitreadspace, sizeof waitreadspace);

  t = dAVLAllocTree();

  /* read snapshot of dnsdatatree */ 
  fill_db();

  /* SIGALRM can be used to check if dumping the database is needed */
  sig_catch(sig_alarm, sigalrm);

  /* SIGHUP can be used to force dumping the database */
  sig_catch(sig_hangup, sighup);  

  /* check if out child is done */
  sig_catch(sig_child, sigchld);  

  // XXX SIGINT, SIGTERM,

  /* do our normal workloop */
  doit();

  /* we shouldn't get here */
  return 1;
}
Esempio n. 12
0
void
sig_ignore(int sig)
{
  sig_catch(sig,SIG_IGN);
}
int main(int argc,char * const *argv) {
  const char *hostname;
  int opt;
  struct servent *se;
  char *x;
  unsigned long u;
  int s;
  int t;

  io_opt = ssl_io_opt_default;
  io_opt.timeout = 3600;

  while ((opt = getopt(argc,argv,"46dDvqQhHrR1UXx:t:T:u:g:l:b:B:c:Z:pPoO3IiEeSsaAw:nNyYuUjJ")) != 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 'T': scan_ulong(optarg,&ssltimeout); break;
      case 'w': scan_uint(optarg,&io_opt.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 'Z': netif=socket_getifidx(optarg); break;
      case '1': flag1 = 1; break;
      case '4': noipv6 = 1; break;
      case '6': forcev6 = 1; break;
      case 'l': localhost = optarg; break;
      case '3': flag3 = 1; break;
      case 'I': flagclientcert = 0; break;
      case 'i': flagclientcert = 1; break;
      case 'S': flagsslenv = 0; break;
      case 's': flagsslenv = 1; break;
      case 'E': flagtcpenv = 0; break;
      case 'e': flagtcpenv = 1; break;
      case 'n': case 'y': flagsslwait = 1; break;
      case 'N': case 'Y': flagsslwait = 0; break;
      case 'j': io_opt.just_shutdown = 1; break;
      case 'J': io_opt.just_shutdown = 0; 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();
  prog = argv;
  if (!*argv) usage();
  if (!x[scan_ulong(x,&u)])
    localport = u;
  else {
    se = getservbyname(x,"tcp");
    if (!se)
      strerr_die3x(111,FATAL,"unable to figure out port number for ",x);
    uint16_unpack_big((char*)&se->s_port,&localport);
  }

  if (x = env_get("VERIFYDEPTH")) {
    scan_ulong(x,&u);
    verifydepth = u;
  }

  if (x = env_get("CAFILE")) cafile = x;
  if (cafile && str_equal(cafile,"")) cafile = 0;

  if (x = env_get("CCAFILE")) ccafile = x;
  if (ccafile && str_equal(ccafile,"")) ccafile = 0;
  if (!flagclientcert) ccafile = 0;

  if (x = env_get("CADIR")) cadir = x;
  if (cadir && str_equal(cadir,"")) cadir= 0;

  if (x = env_get("CERTFILE")) certfile = x;
  if (certfile && str_equal(certfile,"")) certfile = 0;

  if (x = env_get("KEYFILE")) keyfile = x;
  if (keyfile && str_equal(keyfile,"")) keyfile = 0;

  if (x = env_get("DHFILE")) dhfile = x;
  if (dhfile && str_equal(dhfile,"")) dhfile = 0;

  if (x = env_get("CIPHERS")) ciphers = x;
  if (ciphers && str_equal(ciphers,"")) ciphers = 0;

  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))
      strerr_die2x(111,FATAL,"out of memory");
    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);
    byte_copy(localip,16,addresses.s);
    if (ip6_isv4mapped(localip))
      noipv6=1;
  }

  s = socket_tcp6();
  if (s == -1)
    strerr_die2sys(111,FATAL,"unable to create socket: ");

  if (socket_bind6_reuse(s,localip,localport,netif) == -1)
    strerr_die2sys(111,FATAL,"unable to bind: ");

  if (socket_local6(s,localip,&localport,&netif) == -1)
    strerr_die2sys(111,FATAL,"unable to get local address: ");
  if (socket_listen(s,backlog) == -1)
    strerr_die2sys(111,FATAL,"unable to listen: ");
  ndelay_off(s);

  localportstr[fmt_ulong(localportstr,localport)] = 0;
  if (flag1) {
    buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace);
    buffer_puts(&b,localportstr);
    buffer_puts(&b,"\n");
    buffer_flush(&b);
  }
 
  if (flag3) read_passwd();

  ctx = ssl_server();
  ssl_errstr();
  if (!ctx) strerr_die2x(111,FATAL,"unable to create SSL context");

  switch (ssl_certkey(ctx,certfile,keyfile,passwd_cb)) {
    case -1: strerr_die2x(111,FATAL,"unable to load certificate");
    case -2: strerr_die2x(111,FATAL,"unable to load key");
    case -3: strerr_die2x(111,FATAL,"key does not match certificate");
    default: break;
  }

  if (!ssl_ca(ctx,cafile,cadir,verifydepth))
    strerr_die2x(111,FATAL,"unable to load CA list");

  if (!ssl_cca(ctx,ccafile))
    strerr_die2x(111,FATAL,"unable to load client CA list");

  if (!ssl_params(ctx,dhfile,rsalen))
    strerr_die2x(111,FATAL,"unable to set cipher parameters");

  if (!ssl_ciphers(ctx,ciphers))
    strerr_die2x(111,FATAL,"unable to set cipher list");

  if (verbosity >= 2) {
    strnum[fmt_ulong(strnum,getpid())] = 0;
    strnum2[fmt_ulong(strnum2,rsalen)] = 0;
    strerr_warn4("sslserver: cafile ",strnum," ",cafile,0);
    strerr_warn4("sslserver: ccafile ",strnum," ",ccafile,0);
    strerr_warn4("sslserver: cadir ",strnum," ",cadir,0);
    strerr_warn4("sslserver: cert ",strnum," ",certfile,0);
    strerr_warn4("sslserver: key ",strnum," ",keyfile,0);
    strerr_warn6("sslserver: param ",strnum," ",dhfile," ",strnum2,0);
  }

  close(0); open_read("/dev/null");
  close(1); open_append("/dev/null");

  printstatus();
 
  for (;;) {
    while (numchildren >= limit) sig_pause();

    sig_unblock(sig_child);
    t = socket_accept6(s,remoteip,&remoteport,&netif);
    sig_block(sig_child);

    if (t == -1) continue;
    ++numchildren; printstatus();
 
    switch(fork()) {
      case 0:
        close(s);
        doit(t);
	strerr_die4sys(111,DROP,"unable to run ",*argv,": ");
      case -1:
        strerr_warn2(DROP,"unable to fork: ",&strerr_sys);
        --numchildren; printstatus();
    }
    close(t);
  }
}
Esempio n. 14
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);
 }
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
int main(int argc, char **argv) {
  int opt;
  char *user =0;
  char *host;
  unsigned long port;
  int pid;
  int s;
  int conn;
  int delim;

  progname =*argv;
  phccmax =0;

#ifdef SSLSVD
  while ((opt =getopt(argc, (const char **)argv,
                      "c:C:i:x:u:l:Eb:hpt:vVU:/:Z:K:")) != opteof) {
#else
  while ((opt =getopt(argc, (const char **)argv,
                      "c:C:i:x:u:l:Eb:hpt:vV")) != opteof) {
#endif
    switch(opt) {
    case 'c': scan_ulong(optarg, &cmax); if (cmax < 1) usage(); break;
    case 'C':
      delim =scan_ulong(optarg, &phccmax);
      if (phccmax < 1) usage();
      if (optarg[delim] == ':') {
        if (ipsvd_fmt_msg(&msg, optarg +delim +1) == -1) die_nomem();
        if (! stralloc_0(&msg)) die_nomem();
        phccmsg =msg.s;
      }
      break;
    case 'i': if (instructs) usage(); instructs =optarg; break;
    case 'x': if (instructs) usage(); instructs =optarg; iscdb =1; break;
    case 'u': user =(char*)optarg; break;
    case 'l':
      if (! stralloc_copys(&local_hostname, optarg)) die_nomem();
      if (! stralloc_0(&local_hostname)) die_nomem();
      break;
    case 'E': ucspi =0; break;
    case 'b': scan_ulong(optarg, &backlog); break;
    case 'h': lookuphost =1; break;
    case 'p': lookuphost =1; paranoid =1; break;
    case 't': scan_ulong(optarg, &timeout); break;
    case 'v': ++verbose; break;
#ifdef SSLSVD
    case 'U': ssluser =(char*)optarg; break;
    case '/': root =(char*)optarg; break;
    case 'Z': cert =(char*)optarg; break;
    case 'K': key =(char*)optarg; break;
#endif
    case 'V': strerr_warn1(VERSION, 0);
    case '?': usage();
    }
  }
  argv +=optind;

  if (! argv || ! *argv) usage();
  host =*argv++;
  if (! argv || ! *argv) usage();
  local_port =*argv++;
  if (! argv || ! *argv) usage();
  prog =(const char **)argv;
  if (phccmax > cmax) phccmax =cmax;

  if (user)
    if (! uidgids_get(&ugid, user)) {
      if (errno)
        strerr_die4sys(111, FATAL, "unable to get user/group: ", user, ": ");
      strerr_die3x(100, FATAL, "unknown user/group: ", user);
    }
#ifdef SSLSVD
  svuser =user;
  client =0;
  if ((getuid() == 0) && (! ssluser))
    strerr_die2x(100, FATAL, "-U ssluser must be set when running as root");
  if (ssluser)
    if (! uidgids_get(&sslugid, ssluser)) {
      if (errno)
        strerr_die4sys(111, FATAL, "unable to get user/group: ", ssluser, ": ");
      strerr_die3x(100, FATAL, "unknown user/group: ", ssluser);
    }
  if (! cert) cert ="./cert.pem";
  if (! key) key =cert;
  if (matrixSslOpen() < 0) fatal("unable to initialize ssl");
  if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) {
    if (client) fatal("unable to read cert, key, or ca file");
    fatal("unable to read cert or key file");
  }
  if (matrixSslNewSession(&ssl, keys, 0, SSL_FLAGS_SERVER) < 0)
    strerr_die2x(111, FATAL, "unable to create ssl session");
#endif

  dns_random_init(seed);
  sig_block(sig_child);
  sig_catch(sig_child, sig_child_handler);
  sig_catch(sig_term, sig_term_handler);
  sig_ignore(sig_pipe);

  if (phccmax) if (ipsvd_phcc_init(cmax) == -1) die_nomem();

  if (str_equal(host, "")) host ="0.0.0.0";
  if (str_equal(host, "0")) host ="0.0.0.0";

  if (! ipsvd_scan_port(local_port, "tcp", &port))
    strerr_die3x(100, FATAL, "unknown port number or name: ", local_port);

  if (! stralloc_copys(&sa, host)) die_nomem();
  if ((dns_ip4(&ips, &sa) == -1) || (ips.len < 4))
    if (dns_ip4_qualify(&ips, &fqdn, &sa) == -1)
      fatal2("unable to look up ip address", host);
  if (ips.len < 4)
    strerr_die3x(100, FATAL, "unable to look up ip address: ", host);
  ips.len =4;
  if (! stralloc_0(&ips)) die_nomem();
  local_ip[ipsvd_fmt_ip(local_ip, ips.s)] =0;

  if (! lookuphost) {
    if (! stralloc_copys(&remote_hostname, "")) die_nomem();
    if (! stralloc_0(&remote_hostname)) die_nomem();
  }

  if ((s =socket_tcp()) == -1) fatal("unable to create socket");
  if (socket_bind4_reuse(s, ips.s, port) == -1)
    fatal("unable to bind socket");
  if (listen(s, backlog) == -1) fatal("unable to listen");
  ndelay_off(s);

#ifdef SSLSVD
#else
  if (user) {
    /* drop permissions */
    if (setgroups(ugid.gids, ugid.gid) == -1) fatal("unable to set groups");
    if (setgid(*ugid.gid) == -1) fatal("unable to set gid");
    if (prot_uid(ugid.uid) == -1) fatal("unable to set uid");
  }
#endif
  close(0);

  if (verbose) {
    out(INFO); out("listening on "); outfix(local_ip); out(":");
    outfix(local_port);
#ifdef SSLSVD
#else
    if (user) {
      bufnum[fmt_ulong(bufnum, (unsigned long)ugid.uid)] =0;
      out(", uid "); out(bufnum);
      bufnum[fmt_ulong(bufnum, (unsigned long)ugid.gid)] =0;
      out(", gid "); out(bufnum);
    }
#endif
    flush(", starting.\n");
  }
  for (;;) {
    while (cnum >= cmax) sig_pause();
    socka_size =sizeof(socka);

    sig_unblock(sig_child);
    conn =accept(s, (struct sockaddr *)&socka, &socka_size);
    sig_block(sig_child);

    if (conn == -1) {
      if (errno != error_intr) warn("unable to accept connection");
      continue;
    }
    cnum++;

    if (verbose) connection_status();
    if (phccmax) phcc =ipsvd_phcc_add((char*)&socka.sin_addr);
    if ((pid =fork()) == -1) {
      warn2("drop connection", "unable to fork");
      close(conn);
      continue;
    }
    if (pid == 0) {
      /* child */
      close(s);
#ifdef SSLSVD
      if (*progname) *progname ='\\';
#endif
      connection_accept(conn);
    }
    if (phccmax) ipsvd_phcc_setpid(pid);
    close(conn);
  }
  _exit(0);
}
Esempio n. 17
0
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);
  }
}
Esempio n. 18
0
int main(int argc,char * const *argv) {
  const char *hostname;
  int opt;
  char *x;
  unsigned long u;
  int s;
  int t;
  int flagv4 = 1, flagv6 = 1, rc;
  struct addrinfo *localai = NULL, hints = {0}, *ai;
 
  while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:T:u:g:l:b:B:c:pPoO3IiEeSsw:nN46")) != 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 'T': scan_ulong(optarg,&ssltimeout); break;
      case 'w': scan_uint(optarg,&progtimeout); 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 '1': flag1 = 1; break;
      case 'l': localhost = optarg; break;
      case '3': flag3 = 1; break;
      case 'I': flagclientcert = 0; break;
      case 'i': flagclientcert = 1; break;
      case 'S': flagsslenv = 0; break;
      case 's': flagsslenv = 1; break;
      case 'E': flagtcpenv = 0; break;
      case 'e': flagtcpenv = 1; break;
      case 'n': flagsslwait = 1; break;
      case 'N': flagsslwait = 0; break;
      case '4': flagv6 = 0; break;
      case '6': flagv4 = 0; break;
      default: usage();
    }
  if (flagv4 == flagv6) { flagv4 = flagv6 = 1; }
  argc -= optind;
  argv += optind;

  if (!verbosity)
    buffer_2->fd = -1;
 
  hostname = *argv++;
  if (!hostname) usage();
  if (str_equal(hostname,"")) hostname = NULL;
  if (str_equal(hostname,"0")) hostname = NULL;

  x = *argv++;
  if (!x) usage();
  prog = argv;
  if (!*argv) usage();

  hints.ai_family = flagv4 == flagv6 ? AF_UNSPEC : flagv4 ? AF_INET : AF_INET6;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;
  if ((rc = getaddrinfo(hostname, x, &hints, &localai))) {
    strerr_die(111,FATAL "unable to figure out address for ", hostname ? hostname : "0",
		" ",x,": ",gai_strerror(rc),0);
  }
  if (!localai) {
    strerr_die2x(111,FATAL,"address not found");
  }

  if (x = env_get("VERIFYDEPTH")) {
    scan_ulong(x,&u);
    verifydepth = u;
  }

  if (x = env_get("CAFILE")) cafile = x;
  if (cafile && str_equal(cafile,"")) cafile = 0;

  if (x = env_get("CCAFILE")) ccafile = x;
  if (ccafile && str_equal(ccafile,"")) ccafile = 0;
  if (!flagclientcert) ccafile = 0;

  if (x = env_get("CADIR")) cadir = x;
  if (cadir && str_equal(cadir,"")) cadir= 0;

  if (x = env_get("CERTCHAINFILE")) certchainfile = x;
  if (certchainfile && str_equal(certchainfile,"")) certchainfile = 0;

  if (x = env_get("CERTFILE")) certfile = x;
  if (certfile && str_equal(certfile,"")) certfile = 0;

  if (x = env_get("KEYFILE")) keyfile = x;
  if (keyfile && str_equal(keyfile,"")) keyfile = 0;

  if (x = env_get("DHFILE")) dhfile = x;
  if (dhfile && str_equal(dhfile,"")) dhfile = 0;

  if (x = env_get("CIPHERS")) ciphers = x;
  if (ciphers && str_equal(ciphers,"")) ciphers = 0;

  sig_block(sig_child);
  sig_catch(sig_child,sigchld);
  sig_catch(sig_term,sigterm);
  sig_ignore(sig_pipe);

  for (ai = localai; ai; ai = ai->ai_next) { 
    s = socket_tcp(ai->ai_family, ai->ai_protocol);
    if (s == -1)
      strerr_die2sys(111,FATAL,"unable to create socket: ");

    if (socket_bind_reuse(s,ai) == -1)
      strerr_die2sys(111,FATAL,"unable to bind: ");

    if (socket_local(s,&localaddr,&localport) == -1)
      strerr_die2sys(111,FATAL,"unable to get local address: ");
    if (socket_listen(s,backlog) == -1)
      strerr_die2sys(111,FATAL,"unable to listen: ");
    break;
  }
  freeaddrinfo(localai); localai = NULL;
  ndelay_off(s);

  localportstr[fmt_ulong(localportstr,localport)] = 0;
  if (flag1) {
    buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace);
    buffer_puts(&b,localportstr);
    buffer_puts(&b,"\n");
    buffer_flush(&b);
  }
 
  if (flag3) read_passwd();

  ctx = ssl_server();
  ssl_errstr();
  if (!ctx) strerr_die2x(111,FATAL,"unable to create SSL context");

  if (certchainfile) {
    switch (ssl_chainfile(ctx,certchainfile,keyfile,passwd_cb)) {
      case -1: strerr_die2x(111,FATAL,"unable to load certificate chain file");
      case -2: strerr_die2x(111,FATAL,"unable to load key");
      case -3: strerr_die2x(111,FATAL,"key does not match certificate");
      default: break;
    }
  } 
  else {  
    switch (ssl_certkey(ctx,certfile,keyfile,passwd_cb)) {
      case -1: strerr_die2x(111,FATAL,"unable to load certificate");
      case -2: strerr_die2x(111,FATAL,"unable to load key");
      case -3: strerr_die2x(111,FATAL,"key does not match certificate");
      default: break;
    }
  }

  if (!ssl_ca(ctx,cafile,cadir,verifydepth))
    strerr_die2x(111,FATAL,"unable to load CA list");

  if (!ssl_cca(ctx,ccafile))
    strerr_die2x(111,FATAL,"unable to load client CA list");

  if (!ssl_params(ctx,dhfile,rsalen))
    strerr_die2x(111,FATAL,"unable to set DH/RSA parameters");

  if (!ssl_ciphers(ctx,ciphers))
    strerr_die2x(111,FATAL,"unable to set cipher list");

  if (verbosity >= 2) {
    strnum[fmt_ulong(strnum,getpid())] = 0;
    strnum2[fmt_ulong(strnum2,rsalen)] = 0;
    strerr_warn4("sslserver: cafile ",strnum," ",cafile,0);
    strerr_warn4("sslserver: ccafile ",strnum," ",ccafile,0);
    strerr_warn4("sslserver: cadir ",strnum," ",cadir,0);
    strerr_warn4("sslserver: chainfile ",strnum," ",certchainfile,0);
    strerr_warn4("sslserver: cert ",strnum," ",certfile,0);
    strerr_warn4("sslserver: key ",strnum," ",keyfile,0);
    strerr_warn6("sslserver: param ",strnum," ",dhfile," ",strnum2,0);
  }

  close(0); open_read("/dev/null");
  close(1); open_append("/dev/null");

  printstatus();
 
  for (;;) {
    while (numchildren >= limit) sig_pause();

    sig_unblock(sig_child);
    t = socket_accept(s,&remoteaddr,&remoteport);
    sig_block(sig_child);

    if (t == -1) continue;
    ++numchildren; printstatus();
 
    switch(fork()) {
      case 0:
        close(s);
        doit(t);
	strerr_die4sys(111,DROP,"unable to run ",*argv,": ");
      case -1:
        strerr_warn2(DROP,"unable to fork: ",&strerr_sys);
        --numchildren; printstatus();
    }
    close(t);
  }
}
Esempio n. 19
0
int runsvdir_main(int argc, char **argv)
{
	struct stat s;
	dev_t last_dev = last_dev; /* for gcc */
	ino_t last_ino = last_ino; /* for gcc */
	time_t last_mtime = 0;
	int wstat;
	int curdir;
	int pid;
	unsigned deadline;
	unsigned now;
	unsigned stampcheck;
	char ch;
	int i;

	argv++;
	if (!*argv)
		bb_show_usage();
	if (argv[0][0] == '-') {
		switch (argv[0][1]) {
		case 'P': set_pgrp = 1;
		case '-': ++argv;
		}
		if (!*argv)
			bb_show_usage();
	}

	sig_catch(SIGTERM, s_term);
	sig_catch(SIGHUP, s_hangup);
	svdir = *argv++;
	if (argv && *argv) {
		rplog = *argv;
		if (setup_log() != 1) {
			rplog = 0;
			warnx("log service disabled");
		}
	}
	curdir = open_read(".");
	if (curdir == -1)
		fatal2_cannot("open current directory", "");
	coe(curdir);

	stampcheck = monotonic_sec();

	for (;;) {
		/* collect children */
		for (;;) {
			pid = wait_nohang(&wstat);
			if (pid <= 0)
				break;
			for (i = 0; i < svnum; i++) {
				if (pid == sv[i].pid) {
					/* runsv has gone */
					sv[i].pid = 0;
					check = 1;
					break;
				}
			}
		}

		now = monotonic_sec();
		if ((int)(now - stampcheck) >= 0) {
			/* wait at least a second */
			stampcheck = now + 1;

			if (stat(svdir, &s) != -1) {
				if (check || s.st_mtime != last_mtime
				 || s.st_ino != last_ino || s.st_dev != last_dev
				) {
					/* svdir modified */
					if (chdir(svdir) != -1) {
						last_mtime = s.st_mtime;
						last_dev = s.st_dev;
						last_ino = s.st_ino;
						check = 0;
						//if (now <= mtime)
						//	sleep(1);
						runsvdir();
						while (fchdir(curdir) == -1) {
							warn2_cannot("change directory, pausing", "");
							sleep(5);
						}
					} else
						warn2_cannot("change directory to ", svdir);
				}
			} else
				warn2_cannot("stat ", svdir);
		}

		if (rplog) {
			if ((int)(now - stamplog) >= 0) {
				write(logpipe[1], ".", 1);
				stamplog = now + 900;
			}
		}

		pfd[0].revents = 0;
		sig_block(SIGCHLD);
		deadline = (check ? 1 : 5);
		if (rplog)
			poll(pfd, 1, deadline*1000);
		else
			sleep(deadline);
		sig_unblock(SIGCHLD);

		if (pfd[0].revents & POLLIN) {
			while (read(logpipe[0], &ch, 1) > 0) {
				if (ch) {
					for (i = 6; i < rploglen; i++)
						rplog[i-1] = rplog[i];
					rplog[rploglen-1] = ch;
				}
			}
		}

		switch (exitsoon) {
		case 1:
			_exit(0);
		case 2:
			for (i = 0; i < svnum; i++)
				if (sv[i].pid)
					kill(sv[i].pid, SIGTERM);
			_exit(111);
		}
	}
	/* not reached */
	return 0;
}
Esempio n. 20
0
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);
}
Esempio n. 21
0
int main(int argc, char **argv)
{
    struct stat s;
    time_t mtime =0;
    int wstat;
    int curdir;
    int pid;
    struct taia deadline;
    struct taia now;
    struct taia stampcheck;
    char ch;
    int i;

    progname =*argv++;
    if (! argv || ! *argv) usage();
    if (**argv == '-')
    {
        switch (*(*argv +1))
        {
        case 'P':
            pgrp =1;
        case '-':
            ++argv;
        }
        if (! argv || ! *argv) usage();
    }

    sig_catch(sig_term, s_term);
    sig_catch(sig_hangup, s_hangup);
    svdir =*argv++;
    if (argv && *argv)
    {
        rplog =*argv;
        if (setup_log() != 1)
        {
            rplog =0;
            warn3x("log service disabled.", 0, 0);
        }
    }
    if ((curdir =open_read(".")) == -1)
        fatal("unable to open current directory", 0);
    coe(curdir);

    taia_now(&stampcheck);

    for (;;)
    {
        /* collect children */
        for (;;)
        {
            if ((pid =wait_nohang(&wstat)) <= 0) break;
            for (i =0; i < svnum; i++)
            {
                if (pid == sv[i].pid)
                {
                    /* runsv has gone */
                    sv[i].pid =0;
                    check =1;
                    break;
                }
            }
        }

        taia_now(&now);
        if (now.sec.x < (stampcheck.sec.x -3))
        {
            /* time warp */
            warn3x("time warp: resetting time stamp.", 0, 0);
            taia_now(&stampcheck);
            taia_now(&now);
            if (rplog) taia_now(&stamplog);
        }
        if (taia_less(&now, &stampcheck) == 0)
        {
            /* wait at least a second */
            taia_uint(&deadline, 1);
            taia_add(&stampcheck, &now, &deadline);

            if (stat(svdir, &s) != -1)
            {
                if (check || \
                        s.st_mtime != mtime || s.st_ino != ino || s.st_dev != dev)
                {
                    /* svdir modified */
                    if (chdir(svdir) != -1)
                    {
                        mtime =s.st_mtime;
                        dev =s.st_dev;
                        ino =s.st_ino;
                        check =0;
                        if (now.sec.x <= (4611686018427387914ULL +(uint64)mtime))
                            sleep(1);
                        runsvdir();
                        while (fchdir(curdir) == -1)
                        {
                            warn("unable to change directory, pausing", 0);
                            sleep(5);
                        }
                    }
                    else
                        warn("unable to change directory to ", svdir);
                }
            }
            else
                warn("unable to stat ", svdir);
        }

        if (rplog)
            if (taia_less(&now, &stamplog) == 0)
            {
                write(logpipe[1], ".", 1);
                taia_uint(&deadline, 900);
                taia_add(&stamplog, &now, &deadline);
            }
        /* half a second */
        deadline.sec.x =0;
        deadline.nano =500000000UL;
        deadline.atto =0;
        taia_add(&deadline, &now, &deadline);

        sig_block(sig_child);
        if (rplog)
            iopause(io, 1, &deadline, &now);
        else
            iopause(0, 0, &deadline, &now);
        sig_unblock(sig_child);

        if (rplog && (io[0].revents | IOPAUSE_READ))
            while (read(logpipe[0], &ch, 1) > 0)
                if (ch)
                {
                    for (i =6; i < rploglen; i++)
                        rplog[i -1] =rplog[i];
                    rplog[rploglen -1] =ch;
                }

        switch(exitsoon)
        {
        case 1:
            _exit(0);
        case 2:
            for (i =0; i < svnum; i++) if (sv[i].pid) kill(sv[i].pid, SIGTERM);
            _exit(111);
        }
    } /* for (;;) */
    /* not reached */
    _exit(0);
}
Esempio n. 22
0
int
main(int argc, char *argv[], char *envp[])
{
  nextopt_t    nopt = nextopt_INIT(argc, argv, ":hVL:");
  char         opt;
  uint32_t     secs;
  const char  *z;

  progname = nextopt_progname(&nopt);
  while((opt = nextopt(&nopt))){
      char optc[2] = {nopt.opt_got, '\0'};
      switch(opt){
      case 'h': usage(); die(0); break;
      case 'V': version(); die(0); break;
      case 'L': /* label string ignored */ break;
      case ':':
          fatal_usage("missing argument for option -", optc);
          break;
      case '?':
          if(nopt.opt_got != '?'){
              fatal_usage("invalid option: -", optc);
          }
          /* else fallthrough: */
      default :
          die_usage(); break; 
      }
  }

  argc -= nopt.arg_ndx;
  argv += nopt.arg_ndx;

  if(argc < 2){
      fatal_usage("missing required argument(s)");
  }

  z = nuscan_uint32(&secs, argv[0]);
  if(*z != '\0'){
      fatal_usage("bad numeric argument for secs: ", argv[0]);
  }
  ++argv;

  /* catch SIGALRM on pause()/sleep() without termination: */
  sig_catch(SIGALRM, sig_trap);

  if(secs == 0)
      pause();
  else
      sleep(secs);

  sig_uncatch(SIGALRM);
  errno = 0; 

  /* execvx() provides path search for prog */
  execvx(argv[0], argv, envp, NULL);

  /* uh oh: */
  fatal_syserr("unable to run ", argv[0]);

  /* not reached: */
  return 0;
}
Esempio n. 23
0
int supervise_run(void)
{
	g_pid = 0;
	g_flagexit = 0;
	g_flagwant = 1;
	g_flagwantup = opt_auto_start;
	g_flagpaused = 0;

	sig_block(SIGCHLD);
	sig_catch(SIGCHLD, sigchild_handler);

	stat_pidchange();
	stat_update();

	if(g_flagwant && g_flagwantup) {
		trystart();
	}

	while(1) {
		char c;
		ssize_t rl;

		if(g_flagexit && !g_pid) { return 0; }

printf("waiting pid pid=%d\n",g_pid);
		while(1) {
			int stat;
			int r = waitpid(-1, &stat, WNOHANG);
			if(r == 0) { break; }
			if(r < 0 && errno != EAGAIN && errno != EINTR) { break; }
			if(r == g_pid) {
				g_pid = 0;
				stat_pidchange();
				stat_update();
				if(g_flagexit) { return 0; }
				if(g_flagwant && g_flagwantup) {
					trystart();
					break;
				}
			}
		}

printf("reading... pid=%d\n",g_pid);
		sig_unblock(SIGCHLD);
		rl = read(g_ctl_rfd, &c, 1);
		if(rl <= 0) {
			if(errno == EAGAIN || errno == EINTR) {
				continue;
			}
			return -1;
		}
		sig_block(SIGCHLD);

		switch(c) {
		case 'd':  /* down */
printf("down %d\n",g_pid);
			g_flagwant = 1;
			g_flagwantup = 0;
			if(g_pid) {
				kill(g_pid, SIGTERM);
				kill(g_pid, SIGCONT);
				g_flagpaused = 0;
			}
			stat_update();
			break;

		case 'u':  /* up */
printf("up %d\n",g_pid);
			g_flagwant = 1;
			g_flagwantup = 1;
			if(!g_pid) { trystart(); }
			stat_update();
			break;

		case 'o':  /* once */
printf("once %d\n",g_pid);
			g_flagwant = 0;
			if(!g_pid) { trystart(); }
			stat_update();
			break;

		case 'x':  /* exit */
printf("exit %d\n",g_pid);
			g_flagexit = 1;
			stat_update();
			break;

		case 'p':  /* pause */
printf("pause %d\n",g_pid);
			g_flagpaused = 1;
			if(g_pid) { kill(g_pid, SIGSTOP); }
			stat_update();
			break;

		case 'c':  /* continue */
printf("continue %d\n",g_pid);
			g_flagpaused = 0;
			if(g_pid) { kill(g_pid, SIGCONT); }
			stat_update();
			break;

		case 'h':  /* hup */
printf("hup %d\n",g_pid);
			if(g_pid) { kill(g_pid, SIGHUP); }
			break;

		case 'a':  /* alarm */
printf("alarm %d\n",g_pid);
			if(g_pid) { kill(g_pid, SIGALRM); }
			break;

		case 'i':  /* interrupt */
printf("interrupt %d\n",g_pid);
			if(g_pid) { kill(g_pid, SIGINT); }
			break;

		case 't':  /* term */
printf("term %d\n",g_pid);
			if(g_pid) { kill(g_pid, SIGTERM); }
			break;

		case 'k':  /* kill */
printf("kill %d\n",g_pid);
			if(g_pid) { kill(g_pid, SIGKILL); }
			break;

		case '1':  /* usr1 */
printf("usr1 %d\n",g_pid);
			if(g_pid) { kill(g_pid, SIGUSR1); }
			break;

		case '2':  /* usr2 */
printf("usr2 %d\n",g_pid);
			if(g_pid) { kill(g_pid, SIGUSR2); }
			break;

		case 's':  /* sigchld */
printf("sigchld %d\n",g_pid);
			if(!opt_auto_restart) {
				g_flagwant = 0;
				stat_update();
			}
			break;

		case ' ': /* ping */
			// FIXME touch status file
			break;
		}
	}
}
Esempio n. 24
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;
	unsigned int exit_time = 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_t.chdir_path);
    }
    
    // init log
    ctlog(argv[0], 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_t.log_level);
    
    if (chdir(config_t.chdir_path) == -1) {
        log_error("can not start: unable to change directory:%s", config_t.chdir_path);
        return 1;
    }
    log_debug("log_level:%s", config_t.log_level);
    log_debug("chdir_path:%s", config_t.chdir_path);
    log_debug("offset_path:%s", config_t.offset_path);
    log_debug("max_childs:%s", config_t.max_childs);
    
    // ---------- ----------
    
    childs_t = (struct childs_st *)malloc((atoi(config_t.max_childs) + 1) * sizeof(struct childs_st));
    if (childs_t == NULL) {
        log_error("malloc childs [%d] faild:[%d]:%s", (atoi(config_t.max_childs) + 1), errno, strerror(errno));
        exit(1);
    }
    
    int i = 0;
    for (i=0; i<(atoi(config_t.max_childs) +1); i++) {
        init_child_with_idx(i);
    }
    
    // 捕抓子进程退出信号
    sig_catch(SIGCHLD, sigchld_exit);
    
    
    // ------ 开始 ------
    // 初始化,读取文件索引内容
    struct tm *tmp;
    struct stat st;
    
    char now_str[1024] = {0};
    time_t cur = time(NULL);
    
    tmp = localtime(&cur);
    strftime(now_str, sizeof(now_str) - 1, "%Y%m%d", tmp);
    
    if (*(config_t.offset_path) == '\0') {
        config_t.offset_path[0] = '.';
        config_t.offset_path[1] = '\0';
    } else {
        if ( is_dir_exits(config_t.offset_path) != 0 ) {
            log_error("is_dir_exit fail");
            return 1;
        }
    }
    
    char offset_file[MAX_LINE] = {0};
    snprintf(offset_file, sizeof(offset_file), "%s/%s.%s", config_t.offset_path, OFFSET_FILENAME, now_str);
    
    struct file_info_t file_info_st;
    if (init_for_rindex(&file_info_st, offset_file) != 0) {
        printf("init_for_rindex fail\n");
        log_error("init_for_rindex fail");
        return 1;
    }
    
    
    // 打开被分析的文件
    char buf[BUF_SIZE] = {0};
    FILE *fp = fopen(config_t.process_file, "r");
    if (!fp) {
        printf("open file:%s fail:%m\n", config_t.process_file);
        log_error("open file:%s fail:%m", config_t.process_file);
        if (file_info_st.file_rindex_fd)
            close(file_info_st.file_rindex_fd);
        return 1;
    }
    
    // 如果偏移量大于0,则偏移文件到上次读取的地方
    if (file_info_st.rindex_offset > 0) {
        if (lseek(fileno(fp), file_info_st.rindex_offset, SEEK_SET) == -1) {
            printf("lseek fail:%m\n");
            log_error("lseek fail:%m");
            fclose(fp);
            if (file_info_st.file_rindex_fd)
                close(file_info_st.file_rindex_fd);
            return 1;
        }
    }
    
    // 循环读取文件,读一行分析,如果是逻辑开始行, 创建一个子进程去执行
    while (1) {
        if (!fgets(buf, sizeof(buf)-1, fp)) {
            // 读取失败
            if (is_need_master_exit(fileno(fp), config_t.process_file, atoi(config_t.exit_time)) == 1) {
                log_info("file:%s was expire, bye!", config_t.process_file);
                goto MASTER_BYE;
            }
            
            log_debug("fgets is null, sleep 5 second");
            sleep(atoi(config_t.wait_sleep));
            
            continue;
        }
        
        if (*buf == '\0') {
            continue;
        }
        
        
        if ( strstr(buf, " qmail-smtpd[")
            && strstr(buf, "]: [INFO] mail_process ICID:")
            && strstr(buf, " LOGExe:[-M") ) {
        
            // 保存当前读取的偏移量
            file_info_st.rindex_offset = ftell(fp);
            if (file_info_st.rindex_offset > 0) {
                snprintf(file_info_st.file_rindex_offset_ptr, 1023, "%ld", file_info_st.rindex_offset);
            }
            
            
            // 处理
            process_via_child(buf, fp, file_info_st.rindex_offset);
        }
    }
    
MASTER_BYE:
    fclose(fp);
    
    if (file_info_st.file_rindex_fd)
        close(file_info_st.file_rindex_fd);
    
    if (childs_t != NULL) {
        free(childs_t);
        childs_t = NULL;
    }
    
    return 0;
    
}
Esempio n. 25
0
File: runit.c Progetto: Gottox/runit
int main (int argc, const char * const *argv, char * const *envp) {
  const char * prog[2];
  int pid, pid2;
  int wstat;
  int st;
  iopause_fd x;
#ifndef IOPAUSE_POLL
  fd_set rfds;
  struct timeval t;
#endif
  char ch;
  int ttyfd;
  struct stat s;

  if (getpid() != 1) strerr_die2x(111, FATAL, "must be run as process no 1.");
  setsid();

  sig_block(sig_alarm);
  sig_block(sig_child);
  sig_catch(sig_child, sig_child_handler);
  sig_block(sig_cont);
  sig_catch(sig_cont, sig_cont_handler);
  sig_block(sig_hangup);
  sig_block(sig_int);
  sig_catch(sig_int, sig_int_handler);
  sig_block(sig_pipe);
  sig_block(sig_term);

  /* console */
  if ((ttyfd =open_write("/dev/console")) != -1) {
    dup2(ttyfd, 0); dup2(ttyfd, 1); dup2(ttyfd, 2);
    if (ttyfd > 2) close(ttyfd);
  }

  /* create selfpipe */
  while (pipe(selfpipe) == -1) {
    strerr_warn2(FATAL, "unable to create selfpipe, pausing: ", &strerr_sys);
    sleep(5);
  }
  coe(selfpipe[0]);
  coe(selfpipe[1]);
  ndelay_on(selfpipe[0]);
  ndelay_on(selfpipe[1]);

#ifdef RB_DISABLE_CAD
  /* activate ctrlaltdel handling, glibc, dietlibc */
  if (RB_DISABLE_CAD == 0) reboot_system(0);
#endif

  strerr_warn3(INFO, "$Id: 25da3b86f7bed4038b8a039d2f8e8c9bbcf0822b $",
               ": booting.", 0);

  /* runit */
  for (st =0; st < 3; st++) {
    /* if (st == 2) logwtmp("~", "reboot", ""); */
    while ((pid =fork()) == -1) {
      strerr_warn4(FATAL, "unable to fork for \"", stage[st], "\" pausing: ",
                   &strerr_sys);
      sleep(5);
    }
    if (!pid) {
      /* child */
      prog[0] =stage[st];
      prog[1] =0;

      /* stage 1 gets full control of console */
      if (st == 0) {
        if ((ttyfd =open("/dev/console", O_RDWR)) != -1) {
#ifdef TIOCSCTTY 
          ioctl(ttyfd, TIOCSCTTY, (char *)0);
#endif
          dup2(ttyfd, 0);
          if (ttyfd > 2) close(ttyfd);
        }
        else
          strerr_warn2(WARNING, "unable to open /dev/console: ", &strerr_sys);
      }
      else
        setsid();

      sig_unblock(sig_alarm);
      sig_unblock(sig_child);
      sig_uncatch(sig_child);
      sig_unblock(sig_cont);
      sig_ignore(sig_cont);
      sig_unblock(sig_hangup);
      sig_unblock(sig_int);
      sig_uncatch(sig_int);
      sig_unblock(sig_pipe);
      sig_unblock(sig_term);
            
      strerr_warn3(INFO, "enter stage: ", stage[st], 0);
      execve(*prog, (char *const *)prog, envp);
      strerr_die4sys(0, FATAL, "unable to start child: ", stage[st], ": ");
    }

    x.fd =selfpipe[0];
    x.events =IOPAUSE_READ;
    for (;;) {
      int child;

      sig_unblock(sig_child);
      sig_unblock(sig_cont);
      sig_unblock(sig_int);
#ifdef IOPAUSE_POLL
      poll(&x, 1, 14000);
#else
      t.tv_sec =14; t.tv_usec =0;
      FD_ZERO(&rfds);
      FD_SET(x.fd, &rfds);
      select(x.fd +1, &rfds, (fd_set*)0, (fd_set*)0, &t);
#endif
      sig_block(sig_cont);
      sig_block(sig_child);
      sig_block(sig_int);
      
      while (read(selfpipe[0], &ch, 1) == 1) {}
      while ((child =wait_nohang(&wstat)) > 0)
        if (child == pid) break;
      if (child == -1) {
        strerr_warn2(WARNING, "wait_nohang, pausing: ", &strerr_sys);
        sleep(5);
      }

      /* reget stderr */
      if ((ttyfd =open_write("/dev/console")) != -1) {
        dup2(ttyfd, 2);
        if (ttyfd > 2) close(ttyfd);
      }

      if (child == pid) {
        if (wait_exitcode(wstat) != 0) {
          if (wait_crashed(wstat))
            strerr_warn3(WARNING, "child crashed: ", stage[st], 0);
          else
            strerr_warn3(WARNING, "child failed: ", stage[st], 0);
          if (st == 0)
            /* this is stage 1 */
            if (wait_crashed(wstat) || (wait_exitcode(wstat) == 100)) {
              strerr_warn3(INFO, "leave stage: ", stage[st], 0);
              strerr_warn2(WARNING, "skipping stage 2...", 0);
              st++;
              break;
            }
          if (st == 1)
            /* this is stage 2 */
            if (wait_crashed(wstat) || (wait_exitcode(wstat) == 111)) {
              strerr_warn2(WARNING, "killing all processes in stage 2...", 0);
              kill(-pid, 9);
              sleep(5);
              strerr_warn2(WARNING, "restarting.", 0);
              st--;
              break;
            }
        }
        strerr_warn3(INFO, "leave stage: ", stage[st], 0);
        break;
      }
      if (child != 0) {
        /* collect terminated children */
        write(selfpipe[1], "", 1);
        continue;
      }

      /* sig? */
      if (!sigc  && !sigi) {
#ifdef DEBUG
        strerr_warn2(WARNING, "poll: ", &strerr_sys);
#endif
        continue;
      }
      if (st != 1) {
        strerr_warn2(WARNING, "signals only work in stage 2.", 0);
        sigc =sigi =0;
        continue;
      }
      if (sigi && (stat(CTRLALTDEL, &s) != -1) && (s.st_mode & S_IXUSR)) {
        strerr_warn2(INFO, "ctrl-alt-del request...", 0);
        prog[0] =CTRLALTDEL; prog[1] =0;
        while ((pid2 =fork()) == -1) {
          strerr_warn4(FATAL, "unable to fork for \"", CTRLALTDEL,
                       "\" pausing: ", &strerr_sys);
          sleep(5);
        }
        if (!pid2) {
          /* child */
          strerr_warn3(INFO, "enter stage: ", prog[0], 0);
          execve(*prog, (char *const *) prog, envp);
          strerr_die4sys(0, FATAL, "unable to start child: ", prog[0], ": ");
        }
        if (wait_pid(&wstat, pid2) == -1)
          strerr_warn2(FATAL, "wait_pid: ", &strerr_sys);
        if (wait_crashed(wstat))
          strerr_warn3(WARNING, "child crashed: ", CTRLALTDEL, 0);
        strerr_warn3(INFO, "leave stage: ", prog[0], 0);
        sigi =0;
        sigc++;
      }
      if (sigc && (stat(STOPIT, &s) != -1) && (s.st_mode & S_IXUSR)) {
        int i;
        /* unlink(STOPIT); */
        chmod(STOPIT, 0);

        /* kill stage 2 */
#ifdef DEBUG
        strerr_warn2(WARNING, "sending sigterm...", 0);
#endif
        kill(pid, sig_term);
        i =0;
        while (i < 5) {
          if ((child =wait_nohang(&wstat)) == pid) {
#ifdef DEBUG
            strerr_warn2(WARNING, "stage 2 terminated.", 0);
#endif
            pid =0;
            break;
          }
          if (child) continue;
          if (child == -1) 
            strerr_warn2(WARNING, "wait_nohang: ", &strerr_sys);
#ifdef DEBUG
          strerr_warn2(WARNING, "waiting...", 0);
#endif
          sleep(1);
          i++;
        }
        if (pid) {
          /* still there */
          strerr_warn2(WARNING,
                       "stage 2 not terminated, sending sigkill...", 0);
          kill(pid, 9);
          if (wait_pid(&wstat, pid) == -1)
            strerr_warn2(WARNING, "wait_pid: ", &strerr_sys);
        }
        sigc =0;
        strerr_warn3(INFO, "leave stage: ", stage[st], 0);

        /* enter stage 3 */
        break;
      }
      sigc =sigi =0;
#ifdef DEBUG
      strerr_warn2(WARNING, "no request.", 0);
#endif
    }
  }

  /* reget stderr */
  if ((ttyfd =open_write("/dev/console")) != -1) {
    dup2(ttyfd, 2);
    if (ttyfd > 2) close(ttyfd);
  }

#ifdef RB_AUTOBOOT
  /* fallthrough stage 3 */
  strerr_warn2(INFO, "sending KILL signal to all processes...", 0);
  kill(-1, SIGKILL);

  pid =fork();
  switch (pid) {
  case  0:
  case -1:
  if ((stat(REBOOT, &s) != -1) && (s.st_mode & S_IXUSR)) {
    strerr_warn2(INFO, "system reboot.", 0);
    sync();
    reboot_system(RB_AUTOBOOT);
  }
  else {
#ifdef RB_POWER_OFF
    strerr_warn2(INFO, "power off...", 0);
    sync();
    reboot_system(RB_POWER_OFF);
    sleep(2);
#endif
#ifdef RB_HALT_SYSTEM
    strerr_warn2(INFO, "system halt.", 0);
    sync();
    reboot_system(RB_HALT_SYSTEM);
#else
#ifdef RB_HALT
    strerr_warn2(INFO, "system halt.", 0);
    sync();
    reboot_system(RB_HALT);
#else
    strerr_warn2(INFO, "system reboot.", 0);
    sync();
    reboot_system(RB_AUTOBOOT);
#endif
#endif
  }
  if (pid == 0) _exit(0);
  break;
  default:
  sig_unblock(sig_child);
  while (wait_pid(0, pid) == -1);
  }
#endif

  for (;;) sig_pause();
  /* not reached */
  strerr_die2x(0, INFO, "exit.");
  return(0);
}
Esempio n. 26
0
int main(int argc, char **argv)
{
	struct sigaction sa;

	if (parse_argv(argc, argv) < 0)
		_exit(100);

	snprintf(status_files[0], 1024, "%s/lock", status_dir);
	snprintf(status_files[1], 1024, "%s/control", status_dir);
	snprintf(status_files[2], 1024, "%s/ok", status_dir);
	snprintf(status_files[3], 1024, "%s/status", status_dir);
	snprintf(status_files[4], 1024, "%s/status.new", status_dir);
	snprintf(status_files[5], 1024, "%s/supervise.log", status_dir);
	snprintf(status_files[6], 1024, "%s/supervise.log.wf", status_dir);

	sa.sa_handler = SIG_IGN;
	sigemptyset(&sa.sa_mask);
	if (sigaction(SIGHUP, &sa, NULL) < 0)
	{
		printf("unable to ignore SIGHUP for %s\n", service);  
		_exit(110);
	}

	if (mkdir(status_dir, 0700) < 0 && errno !=  EEXIST)
	{
		printf("unable to create dir: %s\n", status_dir);  
		_exit(110);
	}

	fdlog = open_append(status_files[5]);
	if (fdlog == -1)
	{
		printf("unable to open %s%s", status_dir, "/supervise.log");
		_exit(111);
	}
	coe(fdlog);

	fdlogwf = open_append(status_files[6]);
	if (fdlogwf == -1)
	{
		printf("unable to open %s%s", status_dir, "/supervise.log.wf");
		_exit(1);
	}
	coe(fdlogwf);

	if (daemon(1, 0) < 0)
	{
		printf("failed to daemonize supervise!\n");
		_exit(111);
	}

	if (pipe(selfpipe) == -1)
	{
		write_log(fdlogwf, FATAL, "unable to create pipe for ", service, "\n");
		_exit(111);
	}
	coe(selfpipe[0]);
	coe(selfpipe[1]);
	ndelay_on(selfpipe[0]);
	ndelay_on(selfpipe[1]);

	sig_block(sig_child);
	sig_catch(sig_child, trigger);

	sig_block(sig_alarm);
	sig_catch(sig_alarm, timer_handler);
	sig_unblock(sig_alarm);

	fdlock = open_append(status_files[0]);
	if ((fdlock == -1) || (lock_exnb(fdlock) == -1))
	{
		write_log(fdlogwf, FATAL, "Unable to acquier ", status_dir, "/lock\n");
		_exit(111);
	}
	coe(fdlock);

	fifo_make(status_files[1], 0600);
	fdcontrol = open_read(status_files[1]);
	if (fdcontrol == -1)
	{
		write_log(fdlogwf, FATAL, "unable to read ", status_dir, "/control\n");
		_exit(1);
	}
	coe(fdcontrol);
	ndelay_on(fdcontrol);

	fdcontrolwrite = open_write(status_files[1]);
	if (fdcontrolwrite == -1)
	{
		write_log(fdlogwf, FATAL, "unable to write ", status_dir, "/control\n");
		_exit(1);
	}
	coe(fdcontrolwrite);

	fifo_make(status_files[2], 0600);
	fdok = open_read(status_files[2]);
	if (fdok == -1)
	{
		write_log(fdlogwf, FATAL, "unable to read ", status_dir, "/ok\n");
		_exit(1);
	}
	coe(fdok);
	
	if (!restart_sh[0])
	{
		parse_conf(); 
	}
	pidchange();
	announce();

	if (!flagwant || flagwantup)
		trystart();
	doit();
	announce();

	_exit(0);
}