[BACK]Return to cvsd.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Diff for /src/usr.bin/cvs/Attic/cvsd.c between version 1.2 and 1.3

version 1.2, 2004/07/16 01:46:16 version 1.3, 2004/07/25 03:29:35
Line 60 
Line 60 
   
 int foreground = 0;  int foreground = 0;
   
   volatile sig_atomic_t running = 0;
 volatile sig_atomic_t restart = 0;  volatile sig_atomic_t restart = 0;
   
   
Line 68 
Line 69 
   
   
 char *cvsd_root = NULL;  char *cvsd_root = NULL;
 char *cvsd_aclfile = NULL;  char *cvsd_conffile = CVSD_CONF;
   
   
 static int    cvsd_privfd = -1;  static int    cvsd_privfd = -1;
Line 81 
Line 82 
 static volatile sig_atomic_t   cvsd_chmax = CVSD_CHILD_DEFMAX;  static volatile sig_atomic_t   cvsd_chmax = CVSD_CHILD_DEFMAX;
   
   
   void   usage           (void);
   void   sighup_handler  (int);
   void   sigint_handler  (int);
   void   sigchld_handler (int);
   int    cvsd_msghdlr    (struct cvsd_child *, int);
   
   
 /*  /*
  * sighup_handler()   * sighup_handler()
  *   *
Line 103 
Line 111 
 void  void
 sigint_handler(int signo)  sigint_handler(int signo)
 {  {
         cvs_sock_doloop = 0;  
 }  }
   
   
Line 132 
Line 139 
 usage(void)  usage(void)
 {  {
         fprintf(stderr,          fprintf(stderr,
             "Usage: %s [-dfpv] [-a aclfile] [-c config] [-r root] [-s path]\n"              "Usage: %s [-dfpv] [-c config] [-r root] [-s path]\n"
             "\t-a aclfile\tUse the file <aclfile> for ACL ruleset\n"  
             "\t-d\t\tStart the server in debugging mode (very verbose)\n"              "\t-d\t\tStart the server in debugging mode (very verbose)\n"
             "\t-f\t\tStay in foreground instead of becoming a daemon\n"              "\t-f\t\tStay in foreground instead of becoming a daemon\n"
             "\t-p\t\tPerform permission and ownership check on the repository\n"              "\t-p\t\tPerform permission and ownership check on the repository\n"
Line 149 
Line 155 
 {  {
         u_int i;          u_int i;
         int ret, checkrepo;          int ret, checkrepo;
         uid_t uid;  
         struct passwd *pwd;          struct passwd *pwd;
         struct group *grp;          struct group *grp;
   
Line 158 
Line 163 
         if (cvs_log_init(LD_STD|LD_SYSLOG, LF_PID) < 0)          if (cvs_log_init(LD_STD|LD_SYSLOG, LF_PID) < 0)
                 err(1, "failed to initialize logging mechanism");                  err(1, "failed to initialize logging mechanism");
   
         while ((ret = getopt(argc, argv, "a:dfpr:s:v")) != -1) {          while ((ret = getopt(argc, argv, "a:c:dfpr:s:v")) != -1) {
                 switch (ret) {                  switch (ret) {
                 case 'a':                  case 'c':
                         cvsd_aclfile = optarg;                          cvsd_conffile = optarg;
                         break;                          break;
                 case 'd':                  case 'd':
                         cvs_log_filter(LP_FILTER_UNSET, LP_DEBUG);                          cvs_log_filter(LP_FILTER_UNSET, LP_DEBUG);
Line 191 
Line 196 
         argc -= optind;          argc -= optind;
         argv += optind;          argv += optind;
   
         if ((cvsd_aclfile != NULL) && (cvs_acl_parse(cvsd_aclfile) < 0))          if (cvs_conf_read(cvsd_conffile) < 0)
                 errx(1, "error while parsing the ACL file `%s'", cvsd_aclfile);                  errx(1, "error parsing configuration file `%s'", cvsd_conffile);
   
         if (cvsd_root == NULL)          if (cvsd_root == NULL)
                 errx(1, "no CVS root directory specified");                  errx(1, "no CVS root directory specified");
Line 243 
Line 248 
         }          }
   
         /* spawn the initial pool of children */          /* spawn the initial pool of children */
         for (i = 0; i < cvsd_chmin; i++) {          for (i = 0; i < (u_int)cvsd_chmin; i++) {
                 ret = cvsd_forkchild();                  ret = cvsd_child_fork(NULL);
                 if (ret == -1) {                  if (ret == -1) {
                         cvs_log(LP_ERR, "failed to spawn child");                          cvs_log(LP_ERR, "failed to spawn child");
                         exit(EX_OSERR);                          exit(EX_OSERR);
                 }                  }
         }          }
   
         cvsd_sock_loop();          cvsd_parent_loop();
   
         cvs_log(LP_NOTICE, "shutting down");          cvs_log(LP_NOTICE, "shutting down");
         cvs_log_cleanup();          cvs_log_cleanup();
Line 394 
Line 399 
   
   
 /*  /*
  * cvsd_forkchild()   * cvsd_child_fork()
  *   *
  * Fork a child process which chroots to the CVS repository's root directory.   * Fork a child process which chroots to the CVS repository's root directory.
  * We need to temporarily regain privileges in order to chroot.   * We need to temporarily regain privileges in order to chroot.
  * On success, returns 0 if this is the child process, 1 if this is the   * If the <chpp> argument is not NULL, a reference to the newly created child
  * parent, or -1 on failure.   * structure will be returned.
    * On success, returns 0 in the child process context, 1 in the parent's
    * context, or -1 on failure.
  */   */
   
 int  int
 cvsd_forkchild(void)  cvsd_child_fork(struct cvsd_child **chpp)
 {  {
         int svec[2];          int svec[2];
         pid_t pid;          pid_t pid;
         struct cvsd_child *chp;          struct cvsd_child *chp;
   
           if (cvsd_chnum == cvsd_chmax) {
                   cvs_log(LP_WARN, "child pool reached limit of processes");
                   return (-1);
           }
   
         if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, svec) == -1) {          if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, svec) == -1) {
                 cvs_log(LP_ERRNO, "failed to create socket pair");                  cvs_log(LP_ERRNO, "failed to create socket pair");
                 return (-1);                  return (-1);
Line 468 
Line 480 
   
         chp->ch_pid = pid;          chp->ch_pid = pid;
         chp->ch_sock = svec[0];          chp->ch_sock = svec[0];
         (void)close(svec[1]);          chp->ch_state = CVSD_ST_IDLE;
   
           TAILQ_INSERT_TAIL(&cvsd_children, chp, ch_list);
   
           if (chpp != NULL)
                   *chpp = chp;
           (void)close(svec[1]);
         return (1);          return (1);
 }  }
   
   
 /*  /*
    * cvsd_child_reap()
    *
    * Returns 0 on success, or -1 on failure.
    */
   
   int
   cvsd_child_reap(struct cvsd_child *ch)
   {
   
   
           return (0);
   }
   
   
   /*
    * cvsd_child_get()
    *
    * Find a child process in idle state and return a pointer to the child's
    * structure.  If there are no available child processes, a new one will be
    * created unless the number of children has attained the maximum, in which
    * case NULL is returned.
    */
   
   struct cvsd_child*
   cvsd_child_get(void)
   {
           struct cvsd_child *chp;
   
           TAILQ_FOREACH(chp, &cvsd_children, ch_list)
                   if (chp->ch_state == CVSD_ST_IDLE)
                           return (chp);
   
           /* no available child, attempt to fork a new one */
           chp = NULL;
           if ((cvsd_chnum < cvsd_chmax) && (cvsd_child_fork(&chp) < 0))
                   return (NULL);
   
           return (chp);
   }
   
   
   
   /*
  * cvsd_parent_loop()   * cvsd_parent_loop()
  *   *
  * Main loop of the parent cvsd process, which listens on its end of the   * Main loop of the parent cvsd process, which listens on its end of the
  * socket pair for requests from the chrooted child.   * local socket for requests from the cvs(1) program and on any outstanding
    * messages from the children.
  */   */
   
 static void  static void
 cvsd_parent_loop(void)  cvsd_parent_loop(void)
 {  {
         uid_t uid;          int cfd, timeout, ret;
         int timeout, ret;  
         nfds_t nfds, i;          nfds_t nfds, i;
         struct pollfd *pfd;          struct pollfd *pfd;
         struct cvsd_child *chp;          struct cvsd_child *chp;
   
         nfds = 0;          nfds = 0;
         timeout = INFTIM;          timeout = INFTIM;
           pfd = NULL;
   
         for (;;) {          for (;;) {
                 nfds = cvsd_chnum;                  if (!running)
                           break;
   
                   if (restart) {
                           /* restart server */
                   }
                   nfds = cvsd_chnum + 1;
                 pfd = (struct pollfd *)realloc(pfd,                  pfd = (struct pollfd *)realloc(pfd,
                     nfds * sizeof(struct pollfd));                      nfds * sizeof(struct pollfd));
                 if (pfd == NULL) {                  if (pfd == NULL) {
Line 502 
Line 569 
                         return;                          return;
                 }                  }
   
                 i = 0;                  pfd[0].fd = cvsd_sock;
                   pfd[0].events = POLLIN;
                   pfd[0].revents = 0;
                   i = 1;
                 TAILQ_FOREACH(chp, &cvsd_children, ch_list) {                  TAILQ_FOREACH(chp, &cvsd_children, ch_list) {
                         pfd[i].fd = chp->ch_sock;                          pfd[i].fd = chp->ch_sock;
                         pfd[i].events = POLLIN;                          pfd[i].events = POLLIN;
                         pfd[i].revents = 0;                          pfd[i].revents = 0;
                         i++;                          i++;
   
                         if (i == nfds)                          if (i == nfds)   /* just a precaution */
                                 break;                                  break;
                 }                  }
   
Line 519 
Line 589 
                         break;                          break;
                 }                  }
   
                   if (pfd[0].revents & (POLLERR|POLLNVAL)) {
                           cvs_log(LP_ERR, "poll error on request socket");
                   }
                   else if (pfd[0].revents & POLLIN) {
                           cfd = cvsd_sock_accept(pfd[0].fd);
                           if (cfd == -1)
                           chp = cvsd_child_get();
                           if (chp == NULL) {
                                   cvs_log(LP_ALERT,
                                       "request queue not implemented");
                                   break;
                           }
   
                           if (cvsd_sendmsg(chp->ch_sock, CVSD_MSG_PASSFD,
                               &cfd, sizeof(cfd)) < 0)
                                   break;
   
                           /* mark the child as busy */
                           chp->ch_state = CVSD_ST_BUSY;
                   }
   
                 chp = TAILQ_FIRST(&cvsd_children);                  chp = TAILQ_FIRST(&cvsd_children);
                 for (i = 0; i < nfds; i++) {                  for (i = 1; i < nfds; i++) {
                         if (pfd[i].revents & (POLLERR|POLLNVAL)) {                          if (pfd[i].revents & (POLLERR|POLLNVAL)) {
                                 cvs_log(LP_ERR,                                  cvs_log(LP_ERR,
                                     "poll error on child socket (PID %d)",                                      "poll error on child socket (PID %d)",
                                     chp->ch_pid);                                      chp->ch_pid);
                         }                          }
                         else                          else if (pfd[i].revents & POLLIN)
                                 cvsd_msghdlr(chp, pfd[i].fd);                                  cvsd_msghdlr(chp, pfd[i].fd);
   
                         chp = TAILQ_NEXT(chp, ch_list);                          chp = TAILQ_NEXT(chp, ch_list);
Line 545 
Line 636 
 cvsd_child_loop(void)  cvsd_child_loop(void)
 {  {
         int ret, timeout;          int ret, timeout;
           uid_t uid;
           gid_t gid;
         struct pollfd pfd[1];          struct pollfd pfd[1];
   
         pfd[0].fd = cvsd_privfd;          pfd[0].fd = cvsd_privfd;
Line 561 
Line 654 
                 }                  }
                 cvs_log(LP_INFO, "polling");                  cvs_log(LP_INFO, "polling");
   
                   if (pfd[0].revents & (POLLERR|POLLNVAL)) {
                           cvs_log(LP_ERR, "poll error");
                           break;
                   }
         }          }
   
         exit(0);          exit(0);
Line 569 
Line 666 
   
 /*  /*
  * cvsd_msghdlr()   * cvsd_msghdlr()
    *
    * Handler for messages received from child processes.
    * Returns 0 on success, or -1 on failure.
  */   */
   
 int  int
Line 631 
Line 731 
                         iov[1].iov_base = pw->pw_name;                          iov[1].iov_base = pw->pw_name;
                 }                  }
                 break;                  break;
           case CVSD_MSG_GETGID:
                   rbuf[ret] = '\0';
                   cvs_log(LP_INFO, "getting GID for `%s'", rbuf);
   
                   gr = getgrnam(rbuf);
                   if (gr != NULL) {
                           msg.cm_type = CVSD_MSG_GID;
                           msg.cm_len = sizeof(gid_t);
                           iov[1].iov_len = msg.cm_len;
                           iov[1].iov_base = &(gr->gr_gid);
                   }
                   break;
           case CVSD_MSG_SETIDLE:
                   child->ch_state = CVSD_ST_IDLE;
                   break;
         default:          default:
                 cvs_log(LP_ERR, "unknown command type %u", msg.cm_type);                  cvs_log(LP_ERR, "unknown command type %u", msg.cm_type);
                 return (-1);                  return (-1);
Line 639 
Line 754 
         ret = writev(fd, iov, 2);          ret = writev(fd, iov, 2);
   
         return (ret);          return (ret);
   }
   
   
   /*
    * cvsd_set()
    *
    * Generic interface to set some of the parameters of the cvs server.
    * Returns 0 on success, or -1 on failure.
    */
   
   int
   cvsd_set(int what, ...)
   {
           char *str;
           va_list vap;
   
           va_start(vap, what);
   
           switch (what) {
           case CVSD_SET_ROOT:
                   str = va_arg(vap, char *);
                   cvsd_root = str;
                   break;
           case CVSD_SET_CHMIN:
                   cvsd_chmin = va_arg(vap, int);
                   /* we should increase the number of children accordingly */
                   break;
           case CVSD_SET_CHMAX:
                   cvsd_chmax = va_arg(vap, int);
                   /* we should decrease the number of children accordingly */
                   break;
           case CVSD_SET_ADDR:
                   /* this is more like and add than a set */
                   break;
           case CVSD_SET_SOCK:
                   cvsd_sock_path = va_arg(vap, char *);
                   if (cvsd_sock_open() < 0)
                           return (-1);
                   break;
           default:
                   cvs_log(LP_ERR, "invalid field to set");
                   return (-1);
           }
   
           va_end(vap);
   
           return (0);
 }  }

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3