[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.33

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