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

Annotation of src/usr.bin/cvs/server.c, Revision 1.58

1.58    ! ray         1: /*     $OpenBSD: server.c,v 1.57 2007/05/25 22:27:02 ray Exp $ */
1.1       jfb         2: /*
1.29      joris       3:  * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
1.1       jfb         4:  *
1.29      joris       5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
1.1       jfb         8:  *
1.29      joris       9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1       jfb        16:  */
                     17:
1.55      otto       18: #include <sys/stat.h>
                     19:
                     20: #include <errno.h>
                     21: #include <fcntl.h>
                     22: #include <libgen.h>
                     23: #include <stdlib.h>
                     24: #include <string.h>
                     25: #include <unistd.h>
1.1       jfb        26:
                     27: #include "cvs.h"
1.29      joris      28: #include "remote.h"
                     29:
                     30: struct cvs_resp cvs_responses[] = {
                     31:        /* this is what our server uses, the client should support it */
                     32:        { "Valid-requests",     1,      cvs_client_validreq, RESP_NEEDED },
                     33:        { "ok",                 0,      cvs_client_ok, RESP_NEEDED},
                     34:        { "error",              0,      cvs_client_error, RESP_NEEDED },
                     35:        { "E",                  0,      cvs_client_e, RESP_NEEDED },
                     36:        { "M",                  0,      cvs_client_m, RESP_NEEDED },
                     37:        { "Checked-in",         0,      cvs_client_checkedin, RESP_NEEDED },
                     38:        { "Updated",            0,      cvs_client_updated, RESP_NEEDED },
                     39:        { "Merged",             0,      cvs_client_merged, RESP_NEEDED },
                     40:        { "Removed",            0,      cvs_client_removed, RESP_NEEDED },
                     41:        { "Remove-entry",       0,      cvs_client_remove_entry, RESP_NEEDED },
1.46      xsa        42:        { "Set-static-directory",       0,      cvs_client_set_static_directory, RESP_NEEDED },
1.45      xsa        43:        { "Clear-static-directory",     0,      cvs_client_clear_static_directory, RESP_NEEDED },
                     44:        { "Set-sticky",         0,      cvs_client_set_sticky, RESP_NEEDED },
                     45:        { "Clear-sticky",       0,      cvs_client_clear_sticky, RESP_NEEDED },
1.29      joris      46:
                     47:        /* unsupported responses until told otherwise */
                     48:        { "New-entry",                  0,      NULL, 0 },
                     49:        { "Created",                    0,      NULL, 0 },
                     50:        { "Update-existing",            0,      NULL, 0 },
                     51:        { "Rcs-diff",                   0,      NULL, 0 },
                     52:        { "Patched",                    0,      NULL, 0 },
                     53:        { "Mode",                       0,      NULL, 0 },
                     54:        { "Mod-time",                   0,      NULL, 0 },
                     55:        { "Checksum",                   0,      NULL, 0 },
                     56:        { "Copy-file",                  0,      NULL, 0 },
                     57:        { "Template",                   0,      NULL, 0 },
                     58:        { "Set-checkin-prog",           0,      NULL, 0 },
                     59:        { "Set-update-prog",            0,      NULL, 0 },
                     60:        { "Notified",                   0,      NULL, 0 },
                     61:        { "Module-expansion",           0,      NULL, 0 },
                     62:        { "Wrapper-rcsOption",          0,      NULL, 0 },
                     63:        { "Mbinary",                    0,      NULL, 0 },
                     64:        { "F",                          0,      NULL, 0 },
                     65:        { "MT",                         0,      NULL, 0 },
                     66:        { "",                           -1,     NULL, 0 }
                     67: };
1.1       jfb        68:
1.29      joris      69: int    cvs_server(int, char **);
                     70: char   *cvs_server_path = NULL;
1.1       jfb        71:
1.29      joris      72: static char *server_currentdir = NULL;
                     73: static char *server_argv[CVS_CMD_MAXARG];
                     74: static int server_argc = 1;
1.8       joris      75:
1.17      jfb        76: struct cvs_cmd cvs_cmd_server = {
1.29      joris      77:        CVS_OP_SERVER, 0, "server", { "", "" },
                     78:        "server mode",
1.17      jfb        79:        NULL,
1.29      joris      80:        NULL,
                     81:        NULL,
                     82:        cvs_server
1.17      jfb        83: };
1.1       jfb        84:
1.14      joris      85:
1.1       jfb        86: int
                     87: cvs_server(int argc, char **argv)
                     88: {
1.29      joris      89:        char *cmd, *data;
                     90:        struct cvs_req *req;
                     91:
                     92:        server_argv[0] = xstrdup("server");
                     93:
1.58    ! ray        94:        (void)xasprintf(&cvs_server_path, "%s/cvs-serv%d", cvs_tmpdir,
        !            95:            getpid());
1.29      joris      96:
                     97:        if (mkdir(cvs_server_path, 0700) == -1)
                     98:                fatal("failed to create temporary server directory: %s, %s",
                     99:                    cvs_server_path, strerror(errno));
                    100:
                    101:        if (chdir(cvs_server_path) == -1)
                    102:                fatal("failed to change directory to '%s'", cvs_server_path);
                    103:
                    104:        for (;;) {
                    105:                cmd = cvs_remote_input();
                    106:
                    107:                if ((data = strchr(cmd, ' ')) != NULL)
                    108:                        (*data++) = '\0';
                    109:
                    110:                req = cvs_remote_get_request_info(cmd);
                    111:                if (req == NULL)
                    112:                        fatal("request '%s' is not supported by our server",
                    113:                            cmd);
                    114:
                    115:                if (req->hdlr == NULL)
                    116:                        fatal("opencvs server does not support '%s'", cmd);
                    117:
                    118:                (*req->hdlr)(data);
                    119:                xfree(cmd);
1.14      joris     120:        }
                    121:
1.29      joris     122:        return (0);
                    123: }
                    124:
                    125: void
                    126: cvs_server_send_response(char *fmt, ...)
                    127: {
                    128:        va_list ap;
                    129:        char *data, *s;
                    130:        struct cvs_resp *resp;
                    131:
                    132:        va_start(ap, fmt);
1.56      ray       133:        if (vasprintf(&data, fmt, ap) == -1)
                    134:                fatal("vasprintf: %s", strerror(errno));
1.29      joris     135:        va_end(ap);
                    136:
                    137:        if ((s = strchr(data, ' ')) != NULL)
                    138:                *s = '\0';
                    139:
                    140:        resp = cvs_remote_get_response_info(data);
                    141:        if (resp == NULL)
                    142:                fatal("'%s' is an unknown response", data);
                    143:
                    144:        if (resp->supported != 1)
                    145:                fatal("remote cvs client does not support '%s'", data);
1.14      joris     146:
1.29      joris     147:        if (s != NULL)
                    148:                *s = ' ';
1.14      joris     149:
1.30      joris     150:        cvs_log(LP_TRACE, "%s", data);
1.29      joris     151:        cvs_remote_output(data);
                    152:        xfree(data);
                    153: }
                    154:
                    155: void
                    156: cvs_server_root(char *data)
                    157: {
                    158:        fatal("duplicate Root request from client, violates the protocol");
                    159: }
                    160:
                    161: void
                    162: cvs_server_validresp(char *data)
                    163: {
                    164:        int i;
                    165:        char *sp, *ep;
                    166:        struct cvs_resp *resp;
                    167:
1.57      ray       168:        if ((sp = data) == NULL)
                    169:                fatal("Missing argument for Valid-responses");
                    170:
1.29      joris     171:        do {
                    172:                if ((ep = strchr(sp, ' ')) != NULL)
                    173:                        *ep = '\0';
                    174:
                    175:                resp = cvs_remote_get_response_info(sp);
                    176:                if (resp != NULL)
                    177:                        resp->supported = 1;
                    178:
                    179:                if (ep != NULL)
                    180:                        sp = ep + 1;
                    181:        } while (ep != NULL);
                    182:
                    183:        for (i = 0; cvs_responses[i].supported != -1; i++) {
                    184:                resp = &cvs_responses[i];
                    185:                if ((resp->flags & RESP_NEEDED) &&
                    186:                    resp->supported != 1) {
                    187:                        fatal("client does not support required '%s'",
                    188:                            resp->name);
1.1       jfb       189:                }
1.29      joris     190:        }
                    191: }
1.1       jfb       192:
1.29      joris     193: void
                    194: cvs_server_validreq(char *data)
                    195: {
                    196:        BUF *bp;
                    197:        char *d;
                    198:        int i, first;
                    199:
                    200:        first = 0;
                    201:        bp = cvs_buf_alloc(512, BUF_AUTOEXT);
                    202:        for (i = 0; cvs_requests[i].supported != -1; i++) {
                    203:                if (cvs_requests[i].hdlr == NULL)
1.5       jfb       204:                        continue;
1.1       jfb       205:
1.29      joris     206:                if (first != 0)
                    207:                        cvs_buf_append(bp, " ", 1);
                    208:                else
                    209:                        first++;
                    210:
                    211:                cvs_buf_append(bp, cvs_requests[i].name,
                    212:                    strlen(cvs_requests[i].name));
                    213:        }
                    214:
                    215:        cvs_buf_putc(bp, '\0');
                    216:        d = cvs_buf_release(bp);
                    217:
                    218:        cvs_server_send_response("Valid-requests %s", d);
                    219:        cvs_server_send_response("ok");
                    220:        xfree(d);
1.42      xsa       221: }
                    222:
                    223: void
1.43      xsa       224: cvs_server_static_directory(char *data)
                    225: {
                    226:        FILE *fp;
1.51      otto      227:        char fpath[MAXPATHLEN];
1.43      xsa       228:
1.54      xsa       229:        (void)xsnprintf(fpath, MAXPATHLEN, "%s/%s",
                    230:            server_currentdir, CVS_PATH_STATICENTRIES);
1.43      xsa       231:
                    232:        if ((fp = fopen(fpath, "w+")) == NULL) {
                    233:                cvs_log(LP_ERRNO, "%s", fpath);
1.51      otto      234:                return;
1.43      xsa       235:        }
                    236:        (void)fclose(fp);
                    237: }
                    238:
                    239: void
1.42      xsa       240: cvs_server_sticky(char *data)
                    241: {
                    242:        FILE *fp;
1.51      otto      243:        char tagpath[MAXPATHLEN];
1.42      xsa       244:
1.57      ray       245:        if (data == NULL)
                    246:                fatal("Missing argument for Sticky");
                    247:
1.54      xsa       248:        (void)xsnprintf(tagpath, MAXPATHLEN, "%s/%s",
                    249:            server_currentdir, CVS_PATH_TAG);
1.42      xsa       250:
1.43      xsa       251:        if ((fp = fopen(tagpath, "w+")) == NULL) {
1.42      xsa       252:                cvs_log(LP_ERRNO, "%s", tagpath);
1.51      otto      253:                return;
1.42      xsa       254:        }
                    255:
                    256:        (void)fprintf(fp, "%s\n", data);
                    257:        (void)fclose(fp);
1.29      joris     258: }
                    259:
                    260: void
                    261: cvs_server_globalopt(char *data)
                    262: {
1.57      ray       263:        if (data == NULL)
                    264:                fatal("Missing argument for Global_option");
                    265:
1.38      xsa       266:        if (!strcmp(data, "-l"))
                    267:                cvs_nolog = 1;
1.29      joris     268:
                    269:        if (!strcmp(data, "-n"))
                    270:                cvs_noexec = 1;
1.38      xsa       271:
                    272:        if (!strcmp(data, "-Q"))
                    273:                verbosity = 0;
                    274:
                    275:        if (!strcmp(data, "-r"))
                    276:                cvs_readonly = 1;
                    277:
                    278:        if (!strcmp(data, "-t"))
                    279:                cvs_trace = 1;
1.29      joris     280:
                    281:        if (!strcmp(data, "-V"))
                    282:                verbosity = 2;
1.39      xsa       283: }
                    284:
                    285: void
                    286: cvs_server_set(char *data)
                    287: {
                    288:        char *ep;
                    289:
1.57      ray       290:        if (data == NULL)
                    291:                fatal("Missing argument for Set");
                    292:
1.39      xsa       293:        ep = strchr(data, '=');
                    294:        if (ep == NULL)
                    295:                fatal("no = in variable assignment");
                    296:
                    297:        *(ep++) = '\0';
                    298:        if (cvs_var_set(data, ep) < 0)
                    299:                fatal("cvs_server_set: cvs_var_set failed");
1.29      joris     300: }
1.1       jfb       301:
1.29      joris     302: void
                    303: cvs_server_directory(char *data)
                    304: {
                    305:        CVSENTRIES *entlist;
1.51      otto      306:        char *dir, *repo, *parent, entry[CVS_ENT_MAXLINELEN], *dirn, *p;
1.29      joris     307:
                    308:        dir = cvs_remote_input();
1.49      joris     309:        STRIP_SLASH(dir);
                    310:
                    311:        if (strlen(dir) < strlen(current_cvsroot->cr_dir))
1.29      joris     312:                fatal("cvs_server_directory: bad Directory request");
                    313:
1.49      joris     314:        repo = dir + strlen(current_cvsroot->cr_dir);
                    315:
                    316:        /*
                    317:         * This is somewhat required for checkout, as the
                    318:         * directory request will be:
                    319:         *
                    320:         * Directory .
                    321:         * /path/to/cvs/root
                    322:         */
                    323:        if (repo[0] == '\0')
                    324:                p = xstrdup(".");
                    325:        else
                    326:                p = xstrdup(repo + 1);
                    327:
                    328:        cvs_mkpath(p);
1.29      joris     329:
1.49      joris     330:        if ((dirn = basename(p)) == NULL)
1.29      joris     331:                fatal("cvs_server_directory: %s", strerror(errno));
                    332:
1.49      joris     333:        if ((parent = dirname(p)) == NULL)
1.29      joris     334:                fatal("cvs_server_directory: %s", strerror(errno));
                    335:
                    336:        if (strcmp(parent, ".")) {
                    337:                entlist = cvs_ent_open(parent);
1.53      xsa       338:                (void)xsnprintf(entry, CVS_ENT_MAXLINELEN, "D/%s////", dirn);
1.29      joris     339:
                    340:                cvs_ent_add(entlist, entry);
                    341:                cvs_ent_close(entlist, ENT_SYNC);
1.1       jfb       342:        }
                    343:
1.29      joris     344:        if (server_currentdir != NULL)
                    345:                xfree(server_currentdir);
1.49      joris     346:        server_currentdir = xstrdup(p);
1.29      joris     347:
1.49      joris     348:        xfree(p);
1.29      joris     349:        xfree(dir);
                    350: }
                    351:
                    352: void
                    353: cvs_server_entry(char *data)
                    354: {
                    355:        CVSENTRIES *entlist;
                    356:
1.57      ray       357:        if (data == NULL)
                    358:                fatal("Missing argument for Entry");
                    359:
1.29      joris     360:        entlist = cvs_ent_open(server_currentdir);
                    361:        cvs_ent_add(entlist, data);
                    362:        cvs_ent_close(entlist, ENT_SYNC);
                    363: }
                    364:
                    365: void
                    366: cvs_server_modified(char *data)
                    367: {
1.41      xsa       368:        int fd;
1.29      joris     369:        size_t flen;
                    370:        mode_t fmode;
                    371:        const char *errstr;
1.51      otto      372:        char *mode, *len, fpath[MAXPATHLEN];
1.29      joris     373:
1.57      ray       374:        if (data == NULL)
                    375:                fatal("Missing argument for Modified");
                    376:
1.29      joris     377:        mode = cvs_remote_input();
                    378:        len = cvs_remote_input();
                    379:
                    380:        cvs_strtomode(mode, &fmode);
                    381:        xfree(mode);
                    382:
                    383:        flen = strtonum(len, 0, INT_MAX, &errstr);
                    384:        if (errstr != NULL)
                    385:                fatal("cvs_server_modified: %s", errstr);
                    386:        xfree(len);
                    387:
1.54      xsa       388:        (void)xsnprintf(fpath, MAXPATHLEN, "%s/%s", server_currentdir, data);
1.29      joris     389:
                    390:        if ((fd = open(fpath, O_WRONLY | O_CREAT | O_TRUNC)) == -1)
                    391:                fatal("cvs_server_modified: %s: %s", fpath, strerror(errno));
                    392:
1.48      joris     393:        cvs_remote_receive_file(fd, flen);
1.29      joris     394:
                    395:        if (fchmod(fd, 0600) == -1)
                    396:                fatal("cvs_server_modified: failed to set file mode");
                    397:
                    398:        (void)close(fd);
                    399: }
                    400:
                    401: void
                    402: cvs_server_useunchanged(char *data)
                    403: {
                    404: }
                    405:
                    406: void
                    407: cvs_server_unchanged(char *data)
                    408: {
1.41      xsa       409:        int fd;
1.51      otto      410:        char fpath[MAXPATHLEN];
1.29      joris     411:        CVSENTRIES *entlist;
                    412:        struct cvs_ent *ent;
                    413:        struct timeval tv[2];
                    414:
1.57      ray       415:        if (data == NULL)
                    416:                fatal("Missing argument for Unchanged");
                    417:
1.54      xsa       418:        (void)xsnprintf(fpath, MAXPATHLEN, "%s/%s", server_currentdir, data);
1.29      joris     419:
                    420:        if ((fd = open(fpath, O_RDWR | O_CREAT | O_TRUNC)) == -1)
                    421:                fatal("cvs_server_unchanged: %s: %s", fpath, strerror(errno));
                    422:
                    423:        entlist = cvs_ent_open(server_currentdir);
                    424:        ent = cvs_ent_get(entlist, data);
                    425:        if (ent == NULL)
                    426:                fatal("received Unchanged request for non-existing file");
                    427:        cvs_ent_close(entlist, ENT_NOSYNC);
                    428:
1.52      joris     429:        tv[0].tv_sec = ent->ce_mtime;
1.29      joris     430:        tv[0].tv_usec = 0;
                    431:        tv[1] = tv[0];
                    432:        if (futimes(fd, tv) == -1)
                    433:                fatal("cvs_server_unchanged: failed to set modified time");
                    434:
                    435:        if (fchmod(fd, 0600) == -1)
                    436:                fatal("cvs_server_unchanged: failed to set mode");
                    437:
                    438:        cvs_ent_free(ent);
                    439:        (void)close(fd);
                    440: }
                    441:
                    442: void
                    443: cvs_server_questionable(char *data)
                    444: {
                    445: }
                    446:
                    447: void
                    448: cvs_server_argument(char *data)
                    449: {
                    450:
                    451:        if (server_argc > CVS_CMD_MAXARG)
                    452:                fatal("cvs_server_argument: too many arguments sent");
1.57      ray       453:
                    454:        if (data == NULL)
                    455:                fatal("Missing argument for Argument");
1.29      joris     456:
                    457:        server_argv[server_argc++] = xstrdup(data);
1.37      xsa       458: }
                    459:
                    460: void
                    461: cvs_server_argumentx(char *data)
                    462: {
1.44      xsa       463: }
                    464:
                    465: void
                    466: cvs_server_update_patches(char *data)
                    467: {
                    468:        /*
                    469:         * This does not actually do anything.
                    470:         * It is used to tell that the server is able to
                    471:         * generate patches when given an `update' request.
                    472:         * The client must issue the -u argument to `update'
                    473:         * to receive patches.
                    474:         */
1.29      joris     475: }
                    476:
                    477: void
1.31      xsa       478: cvs_server_add(char *data)
                    479: {
                    480:        if (chdir(server_currentdir) == -1)
                    481:                fatal("cvs_server_add: %s", strerror(errno));
                    482:
                    483:        cvs_cmdop = CVS_OP_ADD;
                    484:        cvs_add(server_argc, server_argv);
1.50      joris     485:        cvs_server_send_response("ok");
                    486: }
                    487:
                    488: void
                    489: cvs_server_import(char *data)
                    490: {
                    491:        if (chdir(server_currentdir) == -1)
                    492:                fatal("cvs_server_import: %s", strerror(errno));
                    493:
                    494:        cvs_cmdop = CVS_OP_IMPORT;
                    495:        cvs_import(server_argc, server_argv);
1.31      xsa       496:        cvs_server_send_response("ok");
                    497: }
1.35      xsa       498:
                    499: void
                    500: cvs_server_admin(char *data)
                    501: {
                    502:        if (chdir(server_currentdir) == -1)
                    503:                fatal("cvs_server_admin: %s", strerror(errno));
                    504:
                    505:        cvs_cmdop = CVS_OP_ADMIN;
                    506:        cvs_admin(server_argc, server_argv);
                    507:        cvs_server_send_response("ok");
                    508: }
                    509:
1.40      xsa       510: void
                    511: cvs_server_annotate(char *data)
                    512: {
                    513:        if (chdir(server_currentdir) == -1)
                    514:                fatal("cvs_server_annotate: %s", strerror(errno));
                    515:
                    516:        cvs_cmdop = CVS_OP_ANNOTATE;
                    517:        cvs_annotate(server_argc, server_argv);
                    518:        cvs_server_send_response("ok");
                    519: }
1.31      xsa       520:
                    521: void
1.29      joris     522: cvs_server_commit(char *data)
                    523: {
                    524:        if (chdir(server_currentdir) == -1)
                    525:                fatal("cvs_server_commit: %s", strerror(errno));
                    526:
                    527:        cvs_cmdop = CVS_OP_COMMIT;
                    528:        cvs_commit(server_argc, server_argv);
1.49      joris     529:        cvs_server_send_response("ok");
                    530: }
                    531:
                    532: void
                    533: cvs_server_checkout(char *data)
                    534: {      if (chdir(server_currentdir) == -1)
                    535:                fatal("cvs_server_checkout: %s", strerror(errno));
                    536:
                    537:        cvs_cmdop = CVS_OP_CHECKOUT;
                    538:        cvs_checkout(server_argc, server_argv);
1.29      joris     539:        cvs_server_send_response("ok");
                    540: }
                    541:
                    542: void
                    543: cvs_server_diff(char *data)
                    544: {
                    545:        if (chdir(server_currentdir) == -1)
                    546:                fatal("cvs_server_diff: %s", strerror(errno));
                    547:
                    548:        cvs_cmdop = CVS_OP_DIFF;
                    549:        cvs_diff(server_argc, server_argv);
1.34      xsa       550:        cvs_server_send_response("ok");
                    551: }
                    552:
                    553: void
                    554: cvs_server_init(char *data)
                    555: {
                    556:        if (chdir(server_currentdir) == -1)
                    557:                fatal("cvs_server_init: %s", strerror(errno));
                    558:
                    559:        cvs_cmdop = CVS_OP_INIT;
                    560:        cvs_init(server_argc, server_argv);
1.31      xsa       561:        cvs_server_send_response("ok");
                    562: }
                    563:
                    564: void
                    565: cvs_server_remove(char *data)
                    566: {
                    567:        if (chdir(server_currentdir) == -1)
                    568:                fatal("cvs_server_remove: %s", strerror(errno));
                    569:
                    570:        cvs_cmdop = CVS_OP_REMOVE;
                    571:        cvs_remove(server_argc, server_argv);
1.29      joris     572:        cvs_server_send_response("ok");
                    573: }
                    574:
                    575: void
                    576: cvs_server_status(char *data)
                    577: {
                    578:        if (chdir(server_currentdir) == -1)
                    579:                fatal("cvs_server_status: %s", strerror(errno));
                    580:
                    581:        cvs_cmdop = CVS_OP_STATUS;
                    582:        cvs_status(server_argc, server_argv);
                    583:        cvs_server_send_response("ok");
                    584: }
                    585:
                    586: void
                    587: cvs_server_log(char *data)
                    588: {
                    589:        if (chdir(server_currentdir) == -1)
                    590:                fatal("cvs_server_log: %s", strerror(errno));
                    591:
                    592:        cvs_cmdop = CVS_OP_LOG;
1.32      xsa       593:        cvs_getlog(server_argc, server_argv);
                    594:        cvs_server_send_response("ok");
                    595: }
                    596:
                    597: void
                    598: cvs_server_tag(char *data)
                    599: {
                    600:        if (chdir(server_currentdir) == -1)
                    601:                fatal("cvs_server_tag: %s", strerror(errno));
                    602:
                    603:        cvs_cmdop = CVS_OP_TAG;
1.33      xsa       604:        cvs_tag(server_argc, server_argv);
1.29      joris     605:        cvs_server_send_response("ok");
                    606: }
                    607:
                    608: void
                    609: cvs_server_update(char *data)
                    610: {
                    611:        if (chdir(server_currentdir) == -1)
                    612:                fatal("cvs_server_update: %s", strerror(errno));
1.14      joris     613:
1.29      joris     614:        cvs_cmdop = CVS_OP_UPDATE;
                    615:        cvs_update(server_argc, server_argv);
1.36      xsa       616:        cvs_server_send_response("ok");
                    617: }
                    618:
                    619: void
                    620: cvs_server_version(char *data)
                    621: {
                    622:        cvs_cmdop = CVS_OP_VERSION;
                    623:        cvs_version(server_argc, server_argv);
1.29      joris     624:        cvs_server_send_response("ok");
1.47      joris     625: }
                    626:
                    627: void
                    628: cvs_server_update_entry(const char *resp, struct cvs_file *cf)
                    629: {
1.58    ! ray       630:        char *p;
1.47      joris     631:
                    632:        if ((p = strrchr(cf->file_rpath, ',')) != NULL)
                    633:                *p = '\0';
                    634:
1.58    ! ray       635:        cvs_server_send_response("%s %s/", resp, cf->file_wd);
1.47      joris     636:        cvs_remote_output(cf->file_rpath);
                    637:
                    638:        if (p != NULL)
                    639:                *p = ',';
1.1       jfb       640: }