Annotation of src/usr.bin/cvs/req.c, Revision 1.9
1.9 ! jfb 1: /* $OpenBSD: req.c,v 1.8 2004/12/19 17:32:55 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 <signal.h>
37: #include <string.h>
38: #include <sysexits.h>
39: #ifdef CVS_ZLIB
40: #include <zlib.h>
41: #endif
42:
43: #include "buf.h"
44: #include "cvs.h"
45: #include "log.h"
46: #include "file.h"
47: #include "proto.h"
48:
49:
50: extern int verbosity;
51: extern int cvs_compress;
52: extern char *cvs_rsh;
53: extern int cvs_trace;
54: extern int cvs_nolog;
55: extern int cvs_readonly;
56:
57:
1.9 ! jfb 58: static int cvs_req_set (int, char *);
1.1 jfb 59: static int cvs_req_root (int, char *);
1.4 jfb 60: static int cvs_req_validreq (int, char *);
61: static int cvs_req_validresp (int, char *);
1.1 jfb 62: static int cvs_req_directory (int, char *);
1.5 jfb 63: static int cvs_req_case (int, char *);
1.2 jfb 64: static int cvs_req_argument (int, char *);
1.3 jfb 65: static int cvs_req_globalopt (int, char *);
1.8 jfb 66: static int cvs_req_gzipstream (int, char *);
1.1 jfb 67: static int cvs_req_version (int, char *);
68:
69:
70: struct cvs_reqhdlr {
71: int (*hdlr)(int, char *);
72: } cvs_req_swtab[CVS_REQ_MAX + 1] = {
73: { NULL },
74: { cvs_req_root },
1.4 jfb 75: { cvs_req_validreq },
76: { cvs_req_validresp },
1.1 jfb 77: { cvs_req_directory },
78: { NULL },
79: { NULL },
80: { NULL },
81: { NULL },
82: { NULL },
83: { NULL }, /* 10 */
84: { NULL },
85: { NULL },
86: { NULL },
87: { NULL },
88: { NULL },
89: { NULL },
90: { NULL },
1.5 jfb 91: { cvs_req_case },
1.1 jfb 92: { NULL },
1.2 jfb 93: { cvs_req_argument }, /* 20 */
94: { cvs_req_argument },
1.3 jfb 95: { cvs_req_globalopt },
1.8 jfb 96: { cvs_req_gzipstream },
1.1 jfb 97: { NULL },
98: { NULL },
99: { NULL },
100: { NULL },
101: { NULL },
102: { NULL },
103: { NULL }, /* 30 */
104: { NULL },
105: { NULL },
106: { NULL },
1.9 ! jfb 107: { cvs_req_set },
1.1 jfb 108: { NULL },
109: { NULL },
110: { NULL },
111: { NULL },
112: { NULL },
113: { NULL }, /* 40 */
114: { NULL },
115: { NULL },
116: { NULL },
117: { NULL },
118: { NULL },
119: { NULL },
120: { NULL },
121: { NULL },
122: { NULL },
123: { NULL }, /* 50 */
124: { NULL },
125: { NULL },
126: { NULL },
127: { NULL },
128: { NULL },
129: { NULL },
130: { NULL },
131: { NULL },
132: { NULL },
133: { NULL }, /* 60 */
134: { NULL },
135: { NULL },
136: { NULL },
137: { NULL },
138: { NULL },
139: { NULL },
140: { NULL },
141: { NULL },
142: { cvs_req_version },
143: };
144:
145:
146:
147: /*
1.2 jfb 148: * Argument array built by `Argument' and `Argumentx' requests.
149: */
150:
151: static char *cvs_req_args[CVS_PROTO_MAXARG];
152: static int cvs_req_nargs = 0;
153:
154:
155: /*
1.1 jfb 156: * cvs_req_handle()
157: *
158: * Generic request handler dispatcher. The handler expects the first line
159: * of the command as single argument.
160: * Returns the return value of the command on success, or -1 on failure.
161: */
162: int
163: cvs_req_handle(char *line)
164: {
165: char *cp, *cmd;
166: struct cvs_req *req;
167:
168: cmd = line;
169:
170: cp = strchr(cmd, ' ');
171: if (cp != NULL)
172: *(cp++) = '\0';
173:
174: req = cvs_req_getbyname(cmd);
175: if (req == NULL)
176: return (-1);
177: else if (cvs_req_swtab[req->req_id].hdlr == NULL) {
178: cvs_log(LP_ERRNO, "handler for `%s' not implemented", cmd);
179: return (-1);
180: }
181:
182: return (*cvs_req_swtab[req->req_id].hdlr)(req->req_id, cp);
183: }
184:
185:
186: static int
187: cvs_req_root(int reqid, char *line)
188: {
189:
1.9 ! jfb 190: return (0);
! 191: }
! 192:
! 193:
! 194: static int
! 195: cvs_req_set(int reqid, char *line)
! 196: {
! 197: char *cp;
! 198:
! 199: cp = strchr(line, '=');
! 200: if (cp == NULL) {
! 201: cvs_log(LP_ERR, "error in Set request "
! 202: "(no = in variable assignment)");
! 203: return (-1);
! 204: }
! 205:
! 206: if (cvs_var_set(line, cp) < 0)
! 207: return (-1);
1.4 jfb 208: return (0);
209: }
210:
211:
212: static int
213: cvs_req_validreq(int reqid, char *line)
214: {
215: char *vreq;
216:
217: vreq = cvs_req_getvalid();
218: if (vreq == NULL)
219: return (-1);
220:
221: cvs_sendresp(CVS_RESP_VALIDREQ, vreq);
222:
223: return (0);
224: }
225:
226: static int
227: cvs_req_validresp(int reqid, char *line)
228: {
229: char *sp, *ep;
230: struct cvs_resp *resp;
1.1 jfb 231:
1.4 jfb 232: sp = line;
233: do {
234: ep = strchr(sp, ' ');
235: if (ep != NULL)
236: *(ep++) = '\0';
237:
238: resp = cvs_resp_getbyname(sp);
239: if (resp != NULL)
240: ;
241:
242: if (ep != NULL)
243: sp = ep + 1;
244: } while (ep != NULL);
1.1 jfb 245:
246: return (0);
247: }
248:
249: static int
250: cvs_req_directory(int reqid, char *line)
251: {
252:
1.5 jfb 253: return (0);
254: }
255:
256: /*
257: * cvs_req_case()
258: *
259: * Handler for the `Case' requests, which toggles case sensitivity ON or OFF
260: */
261: static int
262: cvs_req_case(int reqid, char *line)
263: {
264: cvs_nocase = 1;
1.2 jfb 265: return (0);
266: }
267:
268:
269: static int
270: cvs_req_argument(int reqid, char *line)
271: {
272: char *nap;
273:
274: if (cvs_req_nargs == CVS_PROTO_MAXARG) {
275: cvs_log(LP_ERR, "too many arguments");
276: return (-1);
277: }
278:
279: if (reqid == CVS_REQ_ARGUMENT) {
280: cvs_req_args[cvs_req_nargs] = strdup(line);
281: if (cvs_req_args[cvs_req_nargs] == NULL) {
282: cvs_log(LP_ERRNO, "failed to copy argument");
283: return (-1);
284: }
285: cvs_req_nargs++;
1.6 deraadt 286: } else if (reqid == CVS_REQ_ARGUMENTX) {
1.2 jfb 287: if (cvs_req_nargs == 0)
288: cvs_log(LP_WARN, "no argument to append to");
289: else {
290: asprintf(&nap, "%s%s", cvs_req_args[cvs_req_nargs - 1],
291: line);
292: if (nap == NULL) {
293: cvs_log(LP_ERRNO,
294: "failed to append to argument");
295: return (-1);
296: }
297: free(cvs_req_args[cvs_req_nargs - 1]);
298: cvs_req_args[cvs_req_nargs - 1] = nap;
299: }
1.3 jfb 300: }
301:
302: return (0);
303: }
304:
305:
306: static int
307: cvs_req_globalopt(int reqid, char *line)
308: {
309: if ((*line != '-') || (*(line + 2) != '\0')) {
310: cvs_log(LP_ERR,
311: "invalid `Global_option' request format");
312: return (-1);
313: }
314:
315: switch (*(line + 1)) {
316: case 'l':
317: cvs_nolog = 1;
318: break;
319: case 'n':
320: break;
321: case 'Q':
322: verbosity = 0;
323: break;
324: case 'q':
325: if (verbosity > 1)
326: verbosity = 1;
327: break;
328: case 'r':
329: cvs_readonly = 1;
330: break;
331: case 't':
332: cvs_trace = 1;
333: break;
334: default:
335: cvs_log(LP_ERR, "unknown global option `%s'", line);
336: return (-1);
1.2 jfb 337: }
1.8 jfb 338:
339: return (0);
340: }
341:
342:
343: /*
344: * cvs_req_gzipstream()
345: *
346: * Handler for the `Gzip-stream' request, which enables compression at the
347: * level given along with the request. After this request has been processed,
348: * all further connection data should be compressed.
349: */
350:
351: static int
352: cvs_req_gzipstream(int reqid, char *line)
353: {
354: char *ep;
355: long val;
356:
357: val = strtol(line, &ep, 10);
358: if ((line[0] == '\0') || (*ep != '\0')) {
359: cvs_log(LP_ERR, "invalid Gzip-stream level `%s'", line);
360: return (-1);
361: } else if ((errno == ERANGE) && ((val < 0) || (val > 9))) {
362: cvs_log(LP_ERR, "Gzip-stream level %ld out of range", val);
363: return (-1);
364: }
365:
366: cvs_compress = (int)val;
1.1 jfb 367:
368: return (0);
369: }
370:
371:
372: static int
373: cvs_req_version(int reqid, char *line)
374: {
375: cvs_printf("%s\n", CVS_VERSION);
376: return (0);
377: }