Exemplo n.º 1
0
static void sig_pidwait(void *pid, void *statusp)
{
	PROCESS_REC *rec;
        char *str;
	int status = GPOINTER_TO_INT(statusp);

        rec = process_find_pid(GPOINTER_TO_INT(pid));
	if (rec == NULL) return;

	/* process exited - print the last line if
	   there wasn't a newline at end. */
	if (line_split("\n", 1, &str, &rec->databuf) > 0 && *str != '\0')
		signal_emit_id(signal_exec_input, 2, rec, str);

	if (!rec->silent) {
		if (WIFSIGNALED(status)) {
			status = WTERMSIG(status);
			printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
				  "process %d (%s) terminated with signal %d (%s)",
				  rec->id, rec->args,
				  status, g_strsignal(status));
		} else {
                        status = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
			printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
				  "process %d (%s) terminated with return code %d",
				  rec->id, rec->args, status);
		}
	}
	process_destroy(rec, status);
}
Exemplo n.º 2
0
/*
 * Common code for cmd_prog and cmd_shell.
 *
 * Note that this does not wait for the subprogram to finish, but
 * returns immediately to the menu. This is usually not what you want,
 * so you should have it call your system-calls-assignment waitpid
 * code after forking.
 *
 * Also note that because the subprogram's thread uses the "args"
 * array and strings, until you do this a race condition exists
 * between that code and the menu input code.
 */
static
int
common_prog(int nargs, char **args)
{
	int err;
	int exit_code;
    struct process *proc;
    
	err = runprogram(nargs, args, &proc);
	if (err) {
		kprintf("runprogram failed: %s\n", strerror(err));
		return err;
	}
	
	exit_code = process_waiton(proc);
    if (WIFEXITED(exit_code))
        kprintf("%s exited with code %d\n", args[0], WEXITSTATUS(exit_code));
    else if (WIFSIGNALED(exit_code))
        kprintf("%s received a fatal signal: %d\n", args[0], WTERMSIG(exit_code));
    else if (WIFSTOPPED(exit_code))
        kprintf("%s stopped on signal %d\n", args[0], WSTOPSIG(exit_code));
    
    process_destroy(proc->ps_pid);

	return 0;
}
Exemplo n.º 3
0
static void sig_pidwait(void *pid, void *statusp)
{
	PROCESS_REC *rec;
	int status = GPOINTER_TO_INT(statusp);

        rec = process_find_pid(GPOINTER_TO_INT(pid));
	if (rec == NULL) return;

	/* process exited */
	if (!rec->silent) {
		if (WIFSIGNALED(status)) {
			status = WTERMSIG(status);
			printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
				  "process %d (%s) terminated with signal %d (%s)",
				  rec->id, rec->args,
				  status, g_strsignal(status));
		} else {
                        status = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
			printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
				  "process %d (%s) terminated with return code %d",
				  rec->id, rec->args, status);
		}
	}
	process_destroy(rec, status);
}
Exemplo n.º 4
0
int
process_run(char **argv,
            const int keep_fds[], size_t n_keep_fds,
            const int null_fds[], size_t n_null_fds,
            int *status)
{
    struct process *p;
    int retval;

    COVERAGE_INC(process_run);
    retval = process_start(argv, keep_fds, n_keep_fds, null_fds, n_null_fds,
                           &p);
    if (retval) {
        *status = 0;
        return retval;
    }

    while (!process_exited(p)) {
        process_wait(p);
        poll_block();
    }
    *status = process_status(p);
    process_destroy(p);
    return 0;
}
Exemplo n.º 5
0
void collect_children()
{
	for(int i=PID_MIN;i<=PID_MAX;i++)
	{
		if(parentprocesslist[i] == INIT_PROCESS && freepidlist[i] == P_ZOMBIE)
		{
			process_destroy(i);
		}
	}	
}
Exemplo n.º 6
0
void
remove_process(Process *proc)
{
	debug(DEBUG_FUNCTION, "remove_proc(pid=%d)", proc->pid);

	if (proc->leader == proc)
		each_task(proc, NULL, &clear_leader, NULL);

	unlist_process(proc);
	process_removed(proc);
	process_destroy(proc);
	free(proc);
}
Exemplo n.º 7
0
Arquivo: proc.c Projeto: clarkok/CoS
int
proc_do_collect(size_t pid, int *retval)
{
    Process *proc = proc_get_by_id(pid);

    if (!proc) { return 0; }
    if (proc->parent != current_process) { return 0; }

    *retval = process_destroy(proc);

    assert(list_size(&proc_normal_queue) || list_size(&proc_normal_noticks_queue));
    return 1;
}
Exemplo n.º 8
0
bool
process_check_destroy(pid_t pid)
{
    struct process *p = process_get(pid);
    // check whether the process has exited
    if (process_checkon(p) == -1)
        return false;
    
    process_destroy(p->ps_pid);
    // returning true removes pid from the pid_set
    // during pid_set_map()
    return true;
}
Exemplo n.º 9
0
void zmq::own_t::check_term_acks ()
{
    if (_terminating && _processed_seqnum == _sent_seqnum.get ()
        && _term_acks == 0) {
        //  Sanity check. There should be no active children at this point.
        zmq_assert (_owned.empty ());

        //  The root object has nobody to confirm the termination to.
        //  Other nodes will confirm the termination to the owner.
        if (_owner)
            send_term_ack (_owner);

        //  Deallocate the resources.
        process_destroy ();
    }
}
Exemplo n.º 10
0
void fe_exec_deinit(void)
{
	if (processes != NULL) {
		processes_killall(SIGTERM);
		sleep(1);
		processes_killall(SIGKILL);

		while (processes != NULL)
			process_destroy(processes->data, -1);
	}

	command_unbind("exec", (SIGNAL_FUNC) cmd_exec);

        signal_remove("pidwait", (SIGNAL_FUNC) sig_pidwait);
        signal_remove("exec input", (SIGNAL_FUNC) sig_exec_input);
        signal_remove("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
	signal_remove("send text", (SIGNAL_FUNC) event_text);
}
Exemplo n.º 11
0
/* Called by waitpid() */
int
process_wait(pid_t pidToWait, pid_t pidToWaitFor)
{
	(void)pidToWait;
	int exitCode;
	processtable_biglock_acquire();
	struct process *notifier = get_process(pidToWaitFor);
	if(freepidlist[pidToWaitFor] == P_ZOMBIE)
	{
		//The process we're waiting for already exited.
		//Return to sys_waitpid to collect the exit code.
		exitCode = exitcodelist[pidToWaitFor];
		processtable_biglock_release();
	}
	else
	{
		processtable_biglock_release();
		P(notifier->p_waitsem);
		exitCode = exitcodelist[pidToWaitFor];
	}
	process_destroy(notifier->p_id);
	return exitCode;
}
Exemplo n.º 12
0
void gram_SYSTEM()
{
    char *cmd;

    parser_push_fun("SYSTEM");

    cmd = parser_parlist(&parser, COLLECT_SET);

    if (message_show(MSG_NOTICE))
        message("SYSTEM %s", string_short(cmd));

    if (!check_live_data(cmd))
        free(cmd);
    else
    {
        Process process;
        process_construct(&process, "SYSTEM", cmd, NULL);

        process_system(&process);
        process_destroy(&process);
    }

    parser_pop_fun();
}
Exemplo n.º 13
0
int main(int argc, char *argv[]) {
	static struct option long_options[] = {
		{"listen", required_argument, 0, 'l'},
		{"port", required_argument, 0, 'p'},
		{"help", no_argument, 0, 'h'},
		{"verbose", no_argument, 0, 'v'},
		{"ping-parent", no_argument, 0, 'x'},
		{"gcc-command", required_argument, 0, 'g'},
		{"vx32sdk", required_argument, 0, 's'},
		{"tmpdir", required_argument, 0, 't'},
		{"engine", required_argument, 0, 'e'},
		{"no-vx32", no_argument, 0, 'n'},
		{0, 0, 0, 0}
	};
	
	struct server *server = (struct server*)st_calloc(1, sizeof(struct server));
	server->info_handler = &info_handler;
	server->quit_handler = &quit_handler;
	server->process_multi= &process_multi;
	INIT_LIST_HEAD(&server->root);
	
	server->host = "127.0.0.1";
	server->port = 22122;
	
	struct config *config = (struct config*)st_calloc(1, sizeof(struct config));
	server->userdata = config;
	config->tmpdir = "/tmp";
	config->vx32sdk_path = "./untrusted/";
	config->vx32sdk_gcc_command = strdup(flatten_argv(NELEM(default_vx32sdk_gcc_command), default_vx32sdk_gcc_command, " "));
	config->syscall_limit = 4; /* 4 syscalls per request allowed */
	
	int option_index;
	int arg;
	char *engine_name = NULL;
	while((arg = getopt_long_only(argc, argv, "hxvnl:p:g:s:t:e:", long_options, &option_index)) != EOF) {
		switch(arg) {
		case 'h':
			print_help(server, config);
			exit(-1);
			break;
		case 'v':
			server->trace = 1;
			break;
		case 'x':
			server->ping_parent = 1;
			break;
		case 'l':
			server->host = optarg;
			break;
		case 'p':
			server->port = atoi(optarg);
			if(server->port < 0 || server->port > 65536)
				fatal("Port number broken: %i", server->port);
			break;
		case 'g':
			free(config->vx32sdk_gcc_command);
			config->vx32sdk_gcc_command = strdup(optarg);
			break;
		case 's':
			config->vx32sdk_path = optarg;
			break;
		case 't':
			config->tmpdir = optarg;
			break;
		case 'e':
			engine_name = optarg;
			break;
		case 'n':
			config->vx32_disabled = 1;
			break;
		case 0:
		default:
			fatal("\nUnknown option: \"%s\"\n", argv[optind-1]);
		}
	}
	
	int i;
	storage_engine_create *engine_create = NULL;
	storage_engine_destroy *engine_destroy = NULL;
	for(i=0; i<NELEM(engines); i++) {
		if(engine_name && 0 == strcmp(engine_name, engines[i].name)) {
			engine_create = engines[i].create;
			engine_destroy = engines[i].destroy;
		}
	}
	if(NULL == engine_create)
		fatal("\nYou must specify a storage engine:"
		" --engine=[%s]\n", flatten_engine_names() );

	log_info("Process pid %i", getpid());
	signal(SIGPIPE, SIG_IGN);
	
	commands_initialize();
	process_initialize(config);
	char *params = flatten_argv(argc-optind, &argv[optind], ", ");
	log_info("Loading database engine \"%s\" with parameters \"%s\"", engine_name, params);
	
	config->api = engine_create(argc-optind, &argv[optind]);
	
	do_event_loop(server);
	
	log_info("Quit");
	process_destroy();
	commands_destroy();
	pool_free();
	
	engine_destroy(config->api);
	free(config->vx32sdk_gcc_command);
	free(config);
	free(server);
	
	exit(0);
	return(0);
}
Exemplo n.º 14
0
int main(int argc, char **argv)
{
    String *cmd = string_new(0);
    String *input = NULL;

    if (argc == 1)
    {
        fprintf(stderr,
            "Usage: %s [-s] prog [arg(s)]\n"
            "      -s: use system call, not std-input\n"
            "    prog: program or system call to execute\n"
            "  arg(s): optional arguments to prog\n"
            "Input to prog is read from stdin, unless -s was specified\n"
            "   (don't make this too long, it's stored in a String first)\n"
            "\n",
            argv[0]);

        exit(1);
    }

    bool syscall = !strcmp(argv[1], "-s");
    if (syscall)
    {
        argc--;
        argv++;
    }
    else
    {
        input = string_new(0);
        char buffer[100];

        fprintf(stderr, "Reading input from stdin...\n");

        while (fgets(buffer, 100, stdin))
            string_addstr(input, buffer);

        fprintf(stderr, "Input will be:\n"
                        "`%s'\n", string_str(input));
    }

    while (*++argv)
    {
        string_addstr(cmd, *argv);
        string_addchar(cmd, ' ');
    }


    fprintf(stderr, "Command will be:\n"
                        "`%s'\n", string_str(cmd));

    message_setseverity(MSG_ALL);
    message(MSG_NOTICE, "Creating Process");

    Process process;
    process_construct(&process, "process-demo", cmd,
                                                input);

    if (syscall)
        process_system(&process);
    else
        process_fork(&process);

    String const *out = process_output(&process);

    fprintf(stderr, "Output from process: '\n"
            "%s\n"
            "'\n", string_str(out));

    process_destroy(&process);

    return 0;
}
Exemplo n.º 15
0
/*
 * Load program and start running it in usermode
 * in a new thread.
 * This is essentially an amalgam of fork() and execv().
 */
int
runprogram(int nargs, char **args, struct process **created_proc)
{
    if (nargs > ARGNUM_MAX)
        return E2BIG;
    
	struct vnode *v;
	int result;
    struct process *proc;
    
    // copy the string, since vfs_open() will modify it
    char *progname = kstrdup(args[0]);
    if (progname == NULL)
        return ENOMEM;

	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}
    
    // We no longer need the duplicate program name
    kfree(progname);

    // set up new process structure
    proc = process_create(args[0]);
    if (proc == NULL)
    {
        vfs_close(v);
        return ENOMEM;
    }
    
    // Get a PID for the process.  ENPROC is
    // the error code for "no more processes allowed
    // in the system."
    pid_t pid = process_identify(proc);
    if (pid == 0)
    {
        process_cleanup(proc);
        vfs_close(v);
        return ENPROC;
    }
    
    // Create a new file descriptor table
    proc->ps_fdt = fdt_create();
    if (proc->ps_fdt == NULL)
    {
        process_destroy(pid);
        vfs_close(v);
        return ENOMEM;
    }
    
    // Open FDs for stdin, stdout, and stderr
    result = setup_inouterr(proc->ps_fdt);
    if (result)
    {
        process_destroy(pid);
        vfs_close(v);
        return result;
    }
    
	// Create a new address space
	proc->ps_addrspace = as_create();
	if (proc->ps_addrspace==NULL) {
        process_destroy(pid);
		vfs_close(v);
		return ENOMEM;
	}
    
    struct new_process_context *ctxt = kmalloc(sizeof(struct new_process_context));
    if (ctxt == NULL)
    {
        as_activate(NULL);
        process_destroy(pid);
        return ENOMEM;
    }
    ctxt->nargs = nargs;
    ctxt->args = args;
    ctxt->proc = proc;
    ctxt->executable = v;

	// Start a new thread to warp to user mode
    result = thread_fork("user process",
                         run_process,
                         ctxt, 0, NULL);
    if (result)
    {
        kfree(ctxt);
        as_activate(NULL);
        process_destroy(pid);
        return result;
    }
    
    // pass process to caller and return
    *created_proc = proc;
	return 0;
}
Exemplo n.º 16
0
int main(int argc, char ** argv)
{
    options_t options;
    int master_fd, slave_fd;
    pid_t relay_pid, timer_pid, solution_pid, pid;
    int status;

    if (!options_get(argc, argv, &options))
        return EXITCODE_USAGE_ERROR;

    options_display(stderr, &options);

    /* Open a pseudo terminal. Start the child in a new process; it uses the
     * pseudo terminal for its stdin, stdout, and stderr. Start a process whose
     * job it is to relay data bidirectionally between our stdin/out and the
     * child's. Start a timer to enforce the user time limit.
     */
    if (
        !pty_open_raw(&master_fd, &slave_fd)                       ||
        !start_child(&solution_pid, master_fd, slave_fd, &options) ||
        !start_relay(&relay_pid, master_fd, slave_fd)              ||
        !start_timer(&timer_pid, master_fd, slave_fd, options.resource_limits.max_user_time_in_seconds)
    )
        return EXITCODE_INTERNAL_ERROR;

    close(master_fd);
    close(slave_fd);

    /* Wait for a child to end, but wait again if the first we see happens to
     * be the relay (seeing the relay end is inconclusive). The real race is
     * between the timer and child processes.
     */
    do {
        pid = wait(&status);
        if (pid == -1)
            return EXITCODE_INTERNAL_ERROR;
    } while (pid == relay_pid);

    if (pid == timer_pid) {
        /* The timer ended first, which means the child took too much user
         * time.
         */
        process_destroy(solution_pid);
        process_destroy(relay_pid);
        return EXITCODE_USER_TIME_LIMIT_EXCEEDED;
    }

    if (pid == solution_pid) {
        process_destroy(timer_pid);
        process_destroy(relay_pid);

        /* The child ended first. If it exited normally, communicate that to
         * the caller.
         */
        if (WIFEXITED(status))
            return EXITCODE_PROGRAM_EXITED;

        /* It didn't exit normally. Maybe it got killed by the kernel with
         * SIGKILL for taking too much CPU time, or killed by some other signal
         * we didn't expect.
         */
        if (WIFSIGNALED(status))
            return WTERMSIG(status) == SIGKILL
                ? EXITCODE_CPU_TIME_LIMIT_EXCEEDED
                : exitcode_for_fatal_signal(WTERMSIG(status));
    }

    /* Something strange happened.
     */
    return EXITCODE_INTERNAL_ERROR;
}
Exemplo n.º 17
0
/* Starts the process whose arguments are given in the null-terminated array
 * 'argv' and waits for it to exit.  On success returns 0 and stores the
 * process exit value (suitable for passing to process_status_msg()) in
 * '*status'.  On failure, returns a positive errno value and stores 0 in
 * '*status'.
 *
 * If 'stdout_log' is nonnull, then the subprocess's output to stdout (up to a
 * limit of PROCESS_MAX_CAPTURE bytes) is captured in a memory buffer, which
 * when this function returns 0 is stored as a null-terminated string in
 * '*stdout_log'.  The caller is responsible for freeing '*stdout_log' (by
 * passing it to free()).  When this function returns an error, '*stdout_log'
 * is set to NULL.
 *
 * If 'stderr_log' is nonnull, then it is treated like 'stdout_log' except
 * that it captures the subprocess's output to stderr. */
int
process_run_capture(char **argv, char **stdout_log, char **stderr_log,
                    int *status)
{
    struct stream s_stdout, s_stderr;
    sigset_t oldsigs;
    pid_t pid;
    int error;

    COVERAGE_INC(process_run_capture);
    if (stdout_log) {
        *stdout_log = NULL;
    }
    if (stderr_log) {
        *stderr_log = NULL;
    }
    *status = 0;
    error = process_prestart(argv);
    if (error) {
        return error;
    }

    error = stream_open(&s_stdout);
    if (error) {
        return error;
    }

    error = stream_open(&s_stderr);
    if (error) {
        stream_close(&s_stdout);
        return error;
    }

    block_sigchld(&oldsigs);
    pid = fork();
    if (pid < 0) {
        int error = errno;

        unblock_sigchld(&oldsigs);
        VLOG_WARN("fork failed: %s", strerror(error));

        stream_close(&s_stdout);
        stream_close(&s_stderr);
        *status = 0;
        return error;
    } else if (pid) {
        /* Running in parent process. */
        struct process *p;

        p = process_register(argv[0], pid);
        unblock_sigchld(&oldsigs);

        close(s_stdout.fds[1]);
        close(s_stderr.fds[1]);
        while (!process_exited(p)) {
            stream_read(&s_stdout);
            stream_read(&s_stderr);

            stream_wait(&s_stdout);
            stream_wait(&s_stderr);
            process_wait(p);
            poll_block();
        }
        stream_read(&s_stdout);
        stream_read(&s_stderr);

        if (stdout_log) {
            *stdout_log = ds_steal_cstr(&s_stdout.log);
        }
        if (stderr_log) {
            *stderr_log = ds_steal_cstr(&s_stderr.log);
        }

        stream_close(&s_stdout);
        stream_close(&s_stderr);

        *status = process_status(p);
        process_destroy(p);
        return 0;
    } else {
        /* Running in child process. */
        int max_fds;
        int i;

        fatal_signal_fork();
        unblock_sigchld(&oldsigs);

        dup2(get_null_fd(), 0);
        dup2(s_stdout.fds[1], 1);
        dup2(s_stderr.fds[1], 2);

        max_fds = get_max_fds();
        for (i = 3; i < max_fds; i++) {
            close(i);
        }

        execvp(argv[0], argv);
        fprintf(stderr, "execvp(\"%s\") failed: %s\n",
                argv[0], strerror(errno));
        exit(EXIT_FAILURE);
    }
}
Exemplo n.º 18
0
pid_t
sys_fork(const struct trapframe *parent_tf, int *err)
{
    struct process *parent = curthread->t_proc;
    
    // set up new process structure
    struct process *child = process_create(parent->ps_name);
    if (child == NULL)
    {
        *err = ENOMEM;
        return -1;
    }
    
    // Get a PID for the child.  ENPROC is
    // the error code for "no more processes allowed
    // in the system."
    pid_t child_pid = process_identify(child);
    if (child_pid == 0)
    {
        *err = ENPROC;
        process_cleanup(child);
        return -1;
    }
    
    // copy the file descriptor table of the parent
    child->ps_fdt = fdt_copy(parent->ps_fdt);
    if (child->ps_fdt == NULL)
    {
        *err = ENOMEM;
        process_destroy(child_pid);
        return -1;
    }
    
    // copy the address space of the parent
    *err = as_copy(parent->ps_addrspace,
                   &child->ps_addrspace);
    if (*err)
    {
        process_destroy(child_pid);
        return -1;
    }
    
    // add PID to children now.  That way, if we fail to
    // allocate memory, we have not yet forked a thread
    *err = pid_set_add(parent->ps_children, child_pid);
    if (*err)
    {
        process_destroy(child_pid);
        return -1;
    }
    
    // allocate space for child trapframe in the kernel heap
    struct trapframe *child_tf = kmalloc(sizeof(struct trapframe));
    if (child_tf == NULL)
    {
        process_destroy(child_pid);
        pid_set_remove(parent->ps_children, child_pid);
        *err = ENOMEM;
        return -1;
    }
    
    // copy trapframe
    memcpy(child_tf, parent_tf, sizeof(struct trapframe));
    
    // abuse child_tf->TF_RET (which will be set to 0)
    // to pass the process struct to the child thread
    // this cast and assignment will always work,
    // as pointers always fit in machine registers
    child_tf->TF_RET = (uintptr_t)child;
    
    // child thread sets up child return value
    // and ps_thread/t_proc
    *err = thread_fork("user process",
                       enter_forked_process,
                       child_tf, 0,
                       NULL);
    if (*err)
    {
        process_destroy(child_pid);
        kfree(child_tf);
        pid_set_remove(parent->ps_children, child_pid);
        return -1;
    }
    
    return child_pid;
}
Exemplo n.º 19
0
static void handle_exec(const char *args, GHashTable *optlist,
			WI_ITEM_REC *item)
{
	PROCESS_REC *rec;
        char *target, *level;
	int notice, signum, interactive, target_nick, target_channel;

	/* check that there's no unknown options. we allowed them
	   because signals can be used as options, but there should be
	   only one unknown option: the signal name/number. */
	signum = cmd_options_get_signal("exec", optlist);
	if (signum == -2)
                return;

	if (*args == '\0') {
		exec_show_list();
                return;
	}

	target = NULL;
	notice = FALSE;

	if (g_hash_table_lookup(optlist, "in") != NULL) {
		rec = process_find(g_hash_table_lookup(optlist, "in"), TRUE);
		if (rec != NULL) {
			net_sendbuffer_send(rec->out, args, strlen(args));
			net_sendbuffer_send(rec->out, "\n", 1);
		}
		return;
	}

	/* check if args is a process ID or name. if it's ID but not found,
	   complain about it and fail immediately */
	rec = process_find(args, *args == '%');
	if (*args == '%' && rec == NULL)
		return;

        /* common options */
        target_channel = target_nick = FALSE;
	if (g_hash_table_lookup(optlist, "out") != NULL) {
                /* redirect output to active channel/query */
		if (item == NULL)
			cmd_return_error(CMDERR_NOT_JOINED);
		target = (char *) window_item_get_target(item);
		target_channel = IS_CHANNEL(item);
		target_nick = IS_QUERY(item);
	} else if (g_hash_table_lookup(optlist, "msg") != NULL) {
                /* redirect output to /msg <nick> */
		target = g_hash_table_lookup(optlist, "msg");
	} else if (g_hash_table_lookup(optlist, "notice") != NULL) {
		target = g_hash_table_lookup(optlist, "notice");
                notice = TRUE;
	}

        /* options that require process ID/name as argument */
	if (rec == NULL &&
	    (signum != -1 || g_hash_table_lookup(optlist, "close") != NULL)) {
		printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
			  "Unknown process name: %s", args);
		return;
	}
	if (g_hash_table_lookup(optlist, "close") != NULL) {
		/* forcibly close the process */
                process_destroy(rec, -1);
                return;
	}

	if (signum != -1) {
		/* send a signal to process */
                kill(rec->pid, signum);
                return;
	}

        interactive = g_hash_table_lookup(optlist, "interactive") != NULL;
	if (*args == '%') {
		/* do something to already existing process */
		char *name;

		if (target != NULL) {
                        /* redirect output to target */
			g_free_and_null(rec->target);
			rec->target = g_strdup(target);
                        rec->notice = notice;
		}

                name = g_hash_table_lookup(optlist, "name");
		if (name != NULL) {
			/* change window name */
			g_free_not_null(rec->name);
			rec->name = *name == '\0' ? NULL : g_strdup(name);
		} else if (target == NULL &&
			   (rec->target_item == NULL || interactive)) {
			/* no parameters given,
			   redirect output to the active window */
			g_free_and_null(rec->target);
			rec->target_win = active_win;

			if (rec->target_item != NULL)
				exec_wi_destroy(rec->target_item);

			if (interactive) {
				rec->target_item =
					exec_wi_create(active_win, rec);
			}
		}
                return;
	}

        /* starting a new process */
	rec = g_new0(PROCESS_REC, 1);
	rec->pid = -1;
        rec->shell = g_hash_table_lookup(optlist, "nosh") == NULL;

	process_exec(rec, args);
	if (rec->pid == -1) {
                /* pipe() or fork() failed */
		g_free(rec);
		cmd_return_error(CMDERR_ERRNO);
	}

        rec->id = process_get_new_id();
	rec->target = g_strdup(target);
	rec->target_win = active_win;
	rec->target_channel = target_channel;
	rec->target_nick = target_nick;
        rec->args = g_strdup(args);
	rec->notice = notice;
        rec->silent = g_hash_table_lookup(optlist, "-") != NULL;
        rec->quiet = g_hash_table_lookup(optlist, "quiet") != NULL;
	rec->name = g_strdup(g_hash_table_lookup(optlist, "name"));

	level = g_hash_table_lookup(optlist, "level");
	rec->level = level == NULL ? MSGLEVEL_CLIENTCRAP : level2bits(level);

	rec->read_tag = g_input_add(rec->in, G_INPUT_READ,
				    (GInputFunction) sig_exec_input_reader,
				    rec);
	processes = g_slist_append(processes, rec);

	if (rec->target == NULL && interactive)
		rec->target_item = exec_wi_create(active_win, rec);

	signal_emit("exec new", 1, rec);
}
Exemplo n.º 20
0
int main (int argc, char *argv[])
{
  pid_t pid;
  int status = 1;
  struct tracer *tracer = NULL;
  struct process *process = NULL;


  if (argc < 2)
    return 1;

  pid = fork ();

  if (pid < 0)
  {
    perror ("fork");
    return 2;
  }

  if (pid == 0)
    fork_and_trace_child (argv);

  if (wait_for_stopped (pid, false, &status))
  {
    fprintf (stderr, "child process unexpectedly dead\n");
    return 3;
  }

  /*
     When  delivering syscall traps, set bit 7 in the signal number
     (i.e., deliver SIGTRAP | 0x80).  This makes it easy for the tracer
     to tell the difference between normal traps and those caused by a
     syscall.  (PTRACE_O_TRACESYSGOOD may not work on all architectures.)
   */
  if (ptrace (PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) == -1)
    return 5;

  status = 1;

  if (!(tracer = tracer_alloc ()))
  {
    fprintf (stderr, "Can not allocate tracer\n");
    goto end;
  }

  if (!(process = process_alloc (pid)))
  {
    fprintf (stderr, "Can not allocate process\n");
    goto end;
  }

  if (tracer_add_process (tracer, process) == -1)
  {
    fprintf (stderr, "Cannot add process to tracer\n");
    goto end;
  }

  /* process = NULL should be here (!) */

  for (;;)
  {
    struct user_regs_struct state1;
    struct user_regs_struct state2;
    if (wait_for_break (pid, &state1, &status))
      break;
    if (wait_for_break (pid, &state2, &status))
      break;
    trace_syscall (process, &state1, &state2);
  }

  process = NULL;

  status &= 0xff;

end:
  if (process)
    process_destroy (process);
  if (tracer)
    tracer_destroy (tracer);

  return status;
}