[BACK]Return to rumpclient.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / librumpclient

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/librumpclient/rumpclient.c between version 1.16.2.3 and 1.24

version 1.16.2.3, 2011/03/05 15:09:23 version 1.24, 2011/02/06 15:43:20
Line 30 
Line 30 
  */   */
   
 #include <sys/cdefs.h>  #include <sys/cdefs.h>
 __RCSID("$NetBSD$");  __RCSID("$NetBSD");
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/event.h>  #include <sys/event.h>
Line 43  __RCSID("$NetBSD$");
Line 43  __RCSID("$NetBSD$");
   
 #include <assert.h>  #include <assert.h>
 #include <dlfcn.h>  #include <dlfcn.h>
 #include <err.h>  
 #include <errno.h>  #include <errno.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <link.h>  #include <link.h>
Line 69  ssize_t (*host_read)(int, void *, size_t
Line 68  ssize_t (*host_read)(int, void *, size_t
 ssize_t (*host_sendto)(int, const void *, size_t, int,  ssize_t (*host_sendto)(int, const void *, size_t, int,
                        const struct sockaddr *, socklen_t);                         const struct sockaddr *, socklen_t);
 int     (*host_setsockopt)(int, int, int, const void *, socklen_t);  int     (*host_setsockopt)(int, int, int, const void *, socklen_t);
 int     (*host_dup)(int);  
   
 int     (*host_kqueue)(void);  int     (*host_kqueue)(void);
 int     (*host_kevent)(int, const struct kevent *, size_t,  int     (*host_kevent)(int, const struct kevent *, size_t,
                        struct kevent *, size_t, const struct timespec *);                         struct kevent *, size_t, const struct timespec *);
   
 int     (*host_execve)(const char *, char *const[], char *const[]);  
   
 #include "sp_common.c"  #include "sp_common.c"
   
 static struct spclient clispc = {  static struct spclient clispc = {
Line 87  static int kq = -1;
Line 83  static int kq = -1;
 static sigset_t fullset;  static sigset_t fullset;
   
 static int doconnect(bool);  static int doconnect(bool);
 static int handshake_req(struct spclient *, int, void *, int, bool);  static int handshake_req(struct spclient *, uint32_t *, int, bool);
   
 /*  time_t retrytimo = RUMPCLIENT_RETRYCONN_ONCE;
  * Default: don't retry.  Most clients can't handle it  
  * (consider e.g. fds suddenly going missing).  
  */  
 static time_t retrytimo = 0;  
   
 static int  static int
 send_with_recon(struct spclient *spc, const void *data, size_t dlen)  send_with_recon(struct spclient *spc, const void *data, size_t dlen)
Line 107  send_with_recon(struct spclient *spc, co
Line 99  send_with_recon(struct spclient *spc, co
                 rv = dosend(spc, data, dlen);                  rv = dosend(spc, data, dlen);
                 if (__predict_false(rv == ENOTCONN || rv == EBADF)) {                  if (__predict_false(rv == ENOTCONN || rv == EBADF)) {
                         /* no persistent connections */                          /* no persistent connections */
                         if (retrytimo == 0) {                          if (retrytimo == 0)
                                 rv = ENOTCONN;  
                                 break;                                  break;
                         }  
                         if (retrytimo == RUMPCLIENT_RETRYCONN_DIE)                          if (retrytimo == RUMPCLIENT_RETRYCONN_DIE)
                                 exit(1);                                  exit(1);
   
Line 155  send_with_recon(struct spclient *spc, co
Line 145  send_with_recon(struct spclient *spc, co
   
                         if ((rv = doconnect(false)) != 0)                          if ((rv = doconnect(false)) != 0)
                                 continue;                                  continue;
                         if ((rv = handshake_req(&clispc, HANDSHAKE_GUEST,                          if ((rv = handshake_req(&clispc, NULL, 0, true)) != 0)
                             NULL, 0, true)) != 0)  
                                 continue;                                  continue;
   
                         /*                          /*
Line 208  cliwaitresp(struct spclient *spc, struct
Line 197  cliwaitresp(struct spclient *spc, struct
                                         rv = host_kevent(kq, NULL, 0,                                          rv = host_kevent(kq, NULL, 0,
                                             kev, __arraycount(kev), NULL);                                              kev, __arraycount(kev), NULL);
   
                                         if (__predict_false(rv == -1)) {  
                                                 goto cleanup;  
                                         }  
   
                                         /*                                          /*
                                          * XXX: don't know how this can                                           * XXX: don't know how this can
                                          * happen (timeout cannot expire                                           * happen (timeout cannot expire
Line 282  cliwaitresp(struct spclient *spc, struct
Line 267  cliwaitresp(struct spclient *spc, struct
 }  }
   
 static int  static int
 syscall_req(struct spclient *spc, sigset_t *omask, int sysnum,  syscall_req(struct spclient *spc, int sysnum,
         const void *data, size_t dlen, void **resp)          const void *data, size_t dlen, void **resp)
 {  {
         struct rsp_hdr rhdr;          struct rsp_hdr rhdr;
         struct respwait rw;          struct respwait rw;
           sigset_t omask;
         int rv;          int rv;
   
         rhdr.rsp_len = sizeof(rhdr) + dlen;          rhdr.rsp_len = sizeof(rhdr) + dlen;
Line 294  syscall_req(struct spclient *spc, sigset
Line 280  syscall_req(struct spclient *spc, sigset
         rhdr.rsp_type = RUMPSP_SYSCALL;          rhdr.rsp_type = RUMPSP_SYSCALL;
         rhdr.rsp_sysnum = sysnum;          rhdr.rsp_sysnum = sysnum;
   
           pthread_sigmask(SIG_SETMASK, &fullset, &omask);
         do {          do {
                 putwait(spc, &rw, &rhdr);                  putwait(spc, &rw, &rhdr);
                 if ((rv = send_with_recon(spc, &rhdr, sizeof(rhdr))) != 0) {                  if ((rv = send_with_recon(spc, &rhdr, sizeof(rhdr))) != 0) {
Line 305  syscall_req(struct spclient *spc, sigset
Line 292  syscall_req(struct spclient *spc, sigset
                         continue;                          continue;
                 }                  }
   
                 rv = cliwaitresp(spc, &rw, omask, false);                  rv = cliwaitresp(spc, &rw, &omask, false);
                 if (rv == ENOTCONN)                  if (rv == ENOTCONN)
                         rv = EAGAIN;                          rv = EAGAIN;
         } while (rv == EAGAIN);          } while (rv == EAGAIN);
           pthread_sigmask(SIG_SETMASK, &omask, NULL);
   
         *resp = rw.rw_data;          *resp = rw.rw_data;
         return rv;          return rv;
 }  }
   
 static int  static int
 handshake_req(struct spclient *spc, int type, void *data,  handshake_req(struct spclient *spc, uint32_t *auth, int cancel, bool haslock)
         int cancel, bool haslock)  
 {  {
         struct handshake_fork rf;          struct handshake_fork rf;
         struct rsp_hdr rhdr;          struct rsp_hdr rhdr;
Line 325  handshake_req(struct spclient *spc, int 
Line 312  handshake_req(struct spclient *spc, int 
         size_t bonus;          size_t bonus;
         int rv;          int rv;
   
         if (type == HANDSHAKE_FORK) {          if (auth) {
                 bonus = sizeof(rf);                  bonus = sizeof(rf);
         } else {          } else {
                 bonus = strlen(getprogname())+1;                  bonus = strlen(getprogname())+1;
Line 335  handshake_req(struct spclient *spc, int 
Line 322  handshake_req(struct spclient *spc, int 
         rhdr.rsp_len = sizeof(rhdr) + bonus;          rhdr.rsp_len = sizeof(rhdr) + bonus;
         rhdr.rsp_class = RUMPSP_REQ;          rhdr.rsp_class = RUMPSP_REQ;
         rhdr.rsp_type = RUMPSP_HANDSHAKE;          rhdr.rsp_type = RUMPSP_HANDSHAKE;
         rhdr.rsp_handshake = type;          if (auth)
                   rhdr.rsp_handshake = HANDSHAKE_FORK;
           else
                   rhdr.rsp_handshake = HANDSHAKE_GUEST;
   
         pthread_sigmask(SIG_SETMASK, &fullset, &omask);          pthread_sigmask(SIG_SETMASK, &fullset, &omask);
         if (haslock)          if (haslock)
Line 343  handshake_req(struct spclient *spc, int 
Line 333  handshake_req(struct spclient *spc, int 
         else          else
                 putwait(spc, &rw, &rhdr);                  putwait(spc, &rw, &rhdr);
         rv = dosend(spc, &rhdr, sizeof(rhdr));          rv = dosend(spc, &rhdr, sizeof(rhdr));
         if (type == HANDSHAKE_FORK) {          if (auth) {
                 memcpy(rf.rf_auth, data, sizeof(rf.rf_auth)); /* uh, why? */                  memcpy(rf.rf_auth, auth, AUTHLEN*sizeof(*auth));
                 rf.rf_cancel = cancel;                  rf.rf_cancel = cancel;
                 rv = send_with_recon(spc, &rf, sizeof(rf));                  rv = send_with_recon(spc, &rf, sizeof(rf));
         } else {          } else {
Line 356  handshake_req(struct spclient *spc, int 
Line 346  handshake_req(struct spclient *spc, int 
                 else                  else
                         unputwait(spc, &rw);                          unputwait(spc, &rw);
                 if (cancel) {                  if (cancel) {
                         goto out;                          pthread_sigmask(SIG_SETMASK, &omask, NULL);
                           return rv;
                 }                  }
         } else {          } else {
                 rv = cliwaitresp(spc, &rw, &omask, haslock);                  rv = cliwaitresp(spc, &rw, &omask, haslock);
         }          }
           pthread_sigmask(SIG_SETMASK, &omask, NULL);
         if (rv)          if (rv)
                 goto out;                  return rv;
   
         rv = *(int *)rw.rw_data;          rv = *(int *)rw.rw_data;
         free(rw.rw_data);          free(rw.rw_data);
   
  out:  
         pthread_sigmask(SIG_SETMASK, &omask, NULL);  
         return rv;          return rv;
 }  }
   
 static int  static int
 prefork_req(struct spclient *spc, sigset_t *omask, void **resp)  prefork_req(struct spclient *spc, void **resp)
 {  {
         struct rsp_hdr rhdr;          struct rsp_hdr rhdr;
         struct respwait rw;          struct respwait rw;
           sigset_t omask;
         int rv;          int rv;
   
         rhdr.rsp_len = sizeof(rhdr);          rhdr.rsp_len = sizeof(rhdr);
Line 384  prefork_req(struct spclient *spc, sigset
Line 375  prefork_req(struct spclient *spc, sigset
         rhdr.rsp_type = RUMPSP_PREFORK;          rhdr.rsp_type = RUMPSP_PREFORK;
         rhdr.rsp_error = 0;          rhdr.rsp_error = 0;
   
           pthread_sigmask(SIG_SETMASK, &fullset, &omask);
         do {          do {
                 putwait(spc, &rw, &rhdr);                  putwait(spc, &rw, &rhdr);
                 rv = send_with_recon(spc, &rhdr, sizeof(rhdr));                  rv = send_with_recon(spc, &rhdr, sizeof(rhdr));
Line 392  prefork_req(struct spclient *spc, sigset
Line 384  prefork_req(struct spclient *spc, sigset
                         continue;                          continue;
                 }                  }
   
                 rv = cliwaitresp(spc, &rw, omask, false);                  rv = cliwaitresp(spc, &rw, &omask, false);
                 if (rv == ENOTCONN)                  if (rv == ENOTCONN)
                         rv = EAGAIN;                          rv = EAGAIN;
         } while (rv == EAGAIN);          } while (rv == EAGAIN);
           pthread_sigmask(SIG_SETMASK, &omask, NULL);
   
         *resp = rw.rw_data;          *resp = rw.rw_data;
         return rv;          return rv;
Line 470  rumpclient_syscall(int sysnum, const voi
Line 463  rumpclient_syscall(int sysnum, const voi
         register_t *retval)          register_t *retval)
 {  {
         struct rsp_sysresp *resp;          struct rsp_sysresp *resp;
         sigset_t omask;  
         void *rdata;          void *rdata;
         int rv;          int rv;
   
         pthread_sigmask(SIG_SETMASK, &fullset, &omask);  
   
         DPRINTF(("rumpsp syscall_req: syscall %d with %p/%zu\n",          DPRINTF(("rumpsp syscall_req: syscall %d with %p/%zu\n",
             sysnum, data, dlen));              sysnum, data, dlen));
   
         rv = syscall_req(&clispc, &omask, sysnum, data, dlen, &rdata);          rv = syscall_req(&clispc, sysnum, data, dlen, &rdata);
         if (rv)          if (rv)
                 goto out;                  return rv;
   
         resp = rdata;          resp = rdata;
         DPRINTF(("rumpsp syscall_resp: syscall %d error %d, rv: %d/%d\n",          DPRINTF(("rumpsp syscall_resp: syscall %d error %d, rv: %d/%d\n",
Line 491  rumpclient_syscall(int sysnum, const voi
Line 481  rumpclient_syscall(int sysnum, const voi
         rv = resp->rsys_error;          rv = resp->rsys_error;
         free(rdata);          free(rdata);
   
  out:  
         pthread_sigmask(SIG_SETMASK, &omask, NULL);  
         return rv;          return rv;
 }  }
   
Line 556  handlereq(struct spclient *spc)
Line 544  handlereq(struct spclient *spc)
 static unsigned ptab_idx;  static unsigned ptab_idx;
 static struct sockaddr *serv_sa;  static struct sockaddr *serv_sa;
   
 /* dup until we get a "good" fd which does not collide with stdio */  
 static int  
 dupgood(int myfd, int mustchange)  
 {  
         int ofds[4];  
         int i;  
   
         for (i = 0; (myfd <= 2 || mustchange) && myfd != -1; i++) {  
                 assert(i < __arraycount(ofds));  
                 ofds[i] = myfd;  
                 myfd = host_dup(myfd);  
                 if (mustchange) {  
                         i--; /* prevent closing old fd */  
                         mustchange = 0;  
                 }  
         }  
   
         for (i--; i >= 0; i--) {  
                 host_close(ofds[i]);  
         }  
   
         return myfd;  
 }  
   
 static int  static int
 doconnect(bool noisy)  doconnect(bool noisy)
 {  {
Line 627  doconnect(bool noisy)
Line 591  doconnect(bool noisy)
         free(clispc.spc_buf);          free(clispc.spc_buf);
         clispc.spc_off = 0;          clispc.spc_off = 0;
   
         s = dupgood(host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0), 0);          s = host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0);
         if (s == -1)          if (s == -1)
                 return -1;                  return -1;
   
Line 682  doconnect(bool noisy)
Line 646  doconnect(bool noisy)
         clispc.spc_reconnecting = 0;          clispc.spc_reconnecting = 0;
   
         /* setup kqueue, we want all signals and the fd */          /* setup kqueue, we want all signals and the fd */
         if ((kq = dupgood(host_kqueue(), 0)) == -1) {          if ((kq = host_kqueue()) == -1) {
                 error = errno;                  error = errno;
                 if (noisy)                  if (noisy)
                         fprintf(stderr, "rump_sp: cannot setup kqueue");                          fprintf(stderr, "rump_sp: cannot setup kqueue");
Line 717  doinit(void)
Line 681  doinit(void)
         return 0;          return 0;
 }  }
   
 void *rumpclient__dlsym(void *, const char *);  void *(*rumpclient_dlsym)(void *, const char *);
 void *rumphijack_dlsym(void *, const char *);  
 void *  
 rumpclient__dlsym(void *handle, const char *symbol)  
 {  
   
         return dlsym(handle, symbol);  
 }  
 __weak_alias(rumphijack_dlsym,rumpclient__dlsym);  
   
 static pid_t init_done = 0;  
   
 int  int
 rumpclient_init()  rumpclient_init()
 {  {
         char *p;          char *p;
         int error;          int error;
         int rv = -1;  
         int hstype;  
         pid_t mypid;  
   
         /*  
          * Make sure we're not riding the context of a previous  
          * host fork.  Note: it's *possible* that after n>1 forks  
          * we have the same pid as one of our exited parents, but  
          * I'm pretty sure there are 0 practical implications, since  
          * it means generations would have to skip rumpclient init.  
          */  
         if (init_done == (mypid = getpid()))  
                 return 0;  
   
         /* kq does not traverse fork() */  
         if (init_done != 0)  
                 kq = -1;  
         init_done = mypid;  
   
         sigfillset(&fullset);          /* dlsym overrided by rumphijack? */
           if (!rumpclient_dlsym)
                   rumpclient_dlsym = dlsym;
   
         /*          /*
          * sag mir, wo die symbol sind.  zogen fort, der krieg beginnt.           * sag mir, wo die symbol sind.  zogen fort, der krieg beginnt.
          * wann wird man je verstehen?  wann wird man je verstehen?           * wann wird man je verstehen?  wann wird man je verstehen?
          */           */
 #define FINDSYM2(_name_,_syscall_)                                      \  #define FINDSYM2(_name_,_syscall_)                                      \
         if ((host_##_name_ = rumphijack_dlsym(RTLD_NEXT,                \          if ((host_##_name_ = rumpclient_dlsym(RTLD_NEXT,                \
             #_syscall_)) == NULL) {                                     \              #_syscall_)) == NULL)                                       \
                 if (rumphijack_dlsym == rumpclient__dlsym)              \                  /* host_##_name_ = _syscall_ */;
                         host_##_name_ = _name_; /* static fallback */   \  
                 if (host_##_name_ == NULL)                              \  
                         errx(1, "cannot find %s: %s", #_syscall_,       \  
                             dlerror());                                 \  
         }  
 #define FINDSYM(_name_) FINDSYM2(_name_,_name_)  #define FINDSYM(_name_) FINDSYM2(_name_,_name_)
         FINDSYM2(socket,__socket30)          FINDSYM2(socket,__socket30);
         FINDSYM(close)          FINDSYM(close);
         FINDSYM(connect)          FINDSYM(connect);
         FINDSYM(fcntl)          FINDSYM(fcntl);
         FINDSYM(poll)          FINDSYM(poll);
         FINDSYM(read)          FINDSYM(read);
         FINDSYM(sendto)          FINDSYM(sendto);
         FINDSYM(setsockopt)          FINDSYM(setsockopt);
         FINDSYM(dup)          FINDSYM(kqueue);
         FINDSYM(kqueue)  
         FINDSYM(execve)  
 #if !__NetBSD_Prereq__(5,99,7)  #if !__NetBSD_Prereq__(5,99,7)
         FINDSYM(kevent)          FINDSYM(kevent);
 #else  #else
         FINDSYM2(kevent,_sys___kevent50)          FINDSYM2(kevent,_sys___kevent50);
 #endif  #endif
 #undef  FINDSYM  #undef  FINDSYM
 #undef  FINDSY2  #undef  FINDSY2
   
         if ((p = getenv("RUMP__PARSEDSERVER")) == NULL) {          if ((p = getenv("RUMP_SERVER")) == NULL) {
                 if ((p = getenv("RUMP_SERVER")) == NULL) {                  errno = ENOENT;
                         errno = ENOENT;                  return -1;
                         goto out;  
                 }  
         }          }
   
         if ((error = parseurl(p, &serv_sa, &ptab_idx, 0)) != 0) {          if ((error = parseurl(p, &serv_sa, &ptab_idx, 0)) != 0) {
                 errno = error;                  errno = error;
                 goto out;                  return -1;
         }          }
   
         if (doinit() == -1)          if (doinit() == -1)
                 goto out;                  return -1;
           if (doconnect(true) == -1)
         if ((p = getenv("RUMPCLIENT__EXECFD")) != NULL) {                  return -1;
                 sscanf(p, "%d,%d", &clispc.spc_fd, &kq);  
                 unsetenv("RUMPCLIENT__EXECFD");  
                 hstype = HANDSHAKE_EXEC;  
         } else {  
                 if (doconnect(true) == -1)  
                         goto out;  
                 hstype = HANDSHAKE_GUEST;  
         }  
   
         error = handshake_req(&clispc, hstype, NULL, 0, false);          error = handshake_req(&clispc, NULL, 0, false);
         if (error) {          if (error) {
                 pthread_mutex_destroy(&clispc.spc_mtx);                  pthread_mutex_destroy(&clispc.spc_mtx);
                 pthread_cond_destroy(&clispc.spc_cv);                  pthread_cond_destroy(&clispc.spc_cv);
                 if (clispc.spc_fd != -1)                  if (clispc.spc_fd != -1)
                         host_close(clispc.spc_fd);                          host_close(clispc.spc_fd);
                 errno = error;                  errno = error;
                 goto out;                  return -1;
         }          }
         rv = 0;  
   
  out:          sigfillset(&fullset);
         if (rv == -1)          return 0;
                 init_done = 0;  
         return rv;  
 }  }
   
 struct rumpclient_fork {  struct rumpclient_fork {
         uint32_t fork_auth[AUTHLEN];          uint32_t fork_auth[AUTHLEN];
         struct spclient fork_spc;  
         int fork_kq;  
 };  };
   
 struct rumpclient_fork *  struct rumpclient_fork *
 rumpclient_prefork(void)  rumpclient_prefork(void)
 {  {
         struct rumpclient_fork *rpf;          struct rumpclient_fork *rpf;
         sigset_t omask;  
         void *resp;          void *resp;
         int rv;          int rv;
   
         pthread_sigmask(SIG_SETMASK, &fullset, &omask);  
         rpf = malloc(sizeof(*rpf));          rpf = malloc(sizeof(*rpf));
         if (rpf == NULL)          if (rpf == NULL)
                 goto out;                  return NULL;
   
         if ((rv = prefork_req(&clispc, &omask, &resp)) != 0) {          if ((rv = prefork_req(&clispc, &resp)) != 0) {
                 free(rpf);                  free(rpf);
                 errno = rv;                  errno = rv;
                 rpf = NULL;                  return NULL;
                 goto out;  
         }          }
   
         memcpy(rpf->fork_auth, resp, sizeof(rpf->fork_auth));          memcpy(rpf->fork_auth, resp, sizeof(rpf->fork_auth));
         free(resp);          free(resp);
   
         rpf->fork_spc = clispc;  
         rpf->fork_kq = kq;  
   
  out:  
         pthread_sigmask(SIG_SETMASK, &omask, NULL);  
         return rpf;          return rpf;
 }  }
   
Line 884  rumpclient_fork_init(struct rumpclient_f
Line 792  rumpclient_fork_init(struct rumpclient_f
         if (doconnect(false) == -1)          if (doconnect(false) == -1)
                 return -1;                  return -1;
   
         error = handshake_req(&clispc, HANDSHAKE_FORK, rpf->fork_auth,          error = handshake_req(&clispc, rpf->fork_auth, 0, false);
             0, false);  
         if (error) {          if (error) {
                 pthread_mutex_destroy(&clispc.spc_mtx);                  pthread_mutex_destroy(&clispc.spc_mtx);
                 pthread_cond_destroy(&clispc.spc_cv);                  pthread_cond_destroy(&clispc.spc_cv);
Line 897  rumpclient_fork_init(struct rumpclient_f
Line 804  rumpclient_fork_init(struct rumpclient_f
 }  }
   
 void  void
 rumpclient_fork_cancel(struct rumpclient_fork *rpf)  
 {  
   
         /* EUNIMPL */  
 }  
   
 void  
 rumpclient_fork_vparent(struct rumpclient_fork *rpf)  
 {  
   
         clispc = rpf->fork_spc;  
         kq = rpf->fork_kq;  
 }  
   
 void  
 rumpclient_setconnretry(time_t timeout)  rumpclient_setconnretry(time_t timeout)
 {  {
   
Line 920  rumpclient_setconnretry(time_t timeout)
Line 812  rumpclient_setconnretry(time_t timeout)
   
         retrytimo = timeout;          retrytimo = timeout;
 }  }
   
 int  
 rumpclient__closenotify(int *fdp, enum rumpclient_closevariant variant)  
 {  
         int fd = *fdp;  
         int untilfd, rv;  
         int newfd;  
   
         switch (variant) {  
         case RUMPCLIENT_CLOSE_FCLOSEM:  
                 untilfd = MAX(clispc.spc_fd, kq);  
                 for (; fd <= untilfd; fd++) {  
                         if (fd == clispc.spc_fd || fd == kq)  
                                 continue;  
                         rv = host_close(fd);  
                         if (rv == -1)  
                                 return -1;  
                 }  
                 *fdp = fd;  
                 break;  
   
         case RUMPCLIENT_CLOSE_CLOSE:  
         case RUMPCLIENT_CLOSE_DUP2:  
                 if (fd == clispc.spc_fd) {  
                         struct kevent kev[2];  
   
                         newfd = dupgood(clispc.spc_fd, 1);  
                         if (newfd == -1)  
                                 return -1;  
                         /*  
                          * now, we have a new socket number, so change  
                          * the file descriptor that kqueue is  
                          * monitoring.  remove old and add new.  
                          */  
                         EV_SET(&kev[0], clispc.spc_fd,  
                             EVFILT_READ, EV_DELETE, 0, 0, 0);  
                         EV_SET(&kev[1], newfd,  
                             EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0);  
                         if (host_kevent(kq, kev, 2, NULL, 0, NULL) == -1) {  
                                 int sverrno = errno;  
                                 host_close(newfd);  
                                 errno = sverrno;  
                                 return -1;  
                         }  
                         clispc.spc_fd = newfd;  
                 }  
                 if (fd == kq) {  
                         newfd = dupgood(kq, 1);  
                         if (newfd == -1)  
                                 return -1;  
                         kq = newfd;  
                 }  
                 break;  
         }  
   
         return 0;  
 }  
   
 pid_t  
 rumpclient_fork()  
 {  
   
         return rumpclient__dofork(fork);  
 }  
   
 /*  
  * Process is about to exec.  Save info about our existing connection  
  * in the env.  rumpclient will check for this info in init().  
  * This is mostly for the benefit of rumphijack, but regular applications  
  * may use it as well.  
  */  
 int  
 rumpclient_exec(const char *path, char *const argv[], char *const envp[])  
 {  
         char buf[4096];  
         char **newenv;  
         char *envstr, *envstr2;  
         size_t nelem;  
         int rv, sverrno;  
   
         snprintf(buf, sizeof(buf), "RUMPCLIENT__EXECFD=%d,%d",  
             clispc.spc_fd, kq);  
         envstr = malloc(strlen(buf)+1);  
         if (envstr == NULL) {  
                 return ENOMEM;  
         }  
         strcpy(envstr, buf);  
   
         /* do we have a fully parsed url we want to forward in the env? */  
         if (*parsedurl != '\0') {  
                 snprintf(buf, sizeof(buf),  
                     "RUMP__PARSEDSERVER=%s", parsedurl);  
                 envstr2 = malloc(strlen(buf)+1);  
                 if (envstr2 == NULL) {  
                         free(envstr);  
                         return ENOMEM;  
                 }  
                 strcpy(envstr2, buf);  
         } else {  
                 envstr2 = NULL;  
         }  
   
         for (nelem = 0; envp && envp[nelem]; nelem++)  
                 continue;  
   
         newenv = malloc(sizeof(*newenv) * (nelem+3));  
         if (newenv == NULL) {  
                 free(envstr2);  
                 free(envstr);  
                 return ENOMEM;  
         }  
         memcpy(&newenv[0], envp, nelem*sizeof(*envp));  
   
         newenv[nelem] = envstr;  
         newenv[nelem+1] = envstr2;  
         newenv[nelem+2] = NULL;  
   
         rv = host_execve(path, argv, newenv);  
   
         _DIAGASSERT(rv != 0);  
         sverrno = errno;  
         free(envstr2);  
         free(envstr);  
         free(newenv);  
         errno = sverrno;  
         return rv;  
 }  
   
 int  
 rumpclient_daemon(int nochdir, int noclose)  
 {  
         struct rumpclient_fork *rf;  
         int sverrno;  
   
         if ((rf = rumpclient_prefork()) == NULL)  
                 return -1;  
   
         if (daemon(nochdir, noclose) == -1) {  
                 sverrno = errno;  
                 rumpclient_fork_cancel(rf);  
                 errno = sverrno;  
                 return -1;  
         }  
   
         if (rumpclient_fork_init(rf) == -1)  
                 return -1;  
   
         return 0;  
 }  

Legend:
Removed from v.1.16.2.3  
changed lines
  Added in v.1.24

CVSweb <webmaster@jp.NetBSD.org>