int main(int argc, char **argv) { const static char annotate = '#'; char *ptr_annotate = NULL; char path[128] = {0}; char line[128] = {0}; char *buf = NULL; char *ptr = NULL; size_t buf_sz = 0; pid_t pid = -1; // int len = 0; if ((argc == 0) && (strcmp(argv[1], "-d") != 0)) { if ((pid = create_daemon()) < 0) _exit(-1); else if (pid > 0) _exit(1); } openlog("vp-promon", LOG_CONS|LOG_PID|LOG_PERROR, LOG_USER); sprintf(path, "%s/promon.conf", PATH_CFG); if ( ! t_read_full_file(path, &buf, &buf_sz, 0)) { logdbg_fmt("Open configure file failed!(%s)\n", path); return -1; } ptr = buf; while ((ptr = loop_line_from_buf(ptr, line, sizeof(line))) != NULL) { if ((ptr_annotate = strchr(line, annotate)) != NULL) *ptr_annotate = '\0'; trimleft(line); /* if (line[strlen(line)-1] == '&') line[strlen(line)] = '\0'; */ if (line[0] == '\0') continue ; if ((pid = create_daemon()) < 0) break; else if (pid == 0) do_promon(line); } oss_free(&buf); return 0; }
/* * Handle options to control the daemon */ void daemon_manager(const char *bin, const char *cmd) { pid_t pid; char *str; str = str_tolower(cmd); if (strcmp(str, "start") == 0) { if (load_pid_file() > 0) { printf("Daemon is already running\n"); exit(EXIT_FAILURE); } pid = create_daemon(bin); /* If the returned pid is < 0, there was a problem with the fork and we exit with a failure */ if (pid < 0) { free(str); exit(EXIT_FAILURE); } /* If the returned pid > 0 it is the pid of the child and we are the parent. Save the pid to the pid file and exit with success */ if (pid > 0) { save_pid_file(pid); free(str); exit(EXIT_SUCCESS); } /* If this point is reached, the fork was successfull and we are the child process. Continue as daemon from here on. */ } else if (strcmp(str, "stop") == 0) { pid = load_pid_file(); if (pid <= 0) { printf("No pid file, cannot stop\n"); exit(EXIT_FAILURE); } /* Send a SIGTERM signal to the daemon */ kill(pid, SIGTERM); remove_pid_file(); exit(EXIT_SUCCESS); } else if (strcmp(str, "restart") == 0 ) { /* Leave empty for now */ } free(str); }
int main (int argc, char * argv[]) { /* availability options */ char * opts = "d"; /* processed option */ int c; int sock_id; /* dodanie handlera na SIGINT */ signal(SIGINT, sigint_handler); /* check if define more than one option */ if (argc == 2) { /* iteration by each of option */ while ((c = getopt(argc, argv, opts)) != -1) { switch (c) { /* for 'u' run daemon */ case 'd': create_daemon(); break; /* for unrecognized option */ case '?': default: printf("Ignore passed options\n"); } } } printf("=== create server ===\n\n"); /* create socket */ sock_id = create_socket_tcp(); /* bind server to defined port */ bind_port(sock_id, PORT); /* server waiting for client */ listen_for_client_tcp(sock_id, MAX_QUEUE); /* handle client */ handle_incoming_client(sock_id, send_time_to_socket, 1); return 0; }
int main(int argc, char **argv) { struct daemon *daemon; struct config *cfg; int ret; /* if(!check_root()) { fprintf(stderr, "permission denied, root only\n"); exit(EXIT_FAILURE); } */ if(argc < 3) { daemonize(); } signal(SIGPIPE, SIG_IGN); ret = log_init(HADM_LOG_CONF, HADM_SERVER_LOG_CAT); if(ret < 0) { exit(EXIT_FAILURE); } cfg = load_config(CONFIG_FILE); if(cfg == NULL) { log_error("load config file failed, please check config file!"); exit(EXIT_FAILURE); } daemon = create_daemon(cfg); if(daemon == NULL) { exit(EXIT_FAILURE); } if(init_daemon(daemon) < 0) { exit(EXIT_FAILURE); } daemon_run(daemon); return 0; }
/* * @ proto_type: the proxy type of raw-vsudp or raw-vstcp * @ arg: the param of pass videostream process. */ int start_vstream_proxy(char * proto_type, char * arg[]) { pid_t pid; char exec_path[128]; //sprintf(exec_path, "%s/%s", DEFAULT_APP_DIR, proto_type); sprintf(exec_path, "%s/%s", g_p_app_dir, proto_type); signal(SIGCHLD, SIG_IGN); if ((pid = create_daemon()) < 0) _exit(-1); else if (pid == 0) { if (execv(exec_path, arg) == -1) { syslog(LOG_INFO, "start_vstream_proxy() failed"); return -1; } } return pid; }
static void server_loop(const char *socket_path, const char *pidfile_path, int debug, int timeout, int quiet) { struct sockaddr_un my_addr, from_addr; struct flock fl; socklen_t fromlen; int32_t reply_len = 0; uuid_t uu; mode_t save_umask; char reply_buf[1024], *cp; char op, str[37]; int i, s, ns, len, num; int fd_pidfile, ret; fd_pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0664); if (fd_pidfile < 0) { if (!quiet) fprintf(stderr, "Failed to open/create %s: %s\n", pidfile_path, strerror(errno)); exit(1); } cleanup_pidfile = pidfile_path; cleanup_socket = 0; signal(SIGALRM, terminate_intr); alarm(30); fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_pid = 0; while (fcntl(fd_pidfile, F_SETLKW, &fl) < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (!quiet) fprintf(stderr, "Failed to lock %s: %s\n", pidfile_path, strerror(errno)); exit(1); } ret = call_daemon(socket_path, 0, reply_buf, sizeof(reply_buf), 0, 0); if (ret > 0) { if (!quiet) printf(_("uuidd daemon already running at pid %s\n"), reply_buf); exit(1); } alarm(0); if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { if (!quiet) fprintf(stderr, _("Couldn't create unix stream " "socket: %s"), strerror(errno)); exit(1); } /* * Make sure the socket isn't using fd numbers 0-2 to avoid it * getting closed by create_daemon() */ while (!debug && s <= 2) { s = dup(s); if (s < 0) { perror("dup"); exit(1); } } /* * Create the address we will be binding to. */ my_addr.sun_family = AF_UNIX; strncpy(my_addr.sun_path, socket_path, sizeof(my_addr.sun_path)); my_addr.sun_path[sizeof(my_addr.sun_path)-1] = '\0'; (void) unlink(socket_path); save_umask = umask(0); if (bind(s, (const struct sockaddr *) &my_addr, sizeof(struct sockaddr_un)) < 0) { if (!quiet) fprintf(stderr, _("Couldn't bind unix socket %s: %s\n"), socket_path, strerror(errno)); exit(1); } (void) umask(save_umask); if (listen(s, 5) < 0) { if (!quiet) fprintf(stderr, _("Couldn't listen on unix " "socket %s: %s\n"), socket_path, strerror(errno)); exit(1); } cleanup_socket = socket_path; if (!debug) create_daemon(); signal(SIGHUP, terminate_intr); signal(SIGINT, terminate_intr); signal(SIGTERM, terminate_intr); signal(SIGALRM, terminate_intr); signal(SIGPIPE, SIG_IGN); sprintf(reply_buf, "%8d\n", getpid()); if (ftruncate(fd_pidfile, 0)) {} /* Silence warn_unused_result */ write_all(fd_pidfile, reply_buf, strlen(reply_buf)); if (fd_pidfile > 1) close(fd_pidfile); /* Unlock the pid file */ while (1) { fromlen = sizeof(from_addr); if (timeout > 0) alarm(timeout); ns = accept(s, (struct sockaddr *) &from_addr, &fromlen); alarm(0); if (ns < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; perror("accept"); exit(1); } len = read(ns, &op, 1); if (len != 1) { if (len < 0) perror("read"); else printf(_("Error reading from client, " "len = %d\n"), len); goto shutdown_socket; } if ((op == 4) || (op == 5)) { if (read_all(ns, (char *) &num, sizeof(num)) != 4) goto shutdown_socket; if (debug) printf(_("operation %d, incoming num = %d\n"), op, num); } else if (debug) printf("operation %d\n", op); switch(op) { case UUIDD_OP_GETPID: sprintf(reply_buf, "%d", getpid()); reply_len = strlen(reply_buf)+1; break; case UUIDD_OP_GET_MAXOP: sprintf(reply_buf, "%d", UUIDD_MAX_OP); reply_len = strlen(reply_buf)+1; break; case UUIDD_OP_TIME_UUID: num = 1; uuid__generate_time(uu, &num); if (debug) { uuid_unparse(uu, str); printf(_("Generated time UUID: %s\n"), str); } memcpy(reply_buf, uu, sizeof(uu)); reply_len = sizeof(uu); break; case UUIDD_OP_RANDOM_UUID: num = 1; uuid__generate_random(uu, &num); if (debug) { uuid_unparse(uu, str); printf(_("Generated random UUID: %s\n"), str); } memcpy(reply_buf, uu, sizeof(uu)); reply_len = sizeof(uu); break; case UUIDD_OP_BULK_TIME_UUID: uuid__generate_time(uu, &num); if (debug) { uuid_unparse(uu, str); printf(_("Generated time UUID %s and %d " "following\n"), str, num); } memcpy(reply_buf, uu, sizeof(uu)); reply_len = sizeof(uu); memcpy(reply_buf+reply_len, &num, sizeof(num)); reply_len += sizeof(num); break; case UUIDD_OP_BULK_RANDOM_UUID: if (num < 0) num = 1; if (num > 1000) num = 1000; if (num*16 > (int) (sizeof(reply_buf)-sizeof(num))) num = (sizeof(reply_buf)-sizeof(num)) / 16; uuid__generate_random((unsigned char *) reply_buf + sizeof(num), &num); if (debug) { printf(_("Generated %d UUID's:\n"), num); for (i=0, cp=reply_buf+sizeof(num); i < num; i++, cp+=16) { uuid_unparse((unsigned char *)cp, str); printf("\t%s\n", str); } } reply_len = (num*16) + sizeof(num); memcpy(reply_buf, &num, sizeof(num)); break; default: if (debug) printf(_("Invalid operation %d\n"), op); goto shutdown_socket; } write_all(ns, (char *) &reply_len, sizeof(reply_len)); write_all(ns, reply_buf, reply_len); shutdown_socket: close(ns); } }
static void server_loop(const char *socket_path, const char *pidfile_path, const struct uuidd_cxt_t *uuidd_cxt) { struct sockaddr_un from_addr; socklen_t fromlen; int32_t reply_len = 0; uuid_t uu; char reply_buf[1024], *cp; char op, str[UUID_STR_LEN]; int i, ns, len, num; int s = 0; int fd_pidfile = -1; int ret; #ifdef USE_SOCKET_ACTIVATION if (!uuidd_cxt->no_sock) /* no_sock implies no_fork and no_pid */ #endif { signal(SIGALRM, terminate_intr); alarm(30); if (pidfile_path) fd_pidfile = create_pidfile(pidfile_path, uuidd_cxt->quiet); ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf, sizeof(reply_buf), 0, NULL); if (ret > 0) { if (!uuidd_cxt->quiet) warnx(_("uuidd daemon is already running at pid %s"), reply_buf); exit(EXIT_FAILURE); } alarm(0); s = create_socket(socket_path, (!uuidd_cxt->debug || !uuidd_cxt->no_fork), uuidd_cxt->quiet); if (listen(s, SOMAXCONN) < 0) { if (!uuidd_cxt->quiet) warn(_("couldn't listen on unix socket %s"), socket_path); exit(EXIT_FAILURE); } if (!uuidd_cxt->debug && !uuidd_cxt->no_fork) create_daemon(); if (pidfile_path) { sprintf(reply_buf, "%8d\n", getpid()); ignore_result( ftruncate(fd_pidfile, 0) ); write_all(fd_pidfile, reply_buf, strlen(reply_buf)); if (fd_pidfile > 1) close(fd_pidfile); /* Unlock the pid file */ } } signal(SIGHUP, terminate_intr); signal(SIGINT, terminate_intr); signal(SIGTERM, terminate_intr); signal(SIGALRM, terminate_intr); signal(SIGPIPE, SIG_IGN); #ifdef USE_SOCKET_ACTIVATION if (uuidd_cxt->no_sock) { if (sd_listen_fds(0) != 1) errx(EXIT_FAILURE, _("no or too many file descriptors received")); s = SD_LISTEN_FDS_START + 0; } #endif while (1) { fromlen = sizeof(from_addr); if (uuidd_cxt->timeout > 0) alarm(uuidd_cxt->timeout); ns = accept(s, (struct sockaddr *) &from_addr, &fromlen); alarm(0); if (ns < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; else err(EXIT_FAILURE, "accept"); } len = read(ns, &op, 1); if (len != 1) { if (len < 0) warn(_("read failed")); else warnx(_("error reading from client, len = %d"), len); goto shutdown_socket; } if ((op == UUIDD_OP_BULK_TIME_UUID) || (op == UUIDD_OP_BULK_RANDOM_UUID)) { if (read_all(ns, (char *) &num, sizeof(num)) != 4) goto shutdown_socket; if (uuidd_cxt->debug) fprintf(stderr, _("operation %d, incoming num = %d\n"), op, num); } else if (uuidd_cxt->debug) fprintf(stderr, _("operation %d\n"), op); switch (op) { case UUIDD_OP_GETPID: sprintf(reply_buf, "%d", getpid()); reply_len = strlen(reply_buf) + 1; break; case UUIDD_OP_GET_MAXOP: sprintf(reply_buf, "%d", UUIDD_MAX_OP); reply_len = strlen(reply_buf) + 1; break; case UUIDD_OP_TIME_UUID: num = 1; __uuid_generate_time(uu, &num); if (uuidd_cxt->debug) { uuid_unparse(uu, str); fprintf(stderr, _("Generated time UUID: %s\n"), str); } memcpy(reply_buf, uu, sizeof(uu)); reply_len = sizeof(uu); break; case UUIDD_OP_RANDOM_UUID: num = 1; __uuid_generate_random(uu, &num); if (uuidd_cxt->debug) { uuid_unparse(uu, str); fprintf(stderr, _("Generated random UUID: %s\n"), str); } memcpy(reply_buf, uu, sizeof(uu)); reply_len = sizeof(uu); break; case UUIDD_OP_BULK_TIME_UUID: __uuid_generate_time(uu, &num); if (uuidd_cxt->debug) { uuid_unparse(uu, str); fprintf(stderr, P_("Generated time UUID %s " "and %d following\n", "Generated time UUID %s " "and %d following\n", num - 1), str, num - 1); } memcpy(reply_buf, uu, sizeof(uu)); reply_len = sizeof(uu); memcpy(reply_buf + reply_len, &num, sizeof(num)); reply_len += sizeof(num); break; case UUIDD_OP_BULK_RANDOM_UUID: if (num < 0) num = 1; if (num > 1000) num = 1000; if (num * UUID_LEN > (int) (sizeof(reply_buf) - sizeof(num))) num = (sizeof(reply_buf) - sizeof(num)) / UUID_LEN; __uuid_generate_random((unsigned char *) reply_buf + sizeof(num), &num); if (uuidd_cxt->debug) { fprintf(stderr, P_("Generated %d UUID:\n", "Generated %d UUIDs:\n", num), num); for (i = 0, cp = reply_buf + sizeof(num); i < num; i++, cp += UUID_LEN) { uuid_unparse((unsigned char *)cp, str); fprintf(stderr, "\t%s\n", str); } } reply_len = (num * UUID_LEN) + sizeof(num); memcpy(reply_buf, &num, sizeof(num)); break; default: if (uuidd_cxt->debug) fprintf(stderr, _("Invalid operation %d\n"), op); goto shutdown_socket; } write_all(ns, (char *) &reply_len, sizeof(reply_len)); write_all(ns, reply_buf, reply_len); shutdown_socket: close(ns); } }
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; }
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; }
int start_server(int port_number, const char* dir_name, int period) { pthread_t tid; /* Passed to pthread_create */ struct thread_arg* targ; /* Used to pass arguments to threads */ pthread_attr_t tattr; /* Specifies that thread should be detached */ fd_set master; /* Keep track of all connections / pipes to multiplex */ fd_set read_fds; /* Copy of master for select to populate */ int fdmax; /* Highest numbered file descriptor */ int i; /* Used to index the master fd list */ int listener; /* Listening socket of the server */ int newfd; /* New connection socket fd */ struct sockaddr_in local_addr; /* Local connection info */ struct sockaddr_in remote_addr; /* Remote connection info */ socklen_t addr_len; /* Address length */ int pipe_buff[1]; /* Get sockets into here */ pipe_buff[0] = 0; // Init signal mask struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = SIG_IGN; // Start each thread in detached mode, since we don't care about // their return values pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); // Initialize the memory pool to store the direntries direntry_pool = init_mempool(sizeof(struct direntry), 512); // Set done to 0 done = 0; // Initialize the clients linked list clients = (struct clientlist*)malloc(sizeof(struct clientlist)); clients->head = NULL; clients->tail = NULL; clients->count = 0; // Copy into global init_dir strcpy(init_dir, dir_name); gperiod = period; // Initialize pipe if (pipe(remove_client_pipes) < 0) { syslog(LOG_ERR, "Cannot create IPC in server."); exit(1); } // Get full path of the directory if (realpath(dir_name, full_path) == NULL) { syslog(LOG_ERR, "Cannot resolve full path."); exit(1); } #ifdef DAEMONIZE create_daemon("dirapp"); #endif #ifndef DAEMONIZE openlog("dirapp", LOG_CONS, LOG_DAEMON); #endif // Make sure SIGPIPE is blocked if (sigaction(SIGPIPE, &sa, NULL) < 0) { syslog(LOG_WARNING, "SIGPIPE error"); } // Signals for the signal thread to handle sigemptyset(&mask); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGALRM); // Set the mask if (pthread_sigmask(SIG_BLOCK, &mask, NULL) != 0) syslog(LOG_WARNING, "pthread_sigmask failed"); // Initialize file descriptor lists FD_ZERO(&master); FD_ZERO(&read_fds); // Setup local connection info memset(&local_addr, 0, sizeof(local_addr)); local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); local_addr.sin_port = htons(port_number); // Create listener socket listener = socket(AF_INET, SOCK_STREAM, 0); // Try to bind if (bind(listener, (struct sockaddr*)&local_addr, sizeof(local_addr))) { syslog(LOG_ERR, "Cannot bind socket to address"); exit(1); } // Now listen! if (listen(listener, MAX_CLIENTS) < 0) { syslog(LOG_ERR, "Cannot listen on socket"); exit(1); } syslog(LOG_INFO, "Starting server!"); // Have select check for incoming data FD_SET(remove_client_pipes[0], &master); FD_SET(listener, &master); fdmax = listener; // Initialize the direntry lists prevdir = init_direntrylist(); curdir = init_direntrylist(); // Initially populate list of file entries in monitored directory exploredir(prevdir, (const char*)full_path); // Start signal thread pthread_create(&tid, NULL, signal_thread, NULL); int errno = 0; // Main server loop while (1) { read_fds = master; if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) { syslog(LOG_ERR, "select: %s", strerror(errno)); exit(1); } for (i = 0; i <= fdmax; i++) { if (FD_ISSET(i, &read_fds)) { if (i == listener) { addr_len = sizeof(remote_addr); newfd = accept(listener, (struct sockaddr*)&remote_addr, &addr_len); if (newfd == -1) { syslog(LOG_WARNING, "Cannot new client."); } else { FD_SET(newfd, &master); if (newfd > fdmax) { fdmax = newfd; } syslog(LOG_INFO, "New connection from: %s:%d", inet_ntoa(remote_addr.sin_addr), ntohs(remote_addr.sin_port)); // Add client to clients list in order to receive // updates pthread_create(&tid, &tattr, init_client, (void*)newfd); } } else if (i == remove_client_pipes[0]) { // Get the file descriptor of the socket that is to // be removed and store into the first position of // tmp_buff if (read(remove_client_pipes[0], pipe_buff, 1) <= 0) { syslog(LOG_ERR, "Cannot read in socket to close."); } else { // Remove socket from master list pthread_mutex_lock(&slock); FD_CLR(pipe_buff[0], &master); done = 1; pthread_mutex_unlock(&slock); // Tell kill_clients or whoever they // can procede pthread_cond_signal(&sready); } } else { // Handle disconnect targ = (struct thread_arg*)malloc(sizeof(struct thread_arg)); targ->socket = i; targ->pipe = remove_client_pipes[1]; pthread_create(&tid, &tattr, remove_client, (void*)targ); FD_CLR(i, &master); } } } } return 0; }