Annotation of src/usr.bin/cvs/server.c, Revision 1.106
1.106 ! naddy 1: /* $OpenBSD: server.c,v 1.105 2017/08/28 19:33:20 otto 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.73 tobias 18: #include <sys/types.h>
1.55 otto 19: #include <sys/stat.h>
20:
21: #include <errno.h>
22: #include <fcntl.h>
23: #include <libgen.h>
1.68 tobias 24: #include <stdio.h>
1.55 otto 25: #include <stdlib.h>
26: #include <string.h>
27: #include <unistd.h>
1.1 jfb 28:
29: #include "cvs.h"
1.29 joris 30: #include "remote.h"
31:
32: struct cvs_resp cvs_responses[] = {
33: /* this is what our server uses, the client should support it */
34: { "Valid-requests", 1, cvs_client_validreq, RESP_NEEDED },
35: { "ok", 0, cvs_client_ok, RESP_NEEDED},
36: { "error", 0, cvs_client_error, RESP_NEEDED },
37: { "E", 0, cvs_client_e, RESP_NEEDED },
38: { "M", 0, cvs_client_m, RESP_NEEDED },
39: { "Checked-in", 0, cvs_client_checkedin, RESP_NEEDED },
40: { "Updated", 0, cvs_client_updated, RESP_NEEDED },
41: { "Merged", 0, cvs_client_merged, RESP_NEEDED },
42: { "Removed", 0, cvs_client_removed, RESP_NEEDED },
1.99 joris 43: { "Remove-entry", 0, cvs_client_remove_entry, 0 },
44: { "Set-static-directory", 0,
45: cvs_client_set_static_directory, 0 },
46: { "Clear-static-directory", 0,
47: cvs_client_clear_static_directory, 0 },
48: { "Set-sticky", 0, cvs_client_set_sticky, 0 },
49: { "Clear-sticky", 0, cvs_client_clear_sticky, 0 },
1.29 joris 50:
51: /* unsupported responses until told otherwise */
52: { "New-entry", 0, NULL, 0 },
53: { "Created", 0, NULL, 0 },
54: { "Update-existing", 0, NULL, 0 },
55: { "Rcs-diff", 0, NULL, 0 },
56: { "Patched", 0, NULL, 0 },
57: { "Mode", 0, NULL, 0 },
58: { "Mod-time", 0, NULL, 0 },
59: { "Checksum", 0, NULL, 0 },
60: { "Copy-file", 0, NULL, 0 },
61: { "Template", 0, NULL, 0 },
62: { "Set-checkin-prog", 0, NULL, 0 },
63: { "Set-update-prog", 0, NULL, 0 },
64: { "Notified", 0, NULL, 0 },
65: { "Module-expansion", 0, NULL, 0 },
66: { "Wrapper-rcsOption", 0, NULL, 0 },
67: { "Mbinary", 0, NULL, 0 },
68: { "F", 0, NULL, 0 },
69: { "MT", 0, NULL, 0 },
70: { "", -1, NULL, 0 }
71: };
1.1 jfb 72:
1.29 joris 73: int cvs_server(int, char **);
74: char *cvs_server_path = NULL;
1.1 jfb 75:
1.29 joris 76: static char *server_currentdir = NULL;
1.88 tobias 77: static char **server_argv;
1.29 joris 78: static int server_argc = 1;
1.8 joris 79:
1.90 joris 80: extern int disable_fast_checkout;
81:
1.17 jfb 82: struct cvs_cmd cvs_cmd_server = {
1.78 tobias 83: CVS_OP_SERVER, CVS_USE_WDIR, "server", { "", "" },
1.29 joris 84: "server mode",
1.17 jfb 85: NULL,
1.29 joris 86: NULL,
87: NULL,
88: cvs_server
1.17 jfb 89: };
1.1 jfb 90:
1.14 joris 91:
1.1 jfb 92: int
93: cvs_server(int argc, char **argv)
94: {
1.29 joris 95: char *cmd, *data;
96: struct cvs_req *req;
97:
1.68 tobias 98: if (argc > 1)
99: fatal("server does not take any extra arguments");
100:
1.70 tobias 101: /* Be on server-side very verbose per default. */
102: verbosity = 2;
103:
1.68 tobias 104: setvbuf(stdin, NULL, _IOLBF, 0);
105: setvbuf(stdout, NULL, _IOLBF, 0);
106:
107: cvs_server_active = 1;
108:
1.88 tobias 109: server_argv = xcalloc(server_argc + 1, sizeof(*server_argv));
1.29 joris 110: server_argv[0] = xstrdup("server");
111:
1.58 ray 112: (void)xasprintf(&cvs_server_path, "%s/cvs-serv%d", cvs_tmpdir,
113: getpid());
1.29 joris 114:
115: if (mkdir(cvs_server_path, 0700) == -1)
116: fatal("failed to create temporary server directory: %s, %s",
117: cvs_server_path, strerror(errno));
118:
119: if (chdir(cvs_server_path) == -1)
120: fatal("failed to change directory to '%s'", cvs_server_path);
121:
122: for (;;) {
123: cmd = cvs_remote_input();
124:
125: if ((data = strchr(cmd, ' ')) != NULL)
126: (*data++) = '\0';
127:
128: req = cvs_remote_get_request_info(cmd);
129: if (req == NULL)
130: fatal("request '%s' is not supported by our server",
131: cmd);
132:
133: if (req->hdlr == NULL)
134: fatal("opencvs server does not support '%s'", cmd);
1.63 joris 135:
136: if ((req->flags & REQ_NEEDDIR) && (server_currentdir == NULL))
137: fatal("`%s' needs a directory to be sent with "
138: "the `Directory` request first", cmd);
1.29 joris 139:
140: (*req->hdlr)(data);
1.103 nicm 141: free(cmd);
1.14 joris 142: }
143:
1.29 joris 144: return (0);
145: }
146:
147: void
148: cvs_server_send_response(char *fmt, ...)
149: {
1.85 tobias 150: int i;
1.29 joris 151: va_list ap;
1.59 ray 152: char *data;
1.29 joris 153:
154: va_start(ap, fmt);
1.85 tobias 155: i = vasprintf(&data, fmt, ap);
1.29 joris 156: va_end(ap);
1.85 tobias 157: if (i == -1)
1.86 tobias 158: fatal("cvs_server_send_response: could not allocate memory");
1.14 joris 159:
1.30 joris 160: cvs_log(LP_TRACE, "%s", data);
1.29 joris 161: cvs_remote_output(data);
1.103 nicm 162: free(data);
1.29 joris 163: }
164:
165: void
166: cvs_server_root(char *data)
167: {
1.68 tobias 168: if (data == NULL)
169: fatal("Missing argument for Root");
170:
171: if (current_cvsroot != NULL)
172: return;
173:
174: if (data[0] != '/' || (current_cvsroot = cvsroot_get(data)) == NULL)
175: fatal("Invalid Root specified!");
1.73 tobias 176:
177: cvs_parse_configfile();
1.81 joris 178: cvs_parse_modules();
1.73 tobias 179: umask(cvs_umask);
1.29 joris 180: }
181:
182: void
183: cvs_server_validresp(char *data)
184: {
185: int i;
186: char *sp, *ep;
187: struct cvs_resp *resp;
188:
1.57 ray 189: if ((sp = data) == NULL)
190: fatal("Missing argument for Valid-responses");
191:
1.29 joris 192: do {
193: if ((ep = strchr(sp, ' ')) != NULL)
194: *ep = '\0';
195:
196: resp = cvs_remote_get_response_info(sp);
197: if (resp != NULL)
198: resp->supported = 1;
199:
200: if (ep != NULL)
201: sp = ep + 1;
202: } while (ep != NULL);
203:
204: for (i = 0; cvs_responses[i].supported != -1; i++) {
205: resp = &cvs_responses[i];
206: if ((resp->flags & RESP_NEEDED) &&
207: resp->supported != 1) {
208: fatal("client does not support required '%s'",
209: resp->name);
1.1 jfb 210: }
1.29 joris 211: }
212: }
1.1 jfb 213:
1.29 joris 214: void
215: cvs_server_validreq(char *data)
216: {
217: BUF *bp;
218: char *d;
219: int i, first;
220:
221: first = 0;
1.100 ray 222: bp = buf_alloc(512);
1.29 joris 223: for (i = 0; cvs_requests[i].supported != -1; i++) {
224: if (cvs_requests[i].hdlr == NULL)
1.5 jfb 225: continue;
1.1 jfb 226:
1.29 joris 227: if (first != 0)
1.100 ray 228: buf_putc(bp, ' ');
1.29 joris 229: else
230: first++;
231:
1.100 ray 232: buf_puts(bp, cvs_requests[i].name);
1.29 joris 233: }
234:
1.100 ray 235: buf_putc(bp, '\0');
236: d = buf_release(bp);
1.29 joris 237:
238: cvs_server_send_response("Valid-requests %s", d);
239: cvs_server_send_response("ok");
1.103 nicm 240: free(d);
1.42 xsa 241: }
242:
243: void
1.43 xsa 244: cvs_server_static_directory(char *data)
245: {
246: FILE *fp;
1.102 deraadt 247: char fpath[PATH_MAX];
1.43 xsa 248:
1.102 deraadt 249: (void)xsnprintf(fpath, PATH_MAX, "%s/%s",
1.54 xsa 250: server_currentdir, CVS_PATH_STATICENTRIES);
1.43 xsa 251:
252: if ((fp = fopen(fpath, "w+")) == NULL) {
253: cvs_log(LP_ERRNO, "%s", fpath);
1.51 otto 254: return;
1.43 xsa 255: }
256: (void)fclose(fp);
257: }
258:
259: void
1.42 xsa 260: cvs_server_sticky(char *data)
261: {
262: FILE *fp;
1.102 deraadt 263: char tagpath[PATH_MAX];
1.42 xsa 264:
1.57 ray 265: if (data == NULL)
266: fatal("Missing argument for Sticky");
267:
1.102 deraadt 268: (void)xsnprintf(tagpath, PATH_MAX, "%s/%s",
1.54 xsa 269: server_currentdir, CVS_PATH_TAG);
1.42 xsa 270:
1.43 xsa 271: if ((fp = fopen(tagpath, "w+")) == NULL) {
1.42 xsa 272: cvs_log(LP_ERRNO, "%s", tagpath);
1.51 otto 273: return;
1.42 xsa 274: }
275:
276: (void)fprintf(fp, "%s\n", data);
277: (void)fclose(fp);
1.29 joris 278: }
279:
280: void
281: cvs_server_globalopt(char *data)
282: {
1.57 ray 283: if (data == NULL)
284: fatal("Missing argument for Global_option");
285:
1.38 xsa 286: if (!strcmp(data, "-l"))
287: cvs_nolog = 1;
1.29 joris 288:
289: if (!strcmp(data, "-n"))
290: cvs_noexec = 1;
1.38 xsa 291:
292: if (!strcmp(data, "-Q"))
293: verbosity = 0;
294:
1.70 tobias 295: if (!strcmp(data, "-q"))
296: verbosity = 1;
297:
1.38 xsa 298: if (!strcmp(data, "-r"))
299: cvs_readonly = 1;
300:
301: if (!strcmp(data, "-t"))
302: cvs_trace = 1;
1.39 xsa 303: }
304:
305: void
306: cvs_server_set(char *data)
307: {
308: char *ep;
309:
1.57 ray 310: if (data == NULL)
311: fatal("Missing argument for Set");
312:
1.39 xsa 313: ep = strchr(data, '=');
314: if (ep == NULL)
315: fatal("no = in variable assignment");
316:
317: *(ep++) = '\0';
318: if (cvs_var_set(data, ep) < 0)
319: fatal("cvs_server_set: cvs_var_set failed");
1.29 joris 320: }
1.1 jfb 321:
1.29 joris 322: void
323: cvs_server_directory(char *data)
324: {
325: CVSENTRIES *entlist;
1.83 xsa 326: char *dir, *repo, *parent, *entry, *dirn, *p;
1.106 ! naddy 327: char parentbuf[PATH_MAX], dirnbuf[PATH_MAX];
1.68 tobias 328:
329: if (current_cvsroot == NULL)
330: fatal("No Root specified for Directory");
1.29 joris 331:
332: dir = cvs_remote_input();
1.49 joris 333: STRIP_SLASH(dir);
334:
335: if (strlen(dir) < strlen(current_cvsroot->cr_dir))
1.29 joris 336: fatal("cvs_server_directory: bad Directory request");
337:
1.49 joris 338: repo = dir + strlen(current_cvsroot->cr_dir);
339:
340: /*
341: * This is somewhat required for checkout, as the
342: * directory request will be:
343: *
344: * Directory .
345: * /path/to/cvs/root
346: */
347: if (repo[0] == '\0')
348: p = xstrdup(".");
349: else
350: p = xstrdup(repo + 1);
351:
1.65 joris 352: cvs_mkpath(p, NULL);
1.29 joris 353:
1.106 ! naddy 354: if (strlcpy(dirnbuf, p, sizeof(dirnbuf)) >= sizeof(dirnbuf))
! 355: fatal("cvs_server_directory: truncation");
! 356: if ((dirn = basename(dirnbuf)) == NULL)
1.29 joris 357: fatal("cvs_server_directory: %s", strerror(errno));
358:
1.106 ! naddy 359: if (strlcpy(parentbuf, p, sizeof(parentbuf)) >= sizeof(parentbuf))
! 360: fatal("cvs_server_directory: truncation");
! 361: if ((parent = dirname(parentbuf)) == NULL)
1.29 joris 362: fatal("cvs_server_directory: %s", strerror(errno));
363:
364: if (strcmp(parent, ".")) {
1.83 xsa 365: entry = xmalloc(CVS_ENT_MAXLINELEN);
366: cvs_ent_line_str(dirn, NULL, NULL, NULL, NULL, 1, 0,
367: entry, CVS_ENT_MAXLINELEN);
368:
1.29 joris 369: entlist = cvs_ent_open(parent);
370: cvs_ent_add(entlist, entry);
1.103 nicm 371: free(entry);
1.1 jfb 372: }
373:
1.104 mmcc 374: free(server_currentdir);
1.61 ray 375: server_currentdir = p;
1.29 joris 376:
1.103 nicm 377: free(dir);
1.29 joris 378: }
379:
380: void
381: cvs_server_entry(char *data)
382: {
383: CVSENTRIES *entlist;
384:
1.57 ray 385: if (data == NULL)
386: fatal("Missing argument for Entry");
387:
1.29 joris 388: entlist = cvs_ent_open(server_currentdir);
389: cvs_ent_add(entlist, data);
390: }
391:
392: void
393: cvs_server_modified(char *data)
394: {
1.41 xsa 395: int fd;
1.29 joris 396: size_t flen;
397: mode_t fmode;
398: const char *errstr;
1.102 deraadt 399: char *mode, *len, fpath[PATH_MAX];
1.29 joris 400:
1.57 ray 401: if (data == NULL)
402: fatal("Missing argument for Modified");
403:
1.90 joris 404: /* sorry, we have to use TMP_DIR */
405: disable_fast_checkout = 1;
406:
1.29 joris 407: mode = cvs_remote_input();
408: len = cvs_remote_input();
409:
410: cvs_strtomode(mode, &fmode);
1.103 nicm 411: free(mode);
1.29 joris 412:
413: flen = strtonum(len, 0, INT_MAX, &errstr);
414: if (errstr != NULL)
415: fatal("cvs_server_modified: %s", errstr);
1.103 nicm 416: free(len);
1.29 joris 417:
1.102 deraadt 418: (void)xsnprintf(fpath, PATH_MAX, "%s/%s", server_currentdir, data);
1.29 joris 419:
420: if ((fd = open(fpath, O_WRONLY | O_CREAT | O_TRUNC)) == -1)
421: fatal("cvs_server_modified: %s: %s", fpath, strerror(errno));
422:
1.48 joris 423: cvs_remote_receive_file(fd, flen);
1.29 joris 424:
425: if (fchmod(fd, 0600) == -1)
426: fatal("cvs_server_modified: failed to set file mode");
427:
428: (void)close(fd);
429: }
430:
431: void
432: cvs_server_useunchanged(char *data)
433: {
434: }
435:
436: void
437: cvs_server_unchanged(char *data)
438: {
1.102 deraadt 439: char fpath[PATH_MAX];
1.29 joris 440: CVSENTRIES *entlist;
441: struct cvs_ent *ent;
1.71 joris 442: char sticky[CVS_ENT_MAXLINELEN];
443: char rev[CVS_REV_BUFSZ], entry[CVS_ENT_MAXLINELEN];
1.29 joris 444:
1.57 ray 445: if (data == NULL)
446: fatal("Missing argument for Unchanged");
447:
1.90 joris 448: /* sorry, we have to use TMP_DIR */
449: disable_fast_checkout = 1;
450:
1.102 deraadt 451: (void)xsnprintf(fpath, PATH_MAX, "%s/%s", server_currentdir, data);
1.29 joris 452:
453: entlist = cvs_ent_open(server_currentdir);
454: ent = cvs_ent_get(entlist, data);
455: if (ent == NULL)
456: fatal("received Unchanged request for non-existing file");
457:
1.71 joris 458: sticky[0] = '\0';
459: if (ent->ce_tag != NULL)
460: (void)xsnprintf(sticky, sizeof(sticky), "T%s", ent->ce_tag);
461:
462: rcsnum_tostr(ent->ce_rev, rev, sizeof(rev));
463: (void)xsnprintf(entry, sizeof(entry), "/%s/%s/%s/%s/%s",
464: ent->ce_name, rev, CVS_SERVER_UNCHANGED, ent->ce_opts ?
465: ent->ce_opts : "", sticky);
1.29 joris 466:
467: cvs_ent_free(ent);
1.71 joris 468: cvs_ent_add(entlist, entry);
1.29 joris 469: }
470:
471: void
472: cvs_server_questionable(char *data)
473: {
1.94 joris 474: CVSENTRIES *entlist;
475: char entry[CVS_ENT_MAXLINELEN];
476:
477: if (data == NULL)
478: fatal("Questionable request with no data attached");
479:
480: (void)xsnprintf(entry, sizeof(entry), "/%s/%c///", data,
481: CVS_SERVER_QUESTIONABLE);
482:
483: entlist = cvs_ent_open(server_currentdir);
484: cvs_ent_add(entlist, entry);
485:
1.90 joris 486: /* sorry, we have to use TMP_DIR */
487: disable_fast_checkout = 1;
1.29 joris 488: }
489:
490: void
491: cvs_server_argument(char *data)
492: {
1.57 ray 493: if (data == NULL)
494: fatal("Missing argument for Argument");
1.29 joris 495:
1.101 deraadt 496: server_argv = xreallocarray(server_argv, server_argc + 2,
1.88 tobias 497: sizeof(*server_argv));
498: server_argv[server_argc] = xstrdup(data);
499: server_argv[++server_argc] = NULL;
1.37 xsa 500: }
501:
502: void
503: cvs_server_argumentx(char *data)
504: {
1.66 joris 505: int idx;
506: size_t len;
507:
1.87 tobias 508: if (server_argc == 1)
1.66 joris 509: fatal("Protocol Error: ArgumentX without previous argument");
510:
511: idx = server_argc - 1;
512:
513: len = strlen(server_argv[idx]) + strlen(data) + 2;
1.101 deraadt 514: server_argv[idx] = xreallocarray(server_argv[idx], len, sizeof(char));
1.66 joris 515: strlcat(server_argv[idx], "\n", len);
516: strlcat(server_argv[idx], data, len);
1.44 xsa 517: }
518:
519: void
520: cvs_server_update_patches(char *data)
521: {
522: /*
523: * This does not actually do anything.
524: * It is used to tell that the server is able to
525: * generate patches when given an `update' request.
526: * The client must issue the -u argument to `update'
527: * to receive patches.
528: */
1.29 joris 529: }
530:
531: void
1.31 xsa 532: cvs_server_add(char *data)
533: {
534: if (chdir(server_currentdir) == -1)
535: fatal("cvs_server_add: %s", strerror(errno));
536:
537: cvs_cmdop = CVS_OP_ADD;
1.78 tobias 538: cmdp->cmd_flags = cvs_cmd_add.cmd_flags;
1.31 xsa 539: cvs_add(server_argc, server_argv);
1.50 joris 540: cvs_server_send_response("ok");
541: }
542:
543: void
544: cvs_server_import(char *data)
545: {
546: if (chdir(server_currentdir) == -1)
547: fatal("cvs_server_import: %s", strerror(errno));
548:
549: cvs_cmdop = CVS_OP_IMPORT;
1.78 tobias 550: cmdp->cmd_flags = cvs_cmd_import.cmd_flags;
1.50 joris 551: cvs_import(server_argc, server_argv);
1.31 xsa 552: cvs_server_send_response("ok");
553: }
1.35 xsa 554:
555: void
556: cvs_server_admin(char *data)
557: {
558: if (chdir(server_currentdir) == -1)
559: fatal("cvs_server_admin: %s", strerror(errno));
560:
561: cvs_cmdop = CVS_OP_ADMIN;
1.78 tobias 562: cmdp->cmd_flags = cvs_cmd_admin.cmd_flags;
1.35 xsa 563: cvs_admin(server_argc, server_argv);
564: cvs_server_send_response("ok");
565: }
566:
1.40 xsa 567: void
568: cvs_server_annotate(char *data)
569: {
570: if (chdir(server_currentdir) == -1)
571: fatal("cvs_server_annotate: %s", strerror(errno));
572:
573: cvs_cmdop = CVS_OP_ANNOTATE;
1.78 tobias 574: cmdp->cmd_flags = cvs_cmd_annotate.cmd_flags;
1.80 tobias 575: cvs_annotate(server_argc, server_argv);
576: cvs_server_send_response("ok");
577: }
578:
579: void
580: cvs_server_rannotate(char *data)
581: {
582: if (chdir(server_currentdir) == -1)
583: fatal("cvs_server_rannotate: %s", strerror(errno));
584:
585: cvs_cmdop = CVS_OP_RANNOTATE;
586: cmdp->cmd_flags = cvs_cmd_rannotate.cmd_flags;
1.40 xsa 587: cvs_annotate(server_argc, server_argv);
588: cvs_server_send_response("ok");
589: }
1.31 xsa 590:
591: void
1.29 joris 592: cvs_server_commit(char *data)
593: {
594: if (chdir(server_currentdir) == -1)
595: fatal("cvs_server_commit: %s", strerror(errno));
596:
597: cvs_cmdop = CVS_OP_COMMIT;
1.78 tobias 598: cmdp->cmd_flags = cvs_cmd_commit.cmd_flags;
1.29 joris 599: cvs_commit(server_argc, server_argv);
1.49 joris 600: cvs_server_send_response("ok");
601: }
602:
603: void
604: cvs_server_checkout(char *data)
1.77 tobias 605: {
606: if (chdir(server_currentdir) == -1)
1.49 joris 607: fatal("cvs_server_checkout: %s", strerror(errno));
608:
609: cvs_cmdop = CVS_OP_CHECKOUT;
1.78 tobias 610: cmdp->cmd_flags = cvs_cmd_checkout.cmd_flags;
1.49 joris 611: cvs_checkout(server_argc, server_argv);
1.29 joris 612: cvs_server_send_response("ok");
613: }
614:
615: void
616: cvs_server_diff(char *data)
617: {
618: if (chdir(server_currentdir) == -1)
619: fatal("cvs_server_diff: %s", strerror(errno));
620:
621: cvs_cmdop = CVS_OP_DIFF;
1.78 tobias 622: cmdp->cmd_flags = cvs_cmd_diff.cmd_flags;
1.82 tobias 623: cvs_diff(server_argc, server_argv);
624: cvs_server_send_response("ok");
625: }
626:
627: void
628: cvs_server_rdiff(char *data)
629: {
630: if (chdir(server_currentdir) == -1)
631: fatal("cvs_server_rdiff: %s", strerror(errno));
632:
633: cvs_cmdop = CVS_OP_RDIFF;
634: cmdp->cmd_flags = cvs_cmd_rdiff.cmd_flags;
1.29 joris 635: cvs_diff(server_argc, server_argv);
1.76 tobias 636: cvs_server_send_response("ok");
637: }
638:
639: void
640: cvs_server_export(char *data)
1.77 tobias 641: {
642: if (chdir(server_currentdir) == -1)
643: fatal("cvs_server_export: %s", strerror(errno));
1.76 tobias 644:
645: cvs_cmdop = CVS_OP_EXPORT;
1.78 tobias 646: cmdp->cmd_flags = cvs_cmd_export.cmd_flags;
1.90 joris 647: cvs_export(server_argc, server_argv);
1.34 xsa 648: cvs_server_send_response("ok");
649: }
650:
651: void
652: cvs_server_init(char *data)
653: {
1.69 tobias 654: if (data == NULL)
655: fatal("Missing argument for init");
656:
657: if (current_cvsroot != NULL)
658: fatal("Root in combination with init is not supported");
659:
660: if ((current_cvsroot = cvsroot_get(data)) == NULL)
661: fatal("Invalid argument for init");
1.34 xsa 662:
663: cvs_cmdop = CVS_OP_INIT;
1.78 tobias 664: cmdp->cmd_flags = cvs_cmd_init.cmd_flags;
1.34 xsa 665: cvs_init(server_argc, server_argv);
1.64 xsa 666: cvs_server_send_response("ok");
667: }
668:
669: void
670: cvs_server_release(char *data)
671: {
672: if (chdir(server_currentdir) == -1)
1.67 xsa 673: fatal("cvs_server_release: %s", strerror(errno));
1.64 xsa 674:
675: cvs_cmdop = CVS_OP_RELEASE;
1.78 tobias 676: cmdp->cmd_flags = cvs_cmd_release.cmd_flags;
1.64 xsa 677: cvs_release(server_argc, server_argv);
1.31 xsa 678: cvs_server_send_response("ok");
679: }
680:
681: void
682: cvs_server_remove(char *data)
683: {
684: if (chdir(server_currentdir) == -1)
685: fatal("cvs_server_remove: %s", strerror(errno));
686:
687: cvs_cmdop = CVS_OP_REMOVE;
1.78 tobias 688: cmdp->cmd_flags = cvs_cmd_remove.cmd_flags;
1.31 xsa 689: cvs_remove(server_argc, server_argv);
1.29 joris 690: cvs_server_send_response("ok");
691: }
692:
693: void
694: cvs_server_status(char *data)
695: {
696: if (chdir(server_currentdir) == -1)
697: fatal("cvs_server_status: %s", strerror(errno));
698:
699: cvs_cmdop = CVS_OP_STATUS;
1.78 tobias 700: cmdp->cmd_flags = cvs_cmd_status.cmd_flags;
1.29 joris 701: cvs_status(server_argc, server_argv);
702: cvs_server_send_response("ok");
703: }
704:
705: void
706: cvs_server_log(char *data)
707: {
708: if (chdir(server_currentdir) == -1)
709: fatal("cvs_server_log: %s", strerror(errno));
710:
711: cvs_cmdop = CVS_OP_LOG;
1.78 tobias 712: cmdp->cmd_flags = cvs_cmd_log.cmd_flags;
1.62 niallo 713: cvs_getlog(server_argc, server_argv);
714: cvs_server_send_response("ok");
715: }
1.79 xsa 716:
1.62 niallo 717: void
718: cvs_server_rlog(char *data)
719: {
1.74 tobias 720: if (chdir(current_cvsroot->cr_dir) == -1)
1.67 xsa 721: fatal("cvs_server_rlog: %s", strerror(errno));
1.62 niallo 722:
723: cvs_cmdop = CVS_OP_RLOG;
1.78 tobias 724: cmdp->cmd_flags = cvs_cmd_rlog.cmd_flags;
1.32 xsa 725: cvs_getlog(server_argc, server_argv);
726: cvs_server_send_response("ok");
727: }
728:
729: void
730: cvs_server_tag(char *data)
731: {
732: if (chdir(server_currentdir) == -1)
733: fatal("cvs_server_tag: %s", strerror(errno));
734:
735: cvs_cmdop = CVS_OP_TAG;
1.78 tobias 736: cmdp->cmd_flags = cvs_cmd_tag.cmd_flags;
1.75 tobias 737: cvs_tag(server_argc, server_argv);
738: cvs_server_send_response("ok");
739: }
740:
741: void
742: cvs_server_rtag(char *data)
743: {
744: if (chdir(current_cvsroot->cr_dir) == -1)
1.77 tobias 745: fatal("cvs_server_rtag: %s", strerror(errno));
1.75 tobias 746:
747: cvs_cmdop = CVS_OP_RTAG;
1.78 tobias 748: cmdp->cmd_flags = cvs_cmd_rtag.cmd_flags;
1.33 xsa 749: cvs_tag(server_argc, server_argv);
1.29 joris 750: cvs_server_send_response("ok");
751: }
752:
753: void
754: cvs_server_update(char *data)
755: {
756: if (chdir(server_currentdir) == -1)
757: fatal("cvs_server_update: %s", strerror(errno));
1.14 joris 758:
1.29 joris 759: cvs_cmdop = CVS_OP_UPDATE;
1.78 tobias 760: cmdp->cmd_flags = cvs_cmd_update.cmd_flags;
1.29 joris 761: cvs_update(server_argc, server_argv);
1.36 xsa 762: cvs_server_send_response("ok");
763: }
764:
765: void
766: cvs_server_version(char *data)
767: {
768: cvs_cmdop = CVS_OP_VERSION;
1.78 tobias 769: cmdp->cmd_flags = cvs_cmd_version.cmd_flags;
1.36 xsa 770: cvs_version(server_argc, server_argv);
1.29 joris 771: cvs_server_send_response("ok");
1.47 joris 772: }
773:
774: void
775: cvs_server_update_entry(const char *resp, struct cvs_file *cf)
776: {
1.58 ray 777: char *p;
1.102 deraadt 778: char repo[PATH_MAX], fpath[PATH_MAX];
1.47 joris 779:
780: if ((p = strrchr(cf->file_rpath, ',')) != NULL)
781: *p = '\0';
782:
1.102 deraadt 783: cvs_get_repository_path(cf->file_wd, repo, PATH_MAX);
784: (void)xsnprintf(fpath, PATH_MAX, "%s/%s", repo, cf->file_name);
1.65 joris 785:
1.58 ray 786: cvs_server_send_response("%s %s/", resp, cf->file_wd);
1.65 joris 787: cvs_remote_output(fpath);
1.47 joris 788:
789: if (p != NULL)
790: *p = ',';
1.65 joris 791: }
792:
793: void
1.105 otto 794: cvs_server_set_sticky(const char *dir, char *tag)
1.65 joris 795: {
1.102 deraadt 796: char fpath[PATH_MAX];
797: char repo[PATH_MAX];
1.65 joris 798:
1.102 deraadt 799: cvs_get_repository_path(dir, repo, PATH_MAX);
800: (void)xsnprintf(fpath, PATH_MAX, "%s/", repo);
1.65 joris 801:
1.93 joris 802: cvs_server_send_response("Set-sticky %s/", dir);
1.65 joris 803: cvs_remote_output(fpath);
1.72 joris 804: cvs_remote_output(tag);
1.65 joris 805: }
806:
807: void
808: cvs_server_clear_sticky(char *dir)
809: {
1.102 deraadt 810: char fpath[PATH_MAX];
811: char repo[PATH_MAX];
1.65 joris 812:
1.102 deraadt 813: cvs_get_repository_path(dir, repo, PATH_MAX);
814: (void)xsnprintf(fpath, PATH_MAX, "%s/", repo);
1.65 joris 815:
1.93 joris 816: cvs_server_send_response("Clear-sticky %s//", dir);
1.65 joris 817: cvs_remote_output(fpath);
1.96 joris 818: }
819:
820: void
821: cvs_server_exp_modules(char *module)
822: {
823: struct module_checkout *mo;
824: struct cvs_filelist *fl;
825:
826: if (server_argc != 2)
827: fatal("expand-modules with no arguments");
828:
829: mo = cvs_module_lookup(server_argv[1]);
830:
831: RB_FOREACH(fl, cvs_flisthead, &(mo->mc_modules))
832: cvs_server_send_response("Module-expansion %s", fl->file_path);
833: cvs_server_send_response("ok");
834:
835: server_argc--;
1.103 nicm 836: free(server_argv[1]);
1.96 joris 837: server_argv[1] = NULL;
1.1 jfb 838: }