/* Patchdiff2 Portions (C) 2010 Nicolas Pouvesle Portions (C) 2007 - 2009 Tenable Network Security, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #define USE_DANGEROUS_FUNCTIONS #include #include #include "unix_fct.h" #include "system.h" struct ipc_data { int spipe; int rpipe; char *sname; char *rname; pid_t pid; }; typedef struct ipc_data ipc_data_t; /*------------------------------------------------*/ /* function : create_process */ /* description: fork/exec */ /*------------------------------------------------*/ pid_t create_process(char *cmd) { pid_t pid; char *argv[4]; pid = fork(); if (pid == 0) { // Assume execvp is safe to call with const char strings argv[0] = const_cast("/bin/sh"); argv[1] = const_cast("-c"); argv[2] = cmd; argv[3] = NULL; execvp(argv[0], argv); exit(EXIT_FAILURE); } return pid; } /*------------------------------------------------*/ /* function : os_execute_command */ /* description: Executes a command by creating a */ /* new process */ /*------------------------------------------------*/ int os_execute_command(char *cmd, bool close, void *data) { ipc_data_t *id = (ipc_data_t *)data; int ret = -1; int status; pid_t pid; pid = create_process(cmd); if (pid == -1) { return -1; } if (close) { /* we wait until the process finished (IE: sig file is generated) */ if (waitpid(pid, &status, 0) == -1) { return -1; } } else { id->pid = pid; } return 0; } /*------------------------------------------------*/ /* function : os_check_process */ /* description: checks process state */ /*------------------------------------------------*/ bool os_check_process(pid_t pid) { if (kill(pid, 0) == 0) { return true; } return false; } /*------------------------------------------------*/ /* function : os_copy_to_clipboard */ /* description: Copies data to clipboard */ /*------------------------------------------------*/ void os_copy_to_clipboard(char *data) { } /*------------------------------------------------*/ /* function : os_get_pid */ /* description: Returns process ID */ /*------------------------------------------------*/ long os_get_pid() { return (long)getpid(); } /*------------------------------------------------*/ /* function : os_unlink */ /* description: removes a link to a file */ /*------------------------------------------------*/ int os_unlink(const char *path) { return unlink(path); } /*------------------------------------------------*/ /* function : os_tempnam */ /* description: returns a temporary file name */ /*------------------------------------------------*/ void os_tempnam(char *data, size_t size, const char *suffix) { char *str = strdup(P_tmpdir "/patchdiff2-XXXXXX");; // TODO: Just use mkstemp and don't mind the lack of extension int fd = mkstemp(str); close(fd); unlink(str); qsnprintf(data, size, "%s%s", str, suffix); free(str); } /*------------------------------------------------*/ /* function : os_ipc_send */ /* description: Sends data on pipe */ /*------------------------------------------------*/ bool os_ipc_send(void *data, int type, idata_t *d) { ipc_data_t *id = (ipc_data_t *)data; ssize_t num; num = write(id->spipe, d, sizeof(*d)); if (num > 0) { return true; } return false; } /*------------------------------------------------*/ /* function : os_ipc_recv */ /* description: Receives data on pipe */ /*------------------------------------------------*/ bool os_ipc_recv(void *data, int type, idata_t *d) { ipc_data_t *id = (ipc_data_t *)data; fd_set rfds, efds; struct timeval tv; int ret; tv.tv_sec = 0; tv.tv_usec = 1000; if (id->pid) { while (1) { FD_ZERO(&rfds); FD_SET(id->rpipe, &rfds); FD_ZERO(&efds); FD_SET(id->rpipe, &efds); ret = select(id->rpipe + 1, &rfds, NULL, &efds, &tv); if (ret > 0 && FD_ISSET(id->rpipe, &rfds)) { break; } if (ret < 0 || (ret > 0 && FD_ISSET(id->rpipe, &efds)) || !os_check_process(id->pid)) { return false; } } } else { FD_ZERO(&rfds); FD_SET(id->rpipe, &rfds); FD_ZERO(&efds); FD_SET(id->rpipe, &efds); ret = select(id->rpipe + 1, &rfds, NULL, &efds, NULL); if (!(ret > 0 && FD_ISSET(id->rpipe, &rfds))) { return false; } } read(id->rpipe, d, sizeof(*d)); return true; } /*------------------------------------------------*/ /* function : os_ipc_init */ /* description: Inits interprocess communication */ /*------------------------------------------------*/ bool os_ipc_init(void ** data, long pid, int type) { char sname[512]; char rname[512]; ipc_data_t *id; id = new ipc_data_t(); if (!id) { return false; } memset(id, '\0', sizeof(*id)); qsnprintf(sname, sizeof(sname), "/tmp/pdiff2spipe%ld", pid); qsnprintf(rname, sizeof(rname), "/tmp/pdiff2rpipe%ld", pid); id->sname = qstrdup(sname); id->rname = qstrdup(rname); if (type == IPC_SERVER) { mkfifo(sname, 0666); id->spipe = open(sname, O_RDWR|O_NONBLOCK); if (id->spipe == -1) { goto error; } mkfifo(rname, 0666); id->rpipe = open(rname, O_RDWR|O_NONBLOCK); if (id->rpipe == -1) { goto error; } } else { id->spipe = open(rname, O_WRONLY); if (id->spipe == -1) { goto error; } id->rpipe = open(sname, O_RDONLY); if (id->rpipe == -1) { goto error; } } *data = (void *)id; return true; error: if (id->spipe) { close(id->spipe); } if (id->rpipe) { close(id->rpipe); } delete id; return false; } /*------------------------------------------------*/ /* function : os_ipc_close */ /* description: Closes IPC */ /*------------------------------------------------*/ bool os_ipc_close(void *data) { ipc_data_t *id = (ipc_data_t *)data; if (id->spipe) { close(id->spipe); } if (id->rpipe) { close(id->rpipe); } os_unlink(id->sname); os_unlink(id->rname); return true; } /*------------------------------------------------*/ /* function : os_get_pref_int */ /* description: Gets system preferences (integer) */ /*------------------------------------------------*/ bool os_get_pref_int(const char *name, int *i) { *i = 0; return false; }