static void clear_socket (int which, int dofree) { if (dofree) { set_read_callback(which, 0); set_write_callback(which, 0); set_close_callback(which, 0); } lpc_socks[which].fd = -1; lpc_socks[which].flags = 0; lpc_socks[which].mode = MUD; lpc_socks[which].state = STATE_CLOSED; memset((char *) &lpc_socks[which].l_addr, 0, sizeof(lpc_socks[which].l_addr)); memset((char *) &lpc_socks[which].r_addr, 0, sizeof(lpc_socks[which].r_addr)); lpc_socks[which].owner_ob = NULL; lpc_socks[which].release_ob = NULL; lpc_socks[which].read_callback.s = 0; lpc_socks[which].write_callback.s = 0; lpc_socks[which].close_callback.s = 0; lpc_socks[which].r_buf = NULL; lpc_socks[which].r_off = 0; lpc_socks[which].r_len = 0; lpc_socks[which].w_buf = NULL; lpc_socks[which].w_off = 0; lpc_socks[which].w_len = 0; }
void f_thread() { int sv[2]; 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 debug() 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, sp-3); set_write_callback(fd, sp-2); set_close_callback(fd, sp-1); lpc_socks[fd].owner_ob = current_object; lpc_socks[fd].mode = MUD; 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; } close(sv[0]); function_to_call_t cb; memset(&cb, 0, sizeof(function_to_call_t)); process_efun_callback(0, &cb, F_THREAD); for(i=0; i<5; i++) if(external_port[i].port) close(external_port[i].fd); //close external ports for(i=0;i<sizeof(lpc_socks)/sizeof(lpc_socks[0]);i++) close(lpc_sock[i].fd); svalue_t *res = call_efun_callback(&cb, 1); switch (res->type) { case T_OBJECT: break; default: save_svalue_depth = 0; int len = svalue_save_size(message); if (save_svalue_depth > MAX_SAVE_SVALUE_DEPTH) { OS_socket_write(sv[1], "\x00\x00\x00\x11\"result too big\"", 21); break; } char *buf = (char *) DMALLOC(len + 5, TAG_TEMPORARY, "socket_write: default"); if (buf == NULL) break; *(INT_32 *) buf = htonl((long) len); len += 4; buf[4] = '\0'; p = buf + 4; save_svalue(message, &p); int ret,written = 0; while(written < len){ ret = OS_socket_write(sv[1], buf+written, len-written); if(ret < 0) break; written += ret; } break; } fflush(0); exit(0); }
/* * Create an LPC efun socket */ int socket_create (enum socket_mode mode, svalue_t * read_callback, svalue_t * close_callback) { int type, i, fd, optval; #ifndef NO_BUFFER_TYPE int binary = 0; if (mode == STREAM_BINARY) { binary = 1; mode = STREAM; } else if (mode == DATAGRAM_BINARY) { binary = 1; mode = DATAGRAM; } #endif switch (mode) { case MUD: case STREAM: type = SOCK_STREAM; break; case DATAGRAM: type = SOCK_DGRAM; break; default: return EEMODENOTSUPP; } i = find_new_socket(); if (i >= 0) { #ifdef IPV6 fd = socket(PF_INET6, type, 0); #else fd = socket(PF_INET, type, 0); #endif if (fd == INVALID_SOCKET) { socket_perror("socket_create: socket", 0); return EESOCKET; } optval = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof(optval)) == -1) { socket_perror("socket_create: setsockopt", 0); OS_socket_close(fd); return EESETSOCKOPT; } if (set_socket_nonblocking(fd, 1) == -1) { socket_perror("socket_create: set_socket_nonblocking", 0); OS_socket_close(fd); return EENONBLOCK; } lpc_socks[i].fd = fd; lpc_socks[i].flags = S_HEADER; if (type == SOCK_DGRAM) close_callback = 0; set_read_callback(i, read_callback); set_write_callback(i, 0); set_close_callback(i, close_callback); #ifndef NO_BUFFER_TYPE if (binary) { lpc_socks[i].flags |= S_BINARY; } #endif lpc_socks[i].mode = mode; lpc_socks[i].state = STATE_UNBOUND; memset((char *) &lpc_socks[i].l_addr, 0, sizeof(lpc_socks[i].l_addr)); memset((char *) &lpc_socks[i].r_addr, 0, sizeof(lpc_socks[i].r_addr)); lpc_socks[i].owner_ob = current_object; lpc_socks[i].release_ob = NULL; lpc_socks[i].r_buf = NULL; lpc_socks[i].r_off = 0; lpc_socks[i].r_len = 0; lpc_socks[i].w_buf = NULL; lpc_socks[i].w_off = 0; lpc_socks[i].w_len = 0; current_object->flags |= O_EFUN_SOCKET; debug(sockets, ("socket_create: created socket %d mode %d fd %d\n", i, mode, fd)); } return i; }
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; } }