static int init_listen_socket(const char *address, const char *port, int *fds) { int i; int gai_ret; struct addrinfo hints; struct addrinfo *rp=NULL; struct addrinfo *info=NULL; close_fds(fds); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family=AF_UNSPEC; hints.ai_socktype=SOCK_STREAM; hints.ai_protocol=IPPROTO_TCP; hints.ai_flags=AI_NUMERICHOST; hints.ai_flags|=AI_PASSIVE; if((gai_ret=getaddrinfo(address, port, &hints, &info))) { logp("unable to getaddrinfo on port %s: %s\n", port, gai_strerror(gai_ret)); return -1; } i=0; for(rp=info; rp && i<LISTEN_SOCKETS; rp=rp->ai_next) { fds[i]=socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if(fds[i]<0) { logp("unable to create socket on port %s: %s\n", port, strerror(errno)); continue; } set_keepalive(fds[i], 1); #ifdef HAVE_IPV6 if(rp->ai_family==AF_INET6) { // Attempt to say that it should not listen on IPv6 // only. int optval=0; setsockopt(fds[i], IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)); } #endif reuseaddr(fds[i]); if(bind(fds[i], rp->ai_addr, rp->ai_addrlen)) { logp("unable to bind socket on port %s: %s\n", port, strerror(errno)); close(fds[i]); fds[i]=-1; continue; } // Say that we are happy to accept connections. if(listen(fds[i], 5)<0) { close_fd(&(fds[i])); logp("could not listen on main socket %s\n", port); return -1; } #ifdef HAVE_WIN32 { u_long ioctlArg=0; ioctlsocket(fds[i], FIONBIO, &ioctlArg); } #endif i++; } freeaddrinfo(info); if(!i) { logp("could not listen on address: %s\n", address); #ifdef HAVE_IPV6 if(strchr(address, ':')) logp("maybe check whether your OS has IPv6 enabled.\n"); #endif return -1; } return 0; }
/* * Display the contents of a uio structure on a terminal. Used by wall(1), * syslogd(8), and talkd(8). Forks and finishes in child if write would block, * waiting up to tmout seconds. Returns pointer to error string on unexpected * error; string is not newline-terminated. Various "normal" errors are * ignored (exclusive-use, lack of permission, etc.). */ char * ttymsg(struct iovec *iov, size_t iovcnt, char *line, int tmout) { static char device[MAXNAMLEN]; static char errbuf[ERR_BUFLEN]; size_t cnt, left; ssize_t wret; struct iovec localiov[6]; int fd, forked = 0; ssize_t len = 0; if (iovcnt > ARRAY_SIZE(localiov)) { snprintf(errbuf, sizeof(errbuf), _("internal error: too many iov's")); return errbuf; } /* The old code here rejected the line argument when it contained a '/', saying: "A slash may be an attempt to break security...". However, if a user can control the line argument here then he can make this routine write to /dev/hda or /dev/sda already. So, this test was worthless, and these days it is also wrong since people use /dev/pts/xxx. */ len = snprintf(device, sizeof(device), "%s%s", _PATH_DEV, line); if (len < 0 || (size_t)len >= sizeof(device)) { snprintf(errbuf, sizeof(errbuf), _("excessively long line arg")); return errbuf; } /* * open will fail on slip lines or exclusive-use lines * if not running as root; not an error. */ if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) { if (errno == EBUSY || errno == EACCES) return NULL; len = snprintf(errbuf, sizeof(errbuf), "%s: %m", device); if (len < 0 || (size_t)len >= sizeof(errbuf)) snprintf(errbuf, sizeof(errbuf), _("open failed")); return errbuf; } for (cnt = left = 0; cnt < iovcnt; ++cnt) left += iov[cnt].iov_len; for (;;) { wret = writev(fd, iov, iovcnt); if (wret >= (ssize_t) left) break; if (wret >= 0) { left -= wret; if (iov != localiov) { memmove(localiov, iov, iovcnt * sizeof(struct iovec)); iov = localiov; } for (cnt = 0; wret >= (ssize_t) iov->iov_len; ++cnt) { wret -= iov->iov_len; ++iov; --iovcnt; } if (wret) { iov->iov_base = (char *) iov->iov_base + wret; iov->iov_len -= wret; } continue; } if (errno == EWOULDBLOCK) { int cpid, flags; sigset_t sigmask; if (forked) { close(fd); _exit(EXIT_FAILURE); } cpid = fork(); if (cpid < 0) { len = snprintf(errbuf, sizeof(errbuf), _("fork: %m")); if (len < 0 || (size_t)len >= sizeof(errbuf)) snprintf(errbuf, sizeof(errbuf), _("cannot fork")); close(fd); return errbuf; } if (cpid) { /* parent */ close(fd); return NULL; } forked++; /* wait at most tmout seconds */ signal(SIGALRM, SIG_DFL); signal(SIGTERM, SIG_DFL); /* XXX */ sigemptyset(&sigmask); sigprocmask (SIG_SETMASK, &sigmask, NULL); alarm((u_int)tmout); flags = fcntl(fd, F_GETFL); fcntl(flags, F_SETFL, (long) (flags & ~O_NONBLOCK)); continue; } /* * We get ENODEV on a slip line if we're running as root, * and EIO if the line just went away. */ if (errno == ENODEV || errno == EIO) break; if (close_fd(fd) != 0) warn(_("write failed: %s"), device); if (forked) _exit(EXIT_FAILURE); len = snprintf(errbuf, sizeof(errbuf), "%s: %m", device); if (len < 0 || (size_t)len >= sizeof(errbuf)) snprintf(errbuf, sizeof(errbuf), _("%s: BAD ERROR, message is " "far too long"), device); return errbuf; } if (forked) _exit(EXIT_SUCCESS); return NULL; }
static int tmp_inout_popen(FILE **fr, FILE **fw, char *cmd) { char buf[NFILEN + 128]; DWORD dummy, len; int rc, term_status, tmpin_fd; TRACE(("tmp_inout_popen cmd=%s\n", cmd)); proc_handle = BAD_PROC_HANDLE; handles[0] = handles[1] = handles[2] = INVALID_HANDLE_VALUE; tmpin_fd = stdin_fd = stdout_fd = BAD_FD; tmpin_name = stdin_name = stdout_name = NULL; set_console_title(cmd); do { if (fr) { *fr = NULL; if ((stdin_name = _tempnam(getenv("TEMP"), "vile")) == NULL) break; if ((stdin_fd = open(stdin_name, O_RDWR|O_CREAT|O_TRUNC|O_TEXT, _S_IWRITE|_S_IREAD)) == BAD_FD) { break; } handles[2] = handles[1] = (HANDLE) _get_osfhandle(stdin_fd); if (! fw) { /* * This is a read pipe (only). Connect child's stdin to * an empty file. Under no circumstances should the * child's stdin be connected to a device (else lots of * screwy things will occur). In particular, connecting * the child's stdin to the parent's stdin will cause * aborts and hangs on the various Win32 hosts. You've * been warned. */ if ((tmpin_name = _tempnam(getenv("TEMP"), "vile")) == NULL) break; if ((tmpin_fd = open(tmpin_name, O_RDONLY|O_CREAT|O_TRUNC, _S_IWRITE|_S_IREAD)) == BAD_FD) { break; } handles[0] = (HANDLE) _get_osfhandle(tmpin_fd); } else { /* * Set up descriptor for filter operation. Note the * sublteties here: exec'd shell is passed a descriptor * to the temp file that's opened "w". The editor * receives a descriptor to the file that's opened "r". */ if ((*fr = fopen(stdin_name, "r")) == NULL) break; } } if (fw) { *fw = NULL; /* create a temp file to receive data from the editor */ if ((stdout_name = _tempnam(getenv("TEMP"), "vile")) == NULL) break; if ((stdout_fd = open(stdout_name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, _S_IWRITE|_S_IREAD)) == BAD_FD) { break; } if ((*fw = fdopen(stdout_fd, "w")) == 0) break; /* * we're all set up, but can't exec "cmd" until the editor * writes data to the temp file connected to stdout. */ shcmd = cmd; /* remember this */ return (TRUE); } /* This must be a read (only) pipe. Appropriate to exec "cmd". */ rc = (exec_shell(cmd, handles, TRUE /* hide child wdw */ ) == BAD_PROC_HANDLE) ? FALSE : TRUE; if (! rc) { /* * Shell process failed, put complaint in user's buffer, which * is currently proxied by a temp file that the editor will * suck in shortly. */ len = (DWORD) (lsprintf(buf, SHELL_ERR_MSG, get_shell()) - buf); (void) WriteFile(handles[1], buf, len, &dummy, NULL); FlushFileBuffers(handles[1]); } else { /* wait for exec'd process to exit */ (void) cwait(&term_status, (CWAIT_PARAM_TYPE) proc_handle, 0); TRACE(("...CreateProcess finished waiting in tmp_inout_popen\n")); close_proc_handle(); } /* * When closing descriptors shared between parent and child, order * is quite important when $shell == command.com . In this * situation, the descriptors can't be closed until the exec'd * process exits (I kid you not). */ close_fd(stdin_fd); (void) close(tmpin_fd); /* let the editor consume the output of the read pipe */ if ((*fr = fopen(stdin_name, "r")) == NULL) { /* * impossible to put error in user's buffer since that file * descriptor is closed. */ sprintf(buf, "[error opening temp file \"%s\": %s]", stdin_name, strerror(errno)); lastditch_msg(buf); break; } return (rc); } while (FALSE); /* If we get here -- some operation has failed. Clean up. */ tmp_cleanup(); return (FALSE); }
int recv_message(const char * host_name, char * message, size_t message_size) { int rv; struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; struct addrinfo * servinfo; const char * port = "3490"; rv = getaddrinfo(host_name, port, &hints, &servinfo); if (rv != 0) { fputs("getaddrinfo: ", stderr); fputs(gai_strerror(rv) ,stderr); fputc('\n', stderr); return EXIT_FAILURE; } // loop through all the results and connect to the first we can int sock_fd; struct addrinfo * p; for (p = servinfo; p; p = p->ai_next) { sock_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sock_fd == -1) { perror("socket"); continue; } rv = connect(sock_fd, p->ai_addr, p->ai_addrlen); if (rv == -1) { perror("connect"); close_fd(sock_fd); continue; } break; } if (!p) { fputs("client: failed to connect\n", stderr); close_fd(sock_fd); return EXIT_FAILURE; } char address[INET6_ADDRSTRLEN]; const char * dst = inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), address, sizeof address); if (dst == NULL) { perror("inet_ntop"); close_fd(sock_fd); return EXIT_FAILURE; } freeaddrinfo(servinfo); // all done with this structure fputs("client: connecting to ", stdout); fputs(address, stdout); fputc('\n', stdout); const int num_bytes = recv(sock_fd, message, message_size - 1, 0); if (num_bytes == -1) { perror("recv"); close_fd(sock_fd); return EXIT_FAILURE; } message[num_bytes] = '\0'; close_fd(sock_fd); return 0; }
/*===========================================================================* * do_vm_call * *===========================================================================*/ int do_vm_call(message *m_out) { /* A call that VM does to VFS. * We must reply with the fixed type VM_VFS_REPLY (and put our result info * in the rest of the message) so VM can tell the difference between a * request from VFS and a reply to this call. */ int req = job_m_in.VFS_VMCALL_REQ; int req_fd = job_m_in.VFS_VMCALL_FD; u32_t req_id = job_m_in.VFS_VMCALL_REQID; endpoint_t ep = job_m_in.VFS_VMCALL_ENDPOINT; u64_t offset = make64(job_m_in.VFS_VMCALL_OFFSET_LO, job_m_in.VFS_VMCALL_OFFSET_HI); u32_t length = job_m_in.VFS_VMCALL_LENGTH; int result = OK; int slot; struct fproc *rfp, *vmf; struct filp *f = NULL; int r; if(job_m_in.m_source != VM_PROC_NR) return ENOSYS; if(isokendpt(ep, &slot) != OK) rfp = NULL; else rfp = &fproc[slot]; vmf = &fproc[VM_PROC_NR]; assert(fp == vmf); assert(rfp != vmf); switch(req) { case VMVFSREQ_FDLOOKUP: { int procfd; /* Lookup fd in referenced process. */ if(!rfp) { printf("VFS: why isn't ep %d here?!\n", ep); result = ESRCH; goto reqdone; } if((result = dupvm(rfp, req_fd, &procfd, &f)) != OK) { printf("vfs: dupvm failed\n"); goto reqdone; } if(S_ISBLK(f->filp_vno->v_mode)) { assert(f->filp_vno->v_sdev != NO_DEV); m_out->VMV_DEV = f->filp_vno->v_sdev; m_out->VMV_INO = VMC_NO_INODE; m_out->VMV_SIZE_PAGES = LONG_MAX; } else { m_out->VMV_DEV = f->filp_vno->v_dev; m_out->VMV_INO = f->filp_vno->v_inode_nr; m_out->VMV_SIZE_PAGES = roundup(f->filp_vno->v_size, PAGE_SIZE)/PAGE_SIZE; } m_out->VMV_FD = procfd; result = OK; break; } case VMVFSREQ_FDCLOSE: { result = close_fd(fp, req_fd); if(result != OK) { printf("VFS: VM fd close for fd %d, %d (%d)\n", req_fd, fp->fp_endpoint, result); } break; } case VMVFSREQ_FDIO: { message dummy_out; result = actual_llseek(fp, &dummy_out, req_fd, SEEK_SET, offset); if(result == OK) { result = actual_read_write_peek(fp, PEEKING, req_fd, NULL, length); } break; } default: panic("VFS: bad request code from VM\n"); break; } reqdone: if(f) unlock_filp(f); /* fp is VM still. */ assert(fp == vmf); m_out->VMV_ENDPOINT = ep; m_out->VMV_RESULT = result; m_out->VMV_REQID = req_id; /* reply asynchronously as VM may not be able to receive * a sendnb() message */ m_out->m_type = VM_VFS_REPLY; r = asynsend3(VM_PROC_NR, m_out, 0); if(r != OK) printf("VFS: couldn't asynsend3() to VM\n"); /* VFS does not reply any further */ return SUSPEND; }
int champ_chooser_server(struct sdirs *sdirs, struct conf **confs, int resume) { int s; int ret=-1; int len; struct asfd *asfd=NULL; struct sockaddr_un local; struct lock *lock=NULL; struct async *as=NULL; int started=0; struct scores *scores=NULL; const char *directory=get_string(confs[OPT_DIRECTORY]); if(!(lock=lock_alloc_and_init(sdirs->champlock)) || build_path_w(sdirs->champlock)) goto end; lock_get(lock); switch(lock->status) { case GET_LOCK_GOT: log_fzp_set(sdirs->champlog, confs); logp("Got champ lock for dedup_group: %s\n", get_string(confs[OPT_DEDUP_GROUP])); break; case GET_LOCK_NOT_GOT: case GET_LOCK_ERROR: default: //logp("Did not get champ lock\n"); goto end; } if((s=socket(AF_UNIX, SOCK_STREAM, 0))<0) { logp("socket error in %s: %s\n", __func__, strerror(errno)); goto end; } memset(&local, 0, sizeof(struct sockaddr_un)); local.sun_family=AF_UNIX; snprintf(local.sun_path, sizeof(local.sun_path), "%s", sdirs->champsock); len=strlen(local.sun_path)+sizeof(local.sun_family)+1; unlink(sdirs->champsock); if(bind(s, (struct sockaddr *)&local, len)<0) { logp("bind error in %s: %s\n", __func__, strerror(errno)); goto end; } if(listen(s, 5)<0) { logp("listen error in %s: %s\n", __func__, strerror(errno)); goto end; } if(!(as=async_alloc()) || as->init(as, 0) || !(asfd=setup_asfd(as, "champ chooser main socket", &s, /*listen*/""))) goto end; asfd->fdtype=ASFD_FD_SERVER_LISTEN_MAIN; // I think that this is probably the best point at which to run a // cleanup job to delete unused data files, because no other process // can fiddle with the dedup_group at this point. // Cannot do it on a resume, or it will delete files that are // referenced in the backup we are resuming. if(delete_unused_data_files(sdirs, resume)) goto end; // Load the sparse indexes for this dedup group. if(!(scores=champ_chooser_init(sdirs->data))) goto end; while(1) { for(asfd=as->asfd->next; asfd; asfd=asfd->next) { if(!asfd->blist->head || asfd->blist->head->got==BLK_INCOMING) continue; if(results_to_fd(asfd)) goto end; } int removed; switch(as->read_write(as)) { case 0: // Check the main socket last, as it might add // a new client to the list. for(asfd=as->asfd->next; asfd; asfd=asfd->next) { while(asfd->rbuf->buf) { if(deal_with_client_rbuf(asfd, directory, scores)) goto end; // Get as much out of the // readbuf as possible. if(asfd->parse_readbuf(asfd)) goto end; } } if(as->asfd->new_client) { // Incoming client. as->asfd->new_client=0; if(champ_chooser_new_client(as, confs)) goto end; started=1; } break; default: removed=0; // Maybe one of the fds had a problem. // Find and remove it and carry on if possible. for(asfd=as->asfd->next; asfd; ) { struct asfd *a; if(!asfd->want_to_remove) { asfd=asfd->next; continue; } as->asfd_remove(as, asfd); logp("%s: disconnected fd %d\n", asfd->desc, asfd->fd); a=asfd->next; asfd_free(&asfd); asfd=a; removed++; } if(removed) break; // If we got here, there was no fd to remove. // It is a fatal error. goto end; } if(started && !as->asfd->next) { logp("All clients disconnected.\n"); ret=0; break; } } end: logp("champ chooser exiting: %d\n", ret); champ_chooser_free(&scores); log_fzp_set(NULL, confs); async_free(&as); asfd_free(&asfd); // This closes s for us. close_fd(&s); unlink(sdirs->champsock); // FIX THIS: free asfds. lock_release(lock); lock_free(&lock); return ret; }
void *workerFn(void *param) { while (1) { struct epoll_event events[EVENT_LEN]; int n = epoll_wait(epollfd, events, EVENT_LEN, 10000); if (n < 0) { if (errno == EINTR) { continue; } perror("epoll_wait error"); exit(1); } int i; int reenable = 1; for (i = 0; i < n; ++i) { if (events[i].data.fd == listenfd) { int fd = accept(listenfd, NULL, NULL); if (fd > 0) { add_new_fd(fd); } else { perror("accept error"); exit(1); } } else { char buf[1024]; while (1) { ssize_t n = recv(events[i].data.fd, buf, sizeof(buf), MSG_DONTWAIT); if (n == 0) { reenable = 0; close_fd(events[i].data.fd); break; } else if (n < 0) { if (errno == EINTR) { continue; } else if (errno == EAGAIN) { break; } else { reenable = 0; close_fd(events[i].data.fd); break; } } else { __sync_fetch_and_add(&packets, 1); int pos = 0; while (pos < n) { int sent = send(events[i].data.fd, buf+pos, n-pos, 0); if (sent <= 0) { break; } pos += sent; } if (pos < n) { reenable = 0; close_fd(events[i].data.fd); } } if (n < sizeof(buf)) { break; } } } if (reenable) { reenable_fd(events[i].data.fd); } } } }
void fdclose(struct fd_table *fdt, int fd) { close_fd(fdt, fd); }
/* * accepts new connections */ void MakeNewConnections(void) { fd_mask readyconnections; int curconn; int newconn; long connect_time; int i; ClientPtr client; OsCommPtr oc; fd_set tmask; XFD_ANDSET (&tmask, &LastSelectMask, &WellKnownConnections); readyconnections = tmask.fds_bits[0]; if (!readyconnections) return; connect_time = GetTimeInMillis(); /* kill off stragglers */ for (i = MINCLIENT; i < currentMaxClients; i++) { if ((client = clients[i]) != NullClient) { oc = (OsCommPtr) client->osPrivate; if ((oc && (oc->conn_time != 0) && (connect_time - oc->conn_time) >= TimeOutValue) || ((client->noClientException != FSSuccess) && (client->clientGone != CLIENT_GONE))) CloseDownClient(client); } } while (readyconnections) { XtransConnInfo trans_conn, new_trans_conn; int status; curconn = ffs(readyconnections) - 1; readyconnections &= ~(1 << curconn); if ((trans_conn = lookup_trans_conn (curconn)) == NULL) continue; if ((new_trans_conn = _FontTransAccept (trans_conn, &status)) == NULL) continue; newconn = _FontTransGetConnectionNumber (new_trans_conn); _FontTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); oc = (OsCommPtr) fsalloc(sizeof(OsCommRec)); if (!oc) { fsfree(oc); error_conn_max(new_trans_conn); _FontTransClose(new_trans_conn); continue; } FD_SET(newconn, &AllClients); FD_SET(newconn, &AllSockets); oc->fd = newconn; oc->trans_conn = new_trans_conn; oc->input = (ConnectionInputPtr) NULL; oc->output = (ConnectionOutputPtr) NULL; oc->conn_time = connect_time; if ((newconn < lastfdesc) && (client = NextAvailableClient((pointer) oc))) { ConnectionTranslation[newconn] = client->index; } else { error_conn_max(new_trans_conn); close_fd(oc); } } }
/* May return 1 to mean try again. This happens after a successful certificate signing request so that it connects again straight away with the new key/certificate. Returns 2 if there were restore/verify warnings. Returns 3 if timer conditions were not met. */ static int do_client(struct config *conf, enum action act, int vss_restore, int json) { int ret=0; int rfd=-1; int resume=0; SSL *ssl=NULL; BIO *sbio=NULL; char buf[256]=""; SSL_CTX *ctx=NULL; struct cntr cntr; struct cntr p1cntr; char *incexc=NULL; char *server_version=NULL; const char *phase1str="backupphase1"; reset_filecounter(&p1cntr, time(NULL)); reset_filecounter(&cntr, time(NULL)); setup_signals_client(); // settimers(0, 100); logp("begin client\n"); if(act!=ACTION_ESTIMATE) { ssl_load_globals(); if(!(ctx=ssl_initialise_ctx(conf))) { logp("error initialising ssl ctx\n"); ret=-1; goto end; } SSL_CTX_set_session_id_context(ctx, (const unsigned char *)&s_server_session_id_context, sizeof(s_server_session_id_context)); if((rfd=init_client_socket(conf->server, conf->port))<0) { ret=-1; goto end; } if(!(ssl=SSL_new(ctx)) || !(sbio=BIO_new_socket(rfd, BIO_NOCLOSE))) { ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); logp("Problem joining SSL to the socket: %s\n", buf); ret=-1; goto end; } SSL_set_bio(ssl, sbio, sbio); if(SSL_connect(ssl)<=0) { ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); logp("SSL connect error: %s\n", buf); ret=-1; goto end; } } if((ret=async_init(rfd, ssl, conf, act==ACTION_ESTIMATE))) goto end; // Set quality of service bits on backup packets. if(act==ACTION_BACKUP || act==ACTION_BACKUP_TIMED) set_bulk_packets(); if(act!=ACTION_ESTIMATE) { char cmd=0; size_t len=0; char *feat=NULL; int ca_ret=0; if((ret=authorise_client(conf, &server_version, &p1cntr))) goto end; if(server_version) { logp("Server version: %s\n", server_version); // Servers before 1.3.2 did not tell us their versions. // 1.3.2 and above can do the automatic CA stuff that // follows. if((ca_ret=ca_client_setup(conf, &p1cntr))<0) { // Error logp("Error with certificate signing request\n"); ret=-1; goto end; } else if(ca_ret>0) { // Certificate signed successfully. // Everything is OK, but we will reconnect now, in // order to use the new keys/certificates. ret=1; goto end; } } set_non_blocking(rfd); if((ret=ssl_check_cert(ssl, conf))) { logp("check cert failed\n"); goto end; } if((ret=async_write_str(CMD_GEN, "extra_comms_begin"))) { logp("Problem requesting extra_comms_begin\n"); goto end; } // Servers greater than 1.3.0 will list the extra_comms // features they support. else if((ret=async_read(&cmd, &feat, &len))) { logp("Problem reading response to extra_comms_begin\n"); goto end; } else if(cmd!=CMD_GEN) { logp("Unexpected command from server when reading response to extra_comms_begin: %c:%s\n", cmd, feat); ret=-1; goto end; } else if(strncmp(feat, "extra_comms_begin ok", strlen("extra_comms_begin ok"))) { logp("Unexpected response from server when reading response to extra_comms_begin: %c:%s\n", cmd, feat); ret=-1; goto end; } // Can add extra bits here. The first extra bit is the // autoupgrade stuff. if(server_supports_autoupgrade(feat)) { if(conf->autoupgrade_dir && conf->autoupgrade_os && (ret=autoupgrade_client(conf, &p1cntr))) goto end; } // :srestore: means that the server wants to do a restore. if(server_supports(feat, ":srestore:")) { if(conf->server_can_restore) { logp("Server is initiating a restore\n"); if(incexc) { free(incexc); incexc=NULL; } if((ret=incexc_recv_client_restore(&incexc, conf, &p1cntr))) goto end; if(incexc) { if((ret=parse_incexcs_buf(conf, incexc))) goto end; act=ACTION_RESTORE; log_restore_settings(conf, 1); } } else { logp("Server wants to initiate a restore\n"); logp("Client configuration says no\n"); if(async_write_str(CMD_GEN, "srestore not ok")) { ret=-1; goto end; } } } if(conf->orig_client) { char str[512]=""; snprintf(str, sizeof(str), "orig_client=%s", conf->orig_client); if(!server_supports(feat, ":orig_client:")) { logp("Server does not support switching client.\n"); ret=-1; goto end; } if((ret=async_write_str(CMD_GEN, str)) || (ret=async_read_expect(CMD_GEN, "orig_client ok"))) { logp("Problem requesting %s\n", str); ret=-1; goto end; } logp("Switched to client %s\n", conf->orig_client); } // :sincexc: is for the server giving the client the // incexc config. if(act==ACTION_BACKUP || act==ACTION_BACKUP_TIMED) { if(!incexc && server_supports(feat, ":sincexc:")) { logp("Server is setting includes/excludes.\n"); if(incexc) { free(incexc); incexc=NULL; } if((ret=incexc_recv_client(&incexc, conf, &p1cntr))) goto end; if(incexc && (ret=parse_incexcs_buf(conf, incexc))) goto end; } } if(server_supports(feat, ":counters:")) { if(async_write_str(CMD_GEN, "countersok")) goto end; conf->send_client_counters=1; } // :incexc: is for the client sending the server the // incexc config so that it better knows what to do on // resume. if(server_supports(feat, ":incexc:") && (ret=incexc_send_client(conf, &p1cntr))) goto end; if((ret=async_write_str(CMD_GEN, "extra_comms_end")) || (ret=async_read_expect(CMD_GEN, "extra_comms_end ok"))) { logp("Problem requesting extra_comms_end\n"); goto end; } if(feat) free(feat); } rfd=-1; switch(act) { case ACTION_BACKUP_TIMED: phase1str="backupphase1timed"; case ACTION_BACKUP: { // Set bulk packets quality of service flags on backup. if(incexc) { logp("Server is overriding the configuration\n"); logp("with the following settings:\n"); if(log_incexcs_buf(incexc)) { ret=-1; goto end; } } if(!conf->sdcount) { logp("Found no include paths!\n"); ret=-1; goto end; } if(!(ret=maybe_check_timer(phase1str, conf, &resume))) { if(conf->backup_script_pre) { int a=0; const char *args[12]; args[a++]=conf->backup_script_pre; args[a++]="pre"; args[a++]="reserved2"; args[a++]="reserved3"; args[a++]="reserved4"; args[a++]="reserved5"; args[a++]=NULL; if(run_script(args, conf->backup_script_pre_arg, conf->bprecount, &p1cntr, 1, 1)) ret=-1; } if(!ret && do_backup_client(conf, resume, 0, &p1cntr, &cntr)) ret=-1; if((conf->backup_script_post_run_on_fail || !ret) && conf->backup_script_post) { int a=0; const char *args[12]; args[a++]=conf->backup_script_post; args[a++]="post"; // Tell post script whether the restore // failed. args[a++]=ret?"1":"0"; args[a++]="reserved3"; args[a++]="reserved4"; args[a++]="reserved5"; args[a++]=NULL; if(run_script(args, conf->backup_script_post_arg, conf->bpostcount, &cntr, 1, 1)) ret=-1; } } if(ret<0) logp("error in backup\n"); else if(ret>0) { // Timer script said no. // Have a distinct return value to // differentiate between other cases // (ssl reconnection and restore/verify // warnings). ret=3; } else logp("backup finished ok\n"); break; } case ACTION_RESTORE: case ACTION_VERIFY: { if(conf->restore_script_pre) { int a=0; const char *args[12]; args[a++]=conf->restore_script_pre; args[a++]="pre"; args[a++]="reserved2"; args[a++]="reserved3"; args[a++]="reserved4"; args[a++]="reserved5"; args[a++]=NULL; if(run_script(args, conf->restore_script_pre_arg, conf->rprecount, &cntr, 1, 1)) ret=-1; } if(!ret && do_restore_client(conf, act, vss_restore, &p1cntr, &cntr)) ret=-1; if((conf->restore_script_post_run_on_fail || !ret) && conf->restore_script_post) { int a=0; const char *args[12]; args[a++]=conf->restore_script_pre; args[a++]="post"; // Tell post script whether the restore // failed. args[a++]=ret?"1":"0"; args[a++]="reserved3"; args[a++]="reserved4"; args[a++]="reserved5"; args[a++]=NULL; if(run_script(args, conf->restore_script_post_arg, conf->rpostcount, &cntr, 1, 1)) ret=-1; } // Return non-zero if there were warnings, // so that the test script can easily check. if(p1cntr.warning+cntr.warning) ret=2; break; } case ACTION_ESTIMATE: if(!ret) ret=do_backup_client(conf, 0, 1, &p1cntr, &cntr); break; case ACTION_DELETE: if(!ret) ret=do_delete_client(conf); break; case ACTION_LIST: case ACTION_LONG_LIST: default: ret=do_list_client(conf, act, json); break; } end: close_fd(&rfd); async_free(); if(act!=ACTION_ESTIMATE) ssl_destroy_ctx(ctx); if(incexc) free(incexc); if(server_version) free(server_version); //logp("end client\n"); return ret; }
gboolean egg_spawn_sync_with_callbacks (const gchar *working_directory, gchar **argv, gchar **envp, GSpawnFlags flags, GPid *child_pid, EggSpawnCallbacks *cbs, gpointer user_data, gint *exit_status, GError **error) { gint in_fd, out_fd, err_fd, max_fd; fd_set read_fds, write_fds; gboolean failed = FALSE; gint status; GPid pid; gint ret; g_return_val_if_fail (argv != NULL, FALSE); g_return_val_if_fail ((cbs && cbs->standard_input == NULL) || !(flags & G_SPAWN_CHILD_INHERITS_STDIN), 0); g_return_val_if_fail ((cbs && cbs->standard_output == NULL) || !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), 0); g_return_val_if_fail ((cbs && cbs->standard_error == NULL) || !(flags & G_SPAWN_STDERR_TO_DEV_NULL), 0); in_fd = out_fd = err_fd = -1; if (exit_status) flags |= G_SPAWN_DO_NOT_REAP_CHILD; if (!g_spawn_async_with_pipes (working_directory, argv, envp, flags, cbs ? cbs->child_setup : NULL, user_data, &pid, cbs && cbs->standard_input ? &in_fd : NULL, cbs && cbs->standard_output ? &out_fd : NULL, cbs && cbs->standard_error ? &err_fd : NULL, error)) return FALSE; if (child_pid) *child_pid = pid; max_fd = MAX (in_fd, MAX (out_fd, err_fd)) + 1; while (in_fd >= 0 || out_fd >= 0 || err_fd >= 0) { FD_ZERO (&write_fds); if (in_fd >= 0) FD_SET (in_fd, &write_fds); FD_ZERO (&read_fds); if (out_fd >= 0) FD_SET (out_fd, &read_fds); if (err_fd >= 0) FD_SET (err_fd, &read_fds); ret = select (max_fd, &read_fds, &write_fds, NULL, NULL); if (ret < 0 && errno != EINTR) { failed = TRUE; g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ, _("Unexpected error in select() reading data from a child process (%s)"), g_strerror (errno)); break; } if (in_fd >= 0 && FD_ISSET (in_fd, &write_fds)) { g_assert (cbs && cbs->standard_input); if (!(cbs->standard_input) (in_fd, user_data)) close_fd (&in_fd); } if (out_fd >= 0 && FD_ISSET (out_fd, &read_fds)) { g_assert (cbs && cbs->standard_output); if (!(cbs->standard_output) (out_fd, user_data)) close_fd (&out_fd); } if (err_fd >= 0 && FD_ISSET (err_fd, &read_fds)) { g_assert (cbs && cbs->standard_error); if (!(cbs->standard_error) (err_fd, user_data)) close_fd (&err_fd); } } if (in_fd >= 0) close_fd (&in_fd); if (out_fd >= 0) close_fd (&out_fd); if (err_fd >= 0) close_fd (&err_fd); if (!failed) { if (cbs && cbs->completed) (cbs->completed) (user_data); } again: ret = waitpid (pid, &status, 0); if (ret < 0) { if (errno == EINTR) goto again; else if (errno == ECHILD) { if (exit_status) g_warning ("In call to g_spawn_sync(), exit status of a child process was requested but SIGCHLD action was set to SIG_IGN and ECHILD was received by waitpid(), so exit status can't be returned. This is a bug in the program calling g_spawn_sync(); either don't request the exit status, or don't set the SIGCHLD action."); else ; /* We don't need the exit status. */ } else if (!failed) { /* avoid error pileups */ failed = TRUE; g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ, _("Unexpected error in waitpid() (%s)"), g_strerror (errno)); } } else { if (exit_status) *exit_status = status; } if (!child_pid) g_spawn_close_pid (pid); if (cbs && cbs->finalize_func) (cbs->finalize_func) (user_data); return !failed; }
/** * _gcr_gnupg_process_run_async: * @self: The process * @argv: (array zero-terminated=1): The arguments for the process, not including executable, terminated with %NULL. * @envp: (allow-none) (array zero-terminated=1): The environment for new process, terminated with %NULL. * @flags: Flags for starting the process. * @cancellable: (allow-none): Cancellation object * @callback: Will be called when operation completes. * @user_data: (closure): Data passed to callback. * * Run the gpg process. Only one 'run' operation can run per GcrGnupgProcess * object. The GcrGnupgProcess:output_data and GcrGnupgProcess:error_line * signals will be emitted when data is received from the gpg process. * * Unless the %GCR_GNUPG_PROCESS_RESPECT_LOCALE flag is specified, the process * will be run in the 'C' locale. If the %GCR_GNUPG_PROCESS_WITH_STATUS or * %GCR_GNUPG_PROCESS_WITH_ATTRIBUTES flags are set, then the gpg process * will be status and attribute output respectively. The * GcrGnupgProcess:status_record and GcrGnupgProcess:attribute_data signals * will provide this data. */ void _gcr_gnupg_process_run_async (GcrGnupgProcess *self, const gchar **argv, const gchar **envp, GcrGnupgProcessFlags flags, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GError *error = NULL; GPtrArray *args; GPtrArray *envs; int child_fds[NUM_FDS]; int status_fds[2] = { -1, -1 }; int attribute_fds[2] = { -1, -1 }; int output_fd = -1; int error_fd = -1; int input_fd = -1; GnupgSource *gnupg_source; GSource *source; GPid pid; guint i; g_return_if_fail (GCR_IS_GNUPG_PROCESS (self)); g_return_if_fail (argv); g_return_if_fail (callback); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_return_if_fail (self->pv->running == FALSE); g_return_if_fail (self->pv->complete == FALSE); g_return_if_fail (self->pv->executable); self->pv->async_callback = callback; self->pv->user_data = user_data; for (i = 0; i < NUM_FDS; i++) child_fds[i] = -1; /* The command needs to be updated with these status and attribute fds */ args = g_ptr_array_new_with_free_func (g_free); g_ptr_array_add (args, g_strdup (self->pv->executable)); /* Spawn/child will close all other attributes, besides thesthose in child_fds */ child_fds[FD_INPUT] = 0; child_fds[FD_OUTPUT] = 1; child_fds[FD_ERROR] = 2; if (flags & GCR_GNUPG_PROCESS_WITH_STATUS) { if (pipe (status_fds) < 0) g_return_if_reached (); child_fds[FD_STATUS] = status_fds[1]; g_ptr_array_add (args, g_strdup ("--status-fd")); g_ptr_array_add (args, g_strdup_printf ("%d", child_fds[FD_STATUS])); } if (flags & GCR_GNUPG_PROCESS_WITH_ATTRIBUTES) { if (pipe (attribute_fds) < 0) g_return_if_reached (); child_fds[FD_ATTRIBUTE] = attribute_fds[1]; g_ptr_array_add (args, g_strdup ("--attribute-fd")); g_ptr_array_add (args, g_strdup_printf ("%d", child_fds[FD_ATTRIBUTE])); } if (self->pv->directory) { g_ptr_array_add (args, g_strdup ("--homedir")); g_ptr_array_add (args, g_strdup (self->pv->directory)); } /* All the remaining arguments */ for (i = 0; argv[i] != NULL; i++) g_ptr_array_add (args, g_strdup (argv[i])); g_ptr_array_add (args, NULL); envs = g_ptr_array_new (); for (i = 0; envp && envp[i] != NULL; i++) { if (flags & GCR_GNUPG_PROCESS_RESPECT_LOCALE || !g_str_has_prefix (envp[i], "LOCALE=")) g_ptr_array_add (envs, (gpointer)envp[i]); } if (!(flags & GCR_GNUPG_PROCESS_RESPECT_LOCALE)) g_ptr_array_add (envs, (gpointer)"LOCALE=C"); g_ptr_array_add (envs, NULL); gchar *command = g_strjoinv (" ", (gchar**)args->pdata); gchar *environ = g_strjoinv (", ", (gchar**)envs->pdata); g_debug ("running command: %s", command); g_debug ("process environment: %s", environ); g_free (command); g_free (environ); g_spawn_async_with_pipes (self->pv->directory, (gchar**)args->pdata, (gchar**)envs->pdata, G_SPAWN_DO_NOT_REAP_CHILD, on_gnupg_process_child_setup, child_fds, &pid, &input_fd, &output_fd, &error_fd, &error); g_ptr_array_free (args, TRUE); g_ptr_array_free (envs, TRUE); /* Close 'wrong' ends of extra file descriptors */ close_fd (&(status_fds[1])); close_fd (&(attribute_fds[1])); self->pv->complete = FALSE; self->pv->running = TRUE; if (error) { close_fd (&(status_fds[0])); close_fd (&(attribute_fds[0])); g_assert (!self->pv->error); self->pv->error = error; complete_run_process (self); run_async_ready_callback_later (self); return; } g_debug ("process started: %d", (int)pid); source = g_source_new (&gnupg_source_funcs, sizeof (GnupgSource)); /* Initialize the source */ gnupg_source = (GnupgSource*)source; for (i = 0; i < NUM_FDS; i++) gnupg_source->polls[i].fd = -1; gnupg_source->error_buf = g_string_sized_new (128); gnupg_source->status_buf = g_string_sized_new (128); gnupg_source->process = g_object_ref (self); gnupg_source->child_pid = pid; gnupg_source->polls[FD_INPUT].fd = input_fd; if (input_fd >= 0) { gnupg_source->polls[FD_INPUT].events = G_IO_HUP | G_IO_OUT; g_source_add_poll (source, &gnupg_source->polls[FD_INPUT]); } gnupg_source->polls[FD_OUTPUT].fd = output_fd; if (output_fd >= 0) { gnupg_source->polls[FD_OUTPUT].events = G_IO_HUP | G_IO_IN; g_source_add_poll (source, &gnupg_source->polls[FD_OUTPUT]); } gnupg_source->polls[FD_ERROR].fd = error_fd; if (error_fd >= 0) { gnupg_source->polls[FD_ERROR].events = G_IO_HUP | G_IO_IN; g_source_add_poll (source, &gnupg_source->polls[FD_ERROR]); } gnupg_source->polls[FD_STATUS].fd = status_fds[0]; if (status_fds[0] >= 0) { gnupg_source->polls[FD_STATUS].events = G_IO_HUP | G_IO_IN; g_source_add_poll (source, &gnupg_source->polls[FD_STATUS]); } gnupg_source->polls[FD_ATTRIBUTE].fd = attribute_fds[0]; if (attribute_fds[0] >= 0) { gnupg_source->polls[FD_ATTRIBUTE].events = G_IO_HUP | G_IO_IN; g_source_add_poll (source, &gnupg_source->polls[FD_ATTRIBUTE]); } if (cancellable) { gnupg_source->cancellable = g_object_ref (cancellable); gnupg_source->cancel_sig = g_cancellable_connect (cancellable, G_CALLBACK (on_cancellable_cancelled), g_source_ref (source), (GDestroyNotify)g_source_unref); } g_assert (self->pv->source_sig == 0); g_source_set_callback (source, unused_callback, NULL, NULL); self->pv->source_sig = g_source_attach (source, g_main_context_default ()); /* This assumes the outstanding reference to source */ g_assert (gnupg_source->child_sig == 0); gnupg_source->child_sig = g_child_watch_add_full (G_PRIORITY_DEFAULT, pid, on_gnupg_process_child_exited, g_source_ref (source), (GDestroyNotify)g_source_unref); /* source is unreffed in complete_if_source_is_done() */ }
/*===========================================================================* * do_close * *===========================================================================*/ int do_close(message *UNUSED(m_out)) { /* Perform the close(fd) system call. */ int thefd = job_m_in.fd; return close_fd(fp, thefd); }
/*===========================================================================* * do_close * *===========================================================================*/ int do_close() { /* Perform the close(fd) system call. */ return close_fd(fp, m_in.fd); }
bool run_matlab_command(::std::string const& cmd, ArgsT const& args, ConsumerT& consumer) { int pipefd[2]; // Create a pipe to let to communicate with MATLAB. // Specifically, we want to read the output from MATLAB. // So, the parent process read from the pipe, while the child process // write on it. if (::pipe(pipefd) == -1) { char const* err_str = ::strerror(errno); ::std::ostringstream oss; oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] pipe(2) failed: " << ::std::string(err_str); throw ::std::runtime_error(oss.str()); } // // Install signal handlers // struct ::sigaction sig_act; // struct ::sigaction old_sigterm_act; // struct ::sigaction old_sigint_act; // //::memset(&sig_act, 0, sizeof(sig_act)); // ::sigemptyset(&sig_act.sa_mask); // sig_act.sa_flags = 0; // sig_act.sa_handler = self_type::process_signals; // ::sigaction(SIGTERM, &sig_act, &old_sigterm_act); // ::sigaction(SIGINT, &sig_act, &old_sigint_act); // Spawn a new process // Between fork() and execve() only async-signal-safe functions // must be called if multithreaded applications should be supported. // That's why the following code is executed before fork() is called. ::pid_t pid = ::fork(); // check: pid == -1 --> error if (pid == -1) { char const* err_str = ::strerror(errno); ::std::ostringstream oss; oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] fork(2) failed: " << ::std::string(err_str); throw ::std::runtime_error(oss.str()); } if (pid == 0) { // The child // // Cancel signal handler set for parent // sig_act.sa_handler = SIG_DFL; // ::sigaction(SIGTERM, &sig_act, 0); // ::sigaction(SIGINT, &sig_act, 0); // Get the maximum number of files this process is allowed to open #if defined(F_MAXFD) int maxdescs = ::fcntl(-1, F_MAXFD, 0); if (maxdescs == -1) { #if defined(_SC_OPEN_MAX) maxdescs = ::sysconf(_SC_OPEN_MAX); #else ::rlimit limit; if (::getrlimit(RLIMIT_NOFILE, &limit) < 0) { char const* err_str = ::strerror(errno); ::std::ostringstream oss; oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] getrlimit(2) failed: " << ::std::string(err_str); throw ::std::runtime_error(oss.str()); } maxdescs = limit.rlim_cur; #endif // _SC_OPEN_MAX } #else // F_MAXFD #if defined(_SC_OPEN_MAX) int maxdescs = ::sysconf(_SC_OPEN_MAX); #else // _SC_OPEN_MAX ::rlimit limit; if (::getrlimit(RLIMIT_NOFILE, &limit) < 0) { char const* err_str = ::strerror(errno); ::std::ostringstream oss; oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] getrlimit(2) failed: " << ::std::string(err_str); throw ::std::runtime_error(oss.str()); } maxdescs = limit.rlim_cur; #endif // _SC_OPEN_MAX #endif // F_MAXFD if (maxdescs == -1) { maxdescs = 1024; } ::std::vector<bool> close_fd(maxdescs, true); // Associate the child's stdout to the pipe write fd. close_fd[STDOUT_FILENO] = false; if (pipefd[1] != STDOUT_FILENO) { if (::dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) { char const* err_str = ::strerror(errno); ::std::ostringstream oss; oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] dup2(2) failed: " << ::std::string(err_str); throw ::std::runtime_error(oss.str()); } } else { close_fd[pipefd[1]] = false; } // ::close(STDOUT_FILENO); // ::dup(pipefd[1]); // Check if the command already has path information ::std::string cmd_path; ::std::string cmd_name; typename ::std::string::size_type pos; pos = cmd.find_last_of('/'); if (pos != ::std::string::npos) { cmd_path = cmd.substr(0, pos); cmd_name = cmd.substr(pos+1); } //FIXME: use scoped_ptr in place of "new" ::std::size_t nargs = args.size()+1; char** argv = new char*[nargs + 2]; argv[0] = new char[cmd_name.size()+1]; ::std::strncpy(argv[0], cmd_name.c_str(), cmd_name.size()+1); // by convention, the first argument is always the command name typename ArgsT::size_type i(1); typename ArgsT::const_iterator end_it(args.end()); for (typename ArgsT::const_iterator it = args.begin(); it != end_it; ++it) { argv[i] = new char[it->size()+1]; ::std::strncpy(argv[i], it->c_str(), it->size()+1); ++i; } argv[nargs] = 0; //char** envp(0); // Close unused file descriptors #ifdef DCS_DEBUG // Keep standard error open for debug close_fd[STDERR_FILENO] = false; #endif // DCS_DEBUG for (int fd = 0; fd < maxdescs; ++fd) { if (close_fd[fd]) { ::close(fd); } } //[XXX] #ifdef DCS_DEBUG ::std::cerr << "Executing MATLAB: " << cmd;//XXX for (::std::size_t i=0; i < args.size(); ++i)//XXX {//XXX ::std::cerr << " " << args[i] << ::std::flush;//XXX }//XXX ::std::cerr << ::std::endl;//XXX #endif // DCS_DEBUG //[/XXX] //DCS_DEBUG_TRACE("Executing: " << cmd << " " << args[0] << " " << args[1] << " " << args[2] << " - " << args[3]); //::execve(cmd.c_str(), argv, envp); ::execvp(cmd.c_str(), argv); // Actually we should delete argv and envp data. As we must not // call any non-async-signal-safe functions though we simply exit. ::write(STDERR_FILENO, "execvp() failed\n", 17); //_exit(EXIT_FAILURE); _exit(127); } // The parent // // Associate the parent's stdin to the pipe read fd. ::close(pipefd[1]); // ::close(STDIN_FILENO); // ::dup(pipefd[0]); if (pipefd[0] != STDIN_FILENO) { if (::dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { char const* err_str = ::strerror(errno); ::std::ostringstream oss; oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] dup2(2) failed: " << ::std::string(err_str); throw ::std::runtime_error(oss.str()); } ::close(pipefd[0]); } typedef ::boost::iostreams::file_descriptor_source fd_device_type; typedef ::boost::iostreams::stream_buffer<fd_device_type> fd_streambuf_type; //fd_device_type fd_src(pipefd[0], ::boost::iostreams::close_handle); fd_device_type fd_src(STDIN_FILENO, ::boost::iostreams::close_handle); fd_streambuf_type fd_buf(fd_src); ::std::istream is(&fd_buf); consumer(is); DCS_DEBUG_TRACE("END parsing MATLAB output");//XXX DCS_DEBUG_TRACE("IS state: " << is.good() << " - " << is.eof() << " - " << is.fail() << " - " << is.bad());//XXX // Wait the child termination (in order to prevent zombies) int status; // ::pid_t wait_pid; // wait_pid = ::wait(&status); // if (wait_pid != pid) // { // throw ::std::runtime_error("[dcs::des::cloud::detail::rls_miso_matlab_app_proxy::run_matlab] Unexpected child process."); // } if (::waitpid(pid, &status, 0) == -1) { char const* err_str = ::strerror(errno); ::std::ostringstream oss; oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] waitpid(2) failed: " << ::std::string(err_str); throw ::std::runtime_error(oss.str()); } DCS_DEBUG_TRACE("MATLAB exited");//XXX bool ok(true); if (WIFEXITED(status)) { DCS_DEBUG_TRACE("MATLAB exited with a call to 'exit(" << WEXITSTATUS(status) << ")'");//XXX if (WEXITSTATUS(status)) { // status != 0 --> error in the execution ::std::clog << "[Warning] MATLAB command exited with status " << WEXITSTATUS(status) << ::std::endl; ok = false; } } else if (WIFSIGNALED(status)) { DCS_DEBUG_TRACE("MATLAB exited with a call to 'kill(" << WTERMSIG(status) << ")'");//XXX ::std::clog << "[Warning] MATLAB command received signal " << WTERMSIG(status) << ::std::endl; ok = false; } else { DCS_DEBUG_TRACE("MATLAB exited with an unexpected way");//XXX ok = false; } // // Restore signal handler // ::sigaction(SIGTERM, &old_sigterm_act, 0); // ::sigaction(SIGINT, &old_sigint_act, 0); return ok; }
int status_client_ncurses(struct config *conf, enum action act, const char *sclient) { int fd=0; int ret=0; int sel=0; char *rbuf=NULL; char buf[512]=""; int count=0; int details=0; char *last_rbuf=NULL; int srbr=0; char *client=NULL; int enterpressed=0; // int loop=0; int reqdone=0; #ifdef HAVE_NCURSES_H int stdinfd=fileno(stdin); actg=act; // So that the sighandler can call endwin(). #else if(act==ACTION_STATUS) { printf("To use the live status monitor, you need to recompile with ncurses support.\n"); return -1; } #endif setup_signals(); /* NULL == ::1 or 127.0.0.1 */ if((fd=init_client_socket(NULL, conf->status_port))<0) return -1; set_non_blocking(fd); #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) { initscr(); start_color(); init_pair(1, COLOR_WHITE, COLOR_BLACK); init_pair(2, COLOR_WHITE, COLOR_BLACK); init_pair(3, COLOR_WHITE, COLOR_BLACK); raw(); keypad(stdscr, TRUE); noecho(); curs_set(0); halfdelay(3); //nodelay(stdscr, TRUE); } #endif #ifdef DBFP dbfp=fopen("/tmp/dbfp", "w"); #endif while(!ret) { int l; int mfd=-1; fd_set fsr; fd_set fse; struct timeval tval; // Failsafe to prevent the snapshot ever getting permanently // stuck. //if(act==ACTION_STATUS_SNAPSHOT && loop++>10000) // break; if(sclient && !client) { client=strdup(sclient); details=1; } if((enterpressed || need_status()) && !reqdone) { char *req=NULL; if(details && client) req=client; if(request_status(fd, req, conf)) { ret=-1; break; } enterpressed=0; if(act==ACTION_STATUS_SNAPSHOT) reqdone++; } FD_ZERO(&fsr); FD_ZERO(&fse); tval.tv_sec=1; tval.tv_usec=0; add_fd_to_sets(fd, &fsr, NULL, &fse, &mfd); #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) add_fd_to_sets(stdinfd, &fsr, NULL, &fse, &mfd); #endif if(select(mfd+1, &fsr, NULL, &fse, &tval)<0) { if(errno!=EAGAIN && errno!=EINTR) { logp("select error: %s\n", strerror(errno)); ret=-1; break; } continue; } if(FD_ISSET(fd, &fse)) { ret=-1; break; } #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) { if(FD_ISSET(stdinfd, &fse)) { ret=-1; break; } if(FD_ISSET(stdinfd, &fsr)) { int quit=0; switch(getch()) { case 'q': case 'Q': quit++; break; case KEY_UP: case 'k': case 'K': if(details) break; sel--; break; case KEY_DOWN: case 'j': case 'J': if(details) break; sel++; break; case KEY_ENTER: case '\n': case ' ': if(details) details=0; else details++; enterpressed++; break; case KEY_LEFT: case 'h': case 'H': details=0; break; case KEY_RIGHT: case 'l': case 'L': details++; break; case KEY_NPAGE: { int row=0, col=0; getmaxyx(stdscr, row, col); sel+=row-TOP_SPACE; break; } case KEY_PPAGE: { int row=0, col=0; getmaxyx(stdscr, row, col); sel-=row-TOP_SPACE; break; } } if(quit) break; if(sel<0) sel=0; if(sel>=count) sel=count-1; // Attempt to print stuff to the screen right // now, to give the impression of key strokes // being responsive. if(!details && !sclient) { if((srbr=show_rbuf(last_rbuf, conf, sel, &client, &count, details, sclient))<0) { ret=-1; break; } if(!details) print_star(sel); refresh(); } } } #endif if(FD_ISSET(fd, &fsr)) { // ready to read. if((l=read(fd, buf, sizeof(buf)-1))>0) { size_t r=0; buf[l]='\0'; if(rbuf) r=strlen(rbuf); rbuf=(char *)realloc(rbuf, r+l+1); if(!r) *rbuf='\0'; strcat(rbuf+r, buf); } else break; if(act==ACTION_STATUS_SNAPSHOT) { if(rbuf) { if(!strcmp(rbuf, "\n")) { // This happens when there are // no backup clients. break; } if(strstr(rbuf, "\n-list end-\n")) { printf("%s", rbuf); break; } } continue; } //if(rbuf) printf("rbuf: %s\n", rbuf); /* if(l<0) { ret=-1; break; } */ } if((srbr=show_rbuf(rbuf, conf, sel, &client, &count, details, sclient))<0) { ret=-1; break; } else if(srbr) { // Remember it, so that we can present the detailed // screen without delay, above. if(last_rbuf) free(last_rbuf); last_rbuf=rbuf; rbuf=NULL; } if(sclient) details++; usleep(20000); #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) { flushinp(); continue; } #endif if(count) { printf("\n"); break; } } #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) endwin(); #endif close_fd(&fd); if(last_rbuf) free(last_rbuf); if(rbuf) free(rbuf); #ifdef DBFP if(dbfp) fclose(dbfp); #endif return ret; }
/*===========================================================================* * pm_exec * *===========================================================================*/ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, vir_bytes frame, size_t frame_len, vir_bytes *pc, vir_bytes *newsp, int user_exec_flags) { /* Perform the execve(name, argv, envp) call. The user library builds a * complete stack image, including pointers, args, environ, etc. The stack * is copied to a buffer inside VFS, and then to the new core image. */ int r, slot; vir_bytes vsp; struct fproc *rfp; int extrabase = 0; static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ struct vfs_exec_info execi; int i; static char fullpath[PATH_MAX], elf_interpreter[PATH_MAX], firstexec[PATH_MAX], finalexec[PATH_MAX]; struct lookup resolve; struct fproc *vmfp = &fproc[VM_PROC_NR]; stackhook_t makestack = NULL; static int n; n++; struct filp *newfilp = NULL; lock_exec(); lock_proc(vmfp, 0); /* unset execi values are 0. */ memset(&execi, 0, sizeof(execi)); execi.vmfd = -1; /* passed from exec() libc code */ execi.userflags = user_exec_flags; execi.args.stack_high = kinfo.user_sp; execi.args.stack_size = DEFAULT_STACK_LIMIT; okendpt(proc_e, &slot); rfp = fp = &fproc[slot]; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &execi.vmp, &execi.vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; /* Fetch the stack from the user before destroying the old core image. */ if (frame_len > ARG_MAX) FAILCHECK(ENOMEM); /* stack too big */ r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf, (size_t) frame_len); if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */ printf("VFS: pm_exec: sys_datacopy failed\n"); FAILCHECK(r); } /* The default is to keep the original user and group IDs */ execi.args.new_uid = rfp->fp_effuid; execi.args.new_gid = rfp->fp_effgid; /* Get the exec file name. */ FAILCHECK(fetch_name(path, path_len, fullpath)); strlcpy(finalexec, fullpath, PATH_MAX); strlcpy(firstexec, fullpath, PATH_MAX); /* Get_read_vp will return an opened vn in execi. * if necessary it releases the existing vp so we can * switch after we find out what's inside the file. * It reads the start of the file. */ Get_read_vp(execi, fullpath, 1, 1, &resolve, fp); /* If this is a script (i.e. has a #!/interpreter line), * retrieve the name of the interpreter and open that * executable instead. */ if(is_script(&execi)) { /* patch_stack will add interpreter name and * args to stack and retrieve the new binary * name into fullpath. */ FAILCHECK(fetch_name(path, path_len, fullpath)); FAILCHECK(patch_stack(execi.vp, mbuf, &frame_len, fullpath)); strlcpy(finalexec, fullpath, PATH_MAX); strlcpy(firstexec, fullpath, PATH_MAX); Get_read_vp(execi, fullpath, 1, 0, &resolve, fp); } /* If this is a dynamically linked executable, retrieve * the name of that interpreter in elf_interpreter and open that * executable instead. But open the current executable in an * fd for the current process. */ if(elf_has_interpreter(execi.args.hdr, execi.args.hdr_len, elf_interpreter, sizeof(elf_interpreter))) { /* Switch the executable vnode to the interpreter */ execi.is_dyn = 1; /* The interpreter (loader) needs an fd to the main program, * which is currently in finalexec */ if((r = execi.elf_main_fd = common_open(finalexec, O_RDONLY, 0)) < 0) { printf("VFS: exec: dynamic: open main exec failed %s (%d)\n", fullpath, r); FAILCHECK(r); } /* ld.so is linked at 0, but it can relocate itself; we * want it higher to trap NULL pointer dereferences. */ execi.args.load_offset = 0x10000; /* Remember it */ strlcpy(execi.execname, finalexec, PATH_MAX); /* The executable we need to execute first (loader) * is in elf_interpreter, and has to be in fullpath to * be looked up */ strlcpy(fullpath, elf_interpreter, PATH_MAX); strlcpy(firstexec, elf_interpreter, PATH_MAX); Get_read_vp(execi, fullpath, 0, 0, &resolve, fp); } /* We also want an FD for VM to mmap() the process in if possible. */ { struct vnode *vp = execi.vp; assert(vp); if(vp->v_vmnt->m_haspeek && major(vp->v_dev) != MEMORY_MAJOR) { int newfd = -1; if(get_fd(vmfp, 0, R_BIT, &newfd, &newfilp) == OK) { assert(newfd >= 0 && newfd < OPEN_MAX); assert(!vmfp->fp_filp[newfd]); newfilp->filp_count = 1; newfilp->filp_vno = vp; newfilp->filp_flags = O_RDONLY; FD_SET(newfd, &vmfp->fp_filp_inuse); vmfp->fp_filp[newfd] = newfilp; /* dup_vnode(vp); */ execi.vmfd = newfd; execi.args.memmap = vfs_memmap; } } } /* callback functions and data */ execi.args.copymem = read_seg; execi.args.clearproc = libexec_clearproc_vm_procctl; execi.args.clearmem = libexec_clear_sys_memset; execi.args.allocmem_prealloc_cleared = libexec_alloc_mmap_prealloc_cleared; execi.args.allocmem_prealloc_junk = libexec_alloc_mmap_prealloc_junk; execi.args.allocmem_ondemand = libexec_alloc_mmap_ondemand; execi.args.opaque = &execi; execi.args.proc_e = proc_e; execi.args.frame_len = frame_len; execi.args.filesize = execi.vp->v_size; for (i = 0; exec_loaders[i].load_object != NULL; i++) { r = (*exec_loaders[i].load_object)(&execi.args); /* Loaded successfully, so no need to try other loaders */ if (r == OK) { makestack = exec_loaders[i].setup_stack; break; } } FAILCHECK(r); /* Inform PM */ FAILCHECK(libexec_pm_newexec(proc_e, &execi.args)); /* Save off PC */ *pc = execi.args.pc; /* call a stack-setup function if this executable type wants it */ vsp = execi.args.stack_high - frame_len; if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp, &extrabase)); /* Patch up stack and copy it from VFS to new core image. */ libexec_patch_ptr(mbuf, vsp + extrabase); FAILCHECK(sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp, (phys_bytes)frame_len)); /* Return new stack pointer to caller */ *newsp = vsp; clo_exec(rfp); if (execi.args.allow_setuid) { /* If after loading the image we're still allowed to run with * setuid or setgid, change credentials now */ rfp->fp_effuid = execi.args.new_uid; rfp->fp_effgid = execi.args.new_gid; } /* Remember the new name of the process */ strlcpy(rfp->fp_name, execi.args.progname, PROC_NAME_LEN); pm_execfinal: if(newfilp) unlock_filp(newfilp); else if (execi.vp != NULL) { unlock_vnode(execi.vp); put_vnode(execi.vp); } if(execi.vmfd >= 0 && !execi.vmfd_used) { if(OK != close_fd(vmfp, execi.vmfd)) { printf("VFS: unexpected close fail of vm fd\n"); } } unlock_proc(vmfp); unlock_exec(); return(r); }
static void dialog_sync_func(int cmd, int argc, char **argv) { int r, this_expnum, cpid; int gfd; double dval; char *retStr; DLIST *dlist; vInfo info; int ret, tree; char dstr[256]; if (debug > 1) fprintf(stderr, " dialog_sync_func: cmd= %d argc= %d\n", cmd, argc); cpid = atoi(argv[3]); if (debug > 1) fprintf(stderr, " dialog command: %d, pid %d\n", cmd, cpid); dlist = dialog_list; gfd = -1; while (dlist != NULL) { if (dlist->pid == cpid) { gfd = dlist->fout; break; } dlist = dlist->next; } if (dlist == NULL || gfd < 0) { if (debug > 1) fprintf(stderr, " dialog_sync_func: could not find process\n"); return; } if (debug > 1) fprintf(stderr, " execute command: %d, pid %d\n", cmd, cpid); switch (cmd) { case PWD: retStr = get_cwd(); write(gfd, retStr, strlen(retStr)); break; case EXPDIR: write(gfd, curexpdir, strlen(curexpdir)); break; case GEXIT: dlist->used = 0; close_fd(dlist); dlist->pid = -1; break; case GOK: /* verify console is available */ this_expnum = expdir_to_expnum( curexpdir ); r = is_exp_active( this_expnum ); sprintf(data, "%d \n", r); write(gfd, data, strlen(data)); break; case GQUERY: if (argc < 5) { strcpy(data, "0 \n"); write(gfd, data, strlen(data)); return; } retStr = NULL; if (strstr(argv[4], "macro_value") != NULL) { retStr = modify_show_str(argv[4], dstr); } if (retStr == NULL) retStr = argv[4]; queryFlag = 0; sprintf(data, "if (%s) then dialog('SYNCFUNC', %d, %d, '1') else dialog('SYNCFUNC', %d, %d, '0') endif\n", retStr, GTEST,cpid, GTEST, cpid); execString(data); if (queryFlag == 0) { strcpy(data, "0 \n"); write(gfd, data, strlen(data)); } break; case GTEST: if (argc < 5) return; queryFlag = 1; if (debug > 1) fprintf(stderr, " write to dialog: '%s'\n", argv[4]); sprintf(data, "%s \n", argv[4]); write(gfd, data, strlen(data)); break; case VEXEC: if (argc < 5) return; execString(argv[4]); break; case VGET: sprintf(data, " \n"); if (argc < 5) { write(gfd, data, strlen(data)); return; } tree = CURRENT; if ( (ret = P_getVarInfo(tree, argv[4], &info)) ) { tree = GLOBAL; ret = P_getVarInfo(tree, argv[4], &info); } if (ret != 0) { write(gfd, data, strlen(data)); return; } if (info.basicType == T_STRING) { P_getstring(tree,argv[4],data,1,1023); if (strlen(data) < 4) strcat (data, " \n"); } else { dval = 0.0; P_getreal(tree,argv[4],&dval,1); sprintf(data, "%g\n", dval); } write(gfd, data, strlen(data)); break; } }
status_t select_fd(int32 fd, struct select_info* info, bool kernel) { TRACE(("select_fd(fd = %ld, info = %p (%p), 0x%x)\n", fd, info, info->sync, info->selected_events)); FDGetter fdGetter; // define before the context locker, so it will be destroyed after it io_context* context = get_current_io_context(kernel); MutexLocker locker(context->io_mutex); struct file_descriptor* descriptor = fdGetter.SetTo(context, fd, true); if (descriptor == NULL) return B_FILE_ERROR; uint16 eventsToSelect = info->selected_events & ~B_EVENT_INVALID; if (descriptor->ops->fd_select == NULL && eventsToSelect != 0) { // if the I/O subsystem doesn't support select(), we will // immediately notify the select call return notify_select_events(info, eventsToSelect); } // We need the FD to stay open while we're doing this, so no select()/ // deselect() will be called on it after it is closed. atomic_add(&descriptor->open_count, 1); locker.Unlock(); // select any events asked for uint32 selectedEvents = 0; for (uint16 event = 1; event < 16; event++) { if ((eventsToSelect & SELECT_FLAG(event)) != 0 && descriptor->ops->fd_select(descriptor, event, (selectsync*)info) == B_OK) { selectedEvents |= SELECT_FLAG(event); } } info->selected_events = selectedEvents | (info->selected_events & B_EVENT_INVALID); // Add the info to the IO context. Even if nothing has been selected -- we // always support B_EVENT_INVALID. locker.Lock(); if (context->fds[fd] != descriptor) { // Someone close()d the index in the meantime. deselect() all // events. info->next = NULL; deselect_select_infos(descriptor, info); // Release our open reference of the descriptor. close_fd(descriptor); return B_FILE_ERROR; } // The FD index hasn't changed, so we add the select info to the table. info->next = context->select_infos[fd]; context->select_infos[fd] = info; // As long as the info is in the list, we keep a reference to the sync // object. atomic_add(&info->sync->ref_count, 1); // Finally release our open reference. It is safe just to decrement, // since as long as the descriptor is associated with the slot, // someone else still has it open. atomic_add(&descriptor->open_count, -1); return B_OK; }
int main(int argc, char *argv[]) { if (argc < 10) { // TODO: if argv > 3, assume pok[] is given, notifify parent. // usage() and a man-page (help2man) would not be bad, either :) return -1; } int pok[2]; int pin[2]; int pout[2]; pok[0] = atoi(argv[1]); pok[1] = atoi(argv[2]); pin[0] = atoi(argv[3]); pin[1] = atoi(argv[4]); pout[0] = atoi(argv[5]); pout[1] = atoi(argv[6]); int stderr_mode = atoi(argv[7]); int nicelevel = atoi(argv[8]); /* vfork()ed child process - exec external process */ close_fd(&pok[0]); fcntl(pok[1], F_SETFD, FD_CLOEXEC); close_fd(&pin[1]); if (pin[0] != STDIN_FILENO) { dup2(pin[0], STDIN_FILENO); } close_fd(&pin[0]); close_fd(&pout[0]); if (pout[1] != STDOUT_FILENO) { dup2(pout[1], STDOUT_FILENO); } if (stderr_mode == 2) { /* merge STDERR into output */ if (pout[1] != STDERR_FILENO) { dup2(pout[1], STDERR_FILENO); } } else if (stderr_mode == 1) { /* ignore STDERR */ close(STDERR_FILENO); } else { /* keep STDERR */ } if (pout[1] != STDOUT_FILENO && pout[1] != STDERR_FILENO) { close_fd(&pout[1]); } if (nicelevel !=0) { nice(nicelevel); } /* copy current environment */ char **envp = NULL; int i=0; envp = (char **) calloc(1, sizeof(char*)); for (i=0;environ[i];++i) { envp[i] = strdup(environ[i]); envp = (char **) realloc(envp, (i+2) * sizeof(char*)); } envp[i] = 0; #ifdef HAVE_SIGSET sigset(SIGPIPE, SIG_DFL); #else signal(SIGPIPE, SIG_DFL); #endif /* all systems go */ execve(argv[9], &argv[9], envp); /* if we reach here something went wrong.. */ char buf = 0; (void) write(pok[1], &buf, 1 ); close_fd(&pok[1]); #ifdef __clang_analyzer__ // the clang static analyzer warns about a memleak here, // but we don't care. The OS will clean up after us in a jiffy. for (i=0; envp && envp[i]; ++i) { free (envp[i]); } free (envp); #endif return -1; }
void TcpListener::_close_sock(){ if(m_sock != INVALID_FD){ close_fd(m_sock); m_sock =INVALID_FD; } }
int main(int argc, char **argv) { int c; int fd; int mode = 0; int dig = 0; int posix = 0; loff_t length = -2LL; loff_t offset = 0; static const struct option longopts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "keep-size", no_argument, NULL, 'n' }, { "punch-hole", no_argument, NULL, 'p' }, { "collapse-range", no_argument, NULL, 'c' }, { "dig-holes", no_argument, NULL, 'd' }, { "insert-range", no_argument, NULL, 'i' }, { "zero-range", no_argument, NULL, 'z' }, { "offset", required_argument, NULL, 'o' }, { "length", required_argument, NULL, 'l' }, { "posix", no_argument, NULL, 'x' }, { "verbose", no_argument, NULL, 'v' }, { NULL, 0, NULL, 0 } }; static const ul_excl_t excl[] = { /* rows and cols in ASCII order */ { 'c', 'd', 'p', 'z' }, { 'c', 'n' }, { 'x', 'c', 'd', 'i', 'n', 'p', 'z'}, { 0 } }; int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); close_stdout_atexit(); while ((c = getopt_long(argc, argv, "hvVncpdizxl:o:", longopts, NULL)) != -1) { err_exclusive_options(c, longopts, excl, excl_st); switch(c) { case 'c': mode |= FALLOC_FL_COLLAPSE_RANGE; break; case 'd': dig = 1; break; case 'i': mode |= FALLOC_FL_INSERT_RANGE; break; case 'l': length = cvtnum(optarg); break; case 'n': mode |= FALLOC_FL_KEEP_SIZE; break; case 'o': offset = cvtnum(optarg); break; case 'p': mode |= FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; break; case 'z': mode |= FALLOC_FL_ZERO_RANGE; break; case 'x': #ifdef HAVE_POSIX_FALLOCATE posix = 1; break; #else errx(EXIT_FAILURE, _("posix_fallocate support is not compiled")); #endif case 'v': verbose++; break; case 'h': usage(); case 'V': print_version(EXIT_SUCCESS); default: errtryhelp(EXIT_FAILURE); } } if (optind == argc) errx(EXIT_FAILURE, _("no filename specified")); filename = argv[optind++]; if (optind != argc) errx(EXIT_FAILURE, _("unexpected number of arguments")); if (dig) { /* for --dig-holes the default is analyze all file */ if (length == -2LL) length = 0; if (length < 0) errx(EXIT_FAILURE, _("invalid length value specified")); } else { /* it's safer to require the range specification (--length --offset) */ if (length == -2LL) errx(EXIT_FAILURE, _("no length argument specified")); if (length <= 0) errx(EXIT_FAILURE, _("invalid length value specified")); } if (offset < 0) errx(EXIT_FAILURE, _("invalid offset value specified")); /* O_CREAT makes sense only for the default fallocate(2) behavior * when mode is no specified and new space is allocated */ fd = open(filename, O_RDWR | (!dig && !mode ? O_CREAT : 0), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (fd < 0) err(EXIT_FAILURE, _("cannot open %s"), filename); if (dig) dig_holes(fd, offset, length); #ifdef HAVE_POSIX_FALLOCATE else if (posix) xposix_fallocate(fd, offset, length); #endif else xfallocate(fd, mode, offset, length); if (close_fd(fd) != 0) err(EXIT_FAILURE, _("write failed: %s"), filename); return EXIT_SUCCESS; }
int send_message(const char * message, size_t message_size) { int rv; struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_flags = AI_PASSIVE // use my IP }; const char * port = "3490"; struct addrinfo * serv_info; rv = getaddrinfo(NULL, port, &hints, &serv_info); if (rv != 0) { fputs("getaddrinfo: ", stderr); fputs(gai_strerror(rv), stderr); fputc('\n', stderr); return EXIT_FAILURE; } // loop through all the results and bind to the first we can int sock_fd; struct addrinfo * p; for (p = serv_info; p; p = p->ai_next) { sock_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sock_fd == -1) { perror("socket"); continue; } const int yes = 1; rv = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes); if (rv == -1) { perror("setsockopt"); close_fd(sock_fd); continue; } rv = bind(sock_fd, p->ai_addr, p->ai_addrlen); if (rv == -1) { perror("bind"); close_fd(sock_fd); continue; } break; } freeaddrinfo(serv_info); // all done with this structure if (!p) { fputs("server: failed to bind\n", stderr); return EXIT_FAILURE; } const int backlog = 0; // no pending connections rv = listen(sock_fd, backlog); if (rv == -1) { perror("listen"); close_fd(sock_fd); return EXIT_FAILURE; } fputs("server: waiting for connections...\n", stdout); struct sockaddr_storage client_addr; socklen_t sin_size = sizeof client_addr; const int new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size); if (new_fd == -1) { perror("accept"); close_fd(sock_fd); return EXIT_FAILURE; } char address[INET6_ADDRSTRLEN]; const char * dst = inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), address, sizeof address); if (dst == NULL) { perror("inet_ntop"); close_fd(new_fd); close_fd(sock_fd); return EXIT_FAILURE; } fputs("server: got connection from ", stdout); fputs(address, stdout); fputc('\n', stdout); const ssize_t num_bytes = send(new_fd, message, message_size, 0); if (num_bytes == -1) { perror("send"); close_fd(new_fd); close_fd(sock_fd); return EXIT_FAILURE; } close_fd(new_fd); close_fd(sock_fd); return 0; }
void * do_crawler(void *item) { char *url_ptr; int clientfd ; static int pages = 0; static int error = 0; char *buf = NULL; urlq_t *url_list_head = NULL, *p, *p_pre; char cur_dir[256]; hash_table *hash_in, *hash_out; /* int tid = pthread_self();*/ int j = 0; int i= 0; int pos_found = 0; char temp[256]; int status = 0; static int a = 0; static int b = 0; static int c = 0; static int d = 0; static int e = 0; static int f = 0; static int g = 0; while(1){ pthread_mutex_lock(&mutex); while (urlqueue.head_ptr->next == NULL){ pthread_cond_wait(&ready, &mutex); } pthread_mutex_lock(&((threadpool_item *)item)->waitlock); ((threadpool_item *)item)->idle = 0; pthread_mutex_unlock(&((threadpool_item *)item)->waitlock); url_ptr = queue_pop(&urlqueue); g++; pthread_mutex_unlock(&mutex); pthread_mutex_lock(&mutex); /*if not visited, set flag = 1*/ if(has_visited(hash, url_ptr) == 1){ pthread_mutex_unlock(&mutex); free(url_ptr); pthread_mutex_lock(&((threadpool_item *)item)->waitlock); ((threadpool_item *)item)->idle =1; pthread_mutex_unlock(&((threadpool_item *)item)->waitlock); d++; continue; } hash_out = has_url(hash, url_ptr); e++; pthread_mutex_unlock(&mutex); if (hash_out == NULL){ printf("error\n"); getchar(); } *temp = '\0'; cur_dir[0] = '\0'; strcpy(cur_dir, url_ptr); j = strlen(cur_dir); for (;cur_dir[j] != '/' && j != 0; j--) ; if(j == 0) cur_dir[j] = '\0'; else cur_dir[j+1] = '\0'; for (i = 0; i < 3; i++){ if((clientfd = open_tcp("127.0.0.1", 80)) < 0){ close_fd(clientfd); continue; } if( http_do_get(clientfd, rootdir, "127.0.0.1", url_ptr) < 0){ close_fd(clientfd); continue; } if(recv_line(clientfd, temp) <= 0){ close_fd(clientfd); continue; } if((status = http_response_status(temp)) == 4){ printf("%s error %d\n",url_ptr, error++); pthread_mutex_lock(&mutex); set_status(hash, url_ptr, 4); set_webg_status(webg, hash_out, 4); pthread_mutex_unlock(&mutex); pthread_mutex_lock(&((threadpool_item *)item)->waitlock); ((threadpool_item *)item)->idle =1; pthread_mutex_unlock(&((threadpool_item *)item)->waitlock); close_fd(clientfd); break; } buf = http_response_body(clientfd); close_fd(clientfd); break; } if (status == 4) continue; if(i == 3){ pthread_mutex_lock(&((threadpool_item *)item)->waitlock); ((threadpool_item *)item)->idle =1; pthread_mutex_unlock(&((threadpool_item *)item)->waitlock); close_fd(clientfd); continue; } if (buf == NULL){ pthread_mutex_lock(&((threadpool_item *)item)->waitlock); ((threadpool_item *)item)->idle =1; pthread_mutex_unlock(&((threadpool_item *)item)->waitlock); continue; } printf("%s pages %d\n", url_ptr,pages++); extract_link(buf, cur_dir, &url_list_head); free(buf); buf = NULL; p = url_list_head->next; p_pre = url_list_head; while (p != NULL){ if(strcmp(url_ptr, p->url_ptr) == 0){ p_pre->next = p->next; free(p->url_ptr); free(p); a++; p = p_pre->next; printf("a= %d, b= %d, c= %d, d= %d, e= %d, f= %d, g= %d\n", a,b,c,d,e,f,g); continue; } pthread_mutex_lock(&mutex); hash_in = has_url(hash, p->url_ptr); if (hash_in != NULL ){ insert_edge(webg, hash_in, hash_out); pthread_mutex_unlock(&mutex); p_pre->next = p->next; free(p->url_ptr); free(p); p = p_pre->next; b++; printf("a= %d, b= %d, c= %d, d= %d, e= %d, f= %d, g= %d\n", a,b,c,d,e,f,g); continue; } else{ pos_found = insert_vertex(webg, hash_out, p->url_ptr); insert_hash_item(hash, p->url_ptr, pos_found, 0); pthread_mutex_unlock(&mutex); c++; p_pre = p; p = p->next; printf("a= %d, b= %d, c= %d, d= %d, e= %d, f= %d, g= %d\n", a,b,c,d,e,f,g); } } if(p_pre != url_list_head){ pthread_mutex_lock(&mutex); queue_push(&urlqueue, url_list_head->next, p_pre); f++; pthread_mutex_unlock(&mutex); } free(url_list_head); p = p_pre = url_list_head = NULL; pthread_mutex_lock(&((threadpool_item *)item)->waitlock); ((threadpool_item *)item)->idle = 1; pthread_mutex_unlock(&((threadpool_item *)item)->waitlock); /*printf("next time!\n");*/ } /*printf("over!\n");*/ return NULL; }
/*===========================================================================* * free_proc * *===========================================================================*/ static void free_proc(struct fproc *exiter, int flags) { int i; register struct fproc *rfp; register struct filp *rfilp; register struct vnode *vp; dev_t dev; if (exiter->fp_endpoint == NONE) panic("free_proc: already free"); if (fp_is_blocked(exiter)) unpause(exiter->fp_endpoint); /* Loop on file descriptors, closing any that are open. */ for (i = 0; i < OPEN_MAX; i++) { (void) close_fd(exiter, i); } /* Release root and working directories. */ if (exiter->fp_rd) { put_vnode(exiter->fp_rd); exiter->fp_rd = NULL; } if (exiter->fp_wd) { put_vnode(exiter->fp_wd); exiter->fp_wd = NULL; } /* The rest of these actions is only done when processes actually exit. */ if (!(flags & FP_EXITING)) return; exiter->fp_flags |= FP_EXITING; /* Check if any process is SUSPENDed on this driver. * If a driver exits, unmap its entries in the dmap table. * (unmapping has to be done after the first step, because the * dmap table is used in the first step.) */ unsuspend_by_endpt(exiter->fp_endpoint); dmap_unmap_by_endpt(exiter->fp_endpoint); worker_stop_by_endpt(exiter->fp_endpoint); /* Unblock waiting threads */ vmnt_unmap_by_endpt(exiter->fp_endpoint); /* Invalidate open files if this * was an active FS */ /* Invalidate endpoint number for error and sanity checks. */ exiter->fp_endpoint = NONE; /* If a session leader exits and it has a controlling tty, then revoke * access to its controlling tty from all other processes using it. */ if ((exiter->fp_flags & FP_SESLDR) && exiter->fp_tty != 0) { dev = exiter->fp_tty; for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { if(rfp->fp_pid == PID_FREE) continue; if (rfp->fp_tty == dev) rfp->fp_tty = 0; for (i = 0; i < OPEN_MAX; i++) { if ((rfilp = rfp->fp_filp[i]) == NULL) continue; if (rfilp->filp_mode == FILP_CLOSED) continue; vp = rfilp->filp_vno; if (!S_ISCHR(vp->v_mode)) continue; if ((dev_t) vp->v_sdev != dev) continue; lock_filp(rfilp, VNODE_READ); (void) dev_close(dev, rfilp-filp); /* Ignore any errors, even * SUSPEND. */ rfilp->filp_mode = FILP_CLOSED; unlock_filp(rfilp); } } } /* Exit done. Mark slot as free. */ exiter->fp_pid = PID_FREE; if (exiter->fp_flags & FP_PENDING) pending--; /* No longer pending job, not going to do it */ exiter->fp_flags = FP_NOFLAGS; }
// This function is called in order to setup the file descriptors in the // processes. This will deal with stdin, stdout, stderr as well as any // of the extra files defined in the Cmd structure. Once all the file // descriptors have been duplicated into place all other open file descriptors // will be closed. static void setup_files(goclone_cmd *cmd) { DIR *d; char buffer[sizeof(struct dirent) + FILENAMESIZE]; int closed; int fd; int i; struct dirent *results; // Walk through all of the file descriptors to see if any of the // descriptors are actually within the range that will be duped. If so // we need to copy the file descriptor out of the way. for (i = 0; i < cmd->files_len; i++) { if (cmd->files[i] == -1) { continue; } else if (cmd->files[i] >= cmd->files_len) { continue; } else if (cmd->files[i] == i) { continue; } // Its possible for a duped descriptor to land in the range we are // managing. If this happens then we need to dupe again until the // resulting descriptor is greater than the list. do { fd = dup(cmd->files[i]); if (fd == -1) { // FIXME: Log? _exit(EX_OSERR); } } while (fd < cmd->files_len); cmd->files[i] = fd; } // Now walk through duping all of the file descriptors. for (i = 0; i < cmd->files_len; i++) { if (cmd->files[i] == -1) { close_fd(i); } else { if (dup2(cmd->files[i], i) == -1) { // FIXME _exit(EX_OSERR); } } } // Now walk through closing all files larger than the list of descriptors // passed in. This ensures that all descriptors that are not desired are // closed, regardless of the "close on exec" status of the descriptor. do { closed = 0; // Open the /proc directory. This can only real fail if /proc is not // mounted. d = opendir("/proc/self/fdinfo"); if (d == NULL) { _exit(EX_OSERR); } while (1) { // Read each element from the directory listing one at a time. if (readdir_r(d, (struct dirent *) &buffer, &results) != 0) { // FIXME: logging? _exit(EX_OSERR); } // NULL here is the end of the directory list. if (results == NULL) { break; } // Parse the file name into an integer. i = atoi(results->d_name); // Make sure that no descriptor less than the list given above // is not closed, and that the descriptor with the directory // listing is left open as well. if (i < cmd->files_len || i == dirfd(d)) { continue; } // Close the file descriptor. close_fd(i); closed++; } // Close the open directory file descriptor. if (closedir(d) == -1) { _exit(EX_OSERR); } // Keep looping while descriptors are being closed. } while (closed != 0); }
static int native_inout_popen(FILE **fr, FILE **fw, char *cmd) { char buf[NFILEN + 128]; HANDLE handles[3]; int i, rc, rp[3], tmpin_fd, wp[3]; TRACE((T_CALLED "native_inout_popen cmd=%s\n", cmd)); proc_handle = BAD_PROC_HANDLE; rp[0] = rp[1] = rp[2] = wp[0] = wp[1] = wp[2] = BAD_FD; handles[0] = handles[1] = handles[2] = INVALID_HANDLE_VALUE; tmpin_fd = BAD_FD; tmpin_name = NULL; set_console_title(cmd); if (is_win95()) { char *cmdp; /* * If w32pipes is set on a win95 host, you don't ever want slowreadf() * to periodically update the display while an intrinisic, high * bandwidth DOS command is in progress. Reason: the win95 shell, * command.com, will simply hang in the following scenario: * * ^X!<high_bandwidth_cmd> * * and * * PIPESIZ < output of <high_bandwidth_cmd> * * I'm assuming that what's going on here is that command.com is * written in ASM and is using very low level BIOS/DOS calls to * effect output and, furthermore, that these low level calls don't * block when the input consumer is busy. */ cmdp = skip_blanks(cmd); nowait_pipe_cmd = (strnicmp(cmdp, "dir", 3) == 0) || (strnicmp(cmdp, "type", 4) == 0); } do { if (fr) { *fr = NULL; /* * Open (parent's) input pipe in TEXT mode, which will force * translation of the child's CR/LF record delimiters to NL * and keep the dreaded ^M chars from temporarily appearing * in a vile buffer (ugly). */ if (_pipe(rp, PIPESIZ, O_TEXT|O_NOINHERIT) == -1) break; if ((rp[2] = _dup(rp[1])) == -1) break; handles[2] = handles[1] = (HANDLE) _get_osfhandle(rp[2]); (void) close(rp[1]); rp[1] = BAD_FD; if (! fw) { /* * This is a read pipe (only). Connect child's stdin to * an empty file. Under no circumstances should the * child's stdin be connected to a device (else lots of * screwy things will occur). In particular, connecting * the child's stdin to the parent's stdin will cause * aborts and hangs on the various Win32 hosts. You've * been warned. */ if ((tmpin_name = _tempnam(getenv("TEMP"), "vile")) == NULL) break; if ((tmpin_fd = open(tmpin_name, O_RDONLY|O_CREAT|O_TRUNC, _S_IWRITE|_S_IREAD)) == BAD_FD) { break; } handles[0] = (HANDLE) _get_osfhandle(tmpin_fd); } if ((*fr = fdopen(rp[0], "r")) == 0) break; } if (fw) { *fw = NULL; /* * Open (child's) output pipe in binary mode, which will * prevent translation of the parent's CR/LF record delimiters * to NL. Apparently, many apps want those delimiters :-) . */ if (_pipe(wp, PIPESIZ, O_BINARY|O_NOINHERIT) == -1) break; if ((wp[2] = _dup(wp[0])) == -1) break; handles[0] = (HANDLE)_get_osfhandle(wp[2]); (void) close(wp[0]); wp[0] = BAD_FD; if (! fr) handles[1] = handles[2] = GetStdHandle(STD_OUTPUT_HANDLE); if ((*fw = fdopen(wp[1], "w")) == 0) break; } rc = (exec_shell(cmd, handles, fr != NULL /* Child wdw hidden unless write pipe. */ ) == BAD_PROC_HANDLE) ? FALSE : TRUE; if (fw) { if (! rc) { /* Shell process failed, put complaint in user's face. */ sprintf(buf, SHELL_ERR_MSG, get_shell()); lastditch_msg(buf); } w32_close_handle(handles[0]); } if (fr) { if (! rc) { unsigned len; /* * Shell process failed, put complaint in user's buffer. * Can't write to handles[1] on a win2k host because the * previously failed CreateProcess() call damaged the * handle. */ len = (unsigned) (lsprintf(buf, SHELL_ERR_MSG, get_shell()) - buf); (void) write(rp[2], buf, len); (void) close(rp[2]); /* in weird state; why not? */ } w32_close_handle(handles[1]); close_fd(tmpin_fd); } returnCode(rc); } while (FALSE); /* If we get here -- some operation has failed. Clean up. */ close_fd(wp[0]); close_fd(wp[1]); close_fd(wp[2]); close_fd(rp[0]); close_fd(rp[1]); close_fd(rp[2]); close_fd(tmpin_fd); for (i = 0; i < 3; i++) { if (handles[i] != INVALID_HANDLE_VALUE) w32_close_handle(handles[i]); } common_cleanup(); returnCode(FALSE); }
int main(int argc, char **argv) { struct mkswap_control ctl = { .fd = -1 }; int c; uint64_t sz; int version = SWAP_VERSION; char *block_count = NULL, *strsz = NULL; #ifdef HAVE_LIBUUID const char *opt_uuid = NULL; uuid_t uuid_dat; #endif static const struct option longopts[] = { { "check", no_argument, 0, 'c' }, { "force", no_argument, 0, 'f' }, { "pagesize", required_argument, 0, 'p' }, { "label", required_argument, 0, 'L' }, { "swapversion", required_argument, 0, 'v' }, { "uuid", required_argument, 0, 'U' }, { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { NULL, 0, 0, 0 } }; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); while((c = getopt_long(argc, argv, "cfp:L:v:U:Vh", longopts, NULL)) != -1) { switch (c) { case 'c': ctl.check = 1; break; case 'f': ctl.force = 1; break; case 'p': ctl.user_pagesize = strtou32_or_err(optarg, _("parsing page size failed")); break; case 'L': ctl.opt_label = optarg; break; case 'v': version = strtos32_or_err(optarg, _("parsing version number failed")); if (version != SWAP_VERSION) errx(EXIT_FAILURE, _("swapspace version %d is not supported"), version); break; case 'U': #ifdef HAVE_LIBUUID opt_uuid = optarg; #else warnx(_("warning: ignoring -U (UUIDs are unsupported by %s)"), program_invocation_short_name); #endif break; case 'V': printf(UTIL_LINUX_VERSION); exit(EXIT_SUCCESS); case 'h': usage(stdout); default: usage(stderr); } } if (optind < argc) ctl.devname = argv[optind++]; if (optind < argc) block_count = argv[optind++]; if (optind != argc) { warnx(_("only one device argument is currently supported")); usage(stderr); } #ifdef HAVE_LIBUUID if(opt_uuid) { if (uuid_parse(opt_uuid, uuid_dat) != 0) errx(EXIT_FAILURE, _("error: parsing UUID failed")); } else uuid_generate(uuid_dat); ctl.uuid = uuid_dat; #endif init_signature_page(&ctl); /* get pagesize and allocate signature page */ if (!ctl.devname) { warnx(_("error: Nowhere to set up swap on?")); usage(stderr); } if (block_count) { /* this silly user specified the number of blocks explicitly */ uint64_t blks = strtou64_or_err(block_count, _("invalid block count argument")); ctl.npages = blks / (ctl.pagesize / 1024); } sz = get_size(&ctl); if (!ctl.npages) ctl.npages = sz; else if (ctl.npages > sz && !ctl.force) errx(EXIT_FAILURE, _("error: " "size %llu KiB is larger than device size %ju KiB"), ctl.npages * (ctl.pagesize / 1024), sz * (ctl.pagesize / 1024)); if (ctl.npages < MIN_GOODPAGES) errx(EXIT_FAILURE, _("error: swap area needs to be at least %ld KiB"), (long)(MIN_GOODPAGES * ctl.pagesize / 1024)); if (ctl.npages > UINT32_MAX) { /* true when swap is bigger than 17.59 terabytes */ ctl.npages = UINT32_MAX; warnx(_("warning: truncating swap area to %llu KiB"), ctl.npages * ctl.pagesize / 1024); } if (is_mounted(ctl.devname)) errx(EXIT_FAILURE, _("error: " "%s is mounted; will not make swapspace"), ctl.devname); open_device(&ctl); if (ctl.check) check_blocks(&ctl); wipe_device(&ctl); assert(ctl.hdr); ctl.hdr->version = version; ctl.hdr->last_page = ctl.npages - 1; ctl.hdr->nr_badpages = ctl.nbadpages; if ((ctl.npages - MIN_GOODPAGES) < ctl.nbadpages) errx(EXIT_FAILURE, _("Unable to set up swap-space: unreadable")); sz = (ctl.npages - ctl.nbadpages - 1) * ctl.pagesize; strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER, sz); printf(_("Setting up swapspace version %d, size = %s (%ju bytes)\n"), version, strsz, sz); free(strsz); set_signature(&ctl); set_uuid_and_label(&ctl); write_header_to_device(&ctl); deinit_signature_page(&ctl); #ifdef HAVE_LIBSELINUX if (S_ISREG(ctl.devstat.st_mode) && is_selinux_enabled() > 0) { security_context_t context_string; security_context_t oldcontext; context_t newcontext; if (fgetfilecon(ctl.fd, &oldcontext) < 0) { if (errno != ENODATA) err(EXIT_FAILURE, _("%s: unable to obtain selinux file label"), ctl.devname); if (matchpathcon(ctl.devname, ctl.devstat.st_mode, &oldcontext)) errx(EXIT_FAILURE, _("unable to matchpathcon()")); } if (!(newcontext = context_new(oldcontext))) errx(EXIT_FAILURE, _("unable to create new selinux context")); if (context_type_set(newcontext, SELINUX_SWAPFILE_TYPE)) errx(EXIT_FAILURE, _("couldn't compute selinux context")); context_string = context_str(newcontext); if (strcmp(context_string, oldcontext)!=0) { if (fsetfilecon(ctl.fd, context_string)) err(EXIT_FAILURE, _("unable to relabel %s to %s"), ctl.devname, context_string); } context_free(newcontext); freecon(oldcontext); } #endif /* * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) * The fsync() in close_fd() will take care of writing. */ if (close_fd(ctl.fd) != 0) err(EXIT_FAILURE, _("write failed")); return EXIT_SUCCESS; }
static void tmp_npclose(FILE *fp) { char buf[NFILEN + 128]; int rc, term_status; (void) fflush(fp); (void) fclose(fp); if (stdout_fd != BAD_FD) { /* * write pipe, but not a filter. Editor has written data to temp * file, time now to exec "cmd" and hook its stdin to the file. * * It should be noted that exec'ing a process in the npclose() * phase of a write pipe is not exactly keeping in spirit with * the control flow in file.c :-) . However, the strategy used * here ensures that the launched process reads a temp file that * is completey flushed to disk. The only direct drawback with * this approach is that when the exec'd process exits, the user * does not receive a "[press return to continue]" prompt from * file.c . But, cough, we can work around that problem :-) . */ if ((stdout_fd = open(stdout_name, O_RDONLY|O_BINARY)) == BAD_FD) { /* oh my, put complaint in user's face. */ sprintf(buf, "[unable to open temp file \"%s\": %s]", stdout_name, strerror(errno)); lastditch_msg(buf); } else { handles[0] = (HANDLE) _get_osfhandle(stdout_fd); handles[1] = handles[2] = GetStdHandle(STD_OUTPUT_HANDLE); rc = (exec_shell(shcmd, handles, FALSE /* don't hide child window */ ) == BAD_PROC_HANDLE) ? FALSE : TRUE; if (! rc) { /* Shell process failed, put complaint in user's face. */ sprintf(buf, SHELL_ERR_MSG, get_shell()); lastditch_msg(buf); } else { /* now wait for app to exit */ (void) cwait(&term_status, (CWAIT_PARAM_TYPE) proc_handle, 0); TRACE(("...CreateProcess finished waiting in tmp_npclose\n")); close_proc_handle(); } /* * When closing descriptors shared between parent and child, * order is quite important when $shell == command.com . In * this situation, the descriptors can't be closed until the * exec'd process exits. */ close_fd(stdout_fd); } pressreturn(); /* cough */ sgarbf = TRUE; } tmp_cleanup(); }
static void close_fds(int *fds) { for(int i=0; i<LISTEN_SOCKETS; i++) close_fd(&(fds[i])); }