static int FUNC_FS_PROCESS_STOP(struct cmd_data *data) { struct fs_process_ctx *ctx; int ret = 0; if (data->idx < 0 || data->idx > MAX_PROCESS_CNT) { ERROR("index out of range %d", data->idx); return -1; } ctx = &g_proc_context[data->idx]; if (!ctx->status) { ERROR("process %d does not exist", data->idx); return -1; } if (ctx->pid != 0) { ret = pclose_ext(ctx->pid, 1); if (ret) ERROR("process %d failed\n", ctx->pid); close(ctx->stdout); ctx->pid = 0; } ctx->status = 0; return ret; }
static bool Execute_and_report_output (const char* executable, const char* client_host_name, const char* client_IP, const uint16_t client_port, const char* event, TEventType event_type, const size_t payload_len, const char** payload, const int *fd_to_close_in_child, const int fd_to_close_in_child_count) { /* command <client IP> <client port> <event type> <event> <payload length> <payload 1> ...<payload n> */ size_t i = 0; size_t len = 0; size_t buffer_len = 8 + payload_len; size_t line_buffer_len = 0; char* line_buffer = NULL; size_t line_len = 0; int linenr; bool eof_found; FILE *pipe_read, *pipe_write; char** argv = NULL; pid_t childpid = 0; int cmdres = 255; bool res = false; bool close_received = false; bool error_executing = false; bool timer_failed = false; bool message_line = false; /* command <client host name> <client IP> <client port> <event type> <event> <payload length> <payload 1> ...<payload n> */ if (!Add_string_to_string_array (&argv, &len, &buffer_len, executable)) { Free_string_array (&argv, &len, &buffer_len); return false; } if (!Add_string_to_string_array (&argv, &len, &buffer_len, client_host_name)) { Free_string_array (&argv, &len, &buffer_len); return false; } if (!Add_string_to_string_array (&argv, &len, &buffer_len, client_IP)) { Free_string_array (&argv, &len, &buffer_len); return false; } if (!Add_luint_to_string_array (&argv, &len, &buffer_len, client_port)) { Free_string_array (&argv, &len, &buffer_len); return false; } if (!Add_luint_to_string_array (&argv, &len, &buffer_len, event_type)) { Free_string_array (&argv, &len, &buffer_len); return false; } if (!Add_string_to_string_array (&argv, &len, &buffer_len, event)) { Free_string_array (&argv, &len, &buffer_len); return false; } if (!Add_luint_to_string_array (&argv, &len, &buffer_len, payload_len)) { Free_string_array (&argv, &len, &buffer_len); return false; } for (i = 0; i < payload_len; i++) { if (!Add_string_to_string_array (&argv, &len, &buffer_len, payload[i])) { Free_string_array (&argv, &len, &buffer_len); return false; } } errno = 0; line_buffer_len = LINE_BUFFER_SIZE; line_buffer = malloc (LINE_BUFFER_SIZE); bzero (line_buffer, LINE_BUFFER_SIZE); if (line_buffer == NULL) { Free_string_array (&argv, &len, &buffer_len); return false; } if (!popen_ext (argv[0], argv, true, &pipe_read, &pipe_write, NULL, false, false, false, &childpid, fd_to_close_in_child, fd_to_close_in_child_count)) { Free_string_array (&argv, &len, &buffer_len); Free_string (&line_buffer); return false; } /* Set the buffering to lines for the write pipe end. */ setlinebuf (pipe_write); linenr = 1; while (!close_received) { errno = 0; if (!Set_alarm_timer (EXECUTE_READ_WRITE_LINE_TIME_OUT)) { timer_failed = true; break; } error_executing = (!Read_line (pipe_read, &line_buffer, &line_buffer_len, &line_len, &eof_found, false, false)); if (!Set_alarm_timer (0.0)) { timer_failed = true; break; } if (error_executing) break; if ( ( (line_len == strlen (CLOSE_MY_MSG)) && (strncmp (line_buffer, CLOSE_MY_MSG, line_len) == 0))) { /* Child indicates termination. */ close_received = true; } if (!close_received) { if (linenr == 1) { /* HELLO message expected from child. */ if ( (line_len != strlen (HELLO_MY_MSG)) || (strncmp (line_buffer, HELLO_MY_MSG, line_len) != 0)) { /* Invalid HELLO message. */ error_executing = true; break; } } else { /* PAYLOAD message expected from child, requesting a payload line. */ if ( (line_len == strlen (PAYLOAD_MY_MSG)) && (strncmp (line_buffer, PAYLOAD_MY_MSG, line_len) == 0) && ( (size_t) (linenr - 2) < payload_len)) { if (!Set_alarm_timer (EXECUTE_READ_WRITE_LINE_TIME_OUT)) { timer_failed = true; break; } if (!Write_line (pipe_write, payload[linenr - 2])) { error_executing = true; break; } if (!Set_alarm_timer (0.0)) { timer_failed = true; break; } } else if (!message_line) { /* Child process sended an extra info line. */ message_line = true; } else { /* Invalid message or no more payload lines. */ error_executing = true; break; } } } Vlogit (tll_debug, LOG_COMMAND_OUTPUT, LOGLEVELNAME (tll_debug), PROCESS_P_C (g_daemonized, g_processor), getpid(), linenr, line_buffer); ++linenr; if (!Set_alarm_timer (EXECUTE_READ_WRITE_LINE_TIME_OUT)) { timer_failed = true; break; } } if (!Set_alarm_timer (0.0)) timer_failed = true; Free_string (&line_buffer); if (error_executing || timer_failed) { /* The child process was executed but we failed to set a timer or to read from or to write to the process. */ error_executing = true; /* Ask the child process to terminate. */ kill (childpid, SIGTERM); } timer_failed = (!Set_alarm_timer (EXECUTE_WAIT_TIME_OUT)); res = ( (!timer_failed) && pclose_ext (&pipe_read, &pipe_write, NULL, childpid, true, &cmdres)); Set_alarm_timer (0.0); if (!res) { kill (childpid, SIGKILL); usleep (100000); waitpid (childpid, NULL, WNOHANG); if (pipe_read != NULL) fclose (pipe_read); if (pipe_write != NULL) fclose (pipe_write); } Free_string_array (&argv, &len, &buffer_len); return (!error_executing && res && (cmdres == 0)); }
static int FUNC_FS_CPUUSAGE(struct cmd_data *data) { struct fs_cpuusage *ctx = &g_cpuusage_ctx; int ret; if (!ctx->status) { char *cmd[256]; //fp = popen("top -n 1", "re"); cmd[0] = "top"; cmd[1] = "-d"; cmd[2] = "2"; cmd[3] = NULL; ctx->stdout = FD_INVALID; ctx->fd = popen_ext(cmd, NULL, &ctx->stdout); if (ctx->fd == -1) { ERROR("popen top failed"); return -1; } ctx->fpout = fdopen(ctx->stdout, "r"); if (ctx->fpout == NULL) { ERROR("fdopen top failed"); pclose_ext(ctx->fd, 1); ctx->fd = -1; return -1; } ctx->ev.data = ctx; ctx->ev.fd = ctx->stdout; ctx->ev.events = EPOLLIN; ctx->ev.func = fs_cpuusage_callback_func; ret = reactor_event_register(ctx->stdout, &ctx->ev); if (ret) { ERROR("reactor_event_register failed"); close(ctx->fd); ctx->fd = -1; return -1; } ctx->status = 1; } //printf("CPU: %d%% usr %d%% sys %d%% nic %d%% idle\n", // usr, sys, nice, idle); data->out_fields[0] = FIELD_FS_cpuusr; data->out_param[0] = (void*) ctx->usr; data->out_fields[1] = FIELD_FS_cpusys; data->out_param[1] = (void*) ctx->sys; data->out_fields[2] = FIELD_FS_cpunice; data->out_param[2] = (void*) ctx->nice; data->out_fields[3] = FIELD_FS_cpuidle; data->out_param[3] = (void*) ctx->idle; data->out_fields[4] = FIELD_FS_cpuio; data->out_param[4] = (void*) ctx->io; data->out_fields[5] = FIELD_FS_cpuirq; data->out_param[5] = (void*) ctx->irq; data->out_fields[6] = FIELD_FS_cpusirq; data->out_param[6] = (void*) ctx->sirq; data->out_fields[7] = END_OF_FIELD; return 0; }
static int FUNC_FS_PROCESS_START(struct cmd_data *data) { struct fs_process_ctx *ctx; char *cmd[256], *pch; char tmpstr[1024]; int ret, i = 0; if (data->idx < 0 || data->idx > MAX_PROCESS_CNT) { ERROR("index out of range %d", data->idx); return -1; } ctx = &g_proc_context[data->idx]; if (ctx->status) { ERROR("process %d currently running", data->idx); return -1; } strcpy(tmpstr, data->command); /* break command string into tokens for popen/execv */ pch = strtok(tmpstr, " "); while (pch != NULL && i < 256) { cmd[i++] = pch; pch = strtok(NULL, " "); } cmd[i] = NULL; ctx->stdin = FD_INVALID; ctx->stdout = FD_INVALID; if (data->in && strlen(data->in)) { ctx->stdin = open(data->in, O_RDWR); if (ctx->stdin == FD_INVALID) { ret = errno; ERROR("error opening in file %s %s", data->in, strerror(ret)); goto exit_free; } } if (data->out && strlen(data->out)) { ctx->stdout = open(data->out, O_RDWR); if (ctx->stdout == FD_INVALID) { ret = errno; ERROR("error opening out file %s %s", data->out, strerror(ret)); goto exit_free; } } ctx->pid = popen_ext(cmd, &ctx->stdin, &ctx->stdout); if (ctx->pid == -1) { ERROR("popen %s failed", data->command); return -1; } ctx->status = 1; return 0; exit_free: pclose_ext(ctx->pid, 1); if (ctx->stdout != FD_INVALID) close(ctx->stdout); if (ctx->stdin != FD_INVALID) close(ctx->stdin); ctx->pid = -1; return ret; }