int main() { int * pipe_req = pipe_create(); int * pipe_ans = pipe_create(); pid_t fork_res = fork(); switch(fork_res) { case -1: printf("Stopped. Fork error.\n"); break; case 0: close(pipe_req[1]); close(pipe_ans[0]); run_server(pipe_req[0], pipe_ans[1]); close(pipe_req[0]); close(pipe_ans[1]); break; default: close(pipe_req[0]); close(pipe_ans[1]); run_client(pipe_req[1], pipe_ans[0]); close(pipe_req[1]); close(pipe_ans[0]); break; }; pipe_delete(pipe_req); pipe_delete(pipe_ans); return 0; }
/* ARGSUSED */ int sys_opipe(struct proc *p, void *v, register_t *retval) { struct filedesc *fdp = p->p_fd; struct file *rf, *wf; struct pipe *rpipe, *wpipe; int fd, error; fdplock(fdp); rpipe = pool_get(&pipe_pool, PR_WAITOK); error = pipe_create(rpipe); if (error != 0) goto free1; wpipe = pool_get(&pipe_pool, PR_WAITOK); error = pipe_create(wpipe); if (error != 0) goto free2; error = falloc(p, &rf, &fd); if (error != 0) goto free2; rf->f_flag = FREAD | FWRITE; rf->f_type = DTYPE_PIPE; rf->f_data = rpipe; rf->f_ops = &pipeops; retval[0] = fd; error = falloc(p, &wf, &fd); if (error != 0) goto free3; wf->f_flag = FREAD | FWRITE; wf->f_type = DTYPE_PIPE; wf->f_data = wpipe; wf->f_ops = &pipeops; retval[1] = fd; rpipe->pipe_peer = wpipe; wpipe->pipe_peer = rpipe; FILE_SET_MATURE(rf); FILE_SET_MATURE(wf); fdpunlock(fdp); return (0); free3: fdremove(fdp, retval[0]); closef(rf, p); rpipe = NULL; free2: (void)pipeclose(wpipe); free1: if (rpipe != NULL) (void)pipeclose(rpipe); fdpunlock(fdp); return (error); }
/* * The main program to "drive" the pipeline... */ int main (int argc, char *argv[]) { pipe_t my_pipe; long value, result; int status; char line[128]; pipe_create (&my_pipe, 10); printf ("Enter integer values, or \"=\" for next result\n"); while (1) { printf ("Data> "); if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (strlen (line) <= 1) continue; if (strlen (line) <= 2 && line[0] == '=') { if (pipe_result (&my_pipe, &result)) printf ("Result is %ld\n", result); else printf ("Pipe is empty\n"); } else { if (sscanf (line, "%ld", &value) < 1) fprintf (stderr, "Enter an integer value\n"); else pipe_start (&my_pipe, value); } } }
// start_routine for thread A void* threadA_routine (void *args) { // local variable char buf[BUFFER_SIZE]; int rc; ThreadData_t * this_data = (ThreadData_t *)args; for (;;) { // block until pipe write semaphore reached sem_wait(this_data->pipeWrite_sem); printf("......................................\n"); // read a line from data.txt // if eof reached, then thread A B C will stop rc = read_line(this_data->fp0, buf); if ((rc == 0) && (eof_reached == 1)) terminateAll(); // create a pipe pipe_create(this_data->pipefd); // write the line to pipe pipe_in(this_data->pipefd, buf); printf("thread A completed\n"); // post the pipe read signal sem_post(this_data->pipeRead_sem); } }
int sys_pipe2(int pipefd[2], int flags) { struct process *proc; int fdin, fdout; (void)flags; proc = process_get_current(); for(fdin=0; fdin<PROCESS_MAX_FILE && proc->files[fdin] != NULL; fdin++); for(fdout=fdin+1; fdout<PROCESS_MAX_FILE && proc->files[fdout] != NULL; fdout++); if(fdin < PROCESS_MAX_FILE && fdout < PROCESS_MAX_FILE) { struct file *files[2]; if(pipe_create(files) == 0) { proc->files[fdin] = files[0]; pipefd[0] = fdin; proc->files[fdout] = files[1]; pipefd[1] = fdout; return 0; } else { printk(LOG_ERR, "sys_pipe2: pipe creation failed\n"); } } else { printk(LOG_WARNING, "sys_pipe2: no more file desc\n"); } return -1; }
int main(int argc, char *argv[]) { pipe_t pipe; int value, result; char line[128]; pipe_create(&pipe, 2); printf("Enter inter value, or '=' for next result\n"); while (1) { printf("Data> "); E_TEST(NULL, fgets(line, sizeof(line), stdin)); if (strlen(line) <= 1) continue; if (strlen(line) <= 2 && line[0] == '=') { if (pipe_result(&pipe, &result)) printf("Result is %d\n", result); else printf("Pipe is empty\n"); } else { if (sscanf(line, "%d", &value) < 1) fprintf(stderr, "Enter an integer value\n"); else pipe_start(&pipe, value); } } return 0 ; }
/** * POSIX 1003.1b 6.1.1 Create an Inter-Process Channel */ int pipe( int filsdes[2] ) { if (filsdes == NULL) rtems_set_errno_and_return_minus_one( EFAULT ); return pipe_create(filsdes); }
static void worker_control_create (worker_t *worker) { if (pipe_create (&worker->wakeup_fd[0]) < 0) { ERROR0 ("pipe failed, descriptor limit?"); abort(); } sock_set_blocking (worker->wakeup_fd[0], 0); sock_set_blocking (worker->wakeup_fd[1], 0); }
int main() { pipe_t mypipe; long value, result; int status, len; char line[128]; stage_t *stage, *stage_next; pipe_create(&mypipe, 10); printf("Enter integer value, or \"=\" for result, enter quit to leave\n"); while(1) { printf("Data > "); if (fgets(line, sizeof line, stdin) == NULL || my_strcmp("quit", line)) break; len = strlen(line); if (len <= 1) continue; if (len <= 2 && line[0] == '=') { if (pipe_result(&mypipe, &result)) printf("result is %ld\n", result); else printf("pipe is empty\n"); } else { status = sscanf(line, "%ld", &value); if (status < 1) printf("please enter integer\n"); else pipe_start(&mypipe, value); } } for (stage = mypipe.head; stage != NULL;) { stage_next = stage->next; free(stage); printf("free stage\n"); stage = stage_next; } printf("end of pipe\n"); }
struct l2_packet_data * l2_packet_init( const char *ifname, const u8 *own_addr, unsigned short protocol, void (*rx_callback)(void *ctx, const u8 *src_addr, const u8 *buf, size_t len), void *rx_callback_ctx, int l2_hdr) { struct l2_packet_data *l2; l2 = os_zalloc(sizeof(struct l2_packet_data)); if (l2 == NULL) return NULL; os_strncpy(l2->ifname, ifname, sizeof(l2->ifname)); l2->rx_callback = rx_callback; l2->rx_callback_ctx = rx_callback_ctx; l2->l2_hdr = l2_hdr; /* * TODO: open connection for receiving frames */ #if 1 //xhchen l2->write_fd = socket(PF_INET,SOCK_STREAM,0); diag_printf("Open socket(PF_INET, SOCK_STREAM), fd=%d\n", l2->write_fd); l2->fd = pipe_create(NULL); diag_printf("Open pipe for l2 socket, fd=%d\n", l2->fd); if (l2->fd < 0) { perror("open pipe for l2 socket"); close(l2->write_fd); l2->write_fd = -1; l2->fd = -1; } g_l2_pipe = l2->fd; os_memcpy(l2->own_addr, own_addr, sizeof(l2->own_addr)); #else l2->fd = -1; #endif eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); return l2; }
void restart_child_process() { close(pipe_handles[1]); do_del_conn(pipe_handles[2], 2); shmq_destroy (); shmq_create(); pipe_create (); pid_t pid; if ((pid = fork ()) < 0) ERROR_LOG("fork child process, fail"); //parent process else if (pid > 0) { close (pipe_handles[3]); close (pipe_handles[0]); do_add_conn (pipe_handles[2], PIPE_TYPE_FD, NULL); //child process } else { close (pipe_handles[1]); close (pipe_handles[2]); net_init (MAXFDS, pipe_handles[0]); if (handle_init () != 0) goto out; while (!stop || !handle_fini ()) net_loop (1000, RCVBUFSZ, 0); out: shmq_destroy (); } }
int dopipe(struct proc *p, int *ufds, int flags) { struct filedesc *fdp = p->p_fd; struct file *rf, *wf; struct pipe *rpipe, *wpipe = NULL; int fds[2], error; rpipe = pool_get(&pipe_pool, PR_WAITOK); error = pipe_create(rpipe); if (error != 0) goto free1; wpipe = pool_get(&pipe_pool, PR_WAITOK); error = pipe_create(wpipe); if (error != 0) goto free1; fdplock(fdp); error = falloc(p, &rf, &fds[0]); if (error != 0) goto free2; rf->f_flag = FREAD | FWRITE | (flags & FNONBLOCK); rf->f_type = DTYPE_PIPE; rf->f_data = rpipe; rf->f_ops = &pipeops; error = falloc(p, &wf, &fds[1]); if (error != 0) goto free3; wf->f_flag = FREAD | FWRITE | (flags & FNONBLOCK); wf->f_type = DTYPE_PIPE; wf->f_data = wpipe; wf->f_ops = &pipeops; if (flags & O_CLOEXEC) { fdp->fd_ofileflags[fds[0]] |= UF_EXCLOSE; fdp->fd_ofileflags[fds[1]] |= UF_EXCLOSE; } rpipe->pipe_peer = wpipe; wpipe->pipe_peer = rpipe; FILE_SET_MATURE(rf, p); FILE_SET_MATURE(wf, p); error = copyout(fds, ufds, sizeof(fds)); if (error != 0) { fdrelease(p, fds[0]); fdrelease(p, fds[1]); } fdpunlock(fdp); return (error); free3: fdremove(fdp, fds[0]); closef(rf, p); rpipe = NULL; free2: fdpunlock(fdp); free1: pipeclose(wpipe); pipeclose(rpipe); return (error); }
// public API APIE process_spawn(ObjectID executable_id, ObjectID arguments_id, ObjectID environment_id, ObjectID working_directory_id, uint32_t uid, uint32_t gid, ObjectID stdin_id, ObjectID stdout_id, ObjectID stderr_id, Session *session, uint16_t object_create_flags, bool release_on_death, ProcessStateChangedFunction state_changed, void *opaque, ObjectID *id, Process **object) { int phase = 0; APIE error_code; String *executable; List *arguments; Array arguments_array; int i; char **item; List *environment; Array environment_array; String *working_directory; File *stdin; File *stdout; File *stderr; pid_t pid; int status_pipe[2]; int sc_open_max; FILE *log_file; Process *process; // acquire and lock executable string object error_code = string_get_acquired_and_locked(executable_id, &executable); if (error_code != API_E_SUCCESS) { goto cleanup; } phase = 1; if (*executable->buffer == '\0') { error_code = API_E_INVALID_PARAMETER; log_warn("Cannot spawn child process using empty executable name"); goto cleanup; } // lock arguments list object error_code = list_get_acquired_and_locked(arguments_id, OBJECT_TYPE_STRING, &arguments); if (error_code != API_E_SUCCESS) { goto cleanup; } phase = 2; // prepare arguments array for execvpe if (array_create(&arguments_array, 1 + arguments->items.count + 1, sizeof(char *), true) < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not create arguments array for spawning child process (executable: %s): %s (%d)", executable->buffer, get_errno_name(errno), errno); goto cleanup; } phase = 3; item = array_append(&arguments_array); if (item == NULL) { error_code = api_get_error_code_from_errno(); log_error("Could not append to arguments array for spawning child process (executable: %s): %s (%d)", executable->buffer, get_errno_name(errno), errno); goto cleanup; } *item = executable->buffer; for (i = 0; i < arguments->items.count; ++i) { item = array_append(&arguments_array); if (item == NULL) { error_code = api_get_error_code_from_errno(); log_error("Could not append to arguments array for spawning child process (executable: %s): %s (%d)", executable->buffer, get_errno_name(errno), errno); goto cleanup; } *item = (*(String **)array_get(&arguments->items, i))->buffer; } item = array_append(&arguments_array); if (item == NULL) { error_code = api_get_error_code_from_errno(); log_error("Could not append to arguments array for spawning child process (executable: %s): %s (%d)", executable->buffer, get_errno_name(errno), errno); goto cleanup; } *item = NULL; // lock environment list object error_code = list_get_acquired_and_locked(environment_id, OBJECT_TYPE_STRING, &environment); if (error_code != API_E_SUCCESS) { goto cleanup; } phase = 4; // prepare environment array for execvpe if (array_create(&environment_array, environment->items.count + 1, sizeof(char *), true) < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not create environment array for spawning child process (executable: %s): %s (%d)", executable->buffer, get_errno_name(errno), errno); goto cleanup; } phase = 5; for (i = 0; i < environment->items.count; ++i) { item = array_append(&environment_array); if (item == NULL) { error_code = api_get_error_code_from_errno(); log_error("Could not append to environment array for spawning child process (executable: %s): %s (%d)", executable->buffer, get_errno_name(errno), errno); goto cleanup; } // FIXME: if item is not <name>=<value>, but just <name> then use the parent <value> *item = (*(String **)array_get(&environment->items, i))->buffer; } item = array_append(&environment_array); if (item == NULL) { error_code = api_get_error_code_from_errno(); log_error("Could not append to environment array for spawning child process (executable: %s): %s (%d)", executable->buffer, get_errno_name(errno), errno); goto cleanup; } *item = NULL; // acquire and lock working directory string object error_code = string_get_acquired_and_locked(working_directory_id, &working_directory); if (error_code != API_E_SUCCESS) { goto cleanup; } phase = 6; if (*working_directory->buffer == '\0') { error_code = API_E_INVALID_PARAMETER; log_warn("Cannot spawn child process (executable: %s) using empty working directory name", executable->buffer); goto cleanup; } if (*working_directory->buffer != '/') { error_code = API_E_INVALID_PARAMETER; log_warn("Cannot spawn child process (executable: %s) using working directory with relative name '%s'", executable->buffer, working_directory->buffer); goto cleanup; } // acquire stdin file object error_code = file_get_acquired(stdin_id, &stdin); if (error_code != API_E_SUCCESS) { goto cleanup; } phase = 7; // acquire stdout file object error_code = file_get_acquired(stdout_id, &stdout); if (error_code != API_E_SUCCESS) { goto cleanup; } phase = 8; // acquire stderr file object error_code = file_get_acquired(stderr_id, &stderr); if (error_code != API_E_SUCCESS) { goto cleanup; } phase = 9; // create status pipe if (pipe(status_pipe) < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not create status pipe for spawning child process (executable: %s): %s (%d)", executable->buffer, get_errno_name(errno), errno); goto cleanup; } phase = 10; // fork log_debug("Forking to spawn child process (executable: %s)", executable->buffer); error_code = process_fork(&pid); if (error_code != API_E_SUCCESS) { goto cleanup; } if (pid == 0) { // child close(status_pipe[0]); // change user and groups error_code = process_set_identity(uid, gid); if (error_code != API_E_SUCCESS) { goto child_error; } // change directory if (chdir(working_directory->buffer) < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not change directory to '%s' for child process (executable: %s, pid: %u): %s (%d)", working_directory->buffer, executable->buffer, getpid(), get_errno_name(errno), errno); goto child_error; } // get open FD limit sc_open_max = sysconf(_SC_OPEN_MAX); if (sc_open_max < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not get SC_OPEN_MAX value: %s (%d)", get_errno_name(errno), errno); goto child_error; } // redirect stdin if (dup2(file_get_read_handle(stdin), STDIN_FILENO) != STDIN_FILENO) { error_code = api_get_error_code_from_errno(); log_error("Could not redirect stdin for child process (executable: %s, pid: %u): %s (%d)", executable->buffer, getpid(), get_errno_name(errno), errno); goto child_error; } // redirect stdout if (dup2(file_get_write_handle(stdout), STDOUT_FILENO) != STDOUT_FILENO) { error_code = api_get_error_code_from_errno(); log_error("Could not redirect stdout for child process (executable: %s, pid: %u): %s (%d)", executable->buffer, getpid(), get_errno_name(errno), errno); goto child_error; } // stderr is the default log output in non-daemon mode. if this is // the case then disable the log output before redirecting stderr to // avoid polluting stderr for the new process log_file = log_get_file(); if (log_file != NULL && fileno(log_file) == STDERR_FILENO) { log_debug("Disable logging to stderr for child process (executable: %s, pid: %u)", executable->buffer, getpid()); log_set_file(NULL); } // redirect stderr if (dup2(file_get_write_handle(stderr), STDERR_FILENO) != STDERR_FILENO) { error_code = api_get_error_code_from_errno(); log_error("Could not redirect stderr for child process (executable: %s, pid: %u): %s (%d)", executable->buffer, getpid(), get_errno_name(errno), errno); goto child_error; } // notify parent if (robust_write(status_pipe[1], &error_code, sizeof(error_code)) < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not write to status pipe for child process (executable: %s, pid: %u): %s (%d)", executable->buffer, getpid(), get_errno_name(errno), errno); goto child_error; } // disable log output. if stderr was not the current log output then // the log file is still open at this point. the next step is to close // all remaining file descriptors. just for good measure disable the // log output beforehand log_set_file(NULL); // close all file descriptors except the std* ones for (i = STDERR_FILENO + 1; i < sc_open_max; ++i) { close(i); } // execvpe only returns in case of an error execvpe(executable->buffer, (char **)arguments_array.bytes, (char **)environment_array.bytes); if (errno == ENOENT) { _exit(PROCESS_E_DOES_NOT_EXIST); } else { _exit(PROCESS_E_CANNOT_EXECUTE); } child_error: // notify parent in all cases if (robust_write(status_pipe[1], &error_code, sizeof(error_code)) < 0) { log_error("Could not write to status pipe for child process (executable: %s, pid: %u): %s (%d)", executable->buffer, getpid(), get_errno_name(errno), errno); } close(status_pipe[1]); _exit(PROCESS_E_INTERNAL_ERROR); } phase = 11; // wait for child to start successfully if (robust_read(status_pipe[0], &error_code, sizeof(error_code)) < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not read from status pipe for child process (executable: %s, pid: %u): %s (%d)", executable->buffer, pid, get_errno_name(errno), errno); goto cleanup; } if (error_code != API_E_SUCCESS) { goto cleanup; } // create process object process = calloc(1, sizeof(Process)); if (process == NULL) { error_code = API_E_NO_FREE_MEMORY; log_error("Could not allocate process object: %s (%d)", get_errno_name(ENOMEM), ENOMEM); goto cleanup; } phase = 12; // setup process object process->executable = executable; process->arguments = arguments; process->environment = environment; process->working_directory = working_directory; process->uid = uid; process->gid = gid; process->pid = pid; process->stdin = stdin; process->stdout = stdout; process->stderr = stderr; process->release_on_death = release_on_death; process->state_changed = state_changed; process->opaque = opaque; process->state = PROCESS_STATE_RUNNING; process->timestamp = time(NULL); process->exit_code = 0; // invalid if (pipe_create(&process->state_change_pipe, 0) < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not create state change pipe child process (executable: %s, pid: %u): %s (%d)", executable->buffer, pid, get_errno_name(errno), errno); goto cleanup; } phase = 13; if (event_add_source(process->state_change_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, process_handle_state_change, process) < 0) { goto cleanup; } phase = 14; // create process object error_code = object_create(&process->base, OBJECT_TYPE_PROCESS, session, object_create_flags | OBJECT_CREATE_FLAG_INTERNAL, process_destroy, process_signature); if (error_code != API_E_SUCCESS) { goto cleanup; } phase = 15; if (id != NULL) { *id = process->base.id; } if (object != NULL) { *object = process; } // start thread to wait for child process state changes thread_create(&process->wait_thread, process_wait, process); log_debug("Spawned process object (id: %u, executable: %s, pid: %u)", process->base.id, executable->buffer, process->pid); close(status_pipe[0]); close(status_pipe[1]); array_destroy(&arguments_array, NULL); array_destroy(&environment_array, NULL); cleanup: switch (phase) { // no breaks, all cases fall through intentionally case 14: event_remove_source(process->state_change_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC); case 13: pipe_destroy(&process->state_change_pipe); case 12: free(process); case 11: kill(pid, SIGKILL); case 10: close(status_pipe[0]); close(status_pipe[1]); case 9: file_release(stderr); case 8: file_release(stdout); case 7: file_release(stdin); case 6: string_unlock_and_release(working_directory); case 5: array_destroy(&environment_array, NULL); case 4: list_unlock_and_release(environment); case 3: array_destroy(&arguments_array, NULL); case 2: list_unlock_and_release(arguments); case 1: string_unlock_and_release(executable); default: break; } return phase == 15 ? API_E_SUCCESS : error_code; }
int iokit_init(void) { int phase = 0; Semaphore handshake; log_debug("Initializing IOKit subsystem"); // create notification pipe if (pipe_create(&_notification_pipe) < 0) { log_error("Could not create notification pipe: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 1; if (event_add_source(_notification_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, iokit_forward_notifications, NULL) < 0) { goto cleanup; } phase = 2; // create notification poll thread if (semaphore_create(&handshake) < 0) { log_error("Could not create handshake semaphore: %s (%d)", get_errno_name(errno), errno); goto cleanup; } thread_create(&_poll_thread, iokit_poll_notifications, &handshake); semaphore_acquire(&handshake); semaphore_destroy(&handshake); phase = 3; if (!_running) { log_error("Could not start notification poll thread"); goto cleanup; } phase = 4; cleanup: switch (phase) { // no breaks, all cases fall through intentionally case 3: thread_destroy(&_poll_thread); case 2: event_remove_source(_notification_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC); case 1: pipe_destroy(&_notification_pipe); default: break; } return phase == 4 ? 0 : -1; }
int event_init_platform(void) { int phase = 0; // create read set if (event_reserve_socket_set(&_socket_read_set, 32) < 0) { log_error("Could not create socket read set: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 1; // create write set if (event_reserve_socket_set(&_socket_write_set, 32) < 0) { log_error("Could not create socket write set: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 2; // create error set if (event_reserve_socket_set(&_socket_error_set, 32) < 0) { log_error("Could not create socket error set: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 3; // create stop pipe if (pipe_create(&_stop_pipe, 0) < 0) { log_error("Could not create stop pipe: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 4; if (event_add_source(_stop_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, NULL, NULL) < 0) { goto cleanup; } phase = 5; // create USB poll thread _usb_poll_running = false; _usb_poll_stuck = false; if (usbi_pipe(_usb_poll_suspend_pipe) < 0) { log_error("Could not create USB suspend pipe"); goto cleanup; } phase = 6; if (pipe_create(&_usb_poll_ready_pipe, 0) < 0) { log_error("Could not create USB ready pipe: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 7; if (array_create(&_usb_poll_pollfds, 32, sizeof(struct usbi_pollfd), true) < 0) { log_error("Could not create USB pollfd array: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 8; if (semaphore_create(&_usb_poll_resume) < 0) { log_error("Could not create USB resume semaphore: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 9; if (semaphore_create(&_usb_poll_suspend) < 0) { log_error("Could not create USB suspend semaphore: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 10; cleanup: switch (phase) { // no breaks, all cases fall through intentionally case 9: semaphore_destroy(&_usb_poll_suspend); case 8: semaphore_destroy(&_usb_poll_resume); case 7: pipe_destroy(&_usb_poll_ready_pipe); case 6: usbi_close(_usb_poll_suspend_pipe[0]); usbi_close(_usb_poll_suspend_pipe[1]); case 5: event_remove_source(_stop_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC); case 4: pipe_destroy(&_stop_pipe); case 3: free(_socket_error_set); case 2: free(_socket_write_set); case 1: free(_socket_read_set); default: break; } return phase == 10 ? 0 : -1; }
/* ARGSUSED */ int pipe(proc_t p, __unused struct pipe_args *uap, int32_t *retval) { struct fileproc *rf, *wf; struct pipe *rpipe, *wpipe; lck_mtx_t *pmtx; int fd, error; if ((pmtx = lck_mtx_alloc_init(pipe_mtx_grp, pipe_mtx_attr)) == NULL) return (ENOMEM); rpipe = wpipe = NULL; if (pipe_create(&rpipe) || pipe_create(&wpipe)) { error = ENFILE; goto freepipes; } /* * allocate the space for the normal I/O direction up * front... we'll delay the allocation for the other * direction until a write actually occurs (most likely it won't)... */ error = pipespace(rpipe, choose_pipespace(rpipe->pipe_buffer.size, 0)); if (error) goto freepipes; TAILQ_INIT(&rpipe->pipe_evlist); TAILQ_INIT(&wpipe->pipe_evlist); error = falloc(p, &rf, &fd, vfs_context_current()); if (error) { goto freepipes; } retval[0] = fd; /* * for now we'll create half-duplex pipes(refer returns section above). * this is what we've always supported.. */ rf->f_flag = FREAD; rf->f_data = (caddr_t)rpipe; rf->f_ops = &pipeops; error = falloc(p, &wf, &fd, vfs_context_current()); if (error) { fp_free(p, retval[0], rf); goto freepipes; } wf->f_flag = FWRITE; wf->f_data = (caddr_t)wpipe; wf->f_ops = &pipeops; rpipe->pipe_peer = wpipe; wpipe->pipe_peer = rpipe; /* both structures share the same mutex */ rpipe->pipe_mtxp = wpipe->pipe_mtxp = pmtx; retval[1] = fd; #if CONFIG_MACF /* * XXXXXXXX SHOULD NOT HOLD FILE_LOCK() XXXXXXXXXXXX * * struct pipe represents a pipe endpoint. The MAC label is shared * between the connected endpoints. As a result mac_pipe_label_init() and * mac_pipe_label_associate() should only be called on one of the endpoints * after they have been connected. */ mac_pipe_label_init(rpipe); mac_pipe_label_associate(kauth_cred_get(), rpipe); wpipe->pipe_label = rpipe->pipe_label; #endif proc_fdlock_spin(p); procfdtbl_releasefd(p, retval[0], NULL); procfdtbl_releasefd(p, retval[1], NULL); fp_drop(p, retval[0], rf, 1); fp_drop(p, retval[1], wf, 1); proc_fdunlock(p); return (0); freepipes: pipeclose(rpipe); pipeclose(wpipe); lck_mtx_free(pmtx, pipe_mtx_grp); return (error); }
int parse_part(char* part, run_params* par) { char* cmd = (char*)malloc(sizeof(char) * MAX_CMD_LEN); int pos_part = 0, pos_cmd = 0; int c; int return_val; run_params* act_par = (run_params*)malloc(sizeof(run_params)); memcpy_s(act_par, sizeof(run_params), par, sizeof(run_params)); int in_q = 0; return_val = 0; while (true) { c = part[pos_part]; if (c == '"') in_q = 1 - in_q; if ((c == CMD_PIPE_CHAR) && (!in_q)) { cmd[pos_cmd] = '\0'; pos_part++; run_params* act_par_new = (run_params*)malloc(sizeof(run_params)); memcpy_s(act_par_new, sizeof(run_params), act_par, sizeof(run_params)); pipe_in* in_new = (pipe_in*)(malloc(sizeof pipe_in)); pipe_out* out_new = (pipe_out*)(malloc(sizeof pipe_out)); pipe_create(in_new, out_new, 1, 0); act_par_new->out = in_new; act_par->in = out_new; int ret = parse_cmd(cmd, act_par_new, par, 0); if (ret == 1) { return_val = 1; goto end; } pos_cmd = 0; } else if (c == '\0') { cmd[pos_cmd] = '\0'; pos_part++; run_params* act_par_new = (run_params*)malloc(sizeof(run_params)); memcpy_s(act_par_new, sizeof(run_params), act_par, sizeof(run_params)); int ret = parse_cmd(cmd, act_par_new, par, 1); if (ret == 1) { return_val = 1; goto end; } return_val = 0; goto end; } else { cmd[pos_cmd] = part[pos_part]; pos_cmd++; pos_part++; } } end: free(cmd); return return_val; }
int main() { srand((int)time(NULL)); node* root_dir = node_create("Computer", NULL, 1); node* root = node_create("C:", root_dir, 1); node* n1 = node_create("n1", root, 0); node* n2 = node_create("n2", root, 0); node* n3 = node_create("n3", root, 0); node* n4 = node_create("n4", root, 1); node* n5 = node_create("n5", root, 1); node* n5a = node_create("n5a", n5, 0); node* n5b = node_create("n5b", n5, 0); char* str = "n1 - aaaaaa\nbbbb\ncccc\nfskdhjs\ndsfj\niuyffj\n\n\nejrwehjr\n"; n1->content = (char*)malloc(sizeof(char) * strlen(str)+1); memcpy(n1->content, str, strlen(str)+1); n1->content_len = strlen(n1->content); str = ""; n2->content = (char*)malloc(sizeof(char) * strlen(str)+1); memcpy(n2->content, str, strlen(str)+1); n2->content_len = strlen(n2->content); str = "n3 - ,m,mkjhseur\nsjagfjhsdhj\n"; n3->content = (char*)malloc(sizeof(char) * strlen(str)+1); memcpy(n3->content, str, strlen(str)+1); n3->content_len = strlen(n3->content); str = "n4 - yighjgjhgfyufyt\n"; n4->content = (char*)malloc(sizeof(char) * strlen(str)+1); memcpy(n4->content, str, strlen(str) + 1); n4->content_len = strlen(n4->content); str = "n5a - 45455\n"; n5a->content = (char*)malloc(sizeof(char) * strlen(str)+1); memcpy(n5a->content, str, strlen(str) + 1); n5a->content_len = strlen(n5a->content); str = "n5b - 1010\n"; n5b->content = (char*)malloc(sizeof(char) * strlen(str)+1); memcpy(n5b->content, str, strlen(str) + 1); n5b->content_len = strlen(n5b->content); pipe_in* in_in = (pipe_in *)malloc(sizeof(pipe_in)); pipe_out* in_out = (pipe_out *)malloc(sizeof(pipe_out)); pipe_create(in_in, in_out, 0, 0, 1); pipe_in* out_in = (pipe_in *)malloc(sizeof(pipe_in)); pipe_out* out_out = (pipe_out *)malloc(sizeof(pipe_out)); pipe_create(out_in, out_out, 0, 0); pipe_in* err_in = (pipe_in *)malloc(sizeof(pipe_in)); pipe_out* err_out = (pipe_out *)malloc(sizeof(pipe_out)); pipe_create(err_in, err_out, 0, 0); HANDLE h_in = std_reader_run(in_in); HANDLE h_out = std_writter_run(out_out); HANDLE h_err = std_writter_run(err_out); run_params par; par.cmd_name = "cmd\0"; par.in = in_out; par.out = out_in; par.err = err_in; par.start_node = root; par.root_node = root; par.args = (char**)malloc(sizeof(char*) * 1); par.args[0] = "-main"; par.argc = 1; par.secret_params = 1; c_run( (LPTHREAD_START_ROUTINE) c_cmd_run, &par, 0); WaitForSingleObject(h_out, INFINITE); WaitForSingleObject(h_err, INFINITE); TerminateThread(h_in, 0); // needs to be terminated, otherwise would wait for input forever free(par.args); return 0; }
run_params* make_params(run_params* parent_par, char* in, char* out, char* err, int app, char** args, int argc, char* cmd_name) { run_params* nParams = (run_params*)malloc(sizeof(run_params)); nParams->in = parent_par->in; nParams->out = parent_par->out; nParams->err = parent_par->err; nParams->start_node = parent_par->start_node; nParams->root_node = parent_par->root_node; nParams->cmd_name = cmd_name; nParams->argc = argc; nParams->args = args; nParams->secret_params = 0; if (in[0] != '\0') { node* node_in = node_get(in, nParams->root_node, nParams->start_node); if (node_in == NULL) { pipe_write_s(parent_par->err, "File not found!\n"); return NULL; } if (node_in->directory) { pipe_write_s(parent_par->err, "Target is a directory!\n"); return NULL; } // open file if (node_try_lock(node_in)) { pipe_in* p_in = (pipe_in *)malloc(sizeof(pipe_in)); pipe_out* p_out = (pipe_out *)malloc(sizeof(pipe_out)); pipe_create(p_in, p_out, 1, 1); file_reader_run(p_in, node_in); nParams->in = p_out; } else { pipe_write_s(parent_par->err, "Can not open the file.\n"); return NULL; } } if (out[0] != '\0') { node* node_out = node_get(out, nParams->root_node, nParams->start_node); if (node_out == NULL) { node_out = node_create(out, nParams->start_node, 0); if (node_out == NULL) { pipe_write_s(parent_par->err, "Could not create the file!\n"); return NULL; } } if (node_out->directory) { pipe_write_s(parent_par->err, "Target is a directory!\n"); return NULL; } // open file if (node_try_lock(node_out)) { pipe_in* p_in = (pipe_in *)malloc(sizeof(pipe_in)); pipe_out* p_out = (pipe_out *)malloc(sizeof(pipe_out)); pipe_create(p_in, p_out, 1, 1); file_writter_run(p_out, node_out, app); nParams->out = p_in; } else { pipe_write_s(parent_par->err, "Can not open the file.\n"); } } if (err[0] != '\0') { node* node_err = node_get(err, nParams->root_node, nParams->start_node); if (node_err == NULL) { node_err = node_create(err, nParams->start_node, 0); if (node_err == NULL) { pipe_write_s(parent_par->err, "Could not create the file!\n"); return NULL; } } if (node_err->directory) { pipe_write_s(parent_par->err, "Target is a directory!\n"); return NULL; } // open file if (node_try_lock(node_err)) { pipe_in* p_in = (pipe_in *)malloc(sizeof(pipe_in)); pipe_out* p_out = (pipe_out *)malloc(sizeof(pipe_out)); pipe_create(p_in, p_out, 1, 1); file_writter_run(p_out, node_err, 0); nParams->err = p_in; } else { pipe_write_s(parent_par->err, "Can not open the file.\n"); } } return nParams; }
static error_t open_hook (struct trivfs_peropen *po) { error_t err = 0; int flags = po->openmodes; if (flags & (O_READ | O_WRITE)) { mutex_lock (&active_fifo_lock); /* Wait until the active fifo has changed so that CONDITION is true. */ #define WAIT(condition, noblock_err) \ while (!err && !(condition)) \ { \ if (flags & O_NONBLOCK) \ { \ err = noblock_err; \ break; \ } \ else if (hurd_condition_wait (&active_fifo_changed, &active_fifo_lock)) \ err = EINTR; \ } if (flags & O_READ) /* When opening for read, what we do depends on what mode this server is running in. The default (if ONE_READER is set) is to only allow one reader at a time, with additional opens for read blocking here until the old reader goes away; otherwise, we allow multiple readers. If WAIT_FOR_WRITER is true, then once we've created a fifo, we also block until someone opens it for writing; otherwise, the first read will block until someone writes something. */ { if (one_reader) /* Wait until there isn't any active fifo, so we can make one. */ WAIT (!active_fifo || !active_fifo->readers, EWOULDBLOCK); if (!err && active_fifo == NULL) /* No other readers, and indeed, no fifo; make one. */ { err = pipe_create (fifo_pipe_class, &active_fifo); if (! err) active_fifo->flags &= ~PIPE_BROKEN; /* Avoid immediate EOF. */ } if (!err) { pipe_add_reader (active_fifo); condition_broadcast (&active_fifo_changed); /* We'll unlock ACTIVE_FIFO_LOCK below; the writer code won't make us block because we've ensured that there's a reader for it. */ if (wait_for_writer) /* Wait until there's a writer. */ { WAIT (active_fifo->writers, 0); if (err) /* Back out the new pipe creation. */ { pipe_remove_reader (active_fifo); active_fifo = NULL; condition_broadcast (&active_fifo_changed); } } } } if (!err && (flags & O_WRITE)) /* Open the active_fifo for writing. If WAIT_FOR_READER is true, then we block until there's someone to read what we wrote, otherwise, if there's no fifo, we create one, which we just write into and leave it for someone to read later. */ { if (wait_for_reader) /* Wait until there's a fifo to write to. */ WAIT (active_fifo && active_fifo->readers, ENXIO); if (!err && active_fifo == NULL) /* No other readers, and indeed, no fifo; make one. */ { err = pipe_create (fifo_pipe_class, &active_fifo); if (!err) active_fifo->flags &= ~PIPE_BROKEN; } if (!err) { pipe_add_writer (active_fifo); condition_broadcast (&active_fifo_changed); } } po->hook = active_fifo; mutex_unlock (&active_fifo_lock); } return err; }
// NOTE: this function needs to call RegisterServiceCtrlHandlerEx and // SetServiceStatus in all circumstances if brickd is running as service static int generic_main(bool log_to_file, bool debug, bool libusb_debug) { int exit_code = EXIT_FAILURE; const char *mutex_name = "Global\\Tinkerforge-Brick-Daemon-Single-Instance"; HANDLE mutex_handle = NULL; bool fatal_error = false; DWORD service_exit_code = NO_ERROR; int rc; char filename[1024]; int i; FILE *log_file = NULL; WSADATA wsa_data; DEV_BROADCAST_DEVICEINTERFACE notification_filter; HDEVNOTIFY notification_handle; mutex_handle = OpenMutex(SYNCHRONIZE, FALSE, mutex_name); if (mutex_handle == NULL) { rc = GetLastError(); if (rc == ERROR_ACCESS_DENIED) { rc = service_is_running(); if (rc < 0) { fatal_error = true; // FIXME: set service_exit_code goto error_mutex; } else if (rc) { fatal_error = true; service_exit_code = ERROR_SERVICE_ALREADY_RUNNING; log_error("Could not start as %s, another instance is already running as service", _run_as_service ? "service" : "console application"); goto error_mutex; } } if (rc != ERROR_FILE_NOT_FOUND) { fatal_error = true; // FIXME: set service_exit_code rc += ERRNO_WINAPI_OFFSET; log_error("Could not open single instance mutex: %s (%d)", get_errno_name(rc), rc); goto error_mutex; } } if (mutex_handle != NULL) { fatal_error = true; service_exit_code = ERROR_SERVICE_ALREADY_RUNNING; log_error("Could not start as %s, another instance is already running", _run_as_service ? "service" : "console application"); goto error_mutex; } mutex_handle = CreateMutex(NULL, FALSE, mutex_name); if (mutex_handle == NULL) { fatal_error = true; // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_error("Could not create single instance mutex: %s (%d)", get_errno_name(rc), rc); goto error_mutex; } if (log_to_file) { if (GetModuleFileName(NULL, filename, sizeof(filename)) == 0) { rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_warn("Could not get module file name: %s (%d)", get_errno_name(rc), rc); } else { i = strlen(filename); if (i < 4) { log_warn("Module file name '%s' is too short", filename); } else { filename[i - 3] = '\0'; string_append(filename, "log", sizeof(filename)); log_file = fopen(filename, "a+"); if (log_file == NULL) { log_warn("Could not open log file '%s'", filename); } else { printf("Logging to '%s'\n", filename); log_set_file(log_file); } } } } else if (_run_as_service) { log_set_file(NULL); } if (!_run_as_service && !SetConsoleCtrlHandler(console_ctrl_handler, TRUE)) { rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_warn("Could not set console control handler: %s (%d)", get_errno_name(rc), rc); } log_set_debug_override(debug); log_set_level(LOG_CATEGORY_EVENT, config_get_option("log_level.event")->value.log_level); log_set_level(LOG_CATEGORY_USB, config_get_option("log_level.usb")->value.log_level); log_set_level(LOG_CATEGORY_NETWORK, config_get_option("log_level.network")->value.log_level); log_set_level(LOG_CATEGORY_HOTPLUG, config_get_option("log_level.hotplug")->value.log_level); log_set_level(LOG_CATEGORY_HARDWARE, config_get_option("log_level.hardware")->value.log_level); log_set_level(LOG_CATEGORY_WEBSOCKET, config_get_option("log_level.websocket")->value.log_level); log_set_level(LOG_CATEGORY_OTHER, config_get_option("log_level.other")->value.log_level); if (config_has_error()) { log_error("Error(s) in config file '%s', run with --check-config option for details", _config_filename); fatal_error = true; goto error_config; } if (_run_as_service) { log_info("Brick Daemon %s started (as service)", VERSION_STRING); } else { log_info("Brick Daemon %s started", VERSION_STRING); } if (config_has_warning()) { log_warn("Warning(s) in config file '%s', run with --check-config option for details", _config_filename); } // initialize service status error_config: error_mutex: if (_run_as_service) { if (service_init(service_control_handler) < 0) { // FIXME: set service_exit_code goto error; } if (!fatal_error) { // service is starting service_set_status(SERVICE_START_PENDING, NO_ERROR); } } if (fatal_error) { goto error; } // initialize WinSock2 if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + WSAGetLastError(); log_error("Could not initialize Windows Sockets 2.2: %s (%d)", get_errno_name(rc), rc); goto error_event; } if (event_init() < 0) { // FIXME: set service_exit_code goto error_event; } if (hardware_init() < 0) { // FIXME: set service_exit_code goto error_hardware; } if (usb_init(libusb_debug) < 0) { // FIXME: set service_exit_code goto error_usb; } // create notification pipe if (pipe_create(&_notification_pipe) < 0) { // FIXME: set service_exit_code log_error("Could not create notification pipe: %s (%d)", get_errno_name(errno), errno); goto error_pipe; } if (event_add_source(_notification_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, forward_notifications, NULL) < 0) { // FIXME: set service_exit_code goto error_pipe_add; } // register device notification ZeroMemory(¬ification_filter, sizeof(notification_filter)); notification_filter.dbcc_size = sizeof(notification_filter); notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; notification_filter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; if (_run_as_service) { notification_handle = RegisterDeviceNotification((HANDLE)service_get_status_handle(), ¬ification_filter, DEVICE_NOTIFY_SERVICE_HANDLE); } else { if (message_pump_start() < 0) { // FIXME: set service_exit_code goto error_pipe_add; } notification_handle = RegisterDeviceNotification(_message_pump_hwnd, ¬ification_filter, DEVICE_NOTIFY_WINDOW_HANDLE); } if (notification_handle == NULL) { // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_error("Could not register for device notification: %s (%d)", get_errno_name(rc), rc); goto error_notification; } if (network_init() < 0) { // FIXME: set service_exit_code goto error_network; } // running if (_run_as_service) { service_set_status(SERVICE_RUNNING, NO_ERROR); } if (event_run(network_cleanup_clients_and_zombies) < 0) { // FIXME: set service_exit_code goto error_run; } exit_code = EXIT_SUCCESS; error_run: network_exit(); error_network: UnregisterDeviceNotification(notification_handle); error_notification: if (!_run_as_service) { message_pump_stop(); } event_remove_source(_notification_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC); error_pipe_add: pipe_destroy(&_notification_pipe); error_pipe: usb_exit(); error_usb: hardware_exit(); error_hardware: event_exit(); error_event: log_info("Brick Daemon %s stopped", VERSION_STRING); error: if (!_run_as_service) { // unregister the console handler before exiting the log. otherwise a // control event might be send to the control handler after the log // is not available anymore and the control handler tries to write a // log messages triggering a crash. this situation could easily be // created by clicking the close button of the command prompt window // while the getch call is waiting for the user to press a key. SetConsoleCtrlHandler(console_ctrl_handler, FALSE); } log_exit(); config_exit(); if (_run_as_service) { // because the service process can be terminated at any time after // entering SERVICE_STOPPED state the mutex is closed beforehand, // even though this creates a tiny time window in which the service // is still running but the mutex is not held anymore if (mutex_handle != NULL) { CloseHandle(mutex_handle); } // service is now stopped service_set_status(SERVICE_STOPPED, service_exit_code); } else { if (_pause_before_exit) { printf("Press any key to exit...\n"); getch(); } if (mutex_handle != NULL) { CloseHandle(mutex_handle); } } return exit_code; }
// simple exec (no pipe included, but for piping OUTs) int fork_and_exec_pipe(int connfd, char **cmd, int p_n) { // if(strcmp(cmd[0], "cat")==0 && cmd[1]==NULL) return SKIP_SHIFT; // create pipe int client_id = clients_get_id_from_socket(connfd); int *fd = pipe_create(client_id, p_n); pid_t pid; pid = fork(); if(pid<0) { // if error fprintf(stderr, "Fork failed\n"); exit(EXIT_FAILURE); } else if (pid ==0) { // if child // output old_pipe content if exist int *op = get_old_pipe(client_id); if(op!=NULL) { memset(pipe_buff, 0, sizeof(pipe_buff)); int count; if( (count = read(op[READ], pipe_buff, SIZE_PIPE_BUFF)) < 0 ) { fprintf(stderr, "read pipe connent error: %s\n", strerror(errno)); } if(close(op[READ]) < 0) { fprintf(stderr, "pipe close error (old_pipe in): %s\n", strerror(errno)); exit(EXIT_FAILURE); } if(DEBUG) debug_print_pipe_cat_content(count); if( write(fd[WRITE], pipe_buff, count) < 0 ) { fprintf(stderr, "write pipe connent error: %s\n", strerror(errno)); } } // redirect STDOUT to pipe if(close(fd[READ]) < 0) { fprintf(stderr, "pipe close error (fd in): %s\n", strerror(errno)); exit(EXIT_FAILURE); } dup2(fd[WRITE], STDOUT_FILENO); if(!DEBUG) dup2(connfd, STDERR_FILENO); // DEBUG if(DEBUG) debug_print_pipe_map(client_id); // redirect STDIN to pipe_map[0][READ] int fd_in = pipe_get(client_id); if(fd_in) dup2(fd_in, STDIN_FILENO); if(cmd[0][0]=='/' || execvp(cmd[0], cmd)<0) { fprintf(stderr, "Unknown command: [%s].\n", cmd[0]); fprintf(stdout, "Unknown command: [%s].\n", cmd[0]); fflush(stderr); close(fd[WRITE]); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } else { // if parent int return_val; waitpid(pid, &return_val, 0); if( close(fd[WRITE]) < 0 ) { fprintf(stderr, "pipe close error (fd out): %s\n", strerror(errno)); exit(EXIT_FAILURE); } if(WEXITSTATUS(return_val) == EXIT_FAILURE) return EXIT_FAILURE; } return EXIT_SUCCESS; }
/* ARGSUSED */ int sys_pipe(struct proc *p, void *v, register_t *retval) { struct sys_pipe_args /* { syscallarg(int *) fdp; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct file *rf, *wf; struct pipe *rpipe, *wpipe = NULL; int fds[2], error; rpipe = pool_get(&pipe_pool, PR_WAITOK); error = pipe_create(rpipe); if (error != 0) goto free1; wpipe = pool_get(&pipe_pool, PR_WAITOK); error = pipe_create(wpipe); if (error != 0) goto free1; fdplock(fdp); error = falloc(p, &rf, &fds[0]); if (error != 0) goto free2; rf->f_flag = FREAD | FWRITE; rf->f_type = DTYPE_PIPE; rf->f_data = rpipe; rf->f_ops = &pipeops; error = falloc(p, &wf, &fds[1]); if (error != 0) goto free3; wf->f_flag = FREAD | FWRITE; wf->f_type = DTYPE_PIPE; wf->f_data = wpipe; wf->f_ops = &pipeops; rpipe->pipe_peer = wpipe; wpipe->pipe_peer = rpipe; FILE_SET_MATURE(rf, p); FILE_SET_MATURE(wf, p); error = copyout(fds, SCARG(uap, fdp), sizeof(fds)); if (error != 0) { fdrelease(p, fds[0]); fdrelease(p, fds[1]); } fdpunlock(fdp); return (error); free3: fdremove(fdp, fds[0]); closef(rf, p); rpipe = NULL; free2: fdpunlock(fdp); free1: pipeclose(wpipe); pipeclose(rpipe); return (error); }
// NOTE: this function needs to call RegisterServiceCtrlHandlerEx and // SetServiceStatus in all circumstances if brickd is running as service static int generic_main(int log_to_file, int debug) { int exit_code = EXIT_FAILURE; const char *mutex_name = "Global\\Tinkerforge-Brick-Daemon-Single-Instance"; HANDLE mutex_handle = NULL; int mutex_error = 0; DWORD service_exit_code = NO_ERROR; int rc; char filename[1024]; int i; FILE *logfile = NULL; WSADATA wsa_data; DEV_BROADCAST_DEVICEINTERFACE notification_filter; HDEVNOTIFY notification_handle; mutex_handle = OpenMutex(SYNCHRONIZE, FALSE, mutex_name); if (mutex_handle == NULL) { rc = GetLastError(); if (rc == ERROR_ACCESS_DENIED) { rc = service_is_running(); if (rc < 0) { mutex_error = 1; // FIXME: set service_exit_code goto error_mutex; } else if (rc) { mutex_error = 1; service_exit_code = ERROR_SERVICE_ALREADY_RUNNING; log_error("Could not start as %s, another instance is already running as service", _run_as_service ? "service" : "console application"); goto error_mutex; } } if (rc != ERROR_FILE_NOT_FOUND) { mutex_error = 1; // FIXME: set service_exit_code rc += ERRNO_WINAPI_OFFSET; log_error("Could not open single instance mutex: %s (%d)", get_errno_name(rc), rc); goto error_mutex; } } if (mutex_handle != NULL) { mutex_error = 1; service_exit_code = ERROR_SERVICE_ALREADY_RUNNING; log_error("Could not start as %s, another instance is already running", _run_as_service ? "service" : "console application"); goto error_mutex; } mutex_handle = CreateMutex(NULL, FALSE, mutex_name); if (mutex_handle == NULL) { mutex_error = 1; // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_error("Could not create single instance mutex: %s (%d)", get_errno_name(rc), rc); goto error_mutex; } if (!_run_as_service && !SetConsoleCtrlHandler(console_ctrl_handler, TRUE)) { rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_warn("Could not set console control handler: %s (%d)", get_errno_name(rc), rc); } if (log_to_file) { if (GetModuleFileName(NULL, filename, sizeof(filename)) == 0) { rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_warn("Could not get module file name: %s (%d)", get_errno_name(rc), rc); } else { i = strlen(filename); if (i < 4) { log_warn("Module file name '%s' is too short", filename); } else { strcpy(filename + i - 3, "log"); logfile = fopen(filename, "a+"); if (logfile == NULL) { log_warn("Could not open logfile '%s'", filename); } else { log_set_file(logfile); } } } } if (debug) { log_set_level(LOG_CATEGORY_EVENT, LOG_LEVEL_DEBUG); log_set_level(LOG_CATEGORY_USB, LOG_LEVEL_DEBUG); log_set_level(LOG_CATEGORY_NETWORK, LOG_LEVEL_DEBUG); log_set_level(LOG_CATEGORY_HOTPLUG, LOG_LEVEL_DEBUG); log_set_level(LOG_CATEGORY_OTHER, LOG_LEVEL_DEBUG); } else { log_set_level(LOG_CATEGORY_EVENT, config_get_log_level(LOG_CATEGORY_EVENT)); log_set_level(LOG_CATEGORY_USB, config_get_log_level(LOG_CATEGORY_USB)); log_set_level(LOG_CATEGORY_NETWORK, config_get_log_level(LOG_CATEGORY_NETWORK)); log_set_level(LOG_CATEGORY_HOTPLUG, config_get_log_level(LOG_CATEGORY_HOTPLUG)); log_set_level(LOG_CATEGORY_OTHER, config_get_log_level(LOG_CATEGORY_OTHER)); } if (_run_as_service) { log_info("Brick Daemon %s started (as service)", VERSION_STRING); } else { log_info("Brick Daemon %s started", VERSION_STRING); } if (config_has_error()) { log_warn("Errors found in config file '%s', run with --check-config option for details", _config_filename); } // initialize service status error_mutex: if (_run_as_service) { if (service_init(service_control_handler) < 0) { // FIXME: set service_exit_code goto error; } if (!mutex_error) { // service is starting service_set_status(SERVICE_START_PENDING, NO_ERROR); } } if (mutex_error) { goto error; } // initialize WinSock2 if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + WSAGetLastError(); log_error("Could not initialize Windows Sockets 2.2: %s (%d)", get_errno_name(rc), rc); goto error_event; } if (event_init() < 0) { // FIXME: set service_exit_code goto error_event; } if (usb_init() < 0) { // FIXME: set service_exit_code goto error_usb; } // create notification pipe if (pipe_create(_notification_pipe) < 0) { // FIXME: set service_exit_code log_error("Could not create notification pipe: %s (%d)", get_errno_name(errno), errno); goto error_pipe; } if (event_add_source(_notification_pipe[0], EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, forward_notifications, NULL) < 0) { // FIXME: set service_exit_code goto error_pipe_add; } // register device notification ZeroMemory(¬ification_filter, sizeof(notification_filter)); notification_filter.dbcc_size = sizeof(notification_filter); notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; notification_filter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; if (_run_as_service) { notification_handle = RegisterDeviceNotification((HANDLE)service_get_status_handle(), ¬ification_filter, DEVICE_NOTIFY_SERVICE_HANDLE); } else { if (message_pump_start() < 0) { // FIXME: set service_exit_code goto error_pipe_add; } notification_handle = RegisterDeviceNotification(_message_pump_hwnd, ¬ification_filter, DEVICE_NOTIFY_WINDOW_HANDLE); } if (notification_handle == NULL) { // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_error("Could not register for device notification: %s (%d)", get_errno_name(rc), rc); goto error_notification; } if (network_init() < 0) { // FIXME: set service_exit_code goto error_network; } // running if (_run_as_service) { service_set_status(SERVICE_RUNNING, NO_ERROR); } if (event_run() < 0) { // FIXME: set service_exit_code goto error_run; } exit_code = EXIT_SUCCESS; error_run: network_exit(); error_network: UnregisterDeviceNotification(notification_handle); error_notification: if (!_run_as_service) { message_pump_stop(); } event_remove_source(_notification_pipe[0], EVENT_SOURCE_TYPE_GENERIC); error_pipe_add: pipe_destroy(_notification_pipe); error_pipe: usb_exit(); error_usb: event_exit(); error_event: log_info("Brick Daemon %s stopped", VERSION_STRING); error: log_exit(); config_exit(); if (_run_as_service) { // because the service process can be terminated at any time after // entering SERVICE_STOPPED state the mutex is closed beforehand, // even though this creates a tiny time window in which the service // is still running but the mutex is not held anymore if (mutex_handle != NULL) { CloseHandle(mutex_handle); } // service is now stopped service_set_status(SERVICE_STOPPED, service_exit_code); } else { if (_pause_before_exit) { printf("Press any key to exit...\n"); getch(); } if (mutex_handle != NULL) { CloseHandle(mutex_handle); } } return exit_code; }