mud/fluffos-2.23-ds03/packages/external.c
2020-09-06 05:43:07 -07:00

139 lines
3.0 KiB
C

#include "../lpc_incl.h"
#include "../file_incl.h"
#include "../network_incl.h"
#include "../socket_efuns.h"
#include "../include/socket_err.h"
#include "../main.h"
char *external_cmd[NUM_EXTERNAL_CMDS];
#ifdef F_EXTERNAL_START
int external_start (int which, svalue_t * args,
svalue_t * arg1, svalue_t * arg2, svalue_t * arg3) {
int sv[2];
char *cmd;
int fd;
char **argv;
pid_t ret;
if (--which < 0 || which > (NUM_EXTERNAL_CMDS-1) || !external_cmd[which])
error("Bad argument 1 to external_start()\n");
cmd = external_cmd[which];
fd = find_new_socket();
if (fd < 0) return fd;
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
return EESOCKET;
ret = fork();
if (ret == -1) {
error("fork() in external_start() failed: %s\n", strerror(errno));
}
if (ret) {
close(sv[1]);
lpc_socks[fd].fd = sv[0];
lpc_socks[fd].flags = S_EXTERNAL;
set_read_callback(fd, arg1);
set_write_callback(fd, arg2);
set_close_callback(fd, arg3);
lpc_socks[fd].owner_ob = current_object;
lpc_socks[fd].mode = STREAM;
lpc_socks[fd].state = STATE_DATA_XFER;
memset((char *) &lpc_socks[fd].l_addr, 0, sizeof(lpc_socks[fd].l_addr));
memset((char *) &lpc_socks[fd].r_addr, 0, sizeof(lpc_socks[fd].r_addr));
lpc_socks[fd].owner_ob = current_object;
lpc_socks[fd].release_ob = NULL;
lpc_socks[fd].r_buf = NULL;
lpc_socks[fd].r_off = 0;
lpc_socks[fd].r_len = 0;
lpc_socks[fd].w_buf = NULL;
lpc_socks[fd].w_off = 0;
lpc_socks[fd].w_len = 0;
current_object->flags |= O_EFUN_SOCKET;
return fd;
} else {
int flag = 1;
int i = 1;
int n = 1;
const char *p;
char *arg;
if (args->type == T_ARRAY) {
n = args->u.arr->size;
} else {
p = args->u.string;
while (*p) {
if (isspace(*p)) {
flag = 1;
} else {
if (flag) {
n++;
flag = 0;
}
}
p++;
}
}
argv = CALLOCATE(n, char *, TAG_TEMPORARY, "external args");
argv[0] = cmd;
/* need writable version */
if (args->type == T_ARRAY) {
int j;
svalue_t *sv = args->u.arr->item;
for (j = 0; j < n; j++) {
argv[i++] = alloc_cstring(sv[j].u.string, "external args");
}
} else {
flag = 1;
arg = alloc_cstring(args->u.string, "external args");
while (*arg) {
if (isspace(*arg)) {
*arg = 0;
flag = 1;
} else {
if (flag) {
argv[i++] = arg;
flag = 0;
}
}
arg++;
}
}
argv[i] = 0;
close(sv[0]);
for(i=0; i<5; i++)
if(external_port[i].port)
close(external_port[i].fd); //close external ports
dup2(sv[1], 0);
dup2(sv[1], 1);
dup2(sv[1], 2);
execv(cmd, argv);
exit(0);
return 0;
}
}
void f_external_start (void)
{
int fd, num_arg = st_num_arg;
svalue_t *arg = sp - num_arg + 1;
if (check_valid_socket("external", -1, current_object, "N/A", -1)) {
fd = external_start(arg[0].u.number, arg + 1,
arg + 2, arg + 3, (num_arg == 5 ? arg + 4 : 0));
pop_n_elems(num_arg - 1);
sp->u.number = fd;
} else {
pop_n_elems(num_arg - 1);
sp->u.number = EESECURITY;
}
}
#endif