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

Diff for /src/usr.bin/cvs/Attic/proto.c between version 1.12 and 1.13

version 1.12, 2004/07/29 19:03:33 version 1.13, 2004/07/30 01:49:24
Line 58 
Line 58 
 #include "buf.h"  #include "buf.h"
 #include "cvs.h"  #include "cvs.h"
 #include "log.h"  #include "log.h"
   #include "proto.h"
   
   
 #define CVS_MTSTK_MAXDEPTH   16  #define CVS_MTSTK_MAXDEPTH   16
Line 77 
Line 78 
   
   
   
 static int  cvs_resp_validreq  (int, char *);  static int  cvs_resp_validreq  (struct cvsroot *, int, char *);
 static int  cvs_resp_cksum     (int, char *);  static int  cvs_resp_cksum     (struct cvsroot *, int, char *);
 static int  cvs_resp_modtime   (int, char *);  static int  cvs_resp_modtime   (struct cvsroot *, int, char *);
 static int  cvs_resp_m         (int, char *);  static int  cvs_resp_m         (struct cvsroot *, int, char *);
 static int  cvs_resp_ok        (int, char *);  static int  cvs_resp_ok        (struct cvsroot *, int, char *);
 static int  cvs_resp_error     (int, char *);  static int  cvs_resp_error     (struct cvsroot *, int, char *);
 static int  cvs_resp_statdir   (int, char *);  static int  cvs_resp_statdir   (struct cvsroot *, int, char *);
 static int  cvs_resp_sticky    (int, char *);  static int  cvs_resp_sticky    (struct cvsroot *, int, char *);
 static int  cvs_resp_newentry  (int, char *);  static int  cvs_resp_newentry  (struct cvsroot *, int, char *);
 static int  cvs_resp_updated   (int, char *);  static int  cvs_resp_updated   (struct cvsroot *, int, char *);
 static int  cvs_resp_removed   (int, char *);  static int  cvs_resp_removed   (struct cvsroot *, int, char *);
 static int  cvs_resp_mode      (int, char *);  static int  cvs_resp_mode      (struct cvsroot *, int, char *);
 static int  cvs_resp_modxpand  (int, char *);  static int  cvs_resp_modxpand  (struct cvsroot *, int, char *);
   
   static int  cvs_initlog   (void);
   
 static const char *cvs_months[] = {  static const char *cvs_months[] = {
         "Jan", "Feb", "Mar", "Apr", "May", "Jun",          "Jan", "Feb", "Mar", "Apr", "May", "Jun",
Line 103 
Line 105 
         int      req_id;          int      req_id;
         char     req_str[32];          char     req_str[32];
         u_int    req_flags;          u_int    req_flags;
         int    (*req_hdlr)(int, char *);          int     (*req_hdlr)(int, char *);
 } cvs_requests[] = {  } cvs_requests[] = {
         { CVS_REQ_DIRECTORY,     "Directory",         0,  NULL },          { CVS_REQ_DIRECTORY,     "Directory",         0,  NULL },
         { CVS_REQ_MAXDOTDOT,     "Max-dotdot",        0,  NULL },          { CVS_REQ_MAXDOTDOT,     "Max-dotdot",        0,  NULL },
Line 148 
Line 150 
         { CVS_REQ_REMOVE,        "remove",            CVS_REQF_RESP,  NULL },          { CVS_REQ_REMOVE,        "remove",            CVS_REQF_RESP,  NULL },
         { CVS_REQ_RELEASE,       "release",           CVS_REQF_RESP,  NULL },          { CVS_REQ_RELEASE,       "release",           CVS_REQF_RESP,  NULL },
         { CVS_REQ_ROOT,          "Root",              0,  NULL },          { CVS_REQ_ROOT,          "Root",              0,  NULL },
         { CVS_REQ_VALIDRESP,     "Valid-responses",   CVS_REQF_RESP,  NULL },          { CVS_REQ_VALIDRESP,     "Valid-responses",   0,  NULL },
         { CVS_REQ_VALIDREQ,      "valid-requests",    CVS_REQF_RESP,  NULL },          { CVS_REQ_VALIDREQ,      "valid-requests",    CVS_REQF_RESP,  NULL },
         { CVS_REQ_VERSION,       "version",           CVS_REQF_RESP,  NULL },          { CVS_REQ_VERSION,       "version",           CVS_REQF_RESP,  NULL },
         { CVS_REQ_NOOP,          "noop",              CVS_REQF_RESP,  NULL },          { CVS_REQ_NOOP,          "noop",              CVS_REQF_RESP,  NULL },
Line 159 
Line 161 
 struct cvs_resp {  struct cvs_resp {
         u_int  resp_id;          u_int  resp_id;
         char   resp_str[32];          char   resp_str[32];
         int  (*resp_hdlr)(int, char *);          int  (*resp_hdlr)(struct cvsroot *, int, char *);
 } cvs_responses[] = {  } cvs_responses[] = {
         { CVS_RESP_OK,         "ok",                     cvs_resp_ok       },          { CVS_RESP_OK,         "ok",                     cvs_resp_ok       },
         { CVS_RESP_ERROR,      "error",                  cvs_resp_error    },          { CVS_RESP_ERROR,      "error",                  cvs_resp_error    },
Line 209 
Line 211 
   
 mode_t  cvs_lastmode = 0;  mode_t  cvs_lastmode = 0;
   
   static char  cvs_proto_buf[4096];
   
 /*  /*
    * Output files for protocol logging when the CVS_CLIENT_LOG enviroment
    * variable is set.
    */
   static int   cvs_server_logon = 0;
   static FILE *cvs_server_inlog = NULL;
   static FILE *cvs_server_outlog = NULL;
   
   
   /*
    * cvs_connect()
    *
    * Open a client connection to the cvs server whose address is given in
    * the <root> variable.  The method used to connect depends on the
    * setting of the CVS_RSH variable.
    * Returns 0 on success, or -1 on failure.
    */
   
   int
   cvs_connect(struct cvsroot *root)
   {
           int argc, infd[2], outfd[2];
           pid_t pid;
           char *argv[16], *cvs_server_cmd, *vresp;
   
           if (pipe(infd) == -1) {
                   cvs_log(LP_ERRNO,
                       "failed to create input pipe for client connection");
                   return (-1);
           }
   
           if (pipe(outfd) == -1) {
                   cvs_log(LP_ERRNO,
                       "failed to create output pipe for client connection");
                   (void)close(infd[0]);
                   (void)close(infd[1]);
                   return (-1);
           }
   
           pid = fork();
           if (pid == -1) {
                   cvs_log(LP_ERRNO, "failed to fork for cvs server connection");
                   return (-1);
           }
           if (pid == 0) {
                   if ((dup2(infd[0], STDIN_FILENO) == -1) ||
                       (dup2(outfd[1], STDOUT_FILENO) == -1)) {
                           cvs_log(LP_ERRNO,
                               "failed to setup standard streams for cvs server");
                           return (-1);
                   }
                   (void)close(infd[1]);
                   (void)close(outfd[0]);
   
                   argc = 0;
                   argv[argc++] = cvs_rsh;
   
                   if (root->cr_user != NULL) {
                           argv[argc++] = "-l";
                           argv[argc++] = root->cr_user;
                   }
   
   
                   cvs_server_cmd = getenv("CVS_SERVER");
                   if (cvs_server_cmd == NULL)
                           cvs_server_cmd = "cvs";
   
                   argv[argc++] = root->cr_host;
                   argv[argc++] = cvs_server_cmd;
                   argv[argc++] = "server";
                   argv[argc] = NULL;
   
                   execvp(argv[0], argv);
                   cvs_log(LP_ERRNO, "failed to exec");
                   exit(EX_OSERR);
           }
   
           /* we are the parent */
           (void)close(infd[0]);
           (void)close(outfd[1]);
   
           root->cr_srvin = fdopen(infd[1], "w");
           if (root->cr_srvin == NULL) {
                   cvs_log(LP_ERRNO, "failed to create pipe stream");
                   return (-1);
           }
   
           root->cr_srvout = fdopen(outfd[0], "r");
           if (root->cr_srvout == NULL) {
                   cvs_log(LP_ERRNO, "failed to create pipe stream");
                   return (-1);
           }
   
           /* make the streams line-buffered */
           (void)setvbuf(root->cr_srvin, NULL, _IOLBF, 0);
           (void)setvbuf(root->cr_srvout, NULL, _IOLBF, 0);
   
           cvs_initlog();
   
           /*
            * Send the server the list of valid responses, then ask for valid
            * requests.
            */
   
           vresp = cvs_resp_getvalid();
           if (vresp == NULL) {
                   cvs_log(LP_ERR, "can't generate list of valid responses");
                   return (-1);
           }
   
           if (cvs_sendreq(root, CVS_REQ_VALIDRESP, vresp) < 0) {
           }
           free(vresp);
   
           if (cvs_sendreq(root, CVS_REQ_VALIDREQ, NULL) < 0) {
                   cvs_log(LP_ERR, "failed to get valid requests from server");
                   return (-1);
           }
   
           /* now share our global options with the server */
           if (verbosity == 1)
                   cvs_sendreq(root, CVS_REQ_GLOBALOPT, "-q");
           else if (verbosity == 0)
                   cvs_sendreq(root, CVS_REQ_GLOBALOPT, "-Q");
   
           if (cvs_nolog)
                   cvs_sendreq(root, CVS_REQ_GLOBALOPT, "-l");
           if (cvs_readonly)
                   cvs_sendreq(root, CVS_REQ_GLOBALOPT, "-r");
           if (cvs_trace)
                   cvs_sendreq(root, CVS_REQ_GLOBALOPT, "-t");
   
           /* now send the CVSROOT to the server */
           if (cvs_sendreq(root, CVS_REQ_ROOT, root->cr_dir) < 0)
                   return (-1);
   
           /* not sure why, but we have to send this */
           if (cvs_sendreq(root, CVS_REQ_USEUNCHANGED, NULL) < 0)
                   return (-1);
   
   #ifdef CVS_ZLIB
           /* if compression was requested, initialize it */
   #endif
   
           cvs_log(LP_DEBUG, "connected to %s", root->cr_host);
   
           return (0);
   }
   
   
   /*
    * cvs_disconnect()
    *
    * Disconnect from the cvs server.
    */
   
   void
   cvs_disconnect(struct cvsroot *root)
   {
           cvs_log(LP_DEBUG, "closing connection to %s", root->cr_host);
           if (root->cr_srvin != NULL) {
                   (void)fclose(root->cr_srvin);
                   root->cr_srvin = NULL;
           }
           if (root->cr_srvout != NULL) {
                   (void)fclose(root->cr_srvout);
                   root->cr_srvout = NULL;
           }
   }
   
   
   /*
  * cvs_req_getbyid()   * cvs_req_getbyid()
  *   *
  */   */
   
 const char*  struct cvs_req*
 cvs_req_getbyid(int reqid)  cvs_req_getbyid(int reqid)
 {  {
         u_int i;          u_int i;
   
         for (i = 0; i < CVS_NBREQ; i++)          for (i = 0; i < CVS_NBREQ; i++)
                 if (cvs_requests[i].req_id == reqid)                  if (cvs_requests[i].req_id == reqid)
                         return (cvs_requests[i].req_str);                          return &(cvs_requests[i]);
         return (NULL);          return (NULL);
 }  }
   
Line 231 
Line 405 
  * cvs_req_getbyname()   * cvs_req_getbyname()
  */   */
   
 int  struct cvs_req*
 cvs_req_getbyname(const char *rname)  cvs_req_getbyname(const char *rname)
 {  {
         u_int i;          u_int i;
   
         for (i = 0; i < CVS_NBREQ; i++)          for (i = 0; i < CVS_NBREQ; i++)
                 if (strcmp(cvs_requests[i].req_str, rname) == 0)                  if (strcmp(cvs_requests[i].req_str, rname) == 0)
                         return (cvs_requests[i].req_id);                          return &(cvs_requests[i]);
   
         return (-1);          return (NULL);
 }  }
   
   
Line 310 
Line 484 
  *   *
  */   */
   
 const char*  struct cvs_resp*
 cvs_resp_getbyid(int respid)  cvs_resp_getbyid(int respid)
 {  {
         u_int i;          u_int i;
   
         for (i = 0; i < CVS_NBREQ; i++)          for (i = 0; i < CVS_NBREQ; i++)
                 if (cvs_responses[i].resp_id == respid)                  if (cvs_responses[i].resp_id == (u_int)respid)
                         return (cvs_responses[i].resp_str);                          return &(cvs_responses[i]);
         return (NULL);          return (NULL);
 }  }
   
Line 326 
Line 500 
  * cvs_resp_getbyname()   * cvs_resp_getbyname()
  */   */
   
 int  struct cvs_resp*
 cvs_resp_getbyname(const char *rname)  cvs_resp_getbyname(const char *rname)
 {  {
         u_int i;          u_int i;
   
         for (i = 0; i < CVS_NBREQ; i++)          for (i = 0; i < CVS_NBREQ; i++)
                 if (strcmp(cvs_responses[i].resp_str, rname) == 0)                  if (strcmp(cvs_responses[i].resp_str, rname) == 0)
                         return (cvs_responses[i].resp_id);                          return &(cvs_responses[i]);
   
         return (-1);          return (NULL);
 }  }
   
   
Line 395 
Line 569 
  */   */
   
 int  int
 cvs_resp_handle(char *line)  cvs_resp_handle(struct cvsroot *root, char *line)
 {  {
         u_int i;          u_int i;
         size_t len;  
         char *cp, *cmd;          char *cp, *cmd;
   
         cmd = line;          cmd = line;
Line 410 
Line 583 
         for (i = 0; i < CVS_NBRESP; i++) {          for (i = 0; i < CVS_NBRESP; i++) {
                 if (strcmp(cvs_responses[i].resp_str, cmd) == 0)                  if (strcmp(cvs_responses[i].resp_str, cmd) == 0)
                         return (*cvs_responses[i].resp_hdlr)                          return (*cvs_responses[i].resp_hdlr)
                             (cvs_responses[i].resp_id, cp);                              (root, cvs_responses[i].resp_id, cp);
         }          }
   
         /* unhandled */          /* unhandled */
Line 428 
Line 601 
  */   */
   
 static int  static int
 cvs_resp_validreq(int type, char *line)  cvs_resp_validreq(struct cvsroot *root, int type, char *line)
 {  {
         int i;  
         char *sp, *ep;          char *sp, *ep;
           struct cvs_req *req;
   
         /* parse the requests */          /* parse the requests */
         sp = line;          sp = line;
Line 440 
Line 613 
                 if (ep != NULL)                  if (ep != NULL)
                         *ep = '\0';                          *ep = '\0';
   
                 i = cvs_req_getbyname(sp);                  req = cvs_req_getbyname(sp);
                 if (i != -1)                  if (req != NULL)
                         cvs_server_validreq[i] = 1;                          cvs_server_validreq[req->req_id] = 1;
   
                 if (ep != NULL)                  if (ep != NULL)
                         sp = ep + 1;                          sp = ep + 1;
Line 459 
Line 632 
  */   */
   
 static int  static int
 cvs_resp_m(int type, char *line)  cvs_resp_m(struct cvsroot *root, int type, char *line)
 {  {
         char *cp;          char *cp;
         FILE *stream;          FILE *stream;
Line 533 
Line 706 
  */   */
   
 static int  static int
 cvs_resp_ok(int type, char *line)  cvs_resp_ok(struct cvsroot *root, int type, char *line)
 {  {
         return (1);          return (1);
 }  }
Line 546 
Line 719 
  */   */
   
 static int  static int
 cvs_resp_error(int type, char *line)  cvs_resp_error(struct cvsroot *root, int type, char *line)
 {  {
         return (1);          return (1);
 }  }
Line 560 
Line 733 
  */   */
   
 static int  static int
 cvs_resp_statdir(int type, char *line)  cvs_resp_statdir(struct cvsroot *root, int type, char *line)
 {  {
         int fd;          int fd;
         char rpath[MAXPATHLEN], statpath[MAXPATHLEN];          char rpath[MAXPATHLEN], statpath[MAXPATHLEN];
   
         cvs_client_getln(rpath, sizeof(rpath));          cvs_getln(root, rpath, sizeof(rpath));
   
         snprintf(statpath, sizeof(statpath), "%s/%s", line,          snprintf(statpath, sizeof(statpath), "%s/%s", line,
             CVS_PATH_STATICENTRIES);              CVS_PATH_STATICENTRIES);
Line 597 
Line 770 
  */   */
   
 static int  static int
 cvs_resp_sticky(int type, char *line)  cvs_resp_sticky(struct cvsroot *root, int type, char *line)
 {  {
         size_t len;          size_t len;
         char rpath[MAXPATHLEN];          char rpath[MAXPATHLEN];
Line 610 
Line 783 
                 line[--len] = '\0';                  line[--len] = '\0';
   
         /* get the remote path */          /* get the remote path */
         cvs_client_getln(rpath, sizeof(rpath));          cvs_getln(root, rpath, sizeof(rpath));
   
         /* if the directory doesn't exist, create it */          /* if the directory doesn't exist, create it */
         if (stat(line, &st) == -1) {          if (stat(line, &st) == -1) {
Line 647 
Line 820 
  */   */
   
 static int  static int
 cvs_resp_newentry(int type, char *line)  cvs_resp_newentry(struct cvsroot *root, int type, char *line)
 {  {
         char entbuf[128], path[MAXPATHLEN];          char entbuf[128], path[MAXPATHLEN];
         CVSENTRIES *entfile;          CVSENTRIES *entfile;
Line 655 
Line 828 
         snprintf(path, sizeof(path), "%s/" CVS_PATH_ENTRIES, line);          snprintf(path, sizeof(path), "%s/" CVS_PATH_ENTRIES, line);
   
         /* get the remote path */          /* get the remote path */
         cvs_client_getln(entbuf, sizeof(entbuf));          cvs_getln(root, entbuf, sizeof(entbuf));
   
         /* get the new Entries line */          /* get the new Entries line */
         if (cvs_client_getln(entbuf, sizeof(entbuf)) < 0)          if (cvs_getln(root, entbuf, sizeof(entbuf)) < 0)
                 return (-1);                  return (-1);
   
         entfile = cvs_ent_open(path, O_WRONLY);          entfile = cvs_ent_open(path, O_WRONLY);
Line 683 
Line 856 
  */   */
   
 static int  static int
 cvs_resp_cksum(int type, char *line)  cvs_resp_cksum(struct cvsroot *root, int type, char *line)
 {  {
         if (cvs_fcksum != NULL) {          if (cvs_fcksum != NULL) {
                 cvs_log(LP_WARN, "unused checksum");                  cvs_log(LP_WARN, "unused checksum");
Line 709 
Line 882 
  */   */
   
 static int  static int
 cvs_resp_modtime(int type, char *line)  cvs_resp_modtime(struct cvsroot *root, int type, char *line)
 {  {
         int i;          int i;
         long off;          long off;
Line 772 
Line 945 
  */   */
   
 static int  static int
 cvs_resp_updated(int type, char *line)  cvs_resp_updated(struct cvsroot *root, int type, char *line)
 {  {
         size_t len;          size_t len;
         char tbuf[32], path[MAXPATHLEN], cksum_buf[CVS_CKSUM_LEN];          char tbuf[32], path[MAXPATHLEN], cksum_buf[CVS_CKSUM_LEN];
         CVSENTRIES *ef;          CVSENTRIES *ef;
         struct cvs_ent *ep;          struct cvs_ent *ep;
   
           ep = NULL;
   
         if (type == CVS_RESP_CREATED) {          if (type == CVS_RESP_CREATED) {
                 /* read the remote path of the file */                  /* read the remote path of the file */
                 cvs_client_getln(path, sizeof(path));                  cvs_getln(root, path, sizeof(path));
   
                 /* read the new entry */                  /* read the new entry */
                 cvs_client_getln(path, sizeof(path));                  cvs_getln(root, path, sizeof(path));
                 ep = cvs_ent_parse(path);                  ep = cvs_ent_parse(path);
                 if (ep == NULL)                  if (ep == NULL)
                         return (-1);                          return (-1);
Line 808 
Line 983 
         }          }
   
         snprintf(path, sizeof(path), "%s%s", line, ep->ce_name);          snprintf(path, sizeof(path), "%s%s", line, ep->ce_name);
         if (cvs_recvfile(path) < 0) {          if (cvs_recvfile(root, path) < 0) {
                 return (-1);                  return (-1);
         }          }
   
Line 837 
Line 1012 
  */   */
   
 static int  static int
 cvs_resp_removed(int type, char *line)  cvs_resp_removed(struct cvsroot *root, int type, char *line)
 {  {
         return (0);          return (0);
 }  }
Line 850 
Line 1025 
  */   */
   
 static int  static int
 cvs_resp_mode(int type, char *line)  cvs_resp_mode(struct cvsroot *root, int type, char *line)
 {  {
         if (cvs_strtomode(line, &cvs_lastmode) < 0) {          if (cvs_strtomode(line, &cvs_lastmode) < 0) {
                 return (-1);                  return (-1);
Line 866 
Line 1041 
  */   */
   
 static int  static int
 cvs_resp_modxpand(int type, char *line)  cvs_resp_modxpand(struct cvsroot *root, int type, char *line)
 {  {
         return (0);          return (0);
 }  }
Line 880 
Line 1055 
  */   */
   
 int  int
 cvs_sendfile(const char *path)  cvs_sendfile(struct cvsroot *root, const char *path)
 {  {
         int fd;          int fd;
         ssize_t ret;          ssize_t ret;
Line 900 
Line 1075 
         if (cvs_modetostr(st.st_mode, buf, sizeof(buf)) < 0)          if (cvs_modetostr(st.st_mode, buf, sizeof(buf)) < 0)
                 return (-1);                  return (-1);
   
         cvs_client_sendln(buf);          cvs_sendln(root, buf);
         snprintf(buf, sizeof(buf), "%lld\n", st.st_size);          snprintf(buf, sizeof(buf), "%lld\n", st.st_size);
         cvs_client_sendln(buf);          cvs_sendln(root, buf);
   
         while ((ret = read(fd, buf, sizeof(buf))) != 0) {          while ((ret = read(fd, buf, sizeof(buf))) != 0) {
                 if (ret == -1) {                  if (ret == -1) {
Line 910 
Line 1085 
                         return (-1);                          return (-1);
                 }                  }
   
                 cvs_client_sendraw(buf, (size_t)ret);                  cvs_sendraw(root, buf, (size_t)ret);
   
         }          }
   
Line 929 
Line 1104 
  */   */
   
 int  int
 cvs_recvfile(const char *path)  cvs_recvfile(struct cvsroot *root, const char *path)
 {  {
         int fd;          int fd;
         mode_t mode;          mode_t mode;
Line 938 
Line 1113 
         off_t fsz, cnt;          off_t fsz, cnt;
         char buf[4096], *ep;          char buf[4096], *ep;
   
         if ((cvs_client_getln(buf, sizeof(buf)) < 0) ||          if ((cvs_getln(root, buf, sizeof(buf)) < 0) ||
             (cvs_strtomode(buf, &mode) < 0)) {              (cvs_strtomode(buf, &mode) < 0)) {
                 return (-1);                  return (-1);
         }          }
   
         cvs_client_getln(buf, sizeof(buf));          cvs_getln(root, buf, sizeof(buf));
   
         fsz = (off_t)strtol(buf, &ep, 10);          fsz = (off_t)strtol(buf, &ep, 10);
         if (*ep != '\0') {          if (*ep != '\0') {
Line 962 
Line 1137 
                 len = MIN(sizeof(buf), (size_t)(fsz - cnt));                  len = MIN(sizeof(buf), (size_t)(fsz - cnt));
                 if (len == 0)                  if (len == 0)
                         break;                          break;
                 ret = cvs_client_recvraw(buf, len);                  ret = cvs_recvraw(root, buf, len);
                 if (ret == -1) {                  if (ret == -1) {
                         (void)close(fd);                          (void)close(fd);
                         (void)unlink(path);                          (void)unlink(path);
Line 986 
Line 1161 
 }  }
   
   
 #ifdef notyet  
 /*  /*
  * cvs_sendreq()   * cvs_sendreq()
  *   *
Line 996 
Line 1170 
  */   */
   
 int  int
 cvs_sendreq(struct cvs_root *root, u_int rid, const char *arg)  cvs_sendreq(struct cvsroot *root, u_int rid, const char *arg)
 {  {
         int ret;          int ret;
         size_t len;          struct cvs_req *req;
         struct cvs_req *reqp;  
   
         if (root->cr_srvin == NULL) {          if (root->cr_srvin == NULL) {
                 cvs_log(LP_ERR, "cannot send request: Not connected");                  cvs_log(LP_ERR, "cannot send request: Not connected");
                 return (-1);                  return (-1);
         }          }
   
         reqp = cvs_req_getbyid(rid);          req = cvs_req_getbyid(rid);
         if (reqp == NULL) {          if (req == NULL) {
                 cvs_log(LP_ERR, "unsupported request type %u", rid);                  cvs_log(LP_ERR, "unsupported request type %u", rid);
                 return (-1);                  return (-1);
         }          }
   
         snprintf(cvs_client_buf, sizeof(cvs_client_buf), "%s %s\n",          snprintf(cvs_proto_buf, sizeof(cvs_proto_buf), "%s%s%s\n",
             reqp->req_str, (arg == NULL) ? "" : " ", (arg == NULL) ? "" : arg);              req->req_str, (arg == NULL) ? "" : " ", (arg == NULL) ? "" : arg);
   
         if (cvs_server_inlog != NULL)          if (cvs_server_inlog != NULL)
                 fputs(cvs_client_buf, cvs_server_inlog);                  fputs(cvs_proto_buf, cvs_server_inlog);
   
         ret = fputs(cvs_client_buf, root->cr_srvin);          ret = fputs(cvs_proto_buf, root->cr_srvin);
         if (ret == EOF) {          if (ret == EOF) {
                 cvs_log(LP_ERRNO, "failed to send request to server");                  cvs_log(LP_ERRNO, "failed to send request to server");
                 return (-1);                  return (-1);
         }          }
   
         if (reqp->req_flags & CVS_REQF_RESP)          if (req->req_flags & CVS_REQF_RESP)
                 ret = cvs_getresp(root);                  ret = cvs_getresp(root);
   
         return (0);          return (ret);
 }  }
   
   
Line 1042 
Line 1215 
  */   */
   
 int  int
 cvs_getresp(struct cvs_root *root)  cvs_getresp(struct cvsroot *root)
 {  {
         int nbcmd;          int nbcmd, ret;
           size_t len;
   
         nbcmd = 0;          nbcmd = 0;
   
         do {          do {
                 /* wait for incoming data */                  /* wait for incoming data */
                 if (fgets(cvs_client_buf, sizeof(cvs_client_buf),                  if (fgets(cvs_proto_buf, sizeof(cvs_proto_buf),
                     root->cr_srvout) == NULL) {                      root->cr_srvout) == NULL) {
                         if (feof(root->cr_srvout))                          if (feof(root->cr_srvout))
                                 return (0);                                  return (0);
Line 1060 
Line 1234 
                 }                  }
   
                 if (cvs_server_outlog != NULL)                  if (cvs_server_outlog != NULL)
                         fputs(cvs_client_buf, cvs_server_outlog);                          fputs(cvs_proto_buf, cvs_server_outlog);
   
                 if ((len = strlen(cvs_client_buf)) != 0) {                  if ((len = strlen(cvs_proto_buf)) != 0) {
                         if (cvs_client_buf[len - 1] != '\n') {                          if (cvs_proto_buf[len - 1] != '\n') {
                                 /* truncated line */                                  /* truncated line */
                         }                          }
                         else                          else
                                 cvs_client_buf[--len] = '\0';                                  cvs_proto_buf[--len] = '\0';
                 }                  }
   
                 ret = cvs_resp_handle(cvs_client_buf);                  ret = cvs_resp_handle(root, cvs_proto_buf);
                 nbcmd++;                  nbcmd++;
         } while (ret == 0);          } while (ret == 0);
   
Line 1081 
Line 1255 
   
   
 /*  /*
    * cvs_getln()
    *
    * Get a line from the server's output and store it in <lbuf>.  The terminating
    * newline character is stripped from the result.
    */
   
   int
   cvs_getln(struct cvsroot *root, char *lbuf, size_t len)
   {
           size_t rlen;
   
           if (fgets(lbuf, len, root->cr_srvout) == NULL) {
                   if (ferror(root->cr_srvout)) {
                           cvs_log(LP_ERRNO, "failed to read line from server");
                           return (-1);
                   }
   
                   if (feof(root->cr_srvout))
                           *lbuf = '\0';
           }
   
           if (cvs_server_outlog != NULL)
                   fputs(lbuf, cvs_server_outlog);
   
           rlen = strlen(lbuf);
           if ((rlen > 0) && (lbuf[rlen - 1] == '\n'))
                   lbuf[--rlen] = '\0';
   
           return (0);
   }
   
   #ifdef notyet
   /*
  * cvs_sendresp()   * cvs_sendresp()
  *   *
  * Send a response to the client of type <rid>, with optional arguments   * Send a response to the client of type <rid>, with optional arguments
Line 1096 
Line 1303 
         const char *resp;          const char *resp;
   
         resp = cvs_resp_getbyid(rid);          resp = cvs_resp_getbyid(rid);
         if (reqp == NULL) {          if (resp == NULL) {
                 cvs_log(LP_ERR, "unsupported response type %u", rid);                  cvs_log(LP_ERR, "unsupported response type %u", rid);
                 return (-1);                  return (-1);
         }          }
   
         snprintf(cvs_client_buf, sizeof(cvs_client_buf), "%s %s\n", resp,          snprintf(cvs_proto_buf, sizeof(cvs_proto_buf), "%s %s\n", resp,
             (arg == NULL) ? "" : arg);              (arg == NULL) ? "" : arg);
   
         ret = fputs(resp, stdout);          ret = fputs(resp, stdout);
Line 1132 
Line 1339 
   
         do {          do {
                 /* wait for incoming data */                  /* wait for incoming data */
                 if (fgets(cvs_client_buf, sizeof(cvs_client_buf),                  if (fgets(cvs_proto_buf, sizeof(cvs_proto_buf),
                     stdin) == NULL) {                      stdin) == NULL) {
                         if (feof(stdin))                          if (feof(stdin))
                                 return (0);                                  return (0);
Line 1141 
Line 1348 
                         return (-1);                          return (-1);
                 }                  }
   
                 if ((len = strlen(cvs_client_buf)) != 0) {                  if ((len = strlen(cvs_proto_buf)) != 0) {
                         if (cvs_client_buf[len - 1] != '\n') {                          if (cvs_proto_buf[len - 1] != '\n') {
                                 /* truncated line */                                  /* truncated line */
                         }                          }
                         else                          else
                                 cvs_client_buf[--len] = '\0';                                  cvs_proto_buf[--len] = '\0';
                 }                  }
   
                 ret = cvs_resp_handle(cvs_client_buf);                  ret = cvs_resp_handle(cvs_proto_buf);
         } while (ret == 0);          } while (ret == 0);
 }  }
   
   
 /*  
  * cvs_connect()  
  *  
  * Open a client connection to the cvs server whose address is given in  
  * the <root> variable.  The method used to connect depends on the  
  * setting of the CVS_RSH variable.  
  * Returns 0 on success, or -1 on failure.  
  */  
   
 int  
 cvs_connect(struct cvsroot *root)  
 {  
         int i, argc, infd[2], outfd[2];  
         pid_t pid;  
         char *argv[16], *cvs_server_cmd;  
   
         if (pipe(infd) == -1) {  
                 cvs_log(LP_ERRNO,  
                     "failed to create input pipe for client connection");  
                 return (-1);  
         }  
   
         if (pipe(outfd) == -1) {  
                 cvs_log(LP_ERRNO,  
                     "failed to create output pipe for client connection");  
                 (void)close(infd[0]);  
                 (void)close(infd[1]);  
                 return (-1);  
         }  
   
         pid = fork();  
         if (pid == -1) {  
                 cvs_log(LP_ERRNO, "failed to fork for cvs server connection");  
                 return (-1);  
         }  
         if (pid == 0) {  
                 if ((dup2(infd[0], STDIN_FILENO) == -1) ||  
                     (dup2(outfd[1], STDOUT_FILENO) == -1)) {  
                         cvs_log(LP_ERRNO,  
                             "failed to setup standard streams for cvs server");  
                         return (-1);  
                 }  
                 (void)close(infd[1]);  
                 (void)close(outfd[0]);  
   
                 argc = 0;  
                 argv[argc++] = cvs_rsh;  
   
                 if (root->cr_user != NULL) {  
                         argv[argc++] = "-l";  
                         argv[argc++] = root->cr_user;  
                 }  
   
   
                 cvs_server_cmd = getenv("CVS_SERVER");  
                 if (cvs_server_cmd == NULL)  
                         cvs_server_cmd = "cvs";  
   
                 argv[argc++] = root->cr_host;  
                 argv[argc++] = cvs_server_cmd;  
                 argv[argc++] = "server";  
                 argv[argc] = NULL;  
   
                 for (i = 0; i < argc; i++)  
                         printf("argv[%d] = `%s'\n", i, argv[i]);  
   
                 execvp(argv[0], argv);  
                 cvs_log(LP_ERRNO, "failed to exec");  
                 exit(EX_OSERR);  
         }  
   
         /* we are the parent */  
         cvs_server_infd = infd[1];  
         cvs_server_outfd = outfd[0];  
   
         cvs_server_in = fdopen(cvs_server_infd, "w");  
         if (cvs_server_in == NULL) {  
                 cvs_log(LP_ERRNO, "failed to create pipe stream");  
                 return (-1);  
         }  
   
         cvs_server_out = fdopen(cvs_server_outfd, "r");  
         if (cvs_server_out == NULL) {  
                 cvs_log(LP_ERRNO, "failed to create pipe stream");  
                 return (-1);  
         }  
         root->cr_srvin = cvs_server_in;  
         root->cr_srvout = cvs_server_out;  
   
         /* make the streams line-buffered */  
         setvbuf(cvs_server_in, NULL, _IOLBF, 0);  
         setvbuf(cvs_server_out, NULL, _IOLBF, 0);  
   
         (void)close(infd[0]);  
         (void)close(outfd[1]);  
   
         cvs_client_initlog();  
   
         cvs_client_sendinfo();  
   
 #ifdef CVS_ZLIB  
         /* if compression was requested, initialize it */  
 #endif  #endif
   
         return (0);  
 }  
   
   
 /*  /*
  * cvs_disconnect()  
  *  
  * Disconnect from the cvs server.  
  */  
   
 void  
 cvs_disconnect(struct cvsroot *root)  
 {  
         cvs_log(LP_DEBUG, "closing client connection");  
         if (root->cr_srvin != NULL) {  
                 (void)fclose(root->cr_srvin);  
                 root->cr_srvin = NULL;  
         }  
         if (root->cr_srvout != NULL) {  
                 (void)fclose(root->cr_srvout);  
                 root->cr_srvout = NULL;  
         }  
   
         if (cvs_server_inlog != NULL)  
                 fclose(cvs_server_inlog);  
         if (cvs_server_outlog != NULL)  
                 fclose(cvs_server_outlog);  
 }  
   
   
 /*  
  * cvs_sendln()   * cvs_sendln()
  *   *
  * Send a single line <line> string to the server.  The line is sent as is,   * Send a single line <line> string to the server.  The line is sent as is,
Line 1322 
Line 1396 
   
   
 /*  /*
  * cvs_client_sendraw()   * cvs_sendraw()
  *   *
  * Send the first <len> bytes from the buffer <src> to the server.   * Send the first <len> bytes from the buffer <src> to the server.
  */   */
   
 int  int
 cvs_client_sendraw(const void *src, size_t len)  cvs_sendraw(struct cvsroot *root, const void *src, size_t len)
 {  {
         if (cvs_server_inlog != NULL)          if (cvs_server_inlog != NULL)
                 fwrite(src, sizeof(char), len, cvs_server_inlog);                  fwrite(src, sizeof(char), len, cvs_server_inlog);
         if (fwrite(src, sizeof(char), len, cvs_server_in) < len) {          if (fwrite(src, sizeof(char), len, root->cr_srvin) < len) {
                 return (-1);                  return (-1);
         }          }
   
Line 1341 
Line 1415 
   
   
 /*  /*
  * cvs_client_recvraw()   * cvs_recvraw()
  *   *
  * Receive the first <len> bytes from the buffer <src> to the server.   * Receive the first <len> bytes from the buffer <src> to the server.
  */   */
   
 ssize_t  ssize_t
 cvs_client_recvraw(void *dst, size_t len)  cvs_recvraw(struct cvsroot *root, void *dst, size_t len)
 {  {
         size_t ret;          size_t ret;
   
         ret = fread(dst, sizeof(char), len, cvs_server_out);          ret = fread(dst, sizeof(char), len, root->cr_srvout);
         if (ret == 0)          if (ret == 0)
                 return (-1);                  return (-1);
         if (cvs_server_outlog != NULL)          if (cvs_server_outlog != NULL)
Line 1361 
Line 1435 
   
   
 /*  /*
  * cvs_client_getln()   * cvs_senddir()
  *   *
  * Get a line from the server's output and store it in <lbuf>.  The terminating  
  * newline character is stripped from the result.  
  */  
   
 int  
 cvs_client_getln(char *lbuf, size_t len)  
 {  
         size_t rlen;  
   
         if (fgets(lbuf, len, cvs_server_out) == NULL) {  
                 if (ferror(cvs_server_out)) {  
                         cvs_log(LP_ERRNO, "failed to read line from server");  
                         return (-1);  
                 }  
   
                 if (feof(cvs_server_out))  
                         *lbuf = '\0';  
         }  
   
         if (cvs_server_outlog != NULL)  
                 fputs(lbuf, cvs_server_outlog);  
   
         rlen = strlen(lbuf);  
         if ((rlen > 0) && (lbuf[rlen - 1] == '\n'))  
                 lbuf[--rlen] = '\0';  
   
         return (0);  
 }  
   
   
 /*  
  * cvs_client_sendinfo()  
  *  
  * Initialize the connection status by first requesting the list of  
  * supported requests from the server.  Then, we send the CVSROOT variable  
  * with the `Root' request.  
  * Returns 0 on success, or -1 on failure.  
  */  
   
 static int  
 cvs_client_sendinfo(void)  
 {  
         char *vresp;  
         /*  
          * First, send the server the list of valid responses, then ask  
          * for valid requests  
          */  
   
         vresp = cvs_resp_getvalid();  
         if (vresp == NULL) {  
                 cvs_log(LP_ERR, "can't generate list of valid responses");  
                 return (-1);  
         }  
   
         if (cvs_client_sendreq(CVS_REQ_VALIDRESP, vresp, 0) < 0) {  
         }  
         free(vresp);  
   
         if (cvs_client_sendreq(CVS_REQ_VALIDREQ, NULL, 1) < 0) {  
                 cvs_log(LP_ERR, "failed to get valid requests from server");  
                 return (-1);  
         }  
   
         /* now share our global options with the server */  
         if (verbosity == 1)  
                 cvs_client_sendreq(CVS_REQ_GLOBALOPT, "-q", 0);  
         else if (verbosity == 0)  
                 cvs_client_sendreq(CVS_REQ_GLOBALOPT, "-Q", 0);  
   
         if (cvs_nolog)  
                 cvs_client_sendreq(CVS_REQ_GLOBALOPT, "-l", 0);  
         if (cvs_readonly)  
                 cvs_client_sendreq(CVS_REQ_GLOBALOPT, "-r", 0);  
         if (cvs_trace)  
                 cvs_client_sendreq(CVS_REQ_GLOBALOPT, "-t", 0);  
   
         /* now send the CVSROOT to the server */  
         if (cvs_client_sendreq(CVS_REQ_ROOT, cvs_root->cr_dir, 0) < 0)  
                 return (-1);  
   
         /* not sure why, but we have to send this */  
         if (cvs_client_sendreq(CVS_REQ_USEUNCHANGED, NULL, 0) < 0)  
                 return (-1);  
   
         return (0);  
 }  
   
   
 /*  
  * cvs_client_senddir()  
  *  
  * Send a `Directory' request along with the 2 paths that follow it.   * Send a `Directory' request along with the 2 paths that follow it.
  */   */
   
 int  int
 cvs_client_senddir(const char *dir)  cvs_senddir(struct cvsroot *root, CVSFILE *dir)
 {  {
         char repo[MAXPATHLEN], buf[MAXPATHLEN];          char buf[MAXPATHLEN];
   
         if (cvs_readrepo(dir, repo, sizeof(repo)) < 0) {          if (dir->cf_ddat->cd_repo == NULL)
                 repo[0] = '\0';                  strlcpy(buf, root->cr_dir, sizeof(buf));
                 strlcpy(buf, cvs_root->cr_dir, sizeof(buf));          else
         }                  snprintf(buf, sizeof(buf), "%s/%s", root->cr_dir,
         else {                      dir->cf_ddat->cd_repo);
                 snprintf(buf, sizeof(buf), "%s/%s", cvs_root->cr_dir, repo);  
         }  
   
         if ((cvs_client_sendreq(CVS_REQ_DIRECTORY, dir, 0) < 0) ||          if ((cvs_sendreq(root, CVS_REQ_DIRECTORY, dir->cf_path) < 0) ||
             (cvs_client_sendln(buf) < 0))              (cvs_sendln(root, buf) < 0))
                 return (-1);                  return (-1);
   
         return (0);          return (0);
Line 1479 
Line 1460 
   
   
 /*  /*
  * cvs_client_sendarg()   * cvs_sendarg()
  *   *
  * Send the argument <arg> to the server.  The argument <append> is used to   * Send the argument <arg> to the server.  The argument <append> is used to
  * determine if the argument should be simply appended to the last argument   * determine if the argument should be simply appended to the last argument
Line 1487 
Line 1468 
  */   */
   
 int  int
 cvs_client_sendarg(const char *arg, int append)  cvs_sendarg(struct cvsroot *root, const char *arg, int append)
 {  {
         return cvs_client_sendreq(((append == 0) ?          return cvs_sendreq(root, ((append == 0) ?
             CVS_REQ_ARGUMENT : CVS_REQ_ARGUMENTX), arg, 0);              CVS_REQ_ARGUMENT : CVS_REQ_ARGUMENTX), arg);
 }  }
   
   
 /*  /*
  * cvs_client_sendentry()   * cvs_sendentry()
  *   *
  * Send an `Entry' request to the server along with the mandatory fields from   * Send an `Entry' request to the server along with the mandatory fields from
  * the CVS entry <ent> (which are the name and revision).   * the CVS entry <ent> (which are the name and revision).
  */   */
   
 int  int
 cvs_client_sendentry(const struct cvs_ent *ent)  cvs_sendentry(struct cvsroot *root, const struct cvs_ent *ent)
 {  {
         char ebuf[128], numbuf[64];          char ebuf[128], numbuf[64];
   
         snprintf(ebuf, sizeof(ebuf), "/%s/%s///", ent->ce_name,          snprintf(ebuf, sizeof(ebuf), "/%s/%s///", ent->ce_name,
             rcsnum_tostr(ent->ce_rev, numbuf, sizeof(numbuf)));              rcsnum_tostr(ent->ce_rev, numbuf, sizeof(numbuf)));
   
         return cvs_client_sendreq(CVS_REQ_ENTRY, ebuf, 0);          return cvs_sendreq(root, CVS_REQ_ENTRY, ebuf);
 }  }
   
   
 /*  /*
  * cvs_client_initlog()   * cvs_initlog()
  *   *
  * Initialize protocol logging if the CVS_CLIENT_LOG environment variable is   * Initialize protocol logging if the CVS_CLIENT_LOG environment variable is
  * set.  In this case, the variable's value is used as a path to which the   * set.  In this case, the variable's value is used as a path to which the
Line 1524 
Line 1505 
  */   */
   
 static int  static int
 cvs_client_initlog(void)  cvs_initlog(void)
 {  {
         char *env, fpath[MAXPATHLEN];          char *env, fpath[MAXPATHLEN];
   
           /* avoid doing it more than once */
           if (cvs_server_logon)
                   return (0);
   
         env = getenv("CVS_CLIENT_LOG");          env = getenv("CVS_CLIENT_LOG");
         if (env == NULL)          if (env == NULL)
                 return (0);                  return (0);
Line 1554 
Line 1539 
         setvbuf(cvs_server_inlog, NULL, _IOLBF, 0);          setvbuf(cvs_server_inlog, NULL, _IOLBF, 0);
         setvbuf(cvs_server_outlog, NULL, _IOLBF, 0);          setvbuf(cvs_server_outlog, NULL, _IOLBF, 0);
   
         return (0);          cvs_server_logon = 1;
 }  
   
   
 /*  
  * cvs_client_sendfile()  
  *  
  */  
   
 int  
 cvs_client_sendfile(const char *path)  
 {  
         int fd;  
         ssize_t ret;  
         char buf[4096];  
         struct stat st;  
   
         if (stat(path, &st) == -1) {  
                 cvs_log(LP_ERRNO, "failed to stat `%s'", path);  
                 return (-1);  
         }  
   
         fd = open(path, O_RDONLY, 0);  
         if (fd == -1) {  
                 return (-1);  
         }  
   
         if (cvs_modetostr(st.st_mode, buf, sizeof(buf)) < 0)  
                 return (-1);  
   
         cvs_client_sendln(buf);  
         snprintf(buf, sizeof(buf), "%lld\n", st.st_size);  
         cvs_client_sendln(buf);  
   
         while ((ret = read(fd, buf, sizeof(buf))) != 0) {  
                 if (ret == -1) {  
                         cvs_log(LP_ERRNO, "failed to read file `%s'", path);  
                         return (-1);  
                 }  
   
                 cvs_client_sendraw(buf, (size_t)ret);  
   
         }  
   
         (void)close(fd);  
   
         return (0);          return (0);
 }  }
 #endif  

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.13