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

1.12    ! jfb         1: /*     $OpenBSD: req.c,v 1.11 2005/01/13 06:09:14 jfb 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:
                     31: #include <fcntl.h>
                     32: #include <stdio.h>
                     33: #include <errno.h>
                     34: #include <stdlib.h>
                     35: #include <unistd.h>
                     36: #include <string.h>
                     37:
                     38: #include "buf.h"
                     39: #include "cvs.h"
                     40: #include "log.h"
                     41: #include "file.h"
                     42: #include "proto.h"
                     43:
                     44:
                     45: extern int   verbosity;
                     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.11      jfb        53: static int  cvs_req_set          (int, char *);
1.12    ! jfb        54: static int  cvs_req_noop         (int, char *);
1.11      jfb        55: static int  cvs_req_root         (int, char *);
                     56: static int  cvs_req_validreq     (int, char *);
                     57: static int  cvs_req_validresp    (int, char *);
1.12    ! jfb        58: static int  cvs_req_expandmod    (int, char *);
1.11      jfb        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:
                     66: static int  cvs_req_command      (int, char *);
1.1       jfb        67:
                     68:
                     69: struct cvs_reqhdlr {
                     70:        int (*hdlr)(int, char *);
                     71: } cvs_req_swtab[CVS_REQ_MAX + 1] = {
1.11      jfb        72:        { NULL                  },
                     73:        { cvs_req_root          },
                     74:        { cvs_req_validreq      },
                     75:        { cvs_req_validresp     },
                     76:        { cvs_req_directory     },
                     77:        { NULL                  },
                     78:        { NULL                  },
                     79:        { NULL                  },
                     80:        { NULL                  },
                     81:        { NULL                  },
                     82:        { NULL                  },      /* 10 */
                     83:        { NULL                  },
                     84:        { NULL                  },
                     85:        { NULL                  },
                     86:        { cvs_req_useunchanged  },
                     87:        { NULL                  },
                     88:        { NULL                  },
                     89:        { NULL                  },
                     90:        { cvs_req_case          },
                     91:        { NULL                  },
                     92:        { cvs_req_argument      },      /* 20 */
                     93:        { cvs_req_argument      },
                     94:        { cvs_req_globalopt     },
                     95:        { cvs_req_gzipstream    },
                     96:        { NULL                  },
                     97:        { NULL                  },
                     98:        { NULL                  },
                     99:        { NULL                  },
                    100:        { NULL                  },
                    101:        { NULL                  },
                    102:        { NULL                  },      /* 30 */
                    103:        { NULL                  },
                    104:        { NULL                  },
                    105:        { NULL                  },
                    106:        { cvs_req_set           },
1.12    ! jfb       107:        { cvs_req_expandmod     },
1.11      jfb       108:        { cvs_req_command       },
                    109:        { NULL                  },
                    110:        { NULL                  },
                    111:        { NULL                  },
                    112:        { NULL                  },      /* 40 */
                    113:        { NULL                  },
                    114:        { NULL                  },
                    115:        { NULL                  },
                    116:        { NULL                  },
                    117:        { NULL                  },
                    118:        { cvs_req_command       },
                    119:        { NULL                  },
                    120:        { cvs_req_command       },
                    121:        { NULL                  },
                    122:        { NULL                  },      /* 50 */
                    123:        { NULL                  },
                    124:        { NULL                  },
                    125:        { NULL                  },
                    126:        { cvs_req_command       },
                    127:        { cvs_req_command       },
                    128:        { cvs_req_command       },
                    129:        { NULL                  },
                    130:        { NULL                  },
                    131:        { NULL                  },
                    132:        { cvs_req_command       },      /* 60 */
                    133:        { NULL                  },
                    134:        { cvs_req_command       },
                    135:        { cvs_req_command       },
1.12    ! jfb       136:        { cvs_req_noop          },
1.11      jfb       137:        { NULL                  },
                    138:        { NULL                  },
                    139:        { NULL                  },
                    140:        { NULL                  },
                    141:        { cvs_req_command       },
1.1       jfb       142: };
                    143:
                    144:
                    145:
                    146: /*
1.2       jfb       147:  * Argument array built by `Argument' and `Argumentx' requests.
                    148:  */
                    149:
1.11      jfb       150: static char *cvs_req_rootpath;
                    151:
1.2       jfb       152: static char *cvs_req_args[CVS_PROTO_MAXARG];
                    153: static int   cvs_req_nargs = 0;
                    154:
                    155:
                    156: /*
1.1       jfb       157:  * cvs_req_handle()
                    158:  *
                    159:  * Generic request handler dispatcher.  The handler expects the first line
                    160:  * of the command as single argument.
                    161:  * Returns the return value of the command on success, or -1 on failure.
                    162:  */
                    163: int
                    164: cvs_req_handle(char *line)
                    165: {
                    166:        char *cp, *cmd;
                    167:        struct cvs_req *req;
                    168:
                    169:        cmd = line;
                    170:
                    171:        cp = strchr(cmd, ' ');
                    172:        if (cp != NULL)
                    173:                *(cp++) = '\0';
                    174:
                    175:        req = cvs_req_getbyname(cmd);
                    176:        if (req == NULL)
                    177:                return (-1);
                    178:        else if (cvs_req_swtab[req->req_id].hdlr == NULL) {
1.10      jfb       179:                cvs_log(LP_ERR, "handler for `%s' not implemented", cmd);
1.1       jfb       180:                return (-1);
                    181:        }
                    182:
                    183:        return (*cvs_req_swtab[req->req_id].hdlr)(req->req_id, cp);
                    184: }
                    185:
1.12    ! jfb       186: /*
        !           187:  * cvs_req_noop()
        !           188:  */
        !           189: static int
        !           190: cvs_req_noop(int reqid, char *line)
        !           191: {
        !           192:        int ret;
        !           193:
        !           194:        ret = cvs_sendresp(CVS_RESP_OK, NULL);
        !           195:        if (ret < 0)
        !           196:                return (-1);
        !           197:        return (0);
        !           198: }
        !           199:
1.1       jfb       200:
                    201: static int
                    202: cvs_req_root(int reqid, char *line)
                    203: {
1.11      jfb       204:        if (cvs_req_rootpath != NULL) {
                    205:                cvs_log(LP_ERR, "duplicate Root request received");
                    206:                return (-1);
                    207:        }
1.9       jfb       208:
1.11      jfb       209:        cvs_req_rootpath = strdup(line);
                    210:        if (cvs_req_rootpath == NULL) {
                    211:                cvs_log(LP_ERRNO, "failed to copy Root path");
1.9       jfb       212:                return (-1);
                    213:        }
                    214:
1.4       jfb       215:        return (0);
                    216: }
                    217:
                    218:
                    219: static int
                    220: cvs_req_validreq(int reqid, char *line)
                    221: {
                    222:        char *vreq;
                    223:
                    224:        vreq = cvs_req_getvalid();
                    225:        if (vreq == NULL)
                    226:                return (-1);
                    227:
1.11      jfb       228:        if ((cvs_sendresp(CVS_RESP_VALIDREQ, vreq) < 0) ||
                    229:            (cvs_sendresp(CVS_RESP_OK, NULL) < 0))
                    230:                return (-1);
1.4       jfb       231:
                    232:        return (0);
                    233: }
                    234:
                    235: static int
                    236: cvs_req_validresp(int reqid, char *line)
                    237: {
                    238:        char *sp, *ep;
                    239:        struct cvs_resp *resp;
1.1       jfb       240:
1.4       jfb       241:        sp = line;
                    242:        do {
                    243:                ep = strchr(sp, ' ');
                    244:                if (ep != NULL)
                    245:                        *(ep++) = '\0';
                    246:
                    247:                resp = cvs_resp_getbyname(sp);
                    248:                if (resp != NULL)
                    249:                        ;
                    250:
                    251:                if (ep != NULL)
                    252:                        sp = ep + 1;
                    253:        } while (ep != NULL);
1.1       jfb       254:
                    255:        return (0);
                    256: }
                    257:
                    258: static int
                    259: cvs_req_directory(int reqid, char *line)
                    260: {
1.11      jfb       261:        char rdir[MAXPATHLEN];
1.1       jfb       262:
1.11      jfb       263:        if (cvs_getln(NULL, rdir, sizeof(rdir)) < 0)
                    264:                return (-1);
                    265:
                    266:        return (0);
                    267: }
                    268:
1.12    ! jfb       269:
        !           270: /*
        !           271:  * cvs_req_expandmod()
        !           272:  *
        !           273:  */
        !           274: static int
        !           275: cvs_req_expandmod(int reqid, char *line)
        !           276: {
        !           277:        int ret;
        !           278:
        !           279:        ret = cvs_sendresp(CVS_RESP_OK, NULL);
        !           280:        if (ret < 0)
        !           281:                return (-1);
        !           282:        return (0);
        !           283: }
        !           284:
        !           285:
1.11      jfb       286: /*
                    287:  * cvs_req_useunchanged()
                    288:  *
                    289:  * Handler for the `UseUnchanged' requests.  The protocol documentation
                    290:  * specifies that this request must be supported by the server and must be
                    291:  * sent by the client, though it gives no clue regarding its use.
                    292:  */
                    293: static int
                    294: cvs_req_useunchanged(int reqid, char *line)
                    295: {
1.5       jfb       296:        return (0);
                    297: }
                    298:
1.11      jfb       299:
1.5       jfb       300: /*
                    301:  * cvs_req_case()
                    302:  *
                    303:  * Handler for the `Case' requests, which toggles case sensitivity ON or OFF
                    304:  */
                    305: static int
                    306: cvs_req_case(int reqid, char *line)
                    307: {
                    308:        cvs_nocase = 1;
1.2       jfb       309:        return (0);
                    310: }
                    311:
                    312:
                    313: static int
1.11      jfb       314: cvs_req_set(int reqid, char *line)
                    315: {
                    316:        char *cp, *lp;
                    317:
                    318:        if ((lp = strdup(line)) == NULL) {
                    319:                cvs_log(LP_ERRNO, "failed to copy Set argument");
                    320:                return (-1);
                    321:        }
                    322:
                    323:        if ((cp = strchr(lp, '=')) == NULL) {
                    324:                cvs_log(LP_ERR, "error in Set request "
                    325:                    "(no = in variable assignment)");
                    326:                free(lp);
                    327:                return (-1);
                    328:        }
                    329:        *(cp++) = '\0';
                    330:
                    331:        if (cvs_var_set(lp, cp) < 0) {
                    332:                free(lp);
                    333:                return (-1);
                    334:        }
                    335:
                    336:        free(lp);
                    337:
                    338:        return (0);
                    339: }
                    340:
                    341:
                    342: static int
1.2       jfb       343: cvs_req_argument(int reqid, char *line)
                    344: {
                    345:        char *nap;
                    346:
                    347:        if (cvs_req_nargs == CVS_PROTO_MAXARG) {
                    348:                cvs_log(LP_ERR, "too many arguments");
                    349:                return (-1);
                    350:        }
                    351:
                    352:        if (reqid == CVS_REQ_ARGUMENT) {
                    353:                cvs_req_args[cvs_req_nargs] = strdup(line);
                    354:                if (cvs_req_args[cvs_req_nargs] == NULL) {
                    355:                        cvs_log(LP_ERRNO, "failed to copy argument");
                    356:                        return (-1);
                    357:                }
                    358:                cvs_req_nargs++;
1.6       deraadt   359:        } else if (reqid == CVS_REQ_ARGUMENTX) {
1.2       jfb       360:                if (cvs_req_nargs == 0)
                    361:                        cvs_log(LP_WARN, "no argument to append to");
                    362:                else {
                    363:                        asprintf(&nap, "%s%s", cvs_req_args[cvs_req_nargs - 1],
                    364:                            line);
                    365:                        if (nap == NULL) {
                    366:                                cvs_log(LP_ERRNO,
                    367:                                    "failed to append to argument");
                    368:                                return (-1);
                    369:                        }
                    370:                        free(cvs_req_args[cvs_req_nargs - 1]);
                    371:                        cvs_req_args[cvs_req_nargs - 1] = nap;
                    372:                }
1.3       jfb       373:        }
                    374:
                    375:        return (0);
                    376: }
                    377:
                    378:
                    379: static int
                    380: cvs_req_globalopt(int reqid, char *line)
                    381: {
                    382:        if ((*line != '-') || (*(line + 2) != '\0')) {
                    383:                cvs_log(LP_ERR,
                    384:                    "invalid `Global_option' request format");
                    385:                return (-1);
                    386:        }
                    387:
                    388:        switch (*(line + 1)) {
                    389:        case 'l':
                    390:                cvs_nolog = 1;
                    391:                break;
                    392:        case 'n':
                    393:                break;
                    394:        case 'Q':
                    395:                verbosity = 0;
                    396:                break;
                    397:        case 'q':
                    398:                if (verbosity > 1)
                    399:                        verbosity = 1;
                    400:                break;
                    401:        case 'r':
                    402:                cvs_readonly = 1;
                    403:                break;
                    404:        case 't':
                    405:                cvs_trace = 1;
                    406:                break;
                    407:        default:
                    408:                cvs_log(LP_ERR, "unknown global option `%s'", line);
                    409:                return (-1);
1.2       jfb       410:        }
1.8       jfb       411:
                    412:        return (0);
                    413: }
                    414:
                    415:
                    416: /*
                    417:  * cvs_req_gzipstream()
                    418:  *
                    419:  * Handler for the `Gzip-stream' request, which enables compression at the
                    420:  * level given along with the request.  After this request has been processed,
                    421:  * all further connection data should be compressed.
                    422:  */
                    423: static int
                    424: cvs_req_gzipstream(int reqid, char *line)
                    425: {
                    426:        char *ep;
                    427:        long val;
                    428:
                    429:        val = strtol(line, &ep, 10);
                    430:        if ((line[0] == '\0') || (*ep != '\0')) {
                    431:                cvs_log(LP_ERR, "invalid Gzip-stream level `%s'", line);
                    432:                return (-1);
                    433:        } else if ((errno == ERANGE) && ((val < 0) || (val > 9))) {
                    434:                cvs_log(LP_ERR, "Gzip-stream level %ld out of range", val);
                    435:                return (-1);
                    436:        }
                    437:
                    438:        cvs_compress = (int)val;
1.1       jfb       439:
                    440:        return (0);
                    441: }
                    442:
                    443:
1.11      jfb       444: /*
                    445:  * cvs_req_command()
                    446:  *
                    447:  * Generic request handler for CVS command requests (i.e. diff, update, tag).
                    448:  */
1.1       jfb       449: static int
1.11      jfb       450: cvs_req_command(int reqid, char *line)
1.1       jfb       451: {
1.11      jfb       452:        int ret;
                    453:
                    454:        switch (reqid) {
                    455:        case CVS_REQ_VERSION:
                    456:                ret = cvs_sendresp(CVS_RESP_M, CVS_VERSION);
                    457:                break;
                    458:        case CVS_REQ_ADD:
                    459:        case CVS_REQ_ANNOTATE:
1.12    ! jfb       460:        case CVS_REQ_CO:
1.11      jfb       461:        case CVS_REQ_CI:
                    462:        case CVS_REQ_DIFF:
                    463:        case CVS_REQ_LOG:
                    464:        case CVS_REQ_REMOVE:
                    465:        case CVS_REQ_STATUS:
                    466:        case CVS_REQ_TAG:
                    467:        default:
                    468:                cvs_sendresp(CVS_RESP_E, "command not yet implemented");
                    469:                cvs_sendresp(CVS_RESP_ERROR, NULL);
                    470:                return (0);
                    471:        }
                    472:
                    473:        if (ret == 0)
                    474:                ret = cvs_sendresp(CVS_RESP_OK, NULL);
                    475:
                    476:        return (ret);
1.1       jfb       477: }