int main(int argc, char* argv[]) { if (argc < 2) { printf("Please input file\n"); return STAT_OK; } int i = 0; for (i = 1; i < argc; i++) { check_stat(argv[i]); } return STAT_OK; }
void execute_from_asked_dir(char *cmd, char **env, char *cmd_args) { if (check_stat(cmd, 1)) launch_process_from_asked_dir(cmd, cmd_args, env); }
int handle_process(metric_type_t metric, task_option_t *options, char *id) { int keepalive = 0; uint16_t pid; char *pidfile, *runcmd; task_report_t report; init_task_report(&report, id, PROCESS, metric); // Pull out options. // FIXME: Need to go over this again to make sure all necessary validation of parameters // is performed. for (int i = 0; i < NOTGIOS_MAX_OPTIONS; i++) { task_option_t *option = &options[i]; switch (option->type) { case KEEPALIVE: keepalive = strcmp(option->value, "TRUE") ? 0 : 1; break; case PIDFILE: pidfile = option->value; break; case RUNCMD: runcmd = option->value; break; case EMPTY: // User chose not to specify an option. This is fine, move on. break; default: // We've been passed a task containing invalid options. Shouldn't happen, but handle // it for debugging. sprintf(report.message, "FATAL CAUSE INVALID_TASK"); lpush(&reports, &report); return NOTGIOS_GENERIC_ERROR; } } write_log(LOG_DEBUG, "Task %s: Finished parsing arguments for process task...\n", id); // Figure out process running/not running situation. if (keepalive) { FILE *file = fopen(pidfile, "w+"); if (!file) { // We cannot write to the given pidfile path. Most likely the directory just // doesn't exist, but I'm defining this as an unrecoverable error, so send a message // to the frontend and remove the task. write_log(LOG_ERR, "Task %s: Pidfile inaccessible for keepalive process...\n", id); sprintf(report.message, "FATAL CAUSE NO_PIDFILE"); lpush(&reports, &report); return NOTGIOS_TASK_FATAL; } write_log(LOG_DEBUG, "Task %s: Successfully opened pidfile for keepalive process...\n", id); uint16_t *tmp_pid = hash_get(&children, id); if (tmp_pid) { write_log(LOG_DEBUG, "Task %s: Keepalive Process is already running...\n", id); pid = *tmp_pid; fprintf(file, "%hu", pid); } else { pid = fork(); if (pid) { write_log(LOG_DEBUG, "Task %s: Forked...\n", id); uint16_t *pid_cpy = malloc(sizeof(uint16_t)); *pid_cpy = pid; // Put the new pid into the children hash, update the pidfile, and just make // sure we aren't doing all of this for nothing. int retval = hash_put(&children, id, pid_cpy); fprintf(file, "%hu", pid); if (retval == HASH_FROZEN) return NOTGIOS_IN_SHUTDOWN; } else { int elem = 0; char *args[NOTGIOS_MAX_ARGS]; memset(args, 0, sizeof(char *) * NOTGIOS_MAX_ARGS); // Just sleep for a tiny bit to make sure our pid got into the children table. // No validation has been done on the run command, so, odds are, it won't work // and exec will fail. If so, need to make sure our pid is in the children table // so that the SIGCHLD handler will know what to do with our exit status. sleep(0.1); // Get our base command and arguments. char *path = strtok(runcmd, "\t"), *arg; while ((arg = strtok(NULL, "\t")) && elem < NOTGIOS_MAX_ARGS) args[elem++] = arg; // Moment of truth! execv(path, args); exit(NOTGIOS_EXEC_FAILED); } } fclose(file); } else { uint16_t other_pid; FILE *file = fopen(pidfile, "r"); if (file) { // We can access the file. int retval = fscanf(file, "%hu", &other_pid); fclose(file); write_log(LOG_DEBUG, "Task %s: Got pid for watched process...\n", id); if (retval && retval != EOF) { // We read the pid successfully. retval = kill(other_pid, 0); if (!retval) { // The process is running! write_log(LOG_DEBUG, "Task %s: Watched process is still running...\n", id); pid = other_pid; } else { // The process is not currently running, enqueue a report saying this, then return. write_log(LOG_ERR, "Task %s: Kill revealed watched process is not running...\n", id); sprintf(report.message, "ERROR CAUSE PROC_NOT_RUNNING"); lpush(&reports, &report); return NOTGIOS_SUCCESS; } } else { // The process is not currently running, enqueue a report saying this, then return. write_log(LOG_ERR, "Task %s: Pidfile not formatted correctly for watched process...\n", id); sprintf(report.message, "ERROR CAUSE PROC_NOT_RUNNING"); lpush(&reports, &report); return NOTGIOS_SUCCESS; } } else { // We can't access the file. I'm defining this as an unrecoverable error, so // send a message to the frontend, and then remove the task. write_log(LOG_ERR, "Task %s: Pidfile not accessible for watched process...\n", id); sprintf(report.message, "FATAL CAUSE NO_PIDFILE"); lpush(&reports, &report); return NOTGIOS_TASK_FATAL; } } // Collect metrics. int retval; switch (metric) { case MEMORY: retval = process_memory_collect(pid, &report); if (retval == NOTGIOS_NOPROC && keepalive) { if (check_statm()) { // FIXME: This was written before the child handler was figured out. Could need to revisit this // after implementing the child handler. // Since we're keeping alive, this most likely means that the user gave us an invalid command. // Send an error message, and the frontend will eventually kill the task if necessary. write_log(LOG_ERR, "Task %s: Watched/Keepalive process is not running for collection...\n", id); sprintf(report.message, "ERROR CAUSE PROC_NOT_RUNNING"); } else { // We can't even read from /proc/self/statm, which should be guaranteed to work on any version of // linux that supports statm at all. Let the front end know that we're running on an unsupported // distro. RETURN_UNSUPPORTED_DISTRO(report, id); } } else { write_log(LOG_DEBUG, "Task %s: Memory info collected...\n", id); } break; case CPU: retval = process_cpu_collect(pid, &report); if (retval == NOTGIOS_NOPROC) { if (check_stat()) { write_log(LOG_ERR, "Task %s: Watched/Keepalive process is not running for collection...\n", id); sprintf(report.message, "ERROR CAUSE PROC_NOT_RUNNING"); } else { // We can't even read from /proc/self/stat, which means it either doesn't exist, or we don't // support the format it's using. Either way, we're done. RETURN_UNSUPPORTED_DISTRO(report, id); } } else if (retval == NOTGIOS_UNSUPP_DISTRO) { // Collection function encountered an error condition that suggests we're running on an // unsupported distro. RETURN_UNSUPPORTED_DISTRO(report, id); } else { write_log(LOG_DEBUG, "Task %s: CPU Time collected...\n", id); } break; case IO: // This is currently unimplemented. retval = process_io_collect(pid, &report); break; default: // We've been passed a task containing invalid options. Shouldn't happen, but handle it // for debugging. sprintf(report.message, "FATAL CAUSE INVALID_TASK"); lpush(&reports, &report); return NOTGIOS_GENERIC_ERROR; } if (retval == NOTGIOS_UNSUPP_TASK) { write_log(LOG_DEBUG, "Task %s: Received an unsupported task. Removing..."); sprintf(report.message, "FATAL CAUSE UNSUPPORTED_TASK"); lpush(&reports, &report); return NOTGIOS_TASK_FATAL; } // Enqueue metrics for sending. write_log(LOG_DEBUG, "Task %s: Enqueuing report and returning...\n", id); lpush(&reports, &report); return NOTGIOS_SUCCESS; }