/*
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;
}