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

Annotation of src/usr.bin/cvs/req.c, Revision 1.22

1.22    ! joris       1: /*     $OpenBSD: req.c,v 1.21 2005/06/10 21:14:47 joris Exp $  */
1.1       jfb         2: /*
                      3:  * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  *
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. The name of the author may not be used to endorse or promote products
                     13:  *    derived from this software without specific prior written permission.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     16:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     17:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
                     18:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     19:  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     20:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     21:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     22:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     23:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     24:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     25:  */
                     26:
                     27:
                     28: #include <sys/types.h>
                     29: #include <sys/stat.h>
                     30:
1.20      xsa        31: #include <errno.h>
1.1       jfb        32: #include <fcntl.h>
1.22    ! joris      33: #include <libgen.h>
1.1       jfb        34: #include <stdio.h>
                     35: #include <stdlib.h>
1.20      xsa        36: #include <string.h>
1.1       jfb        37: #include <unistd.h>
                     38:
                     39: #include "buf.h"
                     40: #include "cvs.h"
                     41: #include "log.h"
                     42: #include "proto.h"
                     43:
                     44:
1.22    ! joris      45: extern char *cvs_rootstr;
1.1       jfb        46: extern int   verbosity;
                     47: extern int   cvs_compress;
                     48: extern char *cvs_rsh;
                     49: extern int   cvs_trace;
                     50: extern int   cvs_nolog;
                     51: extern int   cvs_readonly;
                     52:
                     53:
1.11      jfb        54: static int  cvs_req_set          (int, char *);
1.12      jfb        55: static int  cvs_req_noop         (int, char *);
1.11      jfb        56: static int  cvs_req_root         (int, char *);
                     57: static int  cvs_req_validreq     (int, char *);
                     58: static int  cvs_req_validresp    (int, char *);
1.12      jfb        59: static int  cvs_req_expandmod    (int, char *);
1.11      jfb        60: static int  cvs_req_directory    (int, char *);
                     61: static int  cvs_req_useunchanged (int, char *);
                     62: static int  cvs_req_case         (int, char *);
                     63: static int  cvs_req_argument     (int, char *);
                     64: static int  cvs_req_globalopt    (int, char *);
                     65: static int  cvs_req_gzipstream   (int, char *);
1.13      jfb        66: static int  cvs_req_entry        (int, char *);
                     67: static int  cvs_req_filestate    (int, char *);
1.11      jfb        68:
                     69: static int  cvs_req_command      (int, char *);
1.1       jfb        70:
                     71:
                     72: struct cvs_reqhdlr {
                     73:        int (*hdlr)(int, char *);
                     74: } cvs_req_swtab[CVS_REQ_MAX + 1] = {
1.11      jfb        75:        { NULL                  },
                     76:        { cvs_req_root          },
                     77:        { cvs_req_validreq      },
                     78:        { cvs_req_validresp     },
                     79:        { cvs_req_directory     },
                     80:        { NULL                  },
                     81:        { NULL                  },
                     82:        { NULL                  },
1.13      jfb        83:        { cvs_req_entry         },
1.11      jfb        84:        { NULL                  },
                     85:        { NULL                  },      /* 10 */
1.13      jfb        86:        { cvs_req_filestate     },
                     87:        { cvs_req_filestate     },
                     88:        { cvs_req_filestate     },
1.11      jfb        89:        { cvs_req_useunchanged  },
                     90:        { NULL                  },
                     91:        { NULL                  },
1.13      jfb        92:        { cvs_req_filestate     },
1.11      jfb        93:        { cvs_req_case          },
                     94:        { NULL                  },
                     95:        { cvs_req_argument      },      /* 20 */
                     96:        { cvs_req_argument      },
                     97:        { cvs_req_globalopt     },
                     98:        { cvs_req_gzipstream    },
                     99:        { NULL                  },
                    100:        { NULL                  },
                    101:        { NULL                  },
                    102:        { NULL                  },
                    103:        { NULL                  },
                    104:        { NULL                  },
                    105:        { NULL                  },      /* 30 */
                    106:        { NULL                  },
                    107:        { NULL                  },
                    108:        { NULL                  },
                    109:        { cvs_req_set           },
1.12      jfb       110:        { cvs_req_expandmod     },
1.11      jfb       111:        { cvs_req_command       },
                    112:        { NULL                  },
                    113:        { NULL                  },
                    114:        { NULL                  },
                    115:        { NULL                  },      /* 40 */
                    116:        { NULL                  },
                    117:        { NULL                  },
                    118:        { NULL                  },
                    119:        { NULL                  },
1.17      joris     120:        { cvs_req_command       },
1.11      jfb       121:        { cvs_req_command       },
                    122:        { NULL                  },
                    123:        { cvs_req_command       },
1.22    ! joris     124:        { cvs_req_command       },
1.11      jfb       125:        { NULL                  },      /* 50 */
                    126:        { NULL                  },
                    127:        { NULL                  },
                    128:        { NULL                  },
                    129:        { cvs_req_command       },
                    130:        { cvs_req_command       },
                    131:        { cvs_req_command       },
                    132:        { NULL                  },
                    133:        { NULL                  },
                    134:        { NULL                  },
                    135:        { cvs_req_command       },      /* 60 */
                    136:        { NULL                  },
                    137:        { cvs_req_command       },
                    138:        { cvs_req_command       },
1.12      jfb       139:        { cvs_req_noop          },
1.11      jfb       140:        { NULL                  },
                    141:        { NULL                  },
                    142:        { NULL                  },
                    143:        { NULL                  },
                    144:        { cvs_req_command       },
1.1       jfb       145: };
                    146:
                    147:
                    148:
                    149: /*
1.2       jfb       150:  * Argument array built by `Argument' and `Argumentx' requests.
                    151:  */
1.22    ! joris     152: static char *cvs_req_args[CVS_PROTO_MAXARG];
        !           153:
        !           154: /* start at 1, because 0 will be the command name */
        !           155: static int  cvs_req_nargs = 1;
1.2       jfb       156:
1.22    ! joris     157: static char *cvs_req_modulename;
1.11      jfb       158: static char *cvs_req_rootpath;
1.14      joris     159: static char *cvs_req_currentdir;
                    160: extern char cvs_server_tmpdir[MAXPATHLEN];
1.22    ! joris     161: static CVSENTRIES *cvs_req_entf;
1.2       jfb       162:
                    163: /*
1.1       jfb       164:  * cvs_req_handle()
                    165:  *
                    166:  * Generic request handler dispatcher.  The handler expects the first line
                    167:  * of the command as single argument.
                    168:  * Returns the return value of the command on success, or -1 on failure.
                    169:  */
                    170: int
                    171: cvs_req_handle(char *line)
                    172: {
                    173:        char *cp, *cmd;
                    174:        struct cvs_req *req;
                    175:
                    176:        cmd = line;
                    177:
                    178:        cp = strchr(cmd, ' ');
                    179:        if (cp != NULL)
                    180:                *(cp++) = '\0';
                    181:
                    182:        req = cvs_req_getbyname(cmd);
                    183:        if (req == NULL)
                    184:                return (-1);
                    185:        else if (cvs_req_swtab[req->req_id].hdlr == NULL) {
1.10      jfb       186:                cvs_log(LP_ERR, "handler for `%s' not implemented", cmd);
1.1       jfb       187:                return (-1);
                    188:        }
                    189:
                    190:        return (*cvs_req_swtab[req->req_id].hdlr)(req->req_id, cp);
                    191: }
                    192:
1.12      jfb       193: /*
                    194:  * cvs_req_noop()
                    195:  */
                    196: static int
                    197: cvs_req_noop(int reqid, char *line)
                    198: {
                    199:        int ret;
                    200:
                    201:        ret = cvs_sendresp(CVS_RESP_OK, NULL);
                    202:        if (ret < 0)
                    203:                return (-1);
                    204:        return (0);
                    205: }
                    206:
1.1       jfb       207:
                    208: static int
                    209: cvs_req_root(int reqid, char *line)
                    210: {
1.11      jfb       211:        if (cvs_req_rootpath != NULL) {
                    212:                cvs_log(LP_ERR, "duplicate Root request received");
1.13      jfb       213:                cvs_printf("Protocol error: Duplicate Root request");
1.11      jfb       214:                return (-1);
                    215:        }
1.9       jfb       216:
1.11      jfb       217:        cvs_req_rootpath = strdup(line);
                    218:        if (cvs_req_rootpath == NULL) {
                    219:                cvs_log(LP_ERRNO, "failed to copy Root path");
1.9       jfb       220:                return (-1);
                    221:        }
                    222:
1.22    ! joris     223:        cvs_rootstr = cvs_req_rootpath;
        !           224:
1.4       jfb       225:        return (0);
                    226: }
                    227:
                    228:
                    229: static int
                    230: cvs_req_validreq(int reqid, char *line)
                    231: {
                    232:        char *vreq;
                    233:
                    234:        vreq = cvs_req_getvalid();
                    235:        if (vreq == NULL)
                    236:                return (-1);
                    237:
1.11      jfb       238:        if ((cvs_sendresp(CVS_RESP_VALIDREQ, vreq) < 0) ||
                    239:            (cvs_sendresp(CVS_RESP_OK, NULL) < 0))
                    240:                return (-1);
1.4       jfb       241:
                    242:        return (0);
                    243: }
                    244:
                    245: static int
                    246: cvs_req_validresp(int reqid, char *line)
                    247: {
                    248:        char *sp, *ep;
                    249:        struct cvs_resp *resp;
1.1       jfb       250:
1.4       jfb       251:        sp = line;
                    252:        do {
                    253:                ep = strchr(sp, ' ');
                    254:                if (ep != NULL)
                    255:                        *(ep++) = '\0';
                    256:
                    257:                resp = cvs_resp_getbyname(sp);
                    258:                if (resp != NULL)
                    259:                        ;
                    260:
                    261:                if (ep != NULL)
                    262:                        sp = ep + 1;
                    263:        } while (ep != NULL);
1.1       jfb       264:
                    265:        return (0);
                    266: }
                    267:
                    268: static int
                    269: cvs_req_directory(int reqid, char *line)
                    270: {
1.22    ! joris     271:        int pwd;
        !           272:        size_t dirlen;
1.11      jfb       273:        char rdir[MAXPATHLEN];
1.22    ! joris     274:        char *repo, *s, *p;
        !           275:
        !           276:        pwd = (!strcmp(line, "."));
1.1       jfb       277:
1.11      jfb       278:        if (cvs_getln(NULL, rdir, sizeof(rdir)) < 0)
                    279:                return (-1);
                    280:
1.14      joris     281:        if (cvs_req_currentdir != NULL)
                    282:                free(cvs_req_currentdir);
                    283:
                    284:        cvs_req_currentdir = strdup(rdir);
                    285:        if (cvs_req_currentdir == NULL) {
1.19      xsa       286:                cvs_log(LP_ERR, "failed to duplicate directory");
1.14      joris     287:                return (-1);
                    288:        }
                    289:
1.22    ! joris     290:        dirlen = strlen(cvs_req_currentdir);
1.14      joris     291:
1.22    ! joris     292:        /*
        !           293:         * Lets make sure we always start at the correct
        !           294:         * directory.
        !           295:         */
        !           296:        if (chdir(cvs_server_tmpdir) == -1) {
        !           297:                cvs_log(LP_ERRNO, "failed to change to top directory");
1.14      joris     298:                return (-1);
                    299:        }
                    300:
1.22    ! joris     301:        /*
        !           302:         * Set repository path.
        !           303:         */
        !           304:        s = cvs_req_currentdir + strlen(cvs_req_rootpath) + 1;
        !           305:        if (s >= (cvs_req_currentdir + dirlen)) {
        !           306:                cvs_log(LP_ERR, "you're bad, go away");
1.14      joris     307:                return (-1);
                    308:        }
                    309:
1.22    ! joris     310:        if ((repo = strdup(s)) == NULL) {
        !           311:                cvs_log(LP_ERR, "failed to save repository path");
        !           312:                return (-1);
        !           313:        }
        !           314:
        !           315:        /*
        !           316:         * Skip back "foo/bar" part, so we can feed the repo
        !           317:         * as a startpoint for cvs_create_dir().
        !           318:         */
        !           319:        if (!pwd) {
        !           320:                s = repo + strlen(repo) - strlen(line) - 1;
        !           321:                if (*s != '/') {
        !           322:                        cvs_log(LP_ERR, "malformed directory");
        !           323:                        free(repo);
        !           324:                        return (-1);
        !           325:                }
        !           326:
        !           327:                *s = '\0';
        !           328:        }
        !           329:
        !           330:        /*
        !           331:         * Obtain the modulename, we only need to do this at
        !           332:         * the very first time we get a Directory request.
        !           333:         */
        !           334:        if (cvs_req_modulename == NULL) {
        !           335:                if ((p = strchr(repo, '/')) != NULL)
        !           336:                        *p = '\0';
        !           337:
        !           338:                if ((cvs_req_modulename = strdup(repo)) == NULL) {
        !           339:                        cvs_log(LP_ERR, "failed to save modulename");
        !           340:                        free(repo);
        !           341:                        return (-1);
        !           342:                }
        !           343:
        !           344:                if (p != NULL)
        !           345:                        *p = '/';
        !           346:
        !           347:                /*
        !           348:                 * Now, create the admin files in the top-level
        !           349:                 * directory for the temp repo.
        !           350:                 */
        !           351:                if (cvs_mkadmin(cvs_server_tmpdir, cvs_rootstr, repo) < 0) {
        !           352:                        cvs_log(LP_ERR, "failed to create admin files");
        !           353:                        free(repo);
        !           354:                        return (-1);
        !           355:                }
        !           356:        }
        !           357:
        !           358:        /*
        !           359:         * create the directory plus the administrative files.
        !           360:         */
        !           361:        if (cvs_create_dir(line, 1, cvs_rootstr, repo) < 0) {
        !           362:                free(repo);
        !           363:                return (-1);
        !           364:        }
1.14      joris     365:
1.22    ! joris     366:        /*
        !           367:         * cvs_create_dir() has already put us in the correct directory
        !           368:         * so now open it's Entry file for incoming files.
        !           369:         */
        !           370:        if (cvs_req_entf != NULL)
        !           371:                cvs_ent_close(cvs_req_entf);
        !           372:        cvs_req_entf = cvs_ent_open(".", O_RDWR);
        !           373:        if (cvs_req_entf == NULL) {
        !           374:                cvs_log(LP_ERR, "failed to open Entry file for %s", line);
        !           375:                free(repo);
        !           376:                return (-1);
        !           377:        }
        !           378:
        !           379:        free(repo);
1.11      jfb       380:        return (0);
                    381: }
                    382:
1.13      jfb       383: static int
                    384: cvs_req_entry(int reqid, char *line)
                    385: {
                    386:        struct cvs_ent *ent;
                    387:
1.22    ! joris     388:        /* parse received entry */
1.13      jfb       389:        if ((ent = cvs_ent_parse(line)) == NULL)
                    390:                return (-1);
                    391:
1.22    ! joris     392:        /* add it to the entry file and done */
        !           393:        if (cvs_ent_add(cvs_req_entf, ent) < 0) {
        !           394:                cvs_log(LP_ERR, "failed to add '%s' to the Entry file",
        !           395:                    ent->ce_name);
        !           396:                return (-1);
        !           397:        }
        !           398:
        !           399:        /* XXX */
        !           400:        cvs_ent_write(cvs_req_entf);
1.15      jfb       401:
1.13      jfb       402:        return (0);
                    403: }
                    404:
                    405: /*
                    406:  * cvs_req_filestate()
                    407:  *
                    408:  * Handler for the `Modified', `Is-Modified', `Unchanged' and `Questionable'
                    409:  * requests, which are all used to report the assumed state of a file from the
                    410:  * client.
                    411:  */
                    412: static int
                    413: cvs_req_filestate(int reqid, char *line)
                    414: {
1.22    ! joris     415:        int ret;
1.13      jfb       416:        mode_t fmode;
                    417:        BUF *fdata;
1.22    ! joris     418:        struct cvs_ent *ent;
1.13      jfb       419:
1.22    ! joris     420:        ret = 0;
        !           421:        switch (reqid) {
        !           422:        case CVS_REQ_MODIFIED:
1.13      jfb       423:                fdata = cvs_recvfile(NULL, &fmode);
                    424:                if (fdata == NULL)
                    425:                        return (-1);
1.14      joris     426:
                    427:                /* write the file */
1.22    ! joris     428:                if (cvs_buf_write(fdata, line, fmode) < 0) {
        !           429:                        cvs_log(LP_ERR, "failed to create file %s", line);
1.14      joris     430:                        cvs_buf_free(fdata);
                    431:                        return (-1);
                    432:                }
                    433:
                    434:                cvs_buf_free(fdata);
1.22    ! joris     435:                break;
        !           436:        case CVS_REQ_ISMODIFIED:
        !           437:                break;
        !           438:        case CVS_REQ_UNCHANGED:
        !           439:                ent = cvs_ent_get(cvs_req_entf, line);
        !           440:                if (ent == NULL) {
        !           441:                        cvs_log(LP_ERR,
        !           442:                            "received Unchanged request for a non-existing file");
        !           443:                        ret = -1;
        !           444:                } else {
        !           445:                        ent->ce_status = CVS_ENT_UPTODATE;
        !           446:                }
        !           447:                break;
        !           448:        case CVS_REQ_QUESTIONABLE:
        !           449:                break;
        !           450:        default:
        !           451:                cvs_log(LP_ERR, "wrong request id type");
        !           452:                ret = -1;
        !           453:                break;
1.13      jfb       454:        }
                    455:
1.22    ! joris     456:        /* XXX */
        !           457:        cvs_req_entf->cef_flags &= ~CVS_ENTF_SYNC;
        !           458:        cvs_ent_write(cvs_req_entf);
        !           459:
        !           460:        return (ret);
1.13      jfb       461: }
1.12      jfb       462:
                    463: /*
                    464:  * cvs_req_expandmod()
                    465:  *
                    466:  */
                    467: static int
                    468: cvs_req_expandmod(int reqid, char *line)
                    469: {
                    470:        int ret;
                    471:
                    472:        ret = cvs_sendresp(CVS_RESP_OK, NULL);
                    473:        if (ret < 0)
                    474:                return (-1);
                    475:        return (0);
                    476: }
                    477:
                    478:
1.11      jfb       479: /*
                    480:  * cvs_req_useunchanged()
                    481:  *
                    482:  * Handler for the `UseUnchanged' requests.  The protocol documentation
                    483:  * specifies that this request must be supported by the server and must be
                    484:  * sent by the client, though it gives no clue regarding its use.
                    485:  */
                    486: static int
                    487: cvs_req_useunchanged(int reqid, char *line)
                    488: {
1.5       jfb       489:        return (0);
                    490: }
                    491:
1.11      jfb       492:
1.5       jfb       493: /*
                    494:  * cvs_req_case()
                    495:  *
                    496:  * Handler for the `Case' requests, which toggles case sensitivity ON or OFF
                    497:  */
                    498: static int
                    499: cvs_req_case(int reqid, char *line)
                    500: {
                    501:        cvs_nocase = 1;
1.2       jfb       502:        return (0);
                    503: }
                    504:
                    505:
                    506: static int
1.11      jfb       507: cvs_req_set(int reqid, char *line)
                    508: {
                    509:        char *cp, *lp;
                    510:
                    511:        if ((lp = strdup(line)) == NULL) {
                    512:                cvs_log(LP_ERRNO, "failed to copy Set argument");
                    513:                return (-1);
                    514:        }
                    515:
                    516:        if ((cp = strchr(lp, '=')) == NULL) {
                    517:                cvs_log(LP_ERR, "error in Set request "
                    518:                    "(no = in variable assignment)");
                    519:                free(lp);
                    520:                return (-1);
                    521:        }
                    522:        *(cp++) = '\0';
                    523:
                    524:        if (cvs_var_set(lp, cp) < 0) {
                    525:                free(lp);
                    526:                return (-1);
                    527:        }
                    528:
                    529:        free(lp);
                    530:
                    531:        return (0);
                    532: }
                    533:
                    534:
                    535: static int
1.2       jfb       536: cvs_req_argument(int reqid, char *line)
                    537: {
                    538:        char *nap;
                    539:
                    540:        if (cvs_req_nargs == CVS_PROTO_MAXARG) {
                    541:                cvs_log(LP_ERR, "too many arguments");
                    542:                return (-1);
                    543:        }
                    544:
                    545:        if (reqid == CVS_REQ_ARGUMENT) {
                    546:                cvs_req_args[cvs_req_nargs] = strdup(line);
                    547:                if (cvs_req_args[cvs_req_nargs] == NULL) {
                    548:                        cvs_log(LP_ERRNO, "failed to copy argument");
                    549:                        return (-1);
                    550:                }
                    551:                cvs_req_nargs++;
1.6       deraadt   552:        } else if (reqid == CVS_REQ_ARGUMENTX) {
1.2       jfb       553:                if (cvs_req_nargs == 0)
                    554:                        cvs_log(LP_WARN, "no argument to append to");
                    555:                else {
                    556:                        asprintf(&nap, "%s%s", cvs_req_args[cvs_req_nargs - 1],
                    557:                            line);
                    558:                        if (nap == NULL) {
                    559:                                cvs_log(LP_ERRNO,
                    560:                                    "failed to append to argument");
                    561:                                return (-1);
                    562:                        }
                    563:                        free(cvs_req_args[cvs_req_nargs - 1]);
                    564:                        cvs_req_args[cvs_req_nargs - 1] = nap;
                    565:                }
1.3       jfb       566:        }
                    567:
                    568:        return (0);
                    569: }
                    570:
                    571:
                    572: static int
                    573: cvs_req_globalopt(int reqid, char *line)
                    574: {
                    575:        if ((*line != '-') || (*(line + 2) != '\0')) {
                    576:                cvs_log(LP_ERR,
                    577:                    "invalid `Global_option' request format");
                    578:                return (-1);
                    579:        }
                    580:
                    581:        switch (*(line + 1)) {
                    582:        case 'l':
                    583:                cvs_nolog = 1;
                    584:                break;
                    585:        case 'n':
                    586:                break;
                    587:        case 'Q':
                    588:                verbosity = 0;
                    589:                break;
                    590:        case 'q':
                    591:                if (verbosity > 1)
                    592:                        verbosity = 1;
                    593:                break;
                    594:        case 'r':
                    595:                cvs_readonly = 1;
                    596:                break;
                    597:        case 't':
                    598:                cvs_trace = 1;
                    599:                break;
                    600:        default:
                    601:                cvs_log(LP_ERR, "unknown global option `%s'", line);
                    602:                return (-1);
1.2       jfb       603:        }
1.8       jfb       604:
                    605:        return (0);
                    606: }
                    607:
                    608:
                    609: /*
                    610:  * cvs_req_gzipstream()
                    611:  *
                    612:  * Handler for the `Gzip-stream' request, which enables compression at the
                    613:  * level given along with the request.  After this request has been processed,
                    614:  * all further connection data should be compressed.
                    615:  */
                    616: static int
                    617: cvs_req_gzipstream(int reqid, char *line)
                    618: {
                    619:        char *ep;
                    620:        long val;
                    621:
                    622:        val = strtol(line, &ep, 10);
                    623:        if ((line[0] == '\0') || (*ep != '\0')) {
                    624:                cvs_log(LP_ERR, "invalid Gzip-stream level `%s'", line);
                    625:                return (-1);
                    626:        } else if ((errno == ERANGE) && ((val < 0) || (val > 9))) {
                    627:                cvs_log(LP_ERR, "Gzip-stream level %ld out of range", val);
                    628:                return (-1);
                    629:        }
                    630:
                    631:        cvs_compress = (int)val;
1.1       jfb       632:
                    633:        return (0);
                    634: }
                    635:
                    636:
1.11      jfb       637: /*
                    638:  * cvs_req_command()
                    639:  *
                    640:  * Generic request handler for CVS command requests (i.e. diff, update, tag).
                    641:  */
1.1       jfb       642: static int
1.11      jfb       643: cvs_req_command(int reqid, char *line)
1.1       jfb       644: {
1.16      jfb       645:        int ret = 0;
1.15      jfb       646:        struct cvs_cmd *cmdp;
1.11      jfb       647:
1.15      jfb       648:        cmdp = cvs_findcmdbyreq(reqid);
                    649:        if (cmdp == NULL) {
1.11      jfb       650:                cvs_sendresp(CVS_RESP_ERROR, NULL);
1.15      jfb       651:                return (-1);
1.11      jfb       652:        }
1.15      jfb       653:
1.22    ! joris     654:        /* close the Entry file if it's still open */
        !           655:        if (cvs_req_entf != NULL)
        !           656:                cvs_ent_close(cvs_req_entf);
        !           657:
        !           658:        /* fill in the command name */
        !           659:        cvs_req_args[0] = cmdp->cmd_name;
        !           660:
        !           661:        /* switch to the correct directory */
        !           662:        if (cmdp->cmd_op != CVS_OP_VERSION) {
        !           663:                if (chdir(cvs_server_tmpdir) == -1) {
        !           664:                        cvs_log(LP_ERRNO, "failed to change dir");
        !           665:                        return (-1);
        !           666:                }
        !           667:        }
        !           668:
1.16      jfb       669:        ret = cvs_startcmd(cmdp, cvs_req_nargs, cvs_req_args);
1.22    ! joris     670:
1.11      jfb       671:        if (ret == 0)
                    672:                ret = cvs_sendresp(CVS_RESP_OK, NULL);
                    673:
                    674:        return (ret);
1.1       jfb       675: }