xref: /netbsd-src/external/gpl2/xcvs/dist/src/client.c (revision d440dc2ce5924a4296f79897b9b1870aa3242ffa)
1 /* CVS client-related stuff.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.  */
12 #include <sys/cdefs.h>
13 __RCSID("$NetBSD: client.c,v 1.6 2024/02/04 21:42:24 christos Exp $");
14 
15 #ifdef HAVE_CONFIG_H
16 # include "config.h"
17 #endif /* HAVE_CONFIG_H */
18 
19 #include "cvs.h"
20 #include "getline.h"
21 #include "edit.h"
22 #include "buffer.h"
23 #include "save-cwd.h"
24 
25 #ifdef CLIENT_SUPPORT
26 
27 # include "log-buffer.h"
28 # include "md5.h"
29 
30 #include "socket-client.h"
31 #include "rsh-client.h"
32 
33 # ifdef HAVE_GSSAPI
34 #   include "gssapi-client.h"
35 # endif
36 
37 # ifdef HAVE_KERBEROS
38 #   include "kerberos4-client.h"
39 # endif
40 
41 
42 
43 /* Keep track of any paths we are sending for Max-dotdot so that we can verify
44  * that uplevel paths coming back form the server are valid.
45  *
46  * FIXME: The correct way to do this is probably provide some sort of virtual
47  * path map on the client side.  This would be generic enough to be applied to
48  * absolute paths supplied by the user too.
49  */
50 static List *uppaths;
51 
52 
53 
54 static void add_prune_candidate (const char *);
55 
56 /* All the commands.  */
57 int add (int argc, char **argv);
58 int admin (int argc, char **argv);
59 int checkout (int argc, char **argv);
60 int commit (int argc, char **argv);
61 int diff (int argc, char **argv);
62 int history (int argc, char **argv);
63 int import (int argc, char **argv);
64 int cvslog (int argc, char **argv);
65 int patch (int argc, char **argv);
66 int release (int argc, char **argv);
67 int cvsremove (int argc, char **argv);
68 int rtag (int argc, char **argv);
69 int status (int argc, char **argv);
70 int tag (int argc, char **argv);
71 int update (int argc, char **argv);
72 
73 #if defined AUTH_CLIENT_SUPPORT || defined HAVE_KERBEROS || defined HAVE_GSSAPI
74 static int connect_to(char *, unsigned int);
75 #endif
76 
77 static size_t try_read_from_server (char *, size_t);
78 
79 static void auth_server (cvsroot_t *, struct buffer *, struct buffer *,
80 			 int, int);
81 
82 
83 
84 /* This is the referrer who referred us to a primary, or write server, using
85  * the "Redirect" request.
86  */
87 static cvsroot_t *client_referrer;
88 
89 /* We need to keep track of the list of directories we've sent to the
90    server.  This list, along with the current CVSROOT, will help us
91    decide which command-line arguments to send.  */
92 List *dirs_sent_to_server;
93 static int
is_arg_a_parent_or_listed_dir(Node * n,void * d)94 is_arg_a_parent_or_listed_dir (Node *n, void *d)
95 {
96     char *directory = n->key;	/* name of the dir sent to server */
97     char *this_argv_elem = d;	/* this argv element */
98 
99     /* Say we should send this argument if the argument matches the
100        beginning of a directory name sent to the server.  This way,
101        the server will know to start at the top of that directory
102        hierarchy and descend. */
103 
104     if (!strncmp (directory, this_argv_elem, strlen (this_argv_elem)))
105 	return 1;
106 
107     return 0;
108 }
109 
110 
111 
112 /* Return nonzero if this argument should not be sent to the
113    server. */
114 static int
arg_should_not_be_sent_to_server(char * arg)115 arg_should_not_be_sent_to_server (char *arg)
116 {
117     /* Decide if we should send this directory name to the server.  We
118        should always send argv[i] if:
119 
120        1) the list of directories sent to the server is empty (as it
121        will be for checkout, etc.).
122 
123        2) the argument is "."
124 
125        3) the argument is a file in the cwd and the cwd is checked out
126        from the current root
127 
128        4) the argument lies within one of the paths in
129        dirs_sent_to_server.
130 
131        */
132 
133     if (list_isempty (dirs_sent_to_server))
134 	return 0;		/* always send it */
135 
136     if (!strcmp (arg, "."))
137 	return 0;		/* always send it */
138 
139     /* We should send arg if it is one of the directories sent to the
140        server or the parent of one; this tells the server to descend
141        the hierarchy starting at this level. */
142     if (isdir (arg))
143     {
144 	if (walklist (dirs_sent_to_server, is_arg_a_parent_or_listed_dir, arg))
145 	    return 0;
146 
147 	/* If arg wasn't a parent, we don't know anything about it (we
148 	   would have seen something related to it during the
149 	   send_files phase).  Don't send it.  */
150 	return 1;
151     }
152 
153     /* Try to decide whether we should send arg to the server by
154        checking the contents of the corresponding CVSADM directory. */
155     {
156 	char *t, *root_string;
157 	cvsroot_t *this_root = NULL;
158 
159 	/* Calculate "dirname arg" */
160 	for (t = arg + strlen (arg) - 1; t >= arg; t--)
161 	{
162 	    if (ISSLASH (*t))
163 		break;
164 	}
165 
166 	/* Now we're either poiting to the beginning of the
167 	   string, or we found a path separator. */
168 	if (t >= arg)
169 	{
170 	    /* Found a path separator.  */
171 	    char c = *t;
172 	    *t = '\0';
173 
174 	    /* First, check to see if we sent this directory to the
175                server, because it takes less time than actually
176                opening the stuff in the CVSADM directory.  */
177 	    if (walklist (dirs_sent_to_server, is_arg_a_parent_or_listed_dir,
178 			  arg))
179 	    {
180 		*t = c;		/* make sure to un-truncate the arg */
181 		return 0;
182 	    }
183 
184 	    /* Since we didn't find it in the list, check the CVSADM
185                files on disk.  */
186 	    this_root = Name_Root (arg, NULL);
187 	    root_string = this_root->original;
188 	    *t = c;
189 	}
190 	else
191 	{
192 	    /* We're at the beginning of the string.  Look at the
193                CVSADM files in cwd.  */
194 	    if (CVSroot_cmdline)
195 		root_string = CVSroot_cmdline;
196 	    else
197 	    {
198 		this_root = Name_Root (NULL, NULL);
199 		root_string = this_root->original;
200 	    }
201 	}
202 
203 	/* Now check the value for root. */
204 	if (root_string && current_parsed_root
205 	    && strcmp (root_string, original_parsed_root->original))
206 	{
207 	    /* Don't send this, since the CVSROOTs don't match. */
208 	    return 1;
209 	}
210     }
211 
212     /* OK, let's send it. */
213     return 0;
214 }
215 #endif /* CLIENT_SUPPORT */
216 
217 
218 
219 #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
220 
221 /* Shared with server.  */
222 
223 /*
224  * Return a malloc'd, '\0'-terminated string
225  * corresponding to the mode in SB.
226  */
227 char *
mode_to_string(mode_t mode)228 mode_to_string (mode_t mode)
229 {
230     char u[4], g[4], o[4];
231     int i;
232 
233     i = 0;
234     if (mode & S_IRUSR) u[i++] = 'r';
235     if (mode & S_IWUSR) u[i++] = 'w';
236     if (mode & S_IXUSR) u[i++] = 'x';
237     u[i] = '\0';
238 
239     i = 0;
240     if (mode & S_IRGRP) g[i++] = 'r';
241     if (mode & S_IWGRP) g[i++] = 'w';
242     if (mode & S_IXGRP) g[i++] = 'x';
243     g[i] = '\0';
244 
245     i = 0;
246     if (mode & S_IROTH) o[i++] = 'r';
247     if (mode & S_IWOTH) o[i++] = 'w';
248     if (mode & S_IXOTH) o[i++] = 'x';
249     o[i] = '\0';
250 
251     return Xasprintf ("u=%s,g=%s,o=%s", u, g, o);
252 }
253 
254 
255 
256 /*
257  * Change mode of FILENAME to MODE_STRING.
258  * Returns 0 for success or errno code.
259  * If RESPECT_UMASK is set, then honor the umask.
260  */
261 int
change_mode(const char * filename,const char * mode_string,int respect_umask)262 change_mode (const char *filename, const char *mode_string, int respect_umask)
263 {
264 #ifdef CHMOD_BROKEN
265     char *p;
266     int writeable = 0;
267 
268     /* We can only distinguish between
269          1) readable
270          2) writeable
271          3) Picasso's "Blue Period"
272        We handle the first two. */
273     p = mode_string;
274     while (*p != '\0')
275     {
276 	if ((p[0] == 'u' || p[0] == 'g' || p[0] == 'o') && p[1] == '=')
277 	{
278 	    char *q = p + 2;
279 	    while (*q != ',' && *q != '\0')
280 	    {
281 		if (*q == 'w')
282 		    writeable = 1;
283 		++q;
284 	    }
285 	}
286 	/* Skip to the next field.  */
287 	while (*p != ',' && *p != '\0')
288 	    ++p;
289 	if (*p == ',')
290 	    ++p;
291     }
292 
293     /* xchmod honors the umask for us.  In the !respect_umask case, we
294        don't try to cope with it (probably to handle that well, the server
295        needs to deal with modes in data structures, rather than via the
296        modes in temporary files).  */
297     xchmod (filename, writeable);
298 	return 0;
299 
300 #else /* ! CHMOD_BROKEN */
301 
302     const char *p;
303     mode_t mode = 0;
304     mode_t oumask;
305 
306     p = mode_string;
307     while (*p != '\0')
308     {
309 	if ((p[0] == 'u' || p[0] == 'g' || p[0] == 'o') && p[1] == '=')
310 	{
311 	    int can_read = 0, can_write = 0, can_execute = 0;
312 	    const char *q = p + 2;
313 	    while (*q != ',' && *q != '\0')
314 	    {
315 		if (*q == 'r')
316 		    can_read = 1;
317 		else if (*q == 'w')
318 		    can_write = 1;
319 		else if (*q == 'x')
320 		    can_execute = 1;
321 		++q;
322 	    }
323 	    if (p[0] == 'u')
324 	    {
325 		if (can_read)
326 		    mode |= S_IRUSR;
327 		if (can_write)
328 		    mode |= S_IWUSR;
329 		if (can_execute)
330 		    mode |= S_IXUSR;
331 	    }
332 	    else if (p[0] == 'g')
333 	    {
334 		if (can_read)
335 		    mode |= S_IRGRP;
336 		if (can_write)
337 		    mode |= S_IWGRP;
338 		if (can_execute)
339 		    mode |= S_IXGRP;
340 	    }
341 	    else if (p[0] == 'o')
342 	    {
343 		if (can_read)
344 		    mode |= S_IROTH;
345 		if (can_write)
346 		    mode |= S_IWOTH;
347 		if (can_execute)
348 		    mode |= S_IXOTH;
349 	    }
350 	}
351 	/* Skip to the next field.  */
352 	while (*p != ',' && *p != '\0')
353 	    ++p;
354 	if (*p == ',')
355 	    ++p;
356     }
357 
358     if (respect_umask)
359     {
360 	oumask = umask (0);
361 	(void) umask (oumask);
362 	mode &= ~oumask;
363     }
364 
365     if (chmod (filename, mode) < 0)
366 	return errno;
367     return 0;
368 #endif /* ! CHMOD_BROKEN */
369 }
370 #endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
371 
372 
373 
374 #ifdef CLIENT_SUPPORT
375 int client_prune_dirs;
376 
377 static List *ignlist = NULL;
378 
379 /* Buffer to write to the server.  */
380 static struct buffer *global_to_server;
381 
382 /* Buffer used to read from the server.  */
383 static struct buffer *global_from_server;
384 
385 
386 
387 /*
388  * Read a line from the server.  Result does not include the terminating \n.
389  *
390  * Space for the result is malloc'd and should be freed by the caller.
391  *
392  * Returns number of bytes read.
393  */
394 static size_t
read_line_via(struct buffer * via_from_buffer,struct buffer * via_to_buffer,char ** resultp)395 read_line_via (struct buffer *via_from_buffer, struct buffer *via_to_buffer,
396                char **resultp)
397 {
398     int status;
399     char *result;
400     size_t len;
401 
402     status = buf_flush (via_to_buffer, 1);
403     if (status != 0)
404 	error (1, status, "writing to server");
405 
406     status = buf_read_line (via_from_buffer, &result, &len);
407     if (status != 0)
408     {
409 	if (status == -1)
410 	    error (1, 0,
411                    "end of file from server (consult above messages if any)");
412 	else if (status == -2)
413 	    error (1, 0, "out of memory");
414 	else
415 	    error (1, status, "reading from server");
416     }
417 
418     if (resultp)
419 	*resultp = result;
420     else
421 	free (result);
422 
423     return len;
424 }
425 
426 
427 
428 static size_t
read_line(char ** resultp)429 read_line (char **resultp)
430 {
431   return read_line_via (global_from_server, global_to_server, resultp);
432 }
433 #endif /* CLIENT_SUPPORT */
434 
435 
436 
437 #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
438 /*
439  * Zero if compression isn't supported or requested; non-zero to indicate
440  * a compression level to request from gzip.
441  */
442 int gzip_level;
443 
444 /*
445  * Level of compression to use when running gzip on a single file.
446  */
447 int file_gzip_level;
448 
449 #endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
450 
451 #ifdef CLIENT_SUPPORT
452 
453 /* Whether the server asked us to force compression.  */
454 static bool force_gzip;
455 
456 /*
457  * The Repository for the top level of this command (not necessarily
458  * the CVSROOT, just the current directory at the time we do it).
459  */
460 static char *toplevel_repos;
461 
462 /* Working directory when we first started.  Note: we could speed things
463    up on some systems by using savecwd.h here instead of just always
464    storing a name.  */
465 char *toplevel_wd;
466 
467 
468 
469 static void
handle_ok(char * args,size_t len)470 handle_ok (char *args, size_t len)
471 {
472     return;
473 }
474 
475 
476 
477 static void
handle_error(char * args,size_t len)478 handle_error (char *args, size_t len)
479 {
480     int something_printed;
481 
482     /*
483      * First there is a symbolic error code followed by a space, which
484      * we ignore.
485      */
486     char *p = strchr (args, ' ');
487     if (!p)
488     {
489 	error (0, 0, "invalid data from cvs server");
490 	return;
491     }
492     ++p;
493 
494     /* Next we print the text of the message from the server.  We
495        probably should be prefixing it with "server error" or some
496        such, because if it is something like "Out of memory", the
497        current behavior doesn't say which machine is out of
498        memory.  */
499 
500     len -= p - args;
501     something_printed = 0;
502     for (; len > 0; --len)
503     {
504 	something_printed = 1;
505 	putc (*p++, stderr);
506     }
507     if (something_printed)
508 	putc ('\n', stderr);
509 }
510 
511 
512 
513 static void
handle_valid_requests(char * args,size_t len)514 handle_valid_requests (char *args, size_t len)
515 {
516     char *p = args;
517     char *q;
518     struct request *rq;
519     do
520     {
521 	q = strchr (p, ' ');
522 	if (q)
523 	    *q++ = '\0';
524 	for (rq = requests; rq->name; ++rq)
525 	{
526 	    if (!strcmp (rq->name, p))
527 		break;
528 	}
529 	if (!rq->name)
530 	    /*
531 	     * It is a request we have never heard of (and thus never
532 	     * will want to use).  So don't worry about it.
533 	     */
534 	    ;
535 	else
536 	{
537 	    if (rq->flags & RQ_ENABLEME)
538 	    {
539 		/*
540 		 * Server wants to know if we have this, to enable the
541 		 * feature.
542 		 */
543 		send_to_server (rq->name, 0);
544                 send_to_server ("\012", 0);
545 	    }
546 	    else
547 		rq->flags |= RQ_SUPPORTED;
548 	}
549 	p = q;
550     } while (q);
551     for (rq = requests; rq->name; ++rq)
552     {
553 	if ((rq->flags & RQ_SUPPORTED)
554 	    || (rq->flags & RQ_ENABLEME))
555 	    continue;
556 	if (rq->flags & RQ_ESSENTIAL)
557 	    error (1, 0, "request `%s' not supported by server", rq->name);
558     }
559 }
560 
561 static void
handle_force_gzip(char * args,size_t len)562 handle_force_gzip (char *args, size_t len)
563 {
564     force_gzip = true;
565 }
566 
567 
568 
569 /* Has the server told us its name since the last redirect?
570  */
571 static bool referred_since_last_redirect = false;
572 static bool free_client_referrer = false;
573 
574 
575 
576 static void
handle_referrer(char * args,size_t len)577 handle_referrer (char *args, size_t len)
578 {
579     TRACE (TRACE_FUNCTION, "handle_referrer (%s)", args);
580     client_referrer = parse_cvsroot (args);
581     referred_since_last_redirect = true;
582     free_client_referrer = true;
583 }
584 
585 
586 
587 /* Redirect our connection to a different server and start over.
588  *
589  * GLOBALS
590  *   current_parsed_root	The CVSROOT being accessed.
591  *   client_referrer		Used to track the server which referred us to a
592  *				new server.  Can be supplied by the referring
593  *				server.
594  *   free_client_referrer	Used to track whether the client_referrer needs
595  *				to be freed before changing it.
596  *   referred_since_last_redirect
597  *				Tracks whether the currect server told us how
598  *				to refer to it.
599  *
600  * OUTPUTS
601  *   current_parsed_root	Updated to point to the new CVSROOT.
602  *   referred_since_last_redirect
603  *				Always cleared.
604  *   client_referrer		Set automatically to current_parsed_root if
605  *				the current server did not give us a name to
606  *				refer to it by.
607  *   free_client_referrer	Reset when necessary.
608  */
609 static void
handle_redirect(char * args,size_t len)610 handle_redirect (char *args, size_t len)
611 {
612     static List *redirects = NULL;
613 
614     TRACE (TRACE_FUNCTION, "handle_redirect (%s)", args);
615 
616     if (redirects && findnode (redirects, args))
617 	error (1, 0, "`Redirect' loop detected.  Server misconfiguration?");
618     else
619     {
620 	if (!redirects) redirects = getlist();
621 	push_string (redirects, args);
622     }
623 
624     if (referred_since_last_redirect)
625 	referred_since_last_redirect = false;
626     else
627     {
628 	if (free_client_referrer) free (client_referrer);
629 	client_referrer = current_parsed_root;
630 	free_client_referrer = false;
631     }
632 
633     current_parsed_root = parse_cvsroot (args);
634 
635     /* We deliberately do not set ORIGINAL_PARSED_ROOT here.
636      * ORIGINAL_PARSED_ROOT is used by the client to determine the current root
637      * being processed for the purpose of looking it up in lists and such, even
638      * after a redirect.
639      *
640      * FIXME
641      *   CURRENT_PARSED_ROOT should not be reset by this function.  Redirects
642      *   should be "added" to it.  The REDIRECTS list should also be replaced
643      *   by this new CURRENT_PARSED_ROOT element.  This way, if, for instance,
644      *   a multi-root workspace had two secondaries pointing to the same
645      *   primary, then the client would not report a looping error.
646      *
647      *   There is also a potential memory leak above and storing new roots as
648      *   part of the original could help avoid it fairly elegantly.
649      */
650     if (!current_parsed_root)
651 	error (1, 0, "Server requested redirect to invalid root: `%s'",
652 	       args);
653 }
654 
655 
656 
657 /*
658  * This is a proc for walklist().  It inverts the error return premise of
659  * walklist.
660  *
661  * RETURNS
662  *   True       If this path is prefixed by one of the paths in walklist and
663  *              does not step above the prefix path.
664  *   False      Otherwise.
665  */
666 static
path_list_prefixed(Node * p,void * closure)667 int path_list_prefixed (Node *p, void *closure)
668 {
669     const char *questionable = closure;
670     const char *prefix = p->key;
671     if (strncmp (prefix, questionable, strlen (prefix))) return 0;
672     questionable += strlen (prefix);
673     while (ISSLASH (*questionable)) questionable++;
674     if (*questionable == '\0') return 1;
675     return pathname_levels (questionable);
676 }
677 
678 
679 
680 /*
681  * Need to validate the client pathname.  Disallowed paths include:
682  *
683  *   1. Absolute paths.
684  *   2. Pathnames that do not reference a specifically requested update
685  *      directory.
686  *
687  * In case 2, we actually only check that the directory is under the uppermost
688  * directories mentioned on the command line.
689  *
690  * RETURNS
691  *   True       If the path is valid.
692  *   False      Otherwise.
693  */
694 static
is_valid_client_path(const char * pathname)695 int is_valid_client_path (const char *pathname)
696 {
697     /* 1. Absolute paths. */
698     if (ISABSOLUTE (pathname)) return 0;
699     /* 2. No up-references in path.  */
700     if (pathname_levels (pathname) == 0) return 1;
701     /* 2. No Max-dotdot paths registered.  */
702     if (!uppaths) return 0;
703 
704     return walklist (uppaths, path_list_prefixed, (void *)pathname);
705 }
706 
707 
708 
709 /*
710  * Do all the processing for PATHNAME, where pathname consists of the
711  * repository and the filename.  The parameters we pass to FUNC are:
712  * DATA is just the DATA parameter which was passed to
713  * call_in_directory; ENT_LIST is a pointer to an entries list (which
714  * we manage the storage for); SHORT_PATHNAME is the pathname of the
715  * file relative to the (overall) directory in which the command is
716  * taking place; and FILENAME is the filename portion only of
717  * SHORT_PATHNAME.  When we call FUNC, the curent directory points to
718  * the directory portion of SHORT_PATHNAME.  */
719 static void
call_in_directory(const char * pathname,void (* func)(void *,List *,const char *,const char *),void * data)720 call_in_directory (const char *pathname,
721                    void (*func) (void *, List *, const char *, const char *),
722                    void *data)
723 {
724     /* This variable holds the result of Entries_Open. */
725     List *last_entries = NULL;
726     char *dir_name;
727     char *filename;
728     /* This is what we get when we hook up the directory (working directory
729        name) from PATHNAME with the filename from REPOSNAME.  For example:
730        pathname: ccvs/src/
731        reposname: /u/src/master/ccvs/foo/ChangeLog
732        short_pathname: ccvs/src/ChangeLog
733        */
734     char *short_pathname;
735     char *p;
736 
737     /*
738      * Do the whole descent in parallel for the repositories, so we
739      * know what to put in CVS/Repository files.  I'm not sure the
740      * full hair is necessary since the server does a similar
741      * computation; I suspect that we only end up creating one
742      * directory at a time anyway.
743      *
744      * Also note that we must *only* worry about this stuff when we
745      * are creating directories; `cvs co foo/bar; cd foo/bar; cvs co
746      * CVSROOT; cvs update' is legitimate, but in this case
747      * foo/bar/CVSROOT/CVS/Repository is not a subdirectory of
748      * foo/bar/CVS/Repository.
749      */
750     char *reposname;
751     char *short_repos;
752     char *reposdirname;
753     char *rdirp;
754     int reposdirname_absolute;
755     int newdir = 0;
756 
757     assert (pathname);
758 
759     reposname = NULL;
760     read_line (&reposname);
761     assert (reposname);
762 
763     reposdirname_absolute = 0;
764     if (strncmp (reposname, toplevel_repos, strlen (toplevel_repos)))
765     {
766 	reposdirname_absolute = 1;
767 	short_repos = reposname;
768     }
769     else
770     {
771 	short_repos = reposname + strlen (toplevel_repos) + 1;
772 	if (short_repos[-1] != '/')
773 	{
774 	    reposdirname_absolute = 1;
775 	    short_repos = reposname;
776 	}
777     }
778 
779    /* Now that we have SHORT_REPOS, we can calculate the path to the file we
780     * are being requested to operate on.
781     */
782     filename = strrchr (short_repos, '/');
783     if (!filename)
784 	filename = short_repos;
785     else
786 	++filename;
787 
788     short_pathname = xmalloc (strlen (pathname) + strlen (filename) + 5);
789     strcpy (short_pathname, pathname);
790     strcat (short_pathname, filename);
791 
792     /* Now that we know the path to the file we were requested to operate on,
793      * we can verify that it is valid.
794      *
795      * For security reasons, if SHORT_PATHNAME is absolute or attempts to
796      * ascend outside of the current sanbbox, we abort.  The server should not
797      * send us anything but relative paths which remain inside the sandbox
798      * here.  Anything less means a trojan CVS server could create and edit
799      * arbitrary files on the client.
800      */
801     if (!is_valid_client_path (short_pathname))
802     {
803 	error (0, 0,
804                "Server attempted to update a file via an invalid pathname:");
805         error (1, 0, "`%s'.", short_pathname);
806     }
807 
808     reposdirname = xstrdup (short_repos);
809     p = strrchr (reposdirname, '/');
810     if (!p)
811     {
812 	reposdirname = xrealloc (reposdirname, 2);
813 	reposdirname[0] = '.'; reposdirname[1] = '\0';
814     }
815     else
816 	*p = '\0';
817 
818     dir_name = xstrdup (pathname);
819     p = strrchr (dir_name, '/');
820     if (!p)
821     {
822 	dir_name = xrealloc (dir_name, 2);
823 	dir_name[0] = '.'; dir_name[1] = '\0';
824     }
825     else
826 	*p = '\0';
827     if (client_prune_dirs)
828 	add_prune_candidate (dir_name);
829 
830     if (!toplevel_wd)
831     {
832 	toplevel_wd = xgetcwd ();
833 	if (!toplevel_wd)
834 	    error (1, errno, "could not get working directory");
835     }
836 
837     if (CVS_CHDIR (toplevel_wd) < 0)
838 	error (1, errno, "could not chdir to %s", toplevel_wd);
839 
840     /* Create the CVS directory at the top level if needed.  The
841        isdir seems like an unneeded system call, but it *does*
842        need to be called both if the CVS_CHDIR below succeeds
843        (e.g.  "cvs co .") or if it fails (e.g. basicb-1a in
844        testsuite).  We only need to do this for the "." case,
845        since the server takes care of forcing this directory to be
846        created in all other cases.  If we don't create CVSADM
847        here, the call to Entries_Open below will fail.  FIXME:
848        perhaps this means that we should change our algorithm
849        below that calls Create_Admin instead of having this code
850        here? */
851     if (/* I think the reposdirname_absolute case has to do with
852 	   things like "cvs update /foo/bar".  In any event, the
853 	   code below which tries to put toplevel_repos into
854 	   CVS/Repository is almost surely unsuited to
855 	   the reposdirname_absolute case.  */
856 	!reposdirname_absolute
857 	&& !strcmp (dir_name, ".")
858 	&& ! isdir (CVSADM))
859     {
860 	char *repo;
861 	char *r;
862 
863 	newdir = 1;
864 
865 	/* If toplevel_repos doesn't have at least one character, then the
866 	 * reference to r[-1] below could be out of bounds.
867 	 */
868 	assert (*toplevel_repos);
869 
870 	repo = xmalloc (strlen (toplevel_repos)
871 			+ 10);
872 	strcpy (repo, toplevel_repos);
873 	r = repo + strlen (repo);
874 	if (r[-1] != '.' || r[-2] != '/')
875 	    strcpy (r, "/.");
876 
877 	Create_Admin (".", ".", repo, NULL, NULL, 0, 1, 1);
878 
879 	free (repo);
880     }
881 
882     if (CVS_CHDIR (dir_name) < 0)
883     {
884 	char *dir;
885 	char *dirp;
886 
887 	if (! existence_error (errno))
888 	    error (1, errno, "could not chdir to %s", dir_name);
889 
890 	/* Directory does not exist, we need to create it.  */
891 	newdir = 1;
892 
893 	/* Provided we are willing to assume that directories get
894 	   created one at a time, we could simplify this a lot.
895 	   Do note that one aspect still would need to walk the
896 	   dir_name path: the checking for "fncmp (dir, CVSADM)".  */
897 
898 	dir = xmalloc (strlen (dir_name) + 1);
899 	dirp = dir_name;
900 	rdirp = reposdirname;
901 
902 	/* This algorithm makes nested directories one at a time
903 	   and create CVS administration files in them.  For
904 	   example, we're checking out foo/bar/baz from the
905 	   repository:
906 
907 	   1) create foo, point CVS/Repository to <root>/foo
908 	   2)     .. foo/bar                   .. <root>/foo/bar
909 	   3)     .. foo/bar/baz               .. <root>/foo/bar/baz
910 
911 	   As you can see, we're just stepping along DIR_NAME (with
912 	   DIRP) and REPOSDIRNAME (with RDIRP) respectively.
913 
914 	   We need to be careful when we are checking out a
915 	   module, however, since DIR_NAME and REPOSDIRNAME are not
916 	   going to be the same.  Since modules will not have any
917 	   slashes in their names, we should watch the output of
918 	   STRCHR to decide whether or not we should use STRCHR on
919 	   the RDIRP.  That is, if we're down to a module name,
920 	   don't keep picking apart the repository directory name.  */
921 
922 	do
923 	{
924 	    dirp = strchr (dirp, '/');
925 	    if (dirp)
926 	    {
927 		strncpy (dir, dir_name, dirp - dir_name);
928 		dir[dirp - dir_name] = '\0';
929 		/* Skip the slash.  */
930 		++dirp;
931 		if (!rdirp)
932 		    /* This just means that the repository string has
933 		       fewer components than the dir_name string.  But
934 		       that is OK (e.g. see modules3-8 in testsuite).  */
935 		    ;
936 		else
937 		    rdirp = strchr (rdirp, '/');
938 	    }
939 	    else
940 	    {
941 		/* If there are no more slashes in the dir name,
942 		   we're down to the most nested directory -OR- to
943 		   the name of a module.  In the first case, we
944 		   should be down to a DIRP that has no slashes,
945 		   so it won't help/hurt to do another STRCHR call
946 		   on DIRP.  It will definitely hurt, however, if
947 		   we're down to a module name, since a module
948 		   name can point to a nested directory (that is,
949 		   DIRP will still have slashes in it.  Therefore,
950 		   we should set it to NULL so the routine below
951 		   copies the contents of REMOTEDIRNAME onto the
952 		   root repository directory (does this if rdirp
953 		   is set to NULL, because we used to do an extra
954 		   STRCHR call here). */
955 
956 		rdirp = NULL;
957 		strcpy (dir, dir_name);
958 	    }
959 
960 	    if (fncmp (dir, CVSADM) == 0)
961 	    {
962 		error (0, 0, "cannot create a directory named %s", dir);
963 		error (0, 0, "because CVS uses \"%s\" for its own uses",
964 		       CVSADM);
965 		error (1, 0, "rename the directory and try again");
966 	    }
967 
968 	    if (mkdir_if_needed (dir))
969 	    {
970 		/* It already existed, fine.  Just keep going.  */
971 	    }
972 	    else if (!strcmp (cvs_cmd_name, "export"))
973 		/* Don't create CVSADM directories if this is export.  */
974 		;
975 	    else
976 	    {
977 		/*
978 		 * Put repository in CVS/Repository.  For historical
979 		 * (pre-CVS/Root) reasons, this is an absolute pathname,
980 		 * but what really matters is the part of it which is
981 		 * relative to cvsroot.
982 		 */
983 		char *repo;
984 		char *r, *b;
985 
986 		repo = xmalloc (strlen (reposdirname)
987 				+ strlen (toplevel_repos)
988 				+ 80);
989 		if (reposdirname_absolute)
990 		    r = repo;
991 		else
992 		{
993 		    strcpy (repo, toplevel_repos);
994 		    strcat (repo, "/");
995 		    r = repo + strlen (repo);
996 		}
997 
998 		if (rdirp)
999 		{
1000 		    /* See comment near start of function; the only
1001 		       way that the server can put the right thing
1002 		       in each CVS/Repository file is to create the
1003 		       directories one at a time.  I think that the
1004 		       CVS server has been doing this all along.  */
1005 		    error (0, 0, "\
1006 warning: server is not creating directories one at a time");
1007 		    strncpy (r, reposdirname, rdirp - reposdirname);
1008 		    r[rdirp - reposdirname] = '\0';
1009 		}
1010 		else
1011 		    strcpy (r, reposdirname);
1012 
1013 		Create_Admin (dir, dir, repo, NULL, NULL, 0, 0, 1);
1014 		free (repo);
1015 
1016 		b = strrchr (dir, '/');
1017 		if (!b)
1018 		    Subdir_Register (NULL, NULL, dir);
1019 		else
1020 		{
1021 		    *b = '\0';
1022 		    Subdir_Register (NULL, dir, b + 1);
1023 		    *b = '/';
1024 		}
1025 	    }
1026 
1027 	    if (rdirp)
1028 	    {
1029 		/* Skip the slash.  */
1030 		++rdirp;
1031 	    }
1032 
1033 	} while (dirp);
1034 	free (dir);
1035 	/* Now it better work.  */
1036 	if (CVS_CHDIR (dir_name) < 0)
1037 	    error (1, errno, "could not chdir to %s", dir_name);
1038     }
1039     else if (!strcmp (cvs_cmd_name, "export"))
1040 	/* Don't create CVSADM directories if this is export.  */
1041 	;
1042     else if (!isdir (CVSADM))
1043     {
1044 	/*
1045 	 * Put repository in CVS/Repository.  For historical
1046 	 * (pre-CVS/Root) reasons, this is an absolute pathname,
1047 	 * but what really matters is the part of it which is
1048 	 * relative to cvsroot.
1049 	 */
1050 	char *repo;
1051 
1052 	if (reposdirname_absolute)
1053 	    repo = reposdirname;
1054 	else
1055 	    repo = Xasprintf ("%s/%s", toplevel_repos, reposdirname);
1056 
1057 	Create_Admin (".", ".", repo, NULL, NULL, 0, 1, 1);
1058 	if (repo != reposdirname)
1059 	    free (repo);
1060     }
1061 
1062     if (strcmp (cvs_cmd_name, "export"))
1063     {
1064 	last_entries = Entries_Open (0, dir_name);
1065 
1066 	/* If this is a newly created directory, we will record
1067 	   all subdirectory information, so call Subdirs_Known in
1068 	   case there are no subdirectories.  If this is not a
1069 	   newly created directory, it may be an old working
1070 	   directory from before we recorded subdirectory
1071 	   information in the Entries file.  We force a search for
1072 	   all subdirectories now, to make sure our subdirectory
1073 	   information is up to date.  If the Entries file does
1074 	   record subdirectory information, then this call only
1075 	   does list manipulation.  */
1076 	if (newdir)
1077 	    Subdirs_Known (last_entries);
1078 	else
1079 	{
1080 	    List *dirlist;
1081 
1082 	    dirlist = Find_Directories (NULL, W_LOCAL, last_entries);
1083 	    dellist (&dirlist);
1084 	}
1085     }
1086     free (reposdirname);
1087     (*func) (data, last_entries, short_pathname, filename);
1088     if (last_entries)
1089 	Entries_Close (last_entries);
1090     free (dir_name);
1091     free (short_pathname);
1092     free (reposname);
1093 }
1094 
1095 
1096 
1097 static void
copy_a_file(void * data,List * ent_list,const char * short_pathname,const char * filename)1098 copy_a_file (void *data, List *ent_list, const char *short_pathname,
1099 	     const char *filename)
1100 {
1101     char *newname;
1102 
1103     read_line (&newname);
1104 
1105 #ifdef USE_VMS_FILENAMES
1106     {
1107 	/* Mogrify the filename so VMS is happy with it. */
1108 	char *p;
1109 	for(p = newname; *p; p++)
1110 	   if(*p == '.' || *p == '#') *p = '_';
1111     }
1112 #endif
1113     /* cvsclient.texi has said for a long time that newname must be in the
1114        same directory.  Wouldn't want a malicious or buggy server overwriting
1115        ~/.profile, /etc/passwd, or anything like that.  */
1116     if (last_component (newname) != newname)
1117 	error (1, 0, "protocol error: Copy-file tried to specify directory");
1118 
1119     if (unlink_file (newname) && !existence_error (errno))
1120 	error (0, errno, "unable to remove %s", newname);
1121     copy_file (filename, newname);
1122     free (newname);
1123 }
1124 
1125 
1126 
1127 static void
handle_copy_file(char * args,size_t len)1128 handle_copy_file (char *args, size_t len)
1129 {
1130     call_in_directory (args, copy_a_file, NULL);
1131 }
1132 
1133 
1134 
1135 /* Read from the server the count for the length of a file, then read
1136    the contents of that file and write them to FILENAME.  FULLNAME is
1137    the name of the file for use in error messages.  FIXME-someday:
1138    extend this to deal with compressed files and make update_entries
1139    use it.  On error, gives a fatal error.  */
1140 static void
read_counted_file(const char * filename,const char * fullname)1141 read_counted_file (const char *filename, const char *fullname)
1142 {
1143     char *size_string;
1144     size_t size;
1145     char *buf;
1146 
1147     /* Pointers in buf to the place to put data which will be read,
1148        and the data which needs to be written, respectively.  */
1149     char *pread;
1150     char *pwrite;
1151     /* Number of bytes left to read and number of bytes in buf waiting to
1152        be written, respectively.  */
1153     size_t nread;
1154     size_t nwrite;
1155 
1156     FILE *fp;
1157 
1158     read_line (&size_string);
1159     if (size_string[0] == 'z')
1160 	error (1, 0, "\
1161 protocol error: compressed files not supported for that operation");
1162     /* FIXME: should be doing more error checking, probably.  Like using
1163        strtoul and making sure we used up the whole line.  */
1164     size = atoi (size_string);
1165     free (size_string);
1166 
1167     /* A more sophisticated implementation would use only a limited amount
1168        of buffer space (8K perhaps), and read that much at a time.  We allocate
1169        a buffer for the whole file only to make it easy to keep track what
1170        needs to be read and written.  */
1171     buf = xmalloc (size);
1172 
1173     /* FIXME-someday: caller should pass in a flag saying whether it
1174        is binary or not.  I haven't carefully looked into whether
1175        CVS/Template files should use local text file conventions or
1176        not.  */
1177     fp = CVS_FOPEN (filename, "wb");
1178     if (!fp)
1179 	error (1, errno, "cannot write %s", fullname);
1180     nread = size;
1181     nwrite = 0;
1182     pread = buf;
1183     pwrite = buf;
1184     while (nread > 0 || nwrite > 0)
1185     {
1186 	size_t n;
1187 
1188 	if (nread > 0)
1189 	{
1190 	    n = try_read_from_server (pread, nread);
1191 	    nread -= n;
1192 	    pread += n;
1193 	    nwrite += n;
1194 	}
1195 
1196 	if (nwrite > 0)
1197 	{
1198 	    n = fwrite (pwrite, sizeof *pwrite, nwrite, fp);
1199 	    if (ferror (fp))
1200 		error (1, errno, "cannot write %s", fullname);
1201 	    nwrite -= n;
1202 	    pwrite += n;
1203 	}
1204     }
1205     free (buf);
1206     if (fclose (fp) < 0)
1207 	error (1, errno, "cannot close %s", fullname);
1208 }
1209 
1210 
1211 
1212 /* OK, we want to swallow the "U foo.c" response and then output it only
1213    if we can update the file.  In the future we probably want some more
1214    systematic approach to parsing tagged text, but for now we keep it
1215    ad hoc.  "Why," I hear you cry, "do we not just look at the
1216    Update-existing and Created responses?"  That is an excellent question,
1217    and the answer is roughly conservatism/laziness--I haven't read through
1218    update.c enough to figure out the exact correspondence or lack thereof
1219    between those responses and a "U foo.c" line (note that Merged, from
1220    join_file, can be either "C foo" or "U foo" depending on the context).  */
1221 /* Nonzero if we have seen +updated and not -updated.  */
1222 static int updated_seen;
1223 /* Filename from an "fname" tagged response within +updated/-updated.  */
1224 static char *updated_fname;
1225 
1226 /* This struct is used to hold data when reading the +importmergecmd
1227    and -importmergecmd tags.  We put the variables in a struct only
1228    for namespace issues.  FIXME: As noted above, we need to develop a
1229    more systematic approach.  */
1230 static struct
1231 {
1232     /* Nonzero if we have seen +importmergecmd and not -importmergecmd.  */
1233     int seen;
1234     /* Number of conflicts, from a "conflicts" tagged response.  */
1235     int conflicts;
1236     /* First merge tag, from a "mergetag1" tagged response.  */
1237     char *mergetag1;
1238     /* Second merge tag, from a "mergetag2" tagged response.  */
1239     char *mergetag2;
1240     /* Repository, from a "repository" tagged response.  */
1241     char *repository;
1242 } importmergecmd;
1243 
1244 /* Nonzero if we should arrange to return with a failure exit status.  */
1245 static bool failure_exit;
1246 
1247 
1248 /*
1249  * The time stamp of the last file we registered.
1250  */
1251 static time_t last_register_time;
1252 
1253 
1254 
1255 /*
1256  * The Checksum response gives the checksum for the file transferred
1257  * over by the next Updated, Merged or Patch response.  We just store
1258  * it here, and then check it in update_entries.
1259  */
1260 static int stored_checksum_valid;
1261 static unsigned char stored_checksum[16];
1262 static void
handle_checksum(char * args,size_t len)1263 handle_checksum (char *args, size_t len)
1264 {
1265     char *s;
1266     char buf[3];
1267     int i;
1268 
1269     if (stored_checksum_valid)
1270         error (1, 0, "Checksum received before last one was used");
1271 
1272     s = args;
1273     buf[2] = '\0';
1274     for (i = 0; i < 16; i++)
1275     {
1276         char *bufend;
1277 
1278 	buf[0] = *s++;
1279 	buf[1] = *s++;
1280 	stored_checksum[i] = (char) strtol (buf, &bufend, 16);
1281 	if (bufend != buf + 2)
1282 	    break;
1283     }
1284 
1285     if (i < 16 || *s != '\0')
1286         error (1, 0, "Invalid Checksum response: `%s'", args);
1287 
1288     stored_checksum_valid = 1;
1289 }
1290 
1291 
1292 
1293 /* Mode that we got in a "Mode" response (malloc'd), or NULL if none.  */
1294 static char *stored_mode;
1295 static void
handle_mode(char * args,size_t len)1296 handle_mode (char *args, size_t len)
1297 {
1298     if (stored_mode)
1299 	error (1, 0, "protocol error: duplicate Mode");
1300     stored_mode = xstrdup (args);
1301 }
1302 
1303 
1304 
1305 /* Nonzero if time was specified in Mod-time.  */
1306 static int stored_modtime_valid;
1307 /* Time specified in Mod-time.  */
1308 static time_t stored_modtime;
1309 static void
handle_mod_time(char * args,size_t len)1310 handle_mod_time (char *args, size_t len)
1311 {
1312     struct timespec newtime;
1313     if (stored_modtime_valid)
1314 	error (0, 0, "protocol error: duplicate Mod-time");
1315     if (get_date (&newtime, args, NULL))
1316     {
1317 	/* Truncate nanoseconds.  */
1318 	stored_modtime = newtime.tv_sec;
1319 	stored_modtime_valid = 1;
1320     }
1321     else
1322 	error (0, 0, "protocol error: cannot parse date %s", args);
1323 }
1324 
1325 
1326 
1327 /*
1328  * If we receive a patch, but the patch program fails to apply it, we
1329  * want to request the original file.  We keep a list of files whose
1330  * patches have failed.
1331  */
1332 
1333 char **failed_patches;
1334 int failed_patches_count;
1335 
1336 struct update_entries_data
1337 {
1338     enum {
1339       /*
1340        * We are just getting an Entries line; the local file is
1341        * correct.
1342        */
1343       UPDATE_ENTRIES_CHECKIN,
1344       /* We are getting the file contents as well.  */
1345       UPDATE_ENTRIES_UPDATE,
1346       /*
1347        * We are getting a patch against the existing local file, not
1348        * an entire new file.
1349        */
1350       UPDATE_ENTRIES_PATCH,
1351       /*
1352        * We are getting an RCS change text (diff -n output) against
1353        * the existing local file, not an entire new file.
1354        */
1355       UPDATE_ENTRIES_RCS_DIFF
1356     } contents;
1357 
1358     enum {
1359 	/* We are replacing an existing file.  */
1360 	UPDATE_ENTRIES_EXISTING,
1361 	/* We are creating a new file.  */
1362 	UPDATE_ENTRIES_NEW,
1363 	/* We don't know whether it is existing or new.  */
1364 	UPDATE_ENTRIES_EXISTING_OR_NEW
1365     } existp;
1366 
1367     /*
1368      * String to put in the timestamp field or NULL to use the timestamp
1369      * of the file.
1370      */
1371     char *timestamp;
1372 };
1373 
1374 
1375 
1376 /* Update the Entries line for this file.  */
1377 static void
update_entries(void * data_arg,List * ent_list,const char * short_pathname,const char * filename)1378 update_entries (void *data_arg, List *ent_list, const char *short_pathname,
1379                 const char *filename)
1380 {
1381     char *entries_line;
1382     struct update_entries_data *data = data_arg;
1383 
1384     char *cp;
1385     char *user;
1386     char *vn;
1387     /* Timestamp field.  Always empty according to the protocol.  */
1388     char *ts;
1389     char *options = NULL;
1390     char *tag = NULL;
1391     char *date = NULL;
1392     char *tag_or_date;
1393     char *scratch_entries = NULL;
1394     int bin;
1395 
1396 #ifdef UTIME_EXPECTS_WRITABLE
1397     int change_it_back = 0;
1398 #endif
1399 
1400     read_line (&entries_line);
1401 
1402     /*
1403      * Parse the entries line.
1404      */
1405     scratch_entries = xstrdup (entries_line);
1406 
1407     if (scratch_entries[0] != '/')
1408         error (1, 0, "bad entries line `%s' from server", entries_line);
1409     user = scratch_entries + 1;
1410     if (!(cp = strchr (user, '/')))
1411         error (1, 0, "bad entries line `%s' from server", entries_line);
1412     *cp++ = '\0';
1413     vn = cp;
1414     if (!(cp = strchr (vn, '/')))
1415         error (1, 0, "bad entries line `%s' from server", entries_line);
1416     *cp++ = '\0';
1417 
1418     ts = cp;
1419     if (!(cp = strchr (ts, '/')))
1420         error (1, 0, "bad entries line `%s' from server", entries_line);
1421     *cp++ = '\0';
1422     options = cp;
1423     if (!(cp = strchr (options, '/')))
1424         error (1, 0, "bad entries line `%s' from server", entries_line);
1425     *cp++ = '\0';
1426     tag_or_date = cp;
1427 
1428     /* If a slash ends the tag_or_date, ignore everything after it.  */
1429     cp = strchr (tag_or_date, '/');
1430     if (cp)
1431         *cp = '\0';
1432     if (*tag_or_date == 'T')
1433         tag = tag_or_date + 1;
1434     else if (*tag_or_date == 'D')
1435         date = tag_or_date + 1;
1436 
1437     /* Done parsing the entries line. */
1438 
1439     if (data->contents == UPDATE_ENTRIES_UPDATE
1440 	|| data->contents == UPDATE_ENTRIES_PATCH
1441 	|| data->contents == UPDATE_ENTRIES_RCS_DIFF)
1442     {
1443 	char *size_string;
1444 	char *mode_string;
1445 	int size;
1446 	char *buf;
1447 	char *temp_filename;
1448 	int use_gzip;
1449 	int patch_failed;
1450 
1451 	read_line (&mode_string);
1452 
1453 	read_line (&size_string);
1454 	if (size_string[0] == 'z')
1455 	{
1456 	    use_gzip = 1;
1457 	    size = atoi (size_string+1);
1458 	}
1459 	else
1460 	{
1461 	    use_gzip = 0;
1462 	    size = atoi (size_string);
1463 	}
1464 	free (size_string);
1465 
1466 	/* Note that checking this separately from writing the file is
1467 	   a race condition: if the existence or lack thereof of the
1468 	   file changes between now and the actual calls which
1469 	   operate on it, we lose.  However (a) there are so many
1470 	   cases, I'm reluctant to try to fix them all, (b) in some
1471 	   cases the system might not even have a system call which
1472 	   does the right thing, and (c) it isn't clear this needs to
1473 	   work.  */
1474 	if (data->existp == UPDATE_ENTRIES_EXISTING
1475 	    && !isfile (filename))
1476 	    /* Emit a warning and update the file anyway.  */
1477 	    error (0, 0, "warning: %s unexpectedly disappeared",
1478 		   short_pathname);
1479 
1480 	if (data->existp == UPDATE_ENTRIES_NEW
1481 	    && isfile (filename))
1482 	{
1483 	    /* Emit a warning and refuse to update the file; we don't want
1484 	       to clobber a user's file.  */
1485 	    size_t nread;
1486 	    size_t toread;
1487 
1488 	    /* size should be unsigned, but until we get around to fixing
1489 	       that, work around it.  */
1490 	    size_t usize;
1491 
1492 	    char buf[8192];
1493 
1494 	    /* This error might be confusing; it isn't really clear to
1495 	       the user what to do about it.  Keep in mind that it has
1496 	       several causes: (1) something/someone creates the file
1497 	       during the time that CVS is running, (2) the repository
1498 	       has two files whose names clash for the client because
1499 	       of case-insensitivity or similar causes, See 3 for
1500 	       additional notes.  (3) a special case of this is that a
1501 	       file gets renamed for example from a.c to A.C.  A
1502 	       "cvs update" on a case-insensitive client will get this
1503 	       error.  In this case and in case 2, the filename
1504 	       (short_pathname) printed in the error message will likely _not_
1505 	       have the same case as seen by the user in a directory listing.
1506 	       (4) the client has a file which the server doesn't know
1507 	       about (e.g. "? foo" file), and that name clashes with a file
1508 	       the server does know about, (5) classify.c will print the same
1509 	       message for other reasons.
1510 
1511 	       I hope the above paragraph makes it clear that making this
1512 	       clearer is not a one-line fix.  */
1513 	    error (0, 0, "move away `%s'; it is in the way", short_pathname);
1514 	    if (updated_fname)
1515 	    {
1516 		cvs_output ("C ", 0);
1517 		cvs_output (updated_fname, 0);
1518 		cvs_output ("\n", 1);
1519 	    }
1520 	    failure_exit = true;
1521 
1522 	discard_file_and_return:
1523 	    /* Now read and discard the file contents.  */
1524 	    usize = size;
1525 	    nread = 0;
1526 	    while (nread < usize)
1527 	    {
1528 		toread = usize - nread;
1529 		if (toread > sizeof buf)
1530 		    toread = sizeof buf;
1531 
1532 		nread += try_read_from_server (buf, toread);
1533 		if (nread == usize)
1534 		    break;
1535 	    }
1536 
1537 	    free (mode_string);
1538 	    free (scratch_entries);
1539 	    free (entries_line);
1540 
1541 	    /* The Mode, Mod-time, and Checksum responses should not carry
1542 	       over to a subsequent Created (or whatever) response, even
1543 	       in the error case.  */
1544 	    if (stored_mode)
1545 	    {
1546 		free (stored_mode);
1547 		stored_mode = NULL;
1548 	    }
1549 	    stored_modtime_valid = 0;
1550 	    stored_checksum_valid = 0;
1551 
1552 	    if (updated_fname)
1553 	    {
1554 		free (updated_fname);
1555 		updated_fname = NULL;
1556 	    }
1557 	    return;
1558 	}
1559 
1560 	temp_filename = xmalloc (strlen (filename) + 80);
1561 #ifdef USE_VMS_FILENAMES
1562         /* A VMS rename of "blah.dat" to "foo" to implies a
1563            destination of "foo.dat" which is unfortinate for CVS */
1564 	sprintf (temp_filename, "%s_new_", filename);
1565 #else
1566 #ifdef _POSIX_NO_TRUNC
1567 	sprintf (temp_filename, ".new.%.9s", filename);
1568 #else /* _POSIX_NO_TRUNC */
1569 	sprintf (temp_filename, ".new.%s", filename);
1570 #endif /* _POSIX_NO_TRUNC */
1571 #endif /* USE_VMS_FILENAMES */
1572 
1573 	buf = xmalloc (size);
1574 
1575         /* Some systems, like OS/2 and Windows NT, end lines with CRLF
1576            instead of just LF.  Format translation is done in the C
1577            library I/O funtions.  Here we tell them whether or not to
1578            convert -- if this file is marked "binary" with the RCS -kb
1579            flag, then we don't want to convert, else we do (because
1580            CVS assumes text files by default). */
1581 
1582 	if (options)
1583 	    bin = !strcmp (options, "-kb");
1584 	else
1585 	    bin = 0;
1586 
1587 	if (data->contents == UPDATE_ENTRIES_RCS_DIFF)
1588 	{
1589 	    /* This is an RCS change text.  We just hold the change
1590 	       text in memory.  */
1591 
1592 	    if (use_gzip)
1593 		error (1, 0,
1594 		       "server error: gzip invalid with RCS change text");
1595 
1596 	    read_from_server (buf, size);
1597 	}
1598 	else
1599 	{
1600 	    int fd;
1601 
1602 	    fd = CVS_OPEN (temp_filename,
1603 			   (O_WRONLY | O_CREAT | O_TRUNC
1604 			    | (bin ? OPEN_BINARY : 0)),
1605 			   0777);
1606 
1607 	    if (fd < 0)
1608 	    {
1609 		/* I can see a case for making this a fatal error; for
1610 		   a condition like disk full or network unreachable
1611 		   (for a file server), carrying on and giving an
1612 		   error on each file seems unnecessary.  But if it is
1613 		   a permission problem, or some such, then it is
1614 		   entirely possible that future files will not have
1615 		   the same problem.  */
1616 		error (0, errno, "cannot write %s", short_pathname);
1617 		free (temp_filename);
1618 		free (buf);
1619 		goto discard_file_and_return;
1620 	    }
1621 
1622 	    if (size > 0)
1623 	    {
1624 		read_from_server (buf, size);
1625 
1626 		if (use_gzip)
1627 		{
1628 		    if (gunzip_and_write (fd, short_pathname,
1629 					  (unsigned char *) buf, size))
1630 			error (1, 0, "aborting due to compression error");
1631 		}
1632 		else if (write (fd, buf, size) != size)
1633 		    error (1, errno, "writing %s", short_pathname);
1634 	    }
1635 
1636 	    if (close (fd) < 0)
1637 		error (1, errno, "writing %s", short_pathname);
1638 	}
1639 
1640 	/* This is after we have read the file from the net (a change
1641 	   from previous versions, where the server would send us
1642 	   "M U foo.c" before Update-existing or whatever), but before
1643 	   we finish writing the file (arguably a bug).  The timing
1644 	   affects a user who wants status info about how far we have
1645 	   gotten, and also affects whether "U foo.c" appears in addition
1646 	   to various error messages.  */
1647 	if (updated_fname)
1648 	{
1649 	    cvs_output ("U ", 0);
1650 	    cvs_output (updated_fname, 0);
1651 	    cvs_output ("\n", 1);
1652 	    free (updated_fname);
1653 	    updated_fname = 0;
1654 	}
1655 
1656 	patch_failed = 0;
1657 
1658 	if (data->contents == UPDATE_ENTRIES_UPDATE)
1659 	{
1660 	    rename_file (temp_filename, filename);
1661 	}
1662 	else if (data->contents == UPDATE_ENTRIES_PATCH)
1663 	{
1664 	    /* You might think we could just leave Patched out of
1665 	       Valid-responses and not get this response.  However, if
1666 	       memory serves, the CVS 1.9 server bases this on -u
1667 	       (update-patches), and there is no way for us to send -u
1668 	       or not based on whether the server supports "Rcs-diff".
1669 
1670 	       Fall back to transmitting entire files.  */
1671 	    patch_failed = 1;
1672 	}
1673 	else
1674 	{
1675 	    char *filebuf;
1676 	    size_t filebufsize;
1677 	    size_t nread;
1678 	    char *patchedbuf;
1679 	    size_t patchedlen;
1680 
1681 	    /* Handle UPDATE_ENTRIES_RCS_DIFF.  */
1682 
1683 	    if (!isfile (filename))
1684 	        error (1, 0, "patch original file %s does not exist",
1685 		       short_pathname);
1686 	    filebuf = NULL;
1687 	    filebufsize = 0;
1688 	    nread = 0;
1689 
1690 	    get_file (filename, short_pathname, bin ? FOPEN_BINARY_READ : "r",
1691 		      &filebuf, &filebufsize, &nread);
1692 	    /* At this point the contents of the existing file are in
1693                FILEBUF, and the length of the contents is in NREAD.
1694                The contents of the patch from the network are in BUF,
1695                and the length of the patch is in SIZE.  */
1696 
1697 	    if (! rcs_change_text (short_pathname, filebuf, nread, buf, size,
1698 				   &patchedbuf, &patchedlen))
1699 		patch_failed = 1;
1700 	    else
1701 	    {
1702 		if (stored_checksum_valid)
1703 		{
1704 		    unsigned char checksum[16];
1705 
1706 		    /* We have a checksum.  Check it before writing
1707 		       the file out, so that we don't have to read it
1708 		       back in again.  */
1709 		    md5_buffer (patchedbuf, patchedlen, checksum);
1710 		    if (memcmp (checksum, stored_checksum, 16) != 0)
1711 		    {
1712 			error (0, 0,
1713 "checksum failure after patch to %s; will refetch",
1714 			       short_pathname);
1715 
1716 			patch_failed = 1;
1717 		    }
1718 
1719 		    stored_checksum_valid = 0;
1720 		}
1721 
1722 		if (! patch_failed)
1723 		{
1724 		    FILE *e;
1725 
1726 		    e = xfopen (temp_filename,
1727 				bin ? FOPEN_BINARY_WRITE : "w");
1728 		    if (fwrite (patchedbuf, sizeof *patchedbuf, patchedlen, e)
1729 			!= patchedlen)
1730 			error (1, errno, "cannot write %s", temp_filename);
1731 		    if (fclose (e) == EOF)
1732 			error (1, errno, "cannot close %s", temp_filename);
1733 		    rename_file (temp_filename, filename);
1734 		}
1735 
1736 		free (patchedbuf);
1737 	    }
1738 
1739 	    free (filebuf);
1740 	}
1741 
1742 	free (temp_filename);
1743 
1744 	if (stored_checksum_valid && ! patch_failed)
1745 	{
1746 	    FILE *e;
1747 	    struct md5_ctx context;
1748 	    unsigned char buf[8192];
1749 	    unsigned len;
1750 	    unsigned char checksum[16];
1751 
1752 	    /*
1753 	     * Compute the MD5 checksum.  This will normally only be
1754 	     * used when receiving a patch, so we always compute it
1755 	     * here on the final file, rather than on the received
1756 	     * data.
1757 	     *
1758 	     * Note that if the file is a text file, we should read it
1759 	     * here using text mode, so its lines will be terminated the same
1760 	     * way they were transmitted.
1761 	     */
1762 	    e = CVS_FOPEN (filename, "r");
1763 	    if (!e)
1764 	        error (1, errno, "could not open %s", short_pathname);
1765 
1766 	    md5_init_ctx (&context);
1767 	    while ((len = fread (buf, 1, sizeof buf, e)) != 0)
1768 		md5_process_bytes (buf, len, &context);
1769 	    if (ferror (e))
1770 		error (1, errno, "could not read %s", short_pathname);
1771 	    md5_finish_ctx (&context, checksum);
1772 
1773 	    fclose (e);
1774 
1775 	    stored_checksum_valid = 0;
1776 
1777 	    if (memcmp (checksum, stored_checksum, 16) != 0)
1778 	    {
1779 	        if (data->contents != UPDATE_ENTRIES_PATCH)
1780 		    error (1, 0, "checksum failure on %s",
1781 			   short_pathname);
1782 
1783 		error (0, 0,
1784 		       "checksum failure after patch to %s; will refetch",
1785 		       short_pathname);
1786 
1787 		patch_failed = 1;
1788 	    }
1789 	}
1790 
1791 	if (patch_failed)
1792 	{
1793 	    /* Save this file to retrieve later.  */
1794 	    failed_patches = xnrealloc (failed_patches,
1795 					failed_patches_count + 1,
1796 					sizeof (char *));
1797 	    failed_patches[failed_patches_count] = xstrdup (short_pathname);
1798 	    ++failed_patches_count;
1799 
1800 	    stored_checksum_valid = 0;
1801 
1802 	    free (mode_string);
1803 	    free (buf);
1804 	    free (scratch_entries);
1805 	    free (entries_line);
1806 
1807 	    return;
1808 	}
1809 
1810         {
1811 	    int status = change_mode (filename, mode_string, 1);
1812 	    if (status != 0)
1813 		error (0, status, "cannot change mode of %s", short_pathname);
1814 	}
1815 
1816 	free (mode_string);
1817 	free (buf);
1818     }
1819 
1820     if (stored_mode)
1821     {
1822 	change_mode (filename, stored_mode, 1);
1823 	free (stored_mode);
1824 	stored_mode = NULL;
1825     }
1826 
1827     if (stored_modtime_valid)
1828     {
1829 	struct utimbuf t;
1830 
1831 	memset (&t, 0, sizeof (t));
1832 	t.modtime = stored_modtime;
1833 	(void) time (&t.actime);
1834 
1835 #ifdef UTIME_EXPECTS_WRITABLE
1836 	if (!iswritable (filename))
1837 	{
1838 	    xchmod (filename, 1);
1839 	    change_it_back = 1;
1840 	}
1841 #endif  /* UTIME_EXPECTS_WRITABLE  */
1842 
1843 	if (utime (filename, &t) < 0)
1844 	    error (0, errno, "cannot set time on %s", filename);
1845 
1846 #ifdef UTIME_EXPECTS_WRITABLE
1847 	if (change_it_back)
1848 	{
1849 	    xchmod (filename, 0);
1850 	    change_it_back = 0;
1851 	}
1852 #endif  /*  UTIME_EXPECTS_WRITABLE  */
1853 
1854 	stored_modtime_valid = 0;
1855     }
1856 
1857     /*
1858      * Process the entries line.  Do this after we've written the file,
1859      * since we need the timestamp.
1860      */
1861     if (strcmp (cvs_cmd_name, "export"))
1862     {
1863 	char *local_timestamp;
1864 	char *file_timestamp;
1865 
1866 	(void) time (&last_register_time);
1867 
1868 	local_timestamp = data->timestamp;
1869 	if (!local_timestamp || ts[0] == '+')
1870 	    file_timestamp = time_stamp (filename);
1871 	else
1872 	    file_timestamp = NULL;
1873 
1874 	/*
1875 	 * These special version numbers signify that it is not up to
1876 	 * date.  Create a dummy timestamp which will never compare
1877 	 * equal to the timestamp of the file.
1878 	 */
1879 	if (vn[0] == '\0' || !strcmp (vn, "0") || vn[0] == '-')
1880 	    local_timestamp = "dummy timestamp";
1881 	else if (!local_timestamp)
1882 	{
1883 	    local_timestamp = file_timestamp;
1884 
1885 	    /* Checking for cvs_cmd_name of "commit" doesn't seem like
1886 	       the cleanest way to handle this, but it seem to roughly
1887 	       parallel what the :local: code which calls
1888 	       mark_up_to_date ends up amounting to.  Some day, should
1889 	       think more about what the Checked-in response means
1890 	       vis-a-vis both Entries and Base and clarify
1891 	       cvsclient.texi accordingly.  */
1892 
1893 	    if (!strcmp (cvs_cmd_name, "commit"))
1894 		mark_up_to_date (filename);
1895 	}
1896 
1897 	Register (ent_list, filename, vn, local_timestamp,
1898 		  options, tag, date, ts[0] == '+' ? file_timestamp : NULL);
1899 
1900 	if (file_timestamp)
1901 	    free (file_timestamp);
1902 
1903     }
1904     free (scratch_entries);
1905     free (entries_line);
1906 }
1907 
1908 
1909 
1910 static void
handle_checked_in(char * args,size_t len)1911 handle_checked_in (char *args, size_t len)
1912 {
1913     struct update_entries_data dat;
1914     dat.contents = UPDATE_ENTRIES_CHECKIN;
1915     dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1916     dat.timestamp = NULL;
1917     call_in_directory (args, update_entries, &dat);
1918 }
1919 
1920 
1921 
1922 static void
handle_new_entry(char * args,size_t len)1923 handle_new_entry (char *args, size_t len)
1924 {
1925     struct update_entries_data dat;
1926     dat.contents = UPDATE_ENTRIES_CHECKIN;
1927     dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1928     dat.timestamp = "dummy timestamp from new-entry";
1929     call_in_directory (args, update_entries, &dat);
1930 }
1931 
1932 
1933 
1934 static void
handle_updated(char * args,size_t len)1935 handle_updated (char *args, size_t len)
1936 {
1937     struct update_entries_data dat;
1938     dat.contents = UPDATE_ENTRIES_UPDATE;
1939     dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1940     dat.timestamp = NULL;
1941     call_in_directory (args, update_entries, &dat);
1942 }
1943 
1944 
1945 
1946 static void
handle_created(char * args,size_t len)1947 handle_created (char *args, size_t len)
1948 {
1949     struct update_entries_data dat;
1950     dat.contents = UPDATE_ENTRIES_UPDATE;
1951     dat.existp = UPDATE_ENTRIES_NEW;
1952     dat.timestamp = NULL;
1953     call_in_directory (args, update_entries, &dat);
1954 }
1955 
1956 
1957 
1958 static void
handle_update_existing(char * args,size_t len)1959 handle_update_existing (char *args, size_t len)
1960 {
1961     struct update_entries_data dat;
1962     dat.contents = UPDATE_ENTRIES_UPDATE;
1963     dat.existp = UPDATE_ENTRIES_EXISTING;
1964     dat.timestamp = NULL;
1965     call_in_directory (args, update_entries, &dat);
1966 }
1967 
1968 
1969 
1970 static void
handle_merged(char * args,size_t len)1971 handle_merged (char *args, size_t len)
1972 {
1973     struct update_entries_data dat;
1974     dat.contents = UPDATE_ENTRIES_UPDATE;
1975     /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case...  */
1976     dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1977     dat.timestamp = "Result of merge";
1978     call_in_directory (args, update_entries, &dat);
1979 }
1980 
1981 
1982 
1983 static void
handle_patched(char * args,size_t len)1984 handle_patched (char *args, size_t len)
1985 {
1986     struct update_entries_data dat;
1987     dat.contents = UPDATE_ENTRIES_PATCH;
1988     /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case...  */
1989     dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1990     dat.timestamp = NULL;
1991     call_in_directory (args, update_entries, &dat);
1992 }
1993 
1994 
1995 
1996 static void
handle_rcs_diff(char * args,size_t len)1997 handle_rcs_diff (char *args, size_t len)
1998 {
1999     struct update_entries_data dat;
2000     dat.contents = UPDATE_ENTRIES_RCS_DIFF;
2001     /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case...  */
2002     dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
2003     dat.timestamp = NULL;
2004     call_in_directory (args, update_entries, &dat);
2005 }
2006 
2007 
2008 
2009 static void
remove_entry(void * data,List * ent_list,const char * short_pathname,const char * filename)2010 remove_entry (void *data, List *ent_list, const char *short_pathname,
2011               const char *filename)
2012 {
2013     Scratch_Entry (ent_list, filename);
2014 }
2015 
2016 
2017 
2018 static void
handle_remove_entry(char * args,size_t len)2019 handle_remove_entry (char *args, size_t len)
2020 {
2021     call_in_directory (args, remove_entry, NULL);
2022 }
2023 
2024 
2025 
2026 static void
remove_entry_and_file(void * data,List * ent_list,const char * short_pathname,const char * filename)2027 remove_entry_and_file (void *data, List *ent_list, const char *short_pathname,
2028                        const char *filename)
2029 {
2030     Scratch_Entry (ent_list, filename);
2031     /* Note that we don't ignore existence_error's here.  The server
2032        should be sending Remove-entry rather than Removed in cases
2033        where the file does not exist.  And if the user removes the
2034        file halfway through a cvs command, we should be printing an
2035        error.  */
2036     if (unlink_file (filename) < 0)
2037 	error (0, errno, "unable to remove %s", short_pathname);
2038 }
2039 
2040 
2041 
2042 static void
handle_removed(char * args,size_t len)2043 handle_removed (char *args, size_t len)
2044 {
2045     call_in_directory (args, remove_entry_and_file, NULL);
2046 }
2047 
2048 
2049 
2050 /* Is this the top level (directory containing CVSROOT)?  */
2051 static int
is_cvsroot_level(char * pathname)2052 is_cvsroot_level (char *pathname)
2053 {
2054     if (strcmp (toplevel_repos, current_parsed_root->directory))
2055 	return 0;
2056 
2057     return !strchr (pathname, '/');
2058 }
2059 
2060 
2061 
2062 static void
set_static(void * data,List * ent_list,const char * short_pathname,const char * filename)2063 set_static (void *data, List *ent_list, const char *short_pathname,
2064 	    const char *filename)
2065 {
2066     FILE *fp;
2067     fp = xfopen (CVSADM_ENTSTAT, "w+");
2068     if (fclose (fp) == EOF)
2069         error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
2070 }
2071 
2072 
2073 
2074 static void
handle_set_static_directory(char * args,size_t len)2075 handle_set_static_directory (char *args, size_t len)
2076 {
2077     if (!strcmp (cvs_cmd_name, "export"))
2078     {
2079 	/* Swallow the repository.  */
2080 	read_line (NULL);
2081 	return;
2082     }
2083     call_in_directory (args, set_static, NULL);
2084 }
2085 
2086 
2087 
2088 static void
clear_static(void * data,List * ent_list,const char * short_pathname,const char * filename)2089 clear_static (void *data, List *ent_list, const char *short_pathname,
2090               const char *filename)
2091 {
2092     if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
2093         error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
2094 }
2095 
2096 
2097 
2098 static void
handle_clear_static_directory(char * pathname,size_t len)2099 handle_clear_static_directory (char *pathname, size_t len)
2100 {
2101     if (!strcmp (cvs_cmd_name, "export"))
2102     {
2103 	/* Swallow the repository.  */
2104 	read_line (NULL);
2105 	return;
2106     }
2107 
2108     if (is_cvsroot_level (pathname))
2109     {
2110         /*
2111 	 * Top level (directory containing CVSROOT).  This seems to normally
2112 	 * lack a CVS directory, so don't try to create files in it.
2113 	 */
2114 	return;
2115     }
2116     call_in_directory (pathname, clear_static, NULL);
2117 }
2118 
2119 
2120 
2121 static void
set_sticky(void * data,List * ent_list,const char * short_pathname,const char * filename)2122 set_sticky (void *data, List *ent_list, const char *short_pathname,
2123 	    const char *filename)
2124 {
2125     char *tagspec;
2126     FILE *f;
2127 
2128     read_line (&tagspec);
2129 
2130     /* FIXME-update-dir: error messages should include the directory.  */
2131     f = CVS_FOPEN (CVSADM_TAG, "w+");
2132     if (!f)
2133     {
2134 	/* Making this non-fatal is a bit of a kludge (see dirs2
2135 	   in testsuite).  A better solution would be to avoid having
2136 	   the server tell us about a directory we shouldn't be doing
2137 	   anything with anyway (e.g. by handling directory
2138 	   addition/removal better).  */
2139 	error (0, errno, "cannot open %s", CVSADM_TAG);
2140 	free (tagspec);
2141 	return;
2142     }
2143     if (fprintf (f, "%s\n", tagspec) < 0)
2144 	error (1, errno, "writing %s", CVSADM_TAG);
2145     if (fclose (f) == EOF)
2146 	error (1, errno, "closing %s", CVSADM_TAG);
2147     free (tagspec);
2148 }
2149 
2150 
2151 
2152 static void
handle_set_sticky(char * pathname,size_t len)2153 handle_set_sticky (char *pathname, size_t len)
2154 {
2155     if (!strcmp (cvs_cmd_name, "export"))
2156     {
2157 	/* Swallow the repository.  */
2158 	read_line (NULL);
2159         /* Swallow the tag line.  */
2160 	read_line (NULL);
2161 	return;
2162     }
2163     if (is_cvsroot_level (pathname))
2164     {
2165         /*
2166 	 * Top level (directory containing CVSROOT).  This seems to normally
2167 	 * lack a CVS directory, so don't try to create files in it.
2168 	 */
2169 
2170 	/* Swallow the repository.  */
2171 	read_line (NULL);
2172         /* Swallow the tag line.  */
2173 	read_line (NULL);
2174 	return;
2175     }
2176 
2177     call_in_directory (pathname, set_sticky, NULL);
2178 }
2179 
2180 
2181 
2182 static void
clear_sticky(void * data,List * ent_list,const char * short_pathname,const char * filename)2183 clear_sticky (void *data, List *ent_list, const char *short_pathname,
2184               const char *filename)
2185 {
2186     if (unlink_file (CVSADM_TAG) < 0 && ! existence_error (errno))
2187 	error (1, errno, "cannot remove %s", CVSADM_TAG);
2188 }
2189 
2190 
2191 
2192 static void
handle_clear_sticky(char * pathname,size_t len)2193 handle_clear_sticky (char *pathname, size_t len)
2194 {
2195     if (!strcmp (cvs_cmd_name, "export"))
2196     {
2197 	/* Swallow the repository.  */
2198 	read_line (NULL);
2199 	return;
2200     }
2201 
2202     if (is_cvsroot_level (pathname))
2203     {
2204         /*
2205 	 * Top level (directory containing CVSROOT).  This seems to normally
2206 	 * lack a CVS directory, so don't try to create files in it.
2207 	 */
2208 	return;
2209     }
2210 
2211     call_in_directory (pathname, clear_sticky, NULL);
2212 }
2213 
2214 
2215 
2216 /* Handle the client-side support for a successful edit.
2217  */
2218 static void
handle_edit_file(char * pathname,size_t len)2219 handle_edit_file (char *pathname, size_t len)
2220 {
2221     call_in_directory (pathname, edit_file, NULL);
2222 }
2223 
2224 
2225 
2226 static void
template(void * data,List * ent_list,const char * short_pathname,const char * filename)2227 template (void *data, List *ent_list, const char *short_pathname,
2228 	  const char *filename)
2229 {
2230     char *buf = Xasprintf ("%s/%s", short_pathname, CVSADM_TEMPLATE);
2231     read_counted_file (CVSADM_TEMPLATE, buf);
2232     free (buf);
2233 }
2234 
2235 
2236 
2237 static void
handle_template(char * pathname,size_t len)2238 handle_template (char *pathname, size_t len)
2239 {
2240     call_in_directory (pathname, template, NULL);
2241 }
2242 
2243 
2244 
2245 static void
clear_template(void * data,List * ent_list,const char * short_pathname,const char * filename)2246 clear_template (void *data, List *ent_list, const char *short_pathname,
2247                 const char *filename)
2248 {
2249     if (unlink_file (CVSADM_TEMPLATE) < 0 && ! existence_error (errno))
2250 	error (1, errno, "cannot remove %s", CVSADM_TEMPLATE);
2251 }
2252 
2253 
2254 
2255 static void
handle_clear_template(char * pathname,size_t len)2256 handle_clear_template (char *pathname, size_t len)
2257 {
2258     call_in_directory (pathname, clear_template, NULL);
2259 }
2260 
2261 
2262 
2263 struct save_dir {
2264     char *dir;
2265     struct save_dir *next;
2266 };
2267 
2268 struct save_dir *prune_candidates;
2269 
2270 static void
add_prune_candidate(const char * dir)2271 add_prune_candidate (const char *dir)
2272 {
2273     struct save_dir *p;
2274 
2275     if ((dir[0] == '.' && dir[1] == '\0')
2276 	|| (prune_candidates && !strcmp (dir, prune_candidates->dir)))
2277 	return;
2278     p = xmalloc (sizeof (struct save_dir));
2279     p->dir = xstrdup (dir);
2280     p->next = prune_candidates;
2281     prune_candidates = p;
2282 }
2283 
2284 
2285 
2286 static void
process_prune_candidates(void)2287 process_prune_candidates (void)
2288 {
2289     struct save_dir *p;
2290     struct save_dir *q;
2291 
2292     processing = "prune";
2293     if (toplevel_wd)
2294     {
2295 	if (CVS_CHDIR (toplevel_wd) < 0)
2296 	    error (1, errno, "could not chdir to %s", toplevel_wd);
2297     }
2298     for (p = prune_candidates; p; )
2299     {
2300 	if (isemptydir (p->dir, 1))
2301 	{
2302 	    char *b;
2303 
2304 	    if (unlink_file_dir (p->dir) < 0)
2305 		error (0, errno, "cannot remove %s", p->dir);
2306 	    b = strrchr (p->dir, '/');
2307 	    if (!b)
2308 		Subdir_Deregister (NULL, NULL, p->dir);
2309 	    else
2310 	    {
2311 		*b = '\0';
2312 		Subdir_Deregister (NULL, p->dir, b + 1);
2313 	    }
2314 	}
2315 	free (p->dir);
2316 	q = p->next;
2317 	free (p);
2318 	p = q;
2319     }
2320     prune_candidates = NULL;
2321 }
2322 
2323 
2324 
2325 /* Send a Repository line.  */
2326 static char *last_repos;
2327 static char *last_update_dir;
2328 static void
send_repository(const char * dir,const char * repos,const char * update_dir)2329 send_repository (const char *dir, const char *repos, const char *update_dir)
2330 {
2331     char *adm_name;
2332 
2333     /* FIXME: this is probably not the best place to check; I wish I
2334      * knew where in here's callers to really trap this bug.  To
2335      * reproduce the bug, just do this:
2336      *
2337      *       mkdir junk
2338      *       cd junk
2339      *       cvs -d some_repos update foo
2340      *
2341      * Poof, CVS seg faults and dies!  It's because it's trying to
2342      * send a NULL string to the server but dies in send_to_server.
2343      * That string was supposed to be the repository, but it doesn't
2344      * get set because there's no CVSADM dir, and somehow it's not
2345      * getting set from the -d argument either... ?
2346      */
2347     if (!repos)
2348     {
2349         /* Lame error.  I want a real fix but can't stay up to track
2350            this down right now. */
2351         error (1, 0, "no repository");
2352     }
2353 
2354     if (!update_dir || update_dir[0] == '\0')
2355 	update_dir = ".";
2356 
2357     if (last_repos && !strcmp (repos, last_repos)
2358 	&& last_update_dir && !strcmp (update_dir, last_update_dir))
2359 	/* We've already sent it.  */
2360 	return;
2361 
2362     if (client_prune_dirs)
2363 	add_prune_candidate (update_dir);
2364 
2365     /* Add a directory name to the list of those sent to the
2366        server. */
2367     if (update_dir && *update_dir != '\0' && strcmp (update_dir, ".")
2368 	&& !findnode (dirs_sent_to_server, update_dir))
2369     {
2370 	Node *n;
2371 	n = getnode ();
2372 	n->type = NT_UNKNOWN;
2373 	n->key = xstrdup (update_dir);
2374 	n->data = NULL;
2375 
2376 	if (addnode (dirs_sent_to_server, n))
2377 	    error (1, 0, "cannot add directory %s to list", n->key);
2378     }
2379 
2380     /* 80 is large enough for any of CVSADM_*.  */
2381     adm_name = xmalloc (strlen (dir) + 80);
2382 
2383     send_to_server ("Directory ", 0);
2384     {
2385 	/* Send the directory name.  I know that this
2386 	   sort of duplicates code elsewhere, but each
2387 	   case seems slightly different...  */
2388 	char buf[1];
2389 	const char *p = update_dir;
2390 	while (*p != '\0')
2391 	{
2392 	    assert (*p != '\012');
2393 	    if (ISSLASH (*p))
2394 	    {
2395 		buf[0] = '/';
2396 		send_to_server (buf, 1);
2397 	    }
2398 	    else
2399 	    {
2400 		buf[0] = *p;
2401 		send_to_server (buf, 1);
2402 	    }
2403 	    ++p;
2404 	}
2405     }
2406     send_to_server ("\012", 1);
2407     if (supported_request ("Relative-directory"))
2408     {
2409 	const char *short_repos = Short_Repository (repos);
2410 	send_to_server (short_repos, 0);
2411     }
2412     else
2413 	send_to_server (repos, 0);
2414     send_to_server ("\012", 1);
2415 
2416     if (supported_request ("Static-directory"))
2417     {
2418 	adm_name[0] = '\0';
2419 	if (dir[0] != '\0')
2420 	{
2421 	    strcat (adm_name, dir);
2422 	    strcat (adm_name, "/");
2423 	}
2424 	strcat (adm_name, CVSADM_ENTSTAT);
2425 	if (isreadable (adm_name))
2426 	{
2427 	    send_to_server ("Static-directory\012", 0);
2428 	}
2429     }
2430     if (supported_request ("Sticky"))
2431     {
2432 	FILE *f;
2433 	if (dir[0] == '\0')
2434 	    strcpy (adm_name, CVSADM_TAG);
2435 	else
2436 	    sprintf (adm_name, "%s/%s", dir, CVSADM_TAG);
2437 
2438 	f = CVS_FOPEN (adm_name, "r");
2439 	if (!f)
2440 	{
2441 	    if (! existence_error (errno))
2442 		error (1, errno, "reading %s", adm_name);
2443 	}
2444 	else
2445 	{
2446 	    char line[80];
2447 	    char *nl = NULL;
2448 	    send_to_server ("Sticky ", 0);
2449 	    while (fgets (line, sizeof (line), f))
2450 	    {
2451 		send_to_server (line, 0);
2452 		nl = strchr (line, '\n');
2453 		if (nl)
2454 		    break;
2455 	    }
2456 	    if (!nl)
2457                 send_to_server ("\012", 1);
2458 	    if (fclose (f) == EOF)
2459 		error (0, errno, "closing %s", adm_name);
2460 	}
2461     }
2462     free (adm_name);
2463     if (last_repos) free (last_repos);
2464     if (last_update_dir) free (last_update_dir);
2465     last_repos = xstrdup (repos);
2466     last_update_dir = xstrdup (update_dir);
2467 }
2468 
2469 
2470 
2471 /* Send a Repository line and set toplevel_repos.  */
2472 void
send_a_repository(const char * dir,const char * repository,const char * update_dir_in)2473 send_a_repository (const char *dir, const char *repository,
2474                    const char *update_dir_in)
2475 {
2476     char *update_dir = xstrdup (update_dir_in);
2477 
2478     if (!toplevel_repos && repository)
2479     {
2480 	if (update_dir[0] == '\0'
2481 	    || (update_dir[0] == '.' && update_dir[1] == '\0'))
2482 	    toplevel_repos = xstrdup (repository);
2483 	else
2484 	{
2485 	    /*
2486 	     * Get the repository from a CVS/Repository file if update_dir
2487 	     * is absolute.  This is not correct in general, because
2488 	     * the CVS/Repository file might not be the top-level one.
2489 	     * This is for cases like "cvs update /foo/bar" (I'm not
2490 	     * sure it matters what toplevel_repos we get, but it does
2491 	     * matter that we don't hit the "internal error" code below).
2492 	     */
2493 	    if (update_dir[0] == '/')
2494 		toplevel_repos = Name_Repository (update_dir, update_dir);
2495 	    else
2496 	    {
2497 		/*
2498 		 * Guess the repository of that directory by looking at a
2499 		 * subdirectory and removing as many pathname components
2500 		 * as are in update_dir.  I think that will always (or at
2501 		 * least almost always) be 1.
2502 		 *
2503 		 * So this deals with directories which have been
2504 		 * renamed, though it doesn't necessarily deal with
2505 		 * directories which have been put inside other
2506 		 * directories (and cvs invoked on the containing
2507 		 * directory).  I'm not sure the latter case needs to
2508 		 * work.
2509 		 *
2510 		 * 21 Aug 1998: Well, Mr. Above-Comment-Writer, it
2511 		 * does need to work after all.  When we are using the
2512 		 * client in a multi-cvsroot environment, it will be
2513 		 * fairly common that we have the above case (e.g.,
2514 		 * cwd checked out from one repository but
2515 		 * subdirectory checked out from another).  We can't
2516 		 * assume that by walking up a directory in our wd we
2517 		 * necessarily walk up a directory in the repository.
2518 		 */
2519 		/*
2520 		 * This gets toplevel_repos wrong for "cvs update ../foo"
2521 		 * but I'm not sure toplevel_repos matters in that case.
2522 		 */
2523 
2524 		int repository_len, update_dir_len;
2525 
2526 		strip_trailing_slashes (update_dir);
2527 
2528 		repository_len = strlen (repository);
2529 		update_dir_len = strlen (update_dir);
2530 
2531 		/* Try to remove the path components in UPDATE_DIR
2532                    from REPOSITORY.  If the path elements don't exist
2533                    in REPOSITORY, or the removal of those path
2534                    elements mean that we "step above"
2535                    current_parsed_root->directory, set toplevel_repos to
2536                    current_parsed_root->directory. */
2537 		if (repository_len > update_dir_len
2538 		    && !strcmp (repository + repository_len - update_dir_len,
2539 				update_dir)
2540 		    /* TOPLEVEL_REPOS shouldn't be above current_parsed_root->directory */
2541 		    && ((size_t)(repository_len - update_dir_len)
2542 			> strlen (current_parsed_root->directory)))
2543 		{
2544 		    /* The repository name contains UPDATE_DIR.  Set
2545                        toplevel_repos to the repository name without
2546                        UPDATE_DIR. */
2547 
2548 		    toplevel_repos = xmalloc (repository_len - update_dir_len);
2549 		    /* Note that we don't copy the trailing '/'.  */
2550 		    strncpy (toplevel_repos, repository,
2551 			     repository_len - update_dir_len - 1);
2552 		    toplevel_repos[repository_len - update_dir_len - 1] = '\0';
2553 		}
2554 		else
2555 		{
2556 		    toplevel_repos = xstrdup (current_parsed_root->directory);
2557 		}
2558 	    }
2559 	}
2560     }
2561 
2562     send_repository (dir, repository, update_dir);
2563     free (update_dir);
2564 }
2565 
2566 
2567 
2568 static void
notified_a_file(void * data,List * ent_list,const char * short_pathname,const char * filename)2569 notified_a_file (void *data, List *ent_list, const char *short_pathname,
2570                  const char *filename)
2571 {
2572     FILE *fp;
2573     FILE *newf;
2574     size_t line_len = 8192;
2575     char *line = xmalloc (line_len);
2576     char *cp;
2577     int nread;
2578     int nwritten;
2579     char *p;
2580 
2581     fp = xfopen (CVSADM_NOTIFY, "r");
2582     if (getline (&line, &line_len, fp) < 0)
2583     {
2584 	if (feof (fp))
2585 	    error (0, 0, "cannot read %s: end of file", CVSADM_NOTIFY);
2586 	else
2587 	    error (0, errno, "cannot read %s", CVSADM_NOTIFY);
2588 	goto error_exit;
2589     }
2590     cp = strchr (line, '\t');
2591     if (!cp)
2592     {
2593 	error (0, 0, "malformed %s file", CVSADM_NOTIFY);
2594 	goto error_exit;
2595     }
2596     *cp = '\0';
2597     if (strcmp (filename, line + 1))
2598 	error (0, 0, "protocol error: notified %s, expected %s", filename,
2599 	       line + 1);
2600 
2601     if (getline (&line, &line_len, fp) < 0)
2602     {
2603 	if (feof (fp))
2604 	{
2605 	    free (line);
2606 	    if (fclose (fp) < 0)
2607 		error (0, errno, "cannot close %s", CVSADM_NOTIFY);
2608 	    if ( CVS_UNLINK (CVSADM_NOTIFY) < 0)
2609 		error (0, errno, "cannot remove %s", CVSADM_NOTIFY);
2610 	    return;
2611 	}
2612 	else
2613 	{
2614 	    error (0, errno, "cannot read %s", CVSADM_NOTIFY);
2615 	    goto error_exit;
2616 	}
2617     }
2618     newf = xfopen (CVSADM_NOTIFYTMP, "w");
2619     if (fputs (line, newf) < 0)
2620     {
2621 	error (0, errno, "cannot write %s", CVSADM_NOTIFYTMP);
2622 	goto error2;
2623     }
2624     while ((nread = fread (line, 1, line_len, fp)) > 0)
2625     {
2626 	p = line;
2627 	while ((nwritten = fwrite (p, sizeof *p, nread, newf)) > 0)
2628 	{
2629 	    nread -= nwritten;
2630 	    p += nwritten;
2631 	}
2632 	if (ferror (newf))
2633 	{
2634 	    error (0, errno, "cannot write %s", CVSADM_NOTIFYTMP);
2635 	    goto error2;
2636 	}
2637     }
2638     if (ferror (fp))
2639     {
2640 	error (0, errno, "cannot read %s", CVSADM_NOTIFY);
2641 	goto error2;
2642     }
2643     if (fclose (newf) < 0)
2644     {
2645 	error (0, errno, "cannot close %s", CVSADM_NOTIFYTMP);
2646 	goto error_exit;
2647     }
2648     free (line);
2649     if (fclose (fp) < 0)
2650     {
2651 	error (0, errno, "cannot close %s", CVSADM_NOTIFY);
2652 	return;
2653     }
2654 
2655     {
2656         /* In this case, we want rename_file() to ignore noexec. */
2657         int saved_noexec = noexec;
2658         noexec = 0;
2659         rename_file (CVSADM_NOTIFYTMP, CVSADM_NOTIFY);
2660         noexec = saved_noexec;
2661     }
2662 
2663     return;
2664   error2:
2665     (void)fclose (newf);
2666   error_exit:
2667     free (line);
2668     (void)fclose (fp);
2669 }
2670 
2671 
2672 
2673 static void
handle_notified(char * args,size_t len)2674 handle_notified (char *args, size_t len)
2675 {
2676     call_in_directory (args, notified_a_file, NULL);
2677 }
2678 
2679 
2680 
2681 /* The "expanded" modules.  */
2682 static int modules_count;
2683 static int modules_allocated;
2684 static char **modules_vector;
2685 
2686 static void
handle_module_expansion(char * args,size_t len)2687 handle_module_expansion (char *args, size_t len)
2688 {
2689     if (!modules_vector)
2690     {
2691 	modules_allocated = 1; /* Small for testing */
2692 	modules_vector = xnmalloc (modules_allocated,
2693 				   sizeof (modules_vector[0]));
2694     }
2695     else if (modules_count >= modules_allocated)
2696     {
2697 	modules_allocated *= 2;
2698 	modules_vector = xnrealloc (modules_vector,
2699 				    modules_allocated,
2700 				    sizeof (modules_vector[0]));
2701     }
2702     modules_vector[modules_count] = xstrdup (args);
2703     ++modules_count;
2704 }
2705 
2706 
2707 
2708 /* Original, not "expanded" modules.  */
2709 static int module_argc;
2710 static char **module_argv;
2711 
2712 void
client_expand_modules(int argc,char ** argv,int local)2713 client_expand_modules (int argc, char **argv, int local)
2714 {
2715     int errs;
2716     int i;
2717 
2718     module_argc = argc;
2719     module_argv = xnmalloc (argc + 1, sizeof (module_argv[0]));
2720     for (i = 0; i < argc; ++i)
2721 	module_argv[i] = xstrdup (argv[i]);
2722     module_argv[argc] = NULL;
2723 
2724     for (i = 0; i < argc; ++i)
2725 	send_arg (argv[i]);
2726     send_a_repository ("", current_parsed_root->directory, "");
2727 
2728     send_to_server ("expand-modules\012", 0);
2729 
2730     errs = get_server_responses ();
2731 
2732     if (last_repos) free (last_repos);
2733     last_repos = NULL;
2734 
2735     if (last_update_dir) free (last_update_dir);
2736     last_update_dir = NULL;
2737 
2738     if (errs)
2739 	error (errs, 0, "cannot expand modules");
2740 }
2741 
2742 
2743 
2744 void
client_send_expansions(int local,char * where,int build_dirs)2745 client_send_expansions (int local, char *where, int build_dirs)
2746 {
2747     int i;
2748     char *argv[1];
2749 
2750     /* Send the original module names.  The "expanded" module name might
2751        not be suitable as an argument to a co request (e.g. it might be
2752        the result of a -d argument in the modules file).  It might be
2753        cleaner if we genuinely expanded module names, all the way to a
2754        local directory and repository, but that isn't the way it works
2755        now.  */
2756     send_file_names (module_argc, module_argv, 0);
2757 
2758     for (i = 0; i < modules_count; ++i)
2759     {
2760 	argv[0] = where ? where : modules_vector[i];
2761 	if (isfile (argv[0]))
2762 	    send_files (1, argv, local, 0, build_dirs ? SEND_BUILD_DIRS : 0);
2763     }
2764     send_a_repository ("", current_parsed_root->directory, "");
2765 }
2766 
2767 
2768 
2769 void
client_nonexpanded_setup(void)2770 client_nonexpanded_setup (void)
2771 {
2772     send_a_repository ("", current_parsed_root->directory, "");
2773 }
2774 
2775 
2776 
2777 /* Receive a cvswrappers line from the server; it must be a line
2778    containing an RCS option (e.g., "*.exe   -k 'b'").
2779 
2780    Note that this doesn't try to handle -t/-f options (which are a
2781    whole separate issue which noone has thought much about, as far
2782    as I know).
2783 
2784    We need to know the keyword expansion mode so we know whether to
2785    read the file in text or binary mode.  */
2786 static void
handle_wrapper_rcs_option(char * args,size_t len)2787 handle_wrapper_rcs_option (char *args, size_t len)
2788 {
2789     char *p;
2790 
2791     /* Enforce the notes in cvsclient.texi about how the response is not
2792        as free-form as it looks.  */
2793     p = strchr (args, ' ');
2794     if (!p)
2795 	goto handle_error;
2796     if (*++p != '-'
2797 	|| *++p != 'k'
2798 	|| *++p != ' '
2799 	|| *++p != '\'')
2800 	goto handle_error;
2801     if (!strchr (p, '\''))
2802 	goto handle_error;
2803 
2804     /* Add server-side cvswrappers line to our wrapper list. */
2805     wrap_add (args, 0);
2806     return;
2807  handle_error:
2808     error (0, errno, "protocol error: ignoring invalid wrappers %s", args);
2809 }
2810 
2811 
2812 
2813 
2814 static void
handle_m(char * args,size_t len)2815 handle_m (char *args, size_t len)
2816 {
2817     /* In the case where stdout and stderr point to the same place,
2818        fflushing stderr will make output happen in the correct order.
2819        Often stderr will be line-buffered and this won't be needed,
2820        but not always (is that true?  I think the comment is probably
2821        based on being confused between default buffering between
2822        stdout and stderr.  But I'm not sure).  */
2823     fflush (stderr);
2824     fwrite (args, sizeof *args, len, stdout);
2825     putc ('\n', stdout);
2826 }
2827 
2828 
2829 
2830 static void
handle_mbinary(char * args,size_t len)2831 handle_mbinary (char *args, size_t len)
2832 {
2833     char *size_string;
2834     size_t size;
2835     size_t totalread;
2836     size_t nread;
2837     size_t toread;
2838     char buf[8192];
2839 
2840     /* See comment at handle_m about (non)flush of stderr.  */
2841 
2842     /* Get the size.  */
2843     read_line (&size_string);
2844     size = atoi (size_string);
2845     free (size_string);
2846 
2847     /* OK, now get all the data.  The algorithm here is that we read
2848        as much as the network wants to give us in
2849        try_read_from_server, and then we output it all, and then
2850        repeat, until we get all the data.  */
2851     totalread = 0;
2852     while (totalread < size)
2853     {
2854 	toread = size - totalread;
2855 	if (toread > sizeof buf)
2856 	    toread = sizeof buf;
2857 
2858 	nread = try_read_from_server (buf, toread);
2859 	cvs_output_binary (buf, nread);
2860 	totalread += nread;
2861     }
2862 }
2863 
2864 
2865 
2866 static void
handle_e(char * args,size_t len)2867 handle_e (char *args, size_t len)
2868 {
2869     /* In the case where stdout and stderr point to the same place,
2870        fflushing stdout will make output happen in the correct order.  */
2871     fflush (stdout);
2872     fwrite (args, sizeof *args, len, stderr);
2873     putc ('\n', stderr);
2874 }
2875 
2876 
2877 
2878 /*ARGSUSED*/
2879 static void
handle_f(char * args,size_t len)2880 handle_f  (char *args, size_t len)
2881 {
2882     fflush (stderr);
2883 }
2884 
2885 
2886 
2887 static void
handle_mt(char * args,size_t len)2888 handle_mt (char *args, size_t len)
2889 {
2890     char *p;
2891     char *tag = args;
2892     char *text;
2893 
2894     /* See comment at handle_m for more details.  */
2895     fflush (stderr);
2896 
2897     p = strchr (args, ' ');
2898     if (!p)
2899 	text = NULL;
2900     else
2901     {
2902 	*p++ = '\0';
2903 	text = p;
2904     }
2905 
2906     switch (tag[0])
2907     {
2908 	case '+':
2909 	    if (!strcmp (tag, "+updated"))
2910 		updated_seen = 1;
2911 	    else if (!strcmp (tag, "+importmergecmd"))
2912 		importmergecmd.seen = 1;
2913 	    break;
2914 	case '-':
2915 	    if (!strcmp (tag, "-updated"))
2916 		updated_seen = 0;
2917 	    else if (!strcmp (tag, "-importmergecmd"))
2918 	    {
2919 		char buf[80];
2920 
2921 		/* Now that we have gathered the information, we can
2922                    output the suggested merge command.  */
2923 
2924 		if (importmergecmd.conflicts == 0
2925 		    || !importmergecmd.mergetag1
2926 		    || !importmergecmd.mergetag2
2927 		    || !importmergecmd.repository)
2928 		{
2929 		    error (0, 0,
2930 			   "invalid server: incomplete importmergecmd tags");
2931 		    break;
2932 		}
2933 
2934 		if (importmergecmd.conflicts == -1)
2935  		    sprintf (buf, "\nNo conflicts created by this import.\n");
2936 		else
2937 		    sprintf (buf, "\n%d conflicts created by this import.\n",
2938 			     importmergecmd.conflicts);
2939 		cvs_output (buf, 0);
2940 		cvs_output ("Use the following command to help the merge:\n\n",
2941 			    0);
2942 		cvs_output ("\t", 1);
2943 		cvs_output (program_name, 0);
2944 		if (CVSroot_cmdline)
2945 		{
2946 		    cvs_output (" -d ", 0);
2947 		    cvs_output (CVSroot_cmdline, 0);
2948 		}
2949 		cvs_output (" checkout -j", 0);
2950 		cvs_output (importmergecmd.mergetag1, 0);
2951 		cvs_output (" -j", 0);
2952 		cvs_output (importmergecmd.mergetag2, 0);
2953 		cvs_output (" ", 1);
2954 		cvs_output (importmergecmd.repository, 0);
2955 		cvs_output ("\n\n", 0);
2956 
2957 		/* Clear the static variables so that everything is
2958                    ready for any subsequent importmergecmd tag.  */
2959 		importmergecmd.conflicts = 0;
2960 		free (importmergecmd.mergetag1);
2961 		importmergecmd.mergetag1 = NULL;
2962 		free (importmergecmd.mergetag2);
2963 		importmergecmd.mergetag2 = NULL;
2964 		free (importmergecmd.repository);
2965 		importmergecmd.repository = NULL;
2966 
2967 		importmergecmd.seen = 0;
2968 	    }
2969 	    break;
2970 	default:
2971 	    if (updated_seen)
2972 	    {
2973 		if (!strcmp (tag, "fname"))
2974 		{
2975 		    if (updated_fname)
2976 		    {
2977 			/* Output the previous message now.  This can happen
2978 			   if there was no Update-existing or other such
2979 			   response, due to the -n global option.  */
2980 			cvs_output ("U ", 0);
2981 			cvs_output (updated_fname, 0);
2982 			cvs_output ("\n", 1);
2983 			free (updated_fname);
2984 		    }
2985 		    updated_fname = xstrdup (text);
2986 		}
2987 		/* Swallow all other tags.  Either they are extraneous
2988 		   or they reflect future extensions that we can
2989 		   safely ignore.  */
2990 	    }
2991 	    else if (importmergecmd.seen)
2992 	    {
2993 		if (!strcmp (tag, "conflicts"))
2994 		{
2995 		    if (!strcmp (text, "No"))
2996 			importmergecmd.conflicts = -1;
2997 		    else
2998 			importmergecmd.conflicts = atoi (text);
2999 		}
3000 		else if (!strcmp (tag, "mergetag1"))
3001 		    importmergecmd.mergetag1 = xstrdup (text);
3002 		else if (!strcmp (tag, "mergetag2"))
3003 		    importmergecmd.mergetag2 = xstrdup (text);
3004 		else if (!strcmp (tag, "repository"))
3005 		    importmergecmd.repository = xstrdup (text);
3006 		/* Swallow all other tags.  Either they are text for
3007                    which we are going to print our own version when we
3008                    see -importmergecmd, or they are future extensions
3009                    we can safely ignore.  */
3010 	    }
3011 	    else if (!strcmp (tag, "newline"))
3012 		printf ("\n");
3013 	    else if (!strcmp (tag, "date"))
3014 	    {
3015 		char *date = format_date_alloc (text);
3016 		printf ("%s", date);
3017 		free (date);
3018 	    }
3019 	    else if (text)
3020 		printf ("%s", text);
3021     }
3022 }
3023 
3024 
3025 
3026 #endif /* CLIENT_SUPPORT */
3027 #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
3028 
3029 /* This table must be writeable if the server code is included.  */
3030 struct response responses[] =
3031 {
3032 #ifdef CLIENT_SUPPORT
3033 #define RSP_LINE(n, f, t, s) {n, f, t, s}
3034 #else /* ! CLIENT_SUPPORT */
3035 #define RSP_LINE(n, f, t, s) {n, s}
3036 #endif /* CLIENT_SUPPORT */
3037 
3038     RSP_LINE("ok", handle_ok, response_type_ok, rs_essential),
3039     RSP_LINE("error", handle_error, response_type_error, rs_essential),
3040     RSP_LINE("Valid-requests", handle_valid_requests, response_type_normal,
3041        rs_essential),
3042     RSP_LINE("Force-gzip", handle_force_gzip, response_type_normal,
3043        rs_optional),
3044     RSP_LINE("Referrer", handle_referrer, response_type_normal, rs_optional),
3045     RSP_LINE("Redirect", handle_redirect, response_type_redirect, rs_optional),
3046     RSP_LINE("Checked-in", handle_checked_in, response_type_normal,
3047        rs_essential),
3048     RSP_LINE("New-entry", handle_new_entry, response_type_normal, rs_optional),
3049     RSP_LINE("Checksum", handle_checksum, response_type_normal, rs_optional),
3050     RSP_LINE("Copy-file", handle_copy_file, response_type_normal, rs_optional),
3051     RSP_LINE("Updated", handle_updated, response_type_normal, rs_essential),
3052     RSP_LINE("Created", handle_created, response_type_normal, rs_optional),
3053     RSP_LINE("Update-existing", handle_update_existing, response_type_normal,
3054        rs_optional),
3055     RSP_LINE("Merged", handle_merged, response_type_normal, rs_essential),
3056     RSP_LINE("Patched", handle_patched, response_type_normal, rs_optional),
3057     RSP_LINE("Rcs-diff", handle_rcs_diff, response_type_normal, rs_optional),
3058     RSP_LINE("Mode", handle_mode, response_type_normal, rs_optional),
3059     RSP_LINE("Mod-time", handle_mod_time, response_type_normal, rs_optional),
3060     RSP_LINE("Removed", handle_removed, response_type_normal, rs_essential),
3061     RSP_LINE("Remove-entry", handle_remove_entry, response_type_normal,
3062        rs_optional),
3063     RSP_LINE("Set-static-directory", handle_set_static_directory,
3064        response_type_normal,
3065        rs_optional),
3066     RSP_LINE("Clear-static-directory", handle_clear_static_directory,
3067        response_type_normal,
3068        rs_optional),
3069     RSP_LINE("Set-sticky", handle_set_sticky, response_type_normal,
3070        rs_optional),
3071     RSP_LINE("Clear-sticky", handle_clear_sticky, response_type_normal,
3072        rs_optional),
3073     RSP_LINE("Edit-file", handle_edit_file, response_type_normal,
3074        rs_optional),
3075     RSP_LINE("Template", handle_template, response_type_normal,
3076        rs_optional),
3077     RSP_LINE("Clear-template", handle_clear_template, response_type_normal,
3078        rs_optional),
3079     RSP_LINE("Notified", handle_notified, response_type_normal, rs_optional),
3080     RSP_LINE("Module-expansion", handle_module_expansion, response_type_normal,
3081        rs_optional),
3082     RSP_LINE("Wrapper-rcsOption", handle_wrapper_rcs_option,
3083        response_type_normal,
3084        rs_optional),
3085     RSP_LINE("M", handle_m, response_type_normal, rs_essential),
3086     RSP_LINE("Mbinary", handle_mbinary, response_type_normal, rs_optional),
3087     RSP_LINE("E", handle_e, response_type_normal, rs_essential),
3088     RSP_LINE("F", handle_f, response_type_normal, rs_optional),
3089     RSP_LINE("MT", handle_mt, response_type_normal, rs_optional),
3090     /* Possibly should be response_type_error.  */
3091     RSP_LINE(NULL, NULL, response_type_normal, rs_essential)
3092 
3093 #undef RSP_LINE
3094 };
3095 
3096 #endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
3097 #ifdef CLIENT_SUPPORT
3098 
3099 
3100 
3101 /*
3102  * If LEN is 0, then send_to_server_via() computes string's length itself.
3103  *
3104  * Therefore, pass the real length when transmitting data that might
3105  * contain 0's.
3106  */
3107 void
send_to_server_via(struct buffer * via_buffer,const char * str,size_t len)3108 send_to_server_via (struct buffer *via_buffer, const char *str, size_t len)
3109 {
3110     static int nbytes;
3111 
3112     if (len == 0)
3113 	len = strlen (str);
3114 
3115     buf_output (via_buffer, str, len);
3116 
3117     /* There is no reason not to send data to the server, so do it
3118        whenever we've accumulated enough information in the buffer to
3119        make it worth sending.  */
3120     nbytes += len;
3121     if (nbytes >= 2 * BUFFER_DATA_SIZE)
3122     {
3123 	int status;
3124 
3125         status = buf_send_output (via_buffer);
3126 	if (status != 0)
3127 	    error (1, status, "error writing to server");
3128 	nbytes = 0;
3129     }
3130 }
3131 
3132 
3133 
3134 void
send_to_server(const char * str,size_t len)3135 send_to_server (const char *str, size_t len)
3136 {
3137   send_to_server_via (global_to_server, str, len);
3138 }
3139 
3140 
3141 
3142 /* Read up to LEN bytes from the server.  Returns actual number of
3143    bytes read, which will always be at least one; blocks if there is
3144    no data available at all.  Gives a fatal error on EOF or error.  */
3145 static size_t
try_read_from_server(char * buf,size_t len)3146 try_read_from_server( char *buf, size_t len )
3147 {
3148     int status;
3149     size_t nread;
3150     char *data;
3151 
3152     status = buf_read_data (global_from_server, len, &data, &nread);
3153     if (status != 0)
3154     {
3155 	if (status == -1)
3156 	    error (1, 0,
3157 		   "end of file from server (consult above messages if any)");
3158 	else if (status == -2)
3159 	    error (1, 0, "out of memory");
3160 	else
3161 	    error (1, status, "reading from server");
3162     }
3163 
3164     memcpy (buf, data, nread);
3165 
3166     return nread;
3167 }
3168 
3169 
3170 
3171 /*
3172  * Read LEN bytes from the server or die trying.
3173  */
3174 void
read_from_server(char * buf,size_t len)3175 read_from_server (char *buf, size_t len)
3176 {
3177     size_t red = 0;
3178     while (red < len)
3179     {
3180 	red += try_read_from_server (buf + red, len - red);
3181 	if (red == len)
3182 	    break;
3183     }
3184 }
3185 
3186 
3187 
3188 /* Get some server responses and process them.
3189  *
3190  * RETURNS
3191  *   0		Success
3192  *   1		Error
3193  *   2		Redirect
3194  */
3195 int
get_server_responses(void)3196 get_server_responses (void)
3197 {
3198     struct response *rs;
3199     do
3200     {
3201 	char *cmd;
3202 	size_t len;
3203 
3204 	len = read_line (&cmd);
3205 	for (rs = responses; rs->name; ++rs)
3206 	    if (!strncmp (cmd, rs->name, strlen (rs->name)))
3207 	    {
3208 		size_t cmdlen = strlen (rs->name);
3209 		if (cmd[cmdlen] == '\0')
3210 		    ;
3211 		else if (cmd[cmdlen] == ' ')
3212 		    ++cmdlen;
3213 		else
3214 		    /*
3215 		     * The first len characters match, but it's a different
3216 		     * response.  e.g. the response is "oklahoma" but we
3217 		     * matched "ok".
3218 		     */
3219 		    continue;
3220 		(*rs->func) (cmd + cmdlen, len - cmdlen);
3221 		break;
3222 	    }
3223 	if (!rs->name)
3224 	    /* It's OK to print just to the first '\0'.  */
3225 	    /* We might want to handle control characters and the like
3226 	       in some other way other than just sending them to stdout.
3227 	       One common reason for this error is if people use :ext:
3228 	       with a version of rsh which is doing CRLF translation or
3229 	       something, and so the client gets "ok^M" instead of "ok".
3230 	       Right now that will tend to print part of this error
3231 	       message over the other part of it.  It seems like we could
3232 	       do better (either in general, by quoting or omitting all
3233 	       control characters, and/or specifically, by detecting the CRLF
3234 	       case and printing a specific error message).  */
3235 	    error (0, 0,
3236 		   "warning: unrecognized response `%s' from cvs server",
3237 		   cmd);
3238 	free (cmd);
3239     } while (rs->type == response_type_normal);
3240 
3241     if (updated_fname)
3242     {
3243 	/* Output the previous message now.  This can happen
3244 	   if there was no Update-existing or other such
3245 	   response, due to the -n global option.  */
3246 	cvs_output ("U ", 0);
3247 	cvs_output (updated_fname, 0);
3248 	cvs_output ("\n", 1);
3249 	free (updated_fname);
3250 	updated_fname = NULL;
3251     }
3252 
3253     if (rs->type == response_type_redirect) return 2;
3254     if (rs->type == response_type_error) return 1;
3255     if (failure_exit) return 1;
3256     return 0;
3257 }
3258 
3259 
3260 
3261 static inline void
close_connection_to_server(struct buffer ** to,struct buffer ** from)3262 close_connection_to_server (struct buffer **to, struct buffer **from)
3263 {
3264     int status;
3265 
3266     /* First we shut down GLOBAL_TO_SERVER.  That tells the server that its
3267      * input is finished.  It then shuts down the buffer it is sending to us,
3268      * at which point our shut down of GLOBAL_FROM_SERVER will complete.
3269      */
3270 
3271     TRACE (TRACE_FUNCTION, "close_connection_to_server ()");
3272 
3273     status = buf_shutdown (*to);
3274     if (status != 0)
3275 	error (0, status, "shutting down buffer to server");
3276     buf_free (*to);
3277     *to = NULL;
3278 
3279     status = buf_shutdown (*from);
3280     if (status != 0)
3281 	error (0, status, "shutting down buffer from server");
3282     buf_free (*from);
3283     *from = NULL;
3284 }
3285 
3286 
3287 
3288 /* Get the responses and then close the connection.  */
3289 
3290 /*
3291  * Flag var; we'll set it in start_server() and not one of its
3292  * callees, such as start_rsh_server().  This means that there might
3293  * be a small window between the starting of the server and the
3294  * setting of this var, but all the code in that window shouldn't care
3295  * because it's busy checking return values to see if the server got
3296  * started successfully anyway.
3297  */
3298 int server_started = 0;
3299 
3300 int
get_responses_and_close(void)3301 get_responses_and_close (void)
3302 {
3303     int errs = get_server_responses ();
3304 
3305     /* The following is necessary when working with multiple cvsroots, at least
3306      * with commit.  It used to be buried nicely in do_deferred_progs() before
3307      * that function was removed.  I suspect it wouldn't be necessary if
3308      * call_in_directory() saved its working directory via save_cwd() before
3309      * changing its directory and restored the saved working directory via
3310      * restore_cwd() before exiting.  Of course, calling CVS_CHDIR only once,
3311      * here, may be more efficient.
3312      */
3313     if (toplevel_wd)
3314     {
3315 	if (CVS_CHDIR (toplevel_wd) < 0)
3316 	    error (1, errno, "could not chdir to %s", toplevel_wd);
3317     }
3318 
3319     if (client_prune_dirs)
3320 	process_prune_candidates ();
3321 
3322     close_connection_to_server (&global_to_server, &global_from_server);
3323     server_started = 0;
3324 
3325     /* see if we need to sleep before returning to avoid time-stamp races */
3326     if (last_register_time)
3327 	sleep_past (last_register_time);
3328 
3329     return errs;
3330 }
3331 
3332 
3333 
3334 bool
supported_request(const char * name)3335 supported_request (const char *name)
3336 {
3337     struct request *rq;
3338 
3339     for (rq = requests; rq->name; rq++)
3340 	if (!strcmp (rq->name, name))
3341 	    return (rq->flags & RQ_SUPPORTED) != 0;
3342     error (1, 0, "internal error: testing support for unknown request?");
3343     /* NOTREACHED */
3344     return 0;
3345 }
3346 
3347 
3348 
3349 #if defined (AUTH_CLIENT_SUPPORT) || defined (SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
3350 
3351 
3352 /* Generic function to do port number lookup tasks.
3353  *
3354  * In order of precedence, will return:
3355  * 	getenv (envname), if defined
3356  * 	getservbyname (portname), if defined
3357  * 	defaultport
3358  */
3359 static int
get_port_number(const char * envname,const char * portname,int defaultport)3360 get_port_number (const char *envname, const char *portname, int defaultport)
3361 {
3362     struct servent *s;
3363     char *port_s;
3364 
3365     if (envname && (port_s = getenv (envname)))
3366     {
3367 	int port = atoi (port_s);
3368 	if (port <= 0)
3369 	{
3370 	    error (0, 0, "%s must be a positive integer!  If you", envname);
3371 	    error (0, 0, "are trying to force a connection via rsh, please");
3372 	    error (0, 0, "put \":server:\" at the beginning of your CVSROOT");
3373 	    error (1, 0, "variable.");
3374 	}
3375 	return port;
3376     }
3377     else if (portname && (s = getservbyname (portname, "tcp")))
3378 	return ntohs (s->s_port);
3379     else
3380 	return defaultport;
3381 }
3382 
3383 
3384 
3385 /* get the port number for a client to connect to based on the port
3386  * and method of a cvsroot_t.
3387  *
3388  * we do this here instead of in parse_cvsroot so that we can keep network
3389  * code confined to a localized area and also to delay the lookup until the
3390  * last possible moment so it remains possible to run cvs client commands that
3391  * skip opening connections to the server (i.e. skip network operations
3392  * entirely)
3393  *
3394  * and yes, I know none of the commands do that now, but here's to planning
3395  * for the future, eh?  cheers.
3396  */
3397 int
get_cvs_port_number(const cvsroot_t * root)3398 get_cvs_port_number (const cvsroot_t *root)
3399 {
3400 
3401     if (root->port) return root->port;
3402 
3403     switch (root->method)
3404     {
3405 # ifdef HAVE_GSSAPI
3406 	case gserver_method:
3407 # endif /* HAVE_GSSAPI */
3408 # ifdef AUTH_CLIENT_SUPPORT
3409 	case pserver_method:
3410 # endif /* AUTH_CLIENT_SUPPORT */
3411 # if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_GSSAPI)
3412 	    return get_port_number ("CVS_CLIENT_PORT", "cvspserver",
3413                                     CVS_AUTH_PORT);
3414 # endif /* defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_GSSAPI) */
3415 # ifdef HAVE_KERBEROS
3416 	case kserver_method:
3417 	    return get_port_number ("CVS_CLIENT_PORT", "cvs", CVS_PORT);
3418 # endif /* HAVE_KERBEROS */
3419 	default:
3420 	    error(1, EINVAL,
3421 "internal error: get_cvs_port_number called for invalid connection method (%s)",
3422 		  method_names[root->method]);
3423 	    break;
3424     }
3425     /* NOTREACHED */
3426     return -1;
3427 }
3428 
3429 
3430 
3431 /* get the port number for a client to connect to based on the proxy port
3432  * of a cvsroot_t.
3433  */
3434 static int
get_proxy_port_number(const cvsroot_t * root)3435 get_proxy_port_number (const cvsroot_t *root)
3436 {
3437 
3438     if (root->proxy_port) return root->proxy_port;
3439 
3440     return get_port_number ("CVS_PROXY_PORT", NULL, CVS_PROXY_PORT);
3441 }
3442 
3443 
3444 
3445 void
make_bufs_from_fds(int tofd,int fromfd,int child_pid,cvsroot_t * root,struct buffer ** to_server_p,struct buffer ** from_server_p,int is_sock)3446 make_bufs_from_fds(int tofd, int fromfd, int child_pid, cvsroot_t *root,
3447                    struct buffer **to_server_p,
3448                    struct buffer **from_server_p, int is_sock)
3449 {
3450 # ifdef NO_SOCKET_TO_FD
3451     if (is_sock)
3452     {
3453 	assert (tofd == fromfd);
3454 	*to_server_p = socket_buffer_initialize (tofd, 0, NULL);
3455 	*from_server_p = socket_buffer_initialize (tofd, 1, NULL);
3456     }
3457     else
3458 # endif /* NO_SOCKET_TO_FD */
3459     {
3460 	/* todo: some OS's don't need these calls... */
3461 	close_on_exec (tofd);
3462 	close_on_exec (fromfd);
3463 
3464 	/* SCO 3 and AIX have a nasty bug in the I/O libraries which precludes
3465 	   fdopening the same file descriptor twice, so dup it if it is the
3466 	   same.  */
3467 	if (tofd == fromfd)
3468 	{
3469 	    fromfd = dup (tofd);
3470 	    if (fromfd < 0)
3471 		error (1, errno, "cannot dup net connection");
3472 	}
3473 
3474 	/* These will use binary mode on systems which have it.  */
3475 	/*
3476 	 * Also, we know that from_server is shut down second, so we pass
3477 	 * child_pid in there.  In theory, it should be stored in both
3478 	 * buffers with a ref count...
3479 	 */
3480 	*to_server_p = fd_buffer_initialize (tofd, 0, root, false, NULL);
3481 	*from_server_p = fd_buffer_initialize (fromfd, child_pid, root,
3482                                                true, NULL);
3483     }
3484 }
3485 #endif /* defined (AUTH_CLIENT_SUPPORT) || defined (SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined(HAVE_GSSAPI) */
3486 
3487 
3488 
3489 #if defined (AUTH_CLIENT_SUPPORT) || defined(HAVE_GSSAPI)
3490 /* Connect to the authenticating server.
3491 
3492    If VERIFY_ONLY is non-zero, then just verify that the password is
3493    correct and then shutdown the connection.
3494 
3495    If VERIFY_ONLY is 0, then really connect to the server.
3496 
3497    If DO_GSSAPI is non-zero, then we use GSSAPI authentication rather
3498    than the pserver password authentication.
3499 
3500    If we fail to connect or if access is denied, then die with fatal
3501    error.  */
3502 void
connect_to_pserver(cvsroot_t * root,struct buffer ** to_server_p,struct buffer ** from_server_p,int verify_only,int do_gssapi)3503 connect_to_pserver (cvsroot_t *root, struct buffer **to_server_p,
3504                     struct buffer **from_server_p, int verify_only,
3505                     int do_gssapi)
3506 {
3507     int sock;
3508     int port_number,
3509 	proxy_port_number = 0; /* Initialize to silence -Wall.  Dumb.  */
3510     char no_passwd = 0;   /* gets set if no password found */
3511     struct buffer *to_server, *from_server;
3512 
3513     port_number = get_cvs_port_number (root);
3514 
3515     /* if we have a proxy connect to that instead */
3516     if (root->proxy_hostname)
3517     {
3518         TRACE (TRACE_FUNCTION, "Connecting to %s:%d via proxy %s:%d.",
3519                root->hostname, port_number, root->proxy_hostname,
3520 	       proxy_port_number);
3521         proxy_port_number = get_proxy_port_number (root);
3522 	sock = connect_to(root->proxy_hostname, proxy_port_number);
3523     }
3524     else
3525     {
3526         TRACE (TRACE_FUNCTION, "Connecting to %s:%d.",
3527                root->hostname, port_number);
3528 	sock = connect_to(root->hostname, port_number);
3529     }
3530 
3531     if (sock == -1)
3532 	error (1, 0, "connect to %s:%d failed: %s",
3533 	       root->proxy_hostname ? root->proxy_hostname : root->hostname,
3534 	       root->proxy_hostname ? proxy_port_number : port_number,
3535                SOCK_STRERROR (SOCK_ERRNO));
3536 
3537     make_bufs_from_fds (sock, sock, 0, root, &to_server, &from_server, 1);
3538 
3539     /* if we have proxy then connect to the proxy first */
3540     if (root->proxy_hostname)
3541     {
3542 #define CONNECT_STRING "CONNECT %s:%d HTTP/1.0\r\n\r\n"
3543 	/* Send a "CONNECT" command to proxy: */
3544 	char* read_buf;
3545 	int codenum;
3546 	size_t count;
3547 	/* 4 characters for port covered by the length of %s & %d */
3548 	char* write_buf = Xasnprintf (NULL, &count, CONNECT_STRING,
3549                                       root->hostname, port_number);
3550 	send_to_server_via (to_server, write_buf, count);
3551 
3552 	/* Wait for HTTP status code, bail out if you don't get back a 2xx
3553          * code.
3554          */
3555 	read_line_via (from_server, to_server, &read_buf);
3556 	count = sscanf (read_buf, "%*s %d", &codenum);
3557 
3558 	if (count != 1 || (codenum / 100) != 2)
3559 	    error (1, 0, "proxy server %s:%d does not support http tunnelling",
3560 		   root->proxy_hostname, proxy_port_number);
3561 	free (read_buf);
3562 	free (write_buf);
3563 
3564 	/* Skip through remaining part of MIME header, recv_line
3565            consumes the trailing \n */
3566 	while (read_line_via (from_server, to_server, &read_buf) > 0)
3567 	{
3568 	    if (read_buf[0] == '\r' || read_buf[0] == 0)
3569 	    {
3570 		free (read_buf);
3571 		break;
3572 	    }
3573 	    free (read_buf);
3574 	}
3575     }
3576 
3577     auth_server (root, to_server, from_server, verify_only, do_gssapi);
3578 
3579     if (verify_only)
3580     {
3581 	int status;
3582 
3583 	status = buf_shutdown (to_server);
3584 	if (status != 0)
3585 	    error (0, status, "shutting down buffer to server");
3586 	buf_free (to_server);
3587 	to_server = NULL;
3588 
3589 	status = buf_shutdown (from_server);
3590 	if (status != 0)
3591 	    error (0, status, "shutting down buffer from server");
3592 	buf_free (from_server);
3593 	from_server = NULL;
3594 
3595 	/* Don't need to set server_started = 0 since we don't set it to 1
3596 	 * until returning from this call.
3597 	 */
3598     }
3599     else
3600     {
3601 	*to_server_p = to_server;
3602 	*from_server_p = from_server;
3603     }
3604 
3605     return;
3606 }
3607 
3608 
3609 
3610 static void
auth_server(cvsroot_t * root,struct buffer * to_server,struct buffer * from_server,int verify_only,int do_gssapi)3611 auth_server (cvsroot_t *root, struct buffer *to_server,
3612              struct buffer *from_server, int verify_only, int do_gssapi)
3613 {
3614     char *username = NULL;		/* the username we use to connect */
3615     char no_passwd = 0;			/* gets set if no password found */
3616 
3617     /* Run the authorization mini-protocol before anything else. */
3618     if (do_gssapi)
3619     {
3620 # ifdef HAVE_GSSAPI
3621 	int fd = buf_get_fd (to_server);
3622 	struct stat s;
3623 
3624 	if ((fd < 0) || (fstat (fd, &s) < 0) || !S_ISSOCK(s.st_mode))
3625 	{
3626 	    error (1, 0,
3627                    "gserver currently only enabled for socket connections");
3628 	}
3629 
3630 	if (! connect_to_gserver (root, fd, root->hostname))
3631 	{
3632 	    error (1, 0,
3633 		    "authorization failed: server %s rejected access to %s",
3634 		    root->hostname, root->directory);
3635 	}
3636 # else /* ! HAVE_GSSAPI */
3637 	error (1, 0,
3638 "INTERNAL ERROR: This client does not support GSSAPI authentication");
3639 # endif /* HAVE_GSSAPI */
3640     }
3641     else /* ! do_gssapi */
3642     {
3643 # ifdef AUTH_CLIENT_SUPPORT
3644 	char *begin      = NULL;
3645 	char *password   = NULL;
3646 	char *end        = NULL;
3647 
3648 	if (verify_only)
3649 	{
3650 	    begin = "BEGIN VERIFICATION REQUEST";
3651 	    end   = "END VERIFICATION REQUEST";
3652 	}
3653 	else
3654 	{
3655 	    begin = "BEGIN AUTH REQUEST";
3656 	    end   = "END AUTH REQUEST";
3657 	}
3658 
3659 	/* Get the password, probably from ~/.cvspass. */
3660 	password = get_cvs_password ();
3661 	username = root->username ? root->username : getcaller();
3662 
3663 	/* Send the empty string by default.  This is so anonymous CVS
3664 	   access doesn't require client to have done "cvs login". */
3665 	if (!password)
3666 	{
3667 	    no_passwd = 1;
3668 	    password = scramble ("");
3669 	}
3670 
3671 	/* Announce that we're starting the authorization protocol. */
3672 	send_to_server_via(to_server, begin, 0);
3673 	send_to_server_via(to_server, "\012", 1);
3674 
3675 	/* Send the data the server needs. */
3676 	send_to_server_via(to_server, root->directory, 0);
3677 	send_to_server_via(to_server, "\012", 1);
3678 	send_to_server_via(to_server, username, 0);
3679 	send_to_server_via(to_server, "\012", 1);
3680 	send_to_server_via(to_server, password, 0);
3681 	send_to_server_via(to_server, "\012", 1);
3682 
3683 	/* Announce that we're ending the authorization protocol. */
3684 	send_to_server_via(to_server, end, 0);
3685 	send_to_server_via(to_server, "\012", 1);
3686 
3687         /* Paranoia. */
3688         free_cvs_password (password);
3689 	password = NULL;
3690 # else /* ! AUTH_CLIENT_SUPPORT */
3691 	error (1, 0, "INTERNAL ERROR: This client does not support pserver authentication");
3692 # endif /* AUTH_CLIENT_SUPPORT */
3693     } /* if (do_gssapi) */
3694 
3695     {
3696 	char *read_buf;
3697 
3698 	/* Loop, getting responses from the server.  */
3699 	while (1)
3700 	{
3701 	    read_line_via (from_server, to_server, &read_buf);
3702 
3703 	    if (!strcmp (read_buf, "I HATE YOU"))
3704 	    {
3705 		/* Authorization not granted.
3706 		 *
3707 		 * This is a little confusing since we can reach this while
3708 		 * loop in GSSAPI mode, but if GSSAPI authentication failed,
3709 		 * we already jumped to the rejected label (there is no case
3710 		 * where the connect_to_gserver function can return 1 and we
3711 		 * will not receive "I LOVE YOU" from the server, barring
3712 		 * broken connections and garbled messages, of course).  The
3713 		 * GSSAPI case is also the case where username can be NULL
3714 		 * since username is initialized in the !gssapi section.
3715 		 *
3716 		 * i.e. This is a pserver specific error message and should be
3717 		 * since GSSAPI doesn't use username.
3718 		 */
3719 		error (0, 0,
3720 "authorization failed: server %s rejected access to %s for user %s",
3721 		       root->hostname, root->directory,
3722 		       username ? username : "(null)");
3723 
3724 		/* Output a special error message if authentication was attempted
3725 		with no password -- the user should be made aware that they may
3726 		have missed a step. */
3727 		if (no_passwd)
3728 		{
3729 		    error (0, 0,
3730 "used empty password; try \"cvs login\" with a real password");
3731 		}
3732 		exit (EXIT_FAILURE);
3733 	    }
3734 	    else if (!strncmp (read_buf, "E ", 2))
3735 	    {
3736 		fprintf (stderr, "%s\n", read_buf + 2);
3737 
3738 		/* Continue with the authentication protocol.  */
3739 	    }
3740 	    else if (!strncmp (read_buf, "error ", 6))
3741 	    {
3742 		char *p;
3743 
3744 		/* First skip the code.  */
3745 		p = read_buf + 6;
3746 		while (*p != ' ' && *p != '\0')
3747 		    ++p;
3748 
3749 		/* Skip the space that follows the code.  */
3750 		if (*p == ' ')
3751 		    ++p;
3752 
3753 		/* Now output the text.  */
3754 		fprintf (stderr, "%s\n", p);
3755 		exit (EXIT_FAILURE);
3756 	    }
3757 	    else if (!strcmp (read_buf, "I LOVE YOU"))
3758 	    {
3759 		free (read_buf);
3760 		break;
3761 	    }
3762 	    else
3763 	    {
3764 		error (1, 0,
3765 		       "unrecognized auth response from %s: %s",
3766 		       root->hostname, read_buf);
3767 	    }
3768 	    free (read_buf);
3769 	}
3770     }
3771 }
3772 #endif /* defined (AUTH_CLIENT_SUPPORT) || defined(HAVE_GSSAPI) */
3773 
3774 
3775 
3776 #if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
3777 /*
3778  * Connect to a forked server process.
3779  */
3780 static void
connect_to_forked_server(cvsroot_t * root,struct buffer ** to_server_p,struct buffer ** from_server_p)3781 connect_to_forked_server (cvsroot_t *root, struct buffer **to_server_p,
3782                           struct buffer **from_server_p)
3783 {
3784     int tofd, fromfd;
3785     int child_pid;
3786 
3787     /* This is pretty simple.  All we need to do is choose the correct
3788        cvs binary and call piped_child. */
3789 
3790      char *command[3];
3791 
3792     command[0] = (root->cvs_server
3793 		  ? root->cvs_server : getenv ("CVS_SERVER"));
3794     if (!command[0])
3795 # ifdef SERVER_SUPPORT
3796         /* FIXME:
3797          * I'm casting out the const below because I know that piped_child, the
3798          * only function we pass COMMAND to, accepts COMMAND as a
3799          * (char *const *) and won't alter it, and we don't alter it in this
3800          * function.  This is yucky, there should be a way to declare COMMAND
3801          * such that this casting isn't needed, but I don't know how.  If I
3802          * declare it as (const char *command[]), the compiler complains about
3803          * an incompatible arg 1 being passed to piped_child and if I declare
3804          * it as (char *const command[3]), then the compiler complains when I
3805          * assign values to command[i].
3806          */
3807 	command[0] = (char *)program_path;
3808 # else /* SERVER_SUPPORT */
3809     {
3810 	error( 0, 0, "You must set the CVS_SERVER environment variable when" );
3811 	error( 0, 0, "using the :fork: access method." );
3812 	error( 1, 0, "This CVS was not compiled with server support." );
3813     }
3814 # endif /* SERVER_SUPPORT */
3815 
3816     command[1] = "server";
3817     command[2] = NULL;
3818 
3819     TRACE (TRACE_FUNCTION, "Forking server: %s %s",
3820 	   command[0] ? command[0] : "(null)", command[1]);
3821 
3822     child_pid = piped_child (command, &tofd, &fromfd, false);
3823     if (child_pid < 0)
3824 	error (1, 0, "could not fork server process");
3825 
3826     make_bufs_from_fds (tofd, fromfd, child_pid, root, to_server_p,
3827                         from_server_p, 0);
3828 }
3829 #endif /* CLIENT_SUPPORT || SERVER_SUPPORT */
3830 
3831 
3832 
3833 static int
send_variable_proc(Node * node,void * closure)3834 send_variable_proc (Node *node, void *closure)
3835 {
3836     send_to_server ("Set ", 0);
3837     send_to_server (node->key, 0);
3838     send_to_server ("=", 1);
3839     send_to_server (node->data, 0);
3840     send_to_server ("\012", 1);
3841     return 0;
3842 }
3843 
3844 
3845 
3846 /* Open up the connection to the server and perform any necessary
3847  * authentication.
3848  */
3849 void
open_connection_to_server(cvsroot_t * root,struct buffer ** to_server_p,struct buffer ** from_server_p)3850 open_connection_to_server (cvsroot_t *root, struct buffer **to_server_p,
3851                            struct buffer **from_server_p)
3852 {
3853     /* Note that generally speaking we do *not* fall back to a different
3854        way of connecting if the first one does not work.  This is slow
3855        (*really* slow on a 14.4kbps link); the clean way to have a CVS
3856        which supports several ways of connecting is with access methods.  */
3857 
3858     TRACE (TRACE_FUNCTION, "open_connection_to_server (%s)", root->original);
3859 
3860     switch (root->method)
3861     {
3862 	case pserver_method:
3863 #ifdef AUTH_CLIENT_SUPPORT
3864 	    /* Toss the return value.  It will die with an error message if
3865 	     * anything goes wrong anyway.
3866 	     */
3867 	    connect_to_pserver (root, to_server_p, from_server_p, 0, 0);
3868 #else /* AUTH_CLIENT_SUPPORT */
3869 	    error (0, 0, "CVSROOT is set for a pserver access method but your");
3870 	    error (1, 0, "CVS executable doesn't support it.");
3871 #endif /* AUTH_CLIENT_SUPPORT */
3872 	    break;
3873 
3874 	case kserver_method:
3875 #if HAVE_KERBEROS
3876 	    start_kerberos4_server (root, to_server_p,
3877                                     from_server_p);
3878 #else /* !HAVE_KERBEROS */
3879 	    error (0, 0,
3880 	           "CVSROOT is set for a kerberos access method but your");
3881 	    error (1, 0, "CVS executable doesn't support it.");
3882 #endif /* HAVE_KERBEROS */
3883 	    break;
3884 
3885 	case gserver_method:
3886 #ifdef HAVE_GSSAPI
3887 	    /* GSSAPI authentication is handled by the pserver.  */
3888 	    connect_to_pserver (root, to_server_p, from_server_p, 0, 1);
3889 #else /* !HAVE_GSSAPI */
3890 	    error (0, 0, "CVSROOT is set for a GSSAPI access method but your");
3891 	    error (1, 0, "CVS executable doesn't support it.");
3892 #endif /* HAVE_GSSAPI */
3893 	    break;
3894 
3895 	case ext_method:
3896 #ifdef NO_EXT_METHOD
3897 	    error (0, 0, ":ext: method not supported by this port of CVS");
3898 	    error (1, 0, "try :server: instead");
3899 #else /* ! NO_EXT_METHOD */
3900 	    start_rsh_server (root, to_server_p,
3901                               from_server_p);
3902 #endif /* NO_EXT_METHOD */
3903 	    break;
3904 
3905 	case server_method:
3906 #ifdef START_SERVER
3907 	    {
3908 	    int tofd, fromfd;
3909 	    START_SERVER (&tofd, &fromfd, getcaller (),
3910 			  root->username,
3911                           root->hostname,
3912 			  root->directory);
3913 # ifdef START_SERVER_RETURNS_SOCKET
3914 	    make_bufs_from_fds (tofd, fromfd, 0, root, to_server_p,
3915                                 from_server_p, 1);
3916 # else /* ! START_SERVER_RETURNS_SOCKET */
3917 	    make_bufs_from_fds (tofd, fromfd, 0, root, to_server_p,
3918                                 from_server_p, 0);
3919 # endif /* START_SERVER_RETURNS_SOCKET */
3920 	    }
3921 #else /* ! START_SERVER */
3922 	    /* FIXME: It should be possible to implement this portably,
3923 	       like pserver, which would get rid of the duplicated code
3924 	       in {vms,windows-NT,...}/startserver.c.  */
3925 	    error (1, 0,
3926 "the :server: access method is not supported by this port of CVS");
3927 #endif /* START_SERVER */
3928 	    break;
3929 
3930         case fork_method:
3931 	    connect_to_forked_server (root, to_server_p, from_server_p);
3932 	    break;
3933 
3934 	default:
3935 	    error (1, 0,
3936                    "(start_server internal error): unknown access method");
3937 	    break;
3938     }
3939 
3940     /* "Hi, I'm Darlene and I'll be your server tonight..." */
3941     server_started = 1;
3942 }
3943 
3944 
3945 
3946 /* Contact the server.  */
3947 void
start_server(void)3948 start_server (void)
3949 {
3950     bool rootless;
3951     int status;
3952     bool have_global;
3953 
3954     do
3955     {
3956 	/* Clear our static variables for this invocation. */
3957 	if (toplevel_repos)
3958 	    free (toplevel_repos);
3959 	toplevel_repos = NULL;
3960 
3961 	open_connection_to_server (current_parsed_root, &global_to_server,
3962 				   &global_from_server);
3963 	setup_logfiles ("CVS_CLIENT_LOG", &global_to_server,
3964 			&global_from_server);
3965 
3966 	/* Clear static variables.  */
3967 	if (toplevel_repos)
3968 	{
3969 	    free (toplevel_repos);
3970 	    toplevel_repos = NULL;
3971 	}
3972 	if (last_repos)
3973 	{
3974 	    free (last_repos);
3975 	    last_repos = NULL;
3976 	}
3977 	if (last_update_dir)
3978 	{
3979 	    free (last_update_dir);
3980 	    last_update_dir = NULL;
3981 	}
3982 	stored_checksum_valid = 0;
3983 	if (stored_mode)
3984 	{
3985 	    free (stored_mode);
3986 	    stored_mode = NULL;
3987 	}
3988 
3989 	rootless = !strcmp (cvs_cmd_name, "init");
3990 	if (!rootless)
3991 	{
3992 	    send_to_server ("Root ", 0);
3993 	    send_to_server (current_parsed_root->directory, 0);
3994 	    send_to_server ("\012", 1);
3995 	}
3996 
3997 	{
3998 	    struct response *rs;
3999 	    bool suppress_redirect = !current_parsed_root->redirect;
4000 
4001 	    send_to_server ("Valid-responses", 0);
4002 
4003 	    for (rs = responses; rs->name; ++rs)
4004 	    {
4005 		if (suppress_redirect && !strcmp (rs->name, "Redirect"))
4006 		    continue;
4007 
4008 		send_to_server (" ", 0);
4009 		send_to_server (rs->name, 0);
4010 	    }
4011 	    send_to_server ("\012", 1);
4012 	}
4013 	send_to_server ("valid-requests\012", 0);
4014 
4015 	if (get_server_responses ())
4016 	    exit (EXIT_FAILURE);
4017 
4018 	have_global = supported_request ("Global_option");
4019 
4020 	/* Encryption needs to come before compression.  Good encryption can
4021 	 * render compression useless in the other direction.
4022 	 */
4023 	if (cvsencrypt && !rootless)
4024 	{
4025 #ifdef ENCRYPTION
4026 	    /* Turn on encryption before turning on compression.  We do
4027 	     * not want to try to compress the encrypted stream.  Instead,
4028 	     * we want to encrypt the compressed stream.  If we can't turn
4029 	     * on encryption, bomb out; don't let the user think the data
4030 	     * is being encrypted when it is not.
4031 	     */
4032 #  ifdef HAVE_KERBEROS
4033 	    if (current_parsed_root->method == kserver_method)
4034 	    {
4035 		if (!supported_request ("Kerberos-encrypt"))
4036 		    error (1, 0, "This server does not support encryption");
4037 		send_to_server ("Kerberos-encrypt\012", 0);
4038 	       initialize_kerberos4_encryption_buffers (&global_to_server,
4039 							&global_from_server);
4040 	    }
4041 	    else
4042 #  endif /* HAVE_KERBEROS */
4043 #  ifdef HAVE_GSSAPI
4044 	    if (current_parsed_root->method == gserver_method)
4045 	    {
4046 		if (!supported_request ("Gssapi-encrypt"))
4047 		    error (1, 0, "This server does not support encryption");
4048 		send_to_server ("Gssapi-encrypt\012", 0);
4049 		initialize_gssapi_buffers (&global_to_server,
4050 					   &global_from_server);
4051 		cvs_gssapi_encrypt = 1;
4052 	    }
4053 	    else
4054 #  endif /* HAVE_GSSAPI */
4055 		error (1, 0,
4056 "Encryption is only supported when using GSSAPI or Kerberos");
4057 #else /* ! ENCRYPTION */
4058 	    error (1, 0, "This client does not support encryption");
4059 #endif /* ! ENCRYPTION */
4060 	}
4061 
4062 	if (nolock && !noexec)
4063 	{
4064 	    if (have_global)
4065 	    {
4066 		send_to_server ("Global_option -u\012", 0);
4067 	    }
4068 	    else
4069 		error (1, 0,
4070 		       "This server does not support the global -u option.");
4071 	}
4072 	/* Send this before compression to enable supression of the
4073 	 * "Forcing compression level Z" messages.
4074 	 */
4075 	if (quiet)
4076 	{
4077 	    if (have_global)
4078 	    {
4079 		send_to_server ("Global_option -q\012", 0);
4080 	    }
4081 	    else
4082 		error (1, 0,
4083 		       "This server does not support the global -q option.");
4084 	}
4085 	if (really_quiet)
4086 	{
4087 	    if (have_global)
4088 	    {
4089 		send_to_server ("Global_option -Q\012", 0);
4090 	    }
4091 	    else
4092 		error (1, 0,
4093 		       "This server does not support the global -Q option.");
4094 	}
4095 
4096 	/* Compression needs to come before any of the rooted requests to
4097 	 * work with compression limits.
4098 	 */
4099 	if (!rootless && (gzip_level || force_gzip))
4100 	{
4101 	    if (supported_request ("Gzip-stream"))
4102 	    {
4103 		char *gzip_level_buf = Xasprintf ("%d", gzip_level);
4104 		send_to_server ("Gzip-stream ", 0);
4105 		send_to_server (gzip_level_buf, 0);
4106 		free (gzip_level_buf);
4107 		send_to_server ("\012", 1);
4108 
4109 		/* All further communication with the server will be
4110 		   compressed.  */
4111 
4112 		global_to_server =
4113 		    compress_buffer_initialize (global_to_server, 0,
4114 					        gzip_level, NULL);
4115 		global_from_server =
4116 		    compress_buffer_initialize (global_from_server, 1,
4117 						gzip_level, NULL);
4118 	    }
4119 #ifndef NO_CLIENT_GZIP_PROCESS
4120 	    else if (supported_request ("gzip-file-contents"))
4121 	    {
4122 		char *gzip_level_buf = Xasprintf ("%d", gzip_level);
4123 		send_to_server ("gzip-file-contents ", 0);
4124 		send_to_server (gzip_level_buf, 0);
4125 		free (gzip_level_buf);
4126 		send_to_server ("\012", 1);
4127 
4128 		file_gzip_level = gzip_level;
4129 	    }
4130 #endif
4131 	    else
4132 	    {
4133 		fprintf (stderr, "server doesn't support gzip-file-contents\n");
4134 		/* Setting gzip_level to 0 prevents us from giving the
4135 		   error twice if update has to contact the server again
4136 		   to fetch unpatchable files.  */
4137 		gzip_level = 0;
4138 	    }
4139 	}
4140 
4141 	if (client_referrer && supported_request ("Referrer"))
4142 	{
4143 	    send_to_server ("Referrer ", 0);
4144 	    send_to_server (client_referrer->original, 0);
4145 	    send_to_server ("\012", 0);
4146 	}
4147 
4148 	/* FIXME: I think we should still be sending this for init.  */
4149 	if (!rootless && supported_request ("Command-prep"))
4150 	{
4151 	    send_to_server ("Command-prep ", 0);
4152 	    send_to_server (cvs_cmd_name, 0);
4153 	    send_to_server ("\012", 0);
4154 	    status = get_server_responses ();
4155 	    if (status == 1) exit (EXIT_FAILURE);
4156 	    if (status == 2) close_connection_to_server (&global_to_server,
4157 							 &global_from_server);
4158 	}
4159 	else status = 0;
4160     } while (status == 2);
4161 
4162 
4163     /*
4164      * Now handle global options.
4165      *
4166      * -H, -f, -d, -e should be handled OK locally.
4167      *
4168      * -b we ignore (treating it as a server installation issue).
4169      * FIXME: should be an error message.
4170      *
4171      * -v we print local version info; FIXME: Add a protocol request to get
4172      * the version from the server so we can print that too.
4173      *
4174      * -l -t -r -w -q -n and -Q need to go to the server.
4175      */
4176     if (noexec)
4177     {
4178 	if (have_global)
4179 	{
4180 	    send_to_server ("Global_option -n\012", 0);
4181 	}
4182 	else
4183 	    error (1, 0,
4184 		   "This server does not support the global -n option.");
4185     }
4186     if (!cvswrite)
4187     {
4188 	if (have_global)
4189 	{
4190 	    send_to_server ("Global_option -r\012", 0);
4191 	}
4192 	else
4193 	    error (1, 0,
4194 		   "This server does not support the global -r option.");
4195     }
4196     if (trace)
4197     {
4198 	if (have_global)
4199 	{
4200 	    int count = trace;
4201 	    while (count--) send_to_server ("Global_option -t\012", 0);
4202 	}
4203 	else
4204 	    error (1, 0,
4205 		   "This server does not support the global -t option.");
4206     }
4207 
4208     /* Find out about server-side cvswrappers.  An extra network
4209        turnaround for cvs import seems to be unavoidable, unless we
4210        want to add some kind of client-side place to configure which
4211        filenames imply binary.  For cvs add, we could avoid the
4212        problem by keeping a copy of the wrappers in CVSADM (the main
4213        reason to bother would be so we could make add work without
4214        contacting the server, I suspect).  */
4215 
4216     if (!strcmp (cvs_cmd_name, "import") || !strcmp (cvs_cmd_name, "add"))
4217     {
4218 	if (supported_request ("wrapper-sendme-rcsOptions"))
4219 	{
4220 	    int err;
4221 	    send_to_server ("wrapper-sendme-rcsOptions\012", 0);
4222 	    err = get_server_responses ();
4223 	    if (err != 0)
4224 		error (err, 0, "error reading from server");
4225 	}
4226     }
4227 
4228     if (cvsauthenticate && ! cvsencrypt && !rootless)
4229     {
4230 	/* Turn on authentication after turning on compression, so
4231 	   that we can compress the authentication information.  We
4232 	   assume that encrypted data is always authenticated--the
4233 	   ability to decrypt the data stream is itself a form of
4234 	   authentication.  */
4235 #ifdef HAVE_GSSAPI
4236 	if (current_parsed_root->method == gserver_method)
4237 	{
4238 	    if (! supported_request ("Gssapi-authenticate"))
4239 		error (1, 0,
4240 		       "This server does not support stream authentication");
4241 	    send_to_server ("Gssapi-authenticate\012", 0);
4242 	    initialize_gssapi_buffers(&global_to_server, &global_from_server);
4243 
4244 	}
4245 	else
4246 	    error (1, 0, "Stream authentication is only supported when using GSSAPI");
4247 #else /* ! HAVE_GSSAPI */
4248 	error (1, 0, "This client does not support stream authentication");
4249 #endif /* ! HAVE_GSSAPI */
4250     }
4251 
4252     /* If "Set" is not supported, just silently fail to send the variables.
4253        Users with an old server should get a useful error message when it
4254        fails to recognize the ${=foo} syntax.  This way if someone uses
4255        several servers, some of which are new and some old, they can still
4256        set user variables in their .cvsrc without trouble.  */
4257     if (supported_request ("Set"))
4258 	walklist (variable_list, send_variable_proc, NULL);
4259 }
4260 
4261 
4262 
4263 /* Send an argument STRING.  */
4264 void
send_arg(const char * string)4265 send_arg (const char *string)
4266 {
4267     const char *p = string;
4268 
4269     send_to_server ("Argument ", 0);
4270 
4271     while (*p)
4272     {
4273 	if (*p == '\n')
4274 	    send_to_server ("\012Argumentx ", 0);
4275 	else
4276 	    send_to_server (p, 1);
4277 	++p;
4278     }
4279     send_to_server ("\012", 1);
4280 }
4281 
4282 
4283 
4284 /* VERS->OPTIONS specifies whether the file is binary or not.  NOTE: BEFORE
4285    using any other fields of the struct vers, we would need to fix
4286    client_process_import_file to set them up.  */
4287 static void
send_modified(const char * file,const char * short_pathname,Vers_TS * vers)4288 send_modified (const char *file, const char *short_pathname, Vers_TS *vers)
4289 {
4290     /* File was modified, send it.  */
4291     struct stat sb;
4292     int fd;
4293     unsigned char *buf;
4294     char *mode_string;
4295     size_t bufsize;
4296     int bin;
4297 
4298     TRACE (TRACE_FUNCTION, "Sending file `%s' to server", file);
4299 
4300     /* Don't think we can assume fstat exists.  */
4301     if (stat (file, &sb) < 0)
4302 	error (1, errno, "reading %s", short_pathname);
4303 
4304     mode_string = mode_to_string (sb.st_mode);
4305 
4306     /* Beware: on systems using CRLF line termination conventions,
4307        the read and write functions will convert CRLF to LF, so the
4308        number of characters read is not the same as sb.st_size.  Text
4309        files should always be transmitted using the LF convention, so
4310        we don't want to disable this conversion.  */
4311     bufsize = sb.st_size;
4312     buf = xmalloc (bufsize);
4313 
4314     /* Is the file marked as containing binary data by the "-kb" flag?
4315        If so, make sure to open it in binary mode: */
4316 
4317     if (vers && vers->options)
4318       bin = !strcmp (vers->options, "-kb");
4319     else
4320       bin = 0;
4321 
4322 #ifdef BROKEN_READWRITE_CONVERSION
4323     if (!bin)
4324     {
4325 	/* If only stdio, not open/write/etc., do text/binary
4326 	   conversion, use convert_file which can compensate
4327 	   (FIXME: we could just use stdio instead which would
4328 	   avoid the whole problem).  */
4329 	char *tfile = Xasprintf ("%s.CVSBFCTMP", file);
4330 	convert_file (file, O_RDONLY,
4331 		      tfile, O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY);
4332 	fd = CVS_OPEN (tfile, O_RDONLY | OPEN_BINARY);
4333 	if (fd < 0)
4334 	    error (1, errno, "reading %s", short_pathname);
4335 	free (tfile);
4336     }
4337     else
4338 	fd = CVS_OPEN (file, O_RDONLY | OPEN_BINARY);
4339 #else
4340     fd = CVS_OPEN (file, O_RDONLY | (bin ? OPEN_BINARY : 0));
4341 #endif
4342 
4343     if (fd < 0)
4344 	error (1, errno, "reading %s", short_pathname);
4345 
4346     if (file_gzip_level && sb.st_size > 100)
4347     {
4348 	size_t newsize = 0;
4349 
4350 	if (read_and_gzip (fd, short_pathname, &buf,
4351 			   &bufsize, &newsize,
4352 			   file_gzip_level))
4353 	    error (1, 0, "aborting due to compression error");
4354 
4355 	if (close (fd) < 0)
4356 	    error (0, errno, "warning: can't close %s", short_pathname);
4357 
4358         {
4359           char tmp[80];
4360 
4361 	  send_to_server ("Modified ", 0);
4362 	  send_to_server (file, 0);
4363 	  send_to_server ("\012", 1);
4364 	  send_to_server (mode_string, 0);
4365 	  send_to_server ("\012z", 2);
4366 	  sprintf (tmp, "%lu\n", (unsigned long) newsize);
4367 	  send_to_server (tmp, 0);
4368 
4369           send_to_server (buf, newsize);
4370         }
4371     }
4372     else
4373     {
4374     	int newsize;
4375 
4376         {
4377 	    unsigned char *bufp = buf;
4378 	    int len;
4379 
4380 	    /* FIXME: This is gross.  It assumes that we might read
4381 	       less than st_size bytes (true on NT), but not more.
4382 	       Instead of this we should just be reading a block of
4383 	       data (e.g. 8192 bytes), writing it to the network, and
4384 	       so on until EOF.  */
4385 	    while ((len = read (fd, bufp, (buf + sb.st_size) - bufp)) > 0)
4386 	        bufp += len;
4387 
4388 	    if (len < 0)
4389 	        error (1, errno, "reading %s", short_pathname);
4390 
4391 	    newsize = bufp - buf;
4392 	}
4393 	if (close (fd) < 0)
4394 	    error (0, errno, "warning: can't close %s", short_pathname);
4395 
4396         {
4397           char tmp[80];
4398 
4399 	  send_to_server ("Modified ", 0);
4400 	  send_to_server (file, 0);
4401 	  send_to_server ("\012", 1);
4402 	  send_to_server (mode_string, 0);
4403 	  send_to_server ("\012", 1);
4404           sprintf (tmp, "%lu\012", (unsigned long) newsize);
4405           send_to_server (tmp, 0);
4406         }
4407 #ifdef BROKEN_READWRITE_CONVERSION
4408 	if (!bin)
4409 	{
4410 	    char *tfile = Xasprintf ("%s.CVSBFCTMP", file);
4411 	    if (CVS_UNLINK (tfile) < 0)
4412 		error (0, errno, "warning: can't remove temp file %s", tfile);
4413 	    free (tfile);
4414 	}
4415 #endif
4416 
4417 	/*
4418 	 * Note that this only ends with a newline if the file ended with
4419 	 * one.
4420 	 */
4421 	if (newsize > 0)
4422 	    send_to_server (buf, newsize);
4423     }
4424     free (buf);
4425     free (mode_string);
4426 }
4427 
4428 
4429 
4430 /* The address of an instance of this structure is passed to
4431    send_fileproc, send_filesdoneproc, and send_direntproc, as the
4432    callerdat parameter.  */
4433 struct send_data
4434 {
4435     /* Each of the following flags are zero for clear or nonzero for set.  */
4436     int build_dirs;
4437     int force;
4438     int no_contents;
4439     int backup_modified;
4440 };
4441 
4442 /* Deal with one file.  */
4443 static int
send_fileproc(void * callerdat,struct file_info * finfo)4444 send_fileproc (void *callerdat, struct file_info *finfo)
4445 {
4446     struct send_data *args = callerdat;
4447     Vers_TS *vers;
4448     struct file_info xfinfo;
4449     /* File name to actually use.  Might differ in case from
4450        finfo->file.  */
4451     const char *filename;
4452 
4453     send_a_repository ("", finfo->repository, finfo->update_dir);
4454 
4455     xfinfo = *finfo;
4456     xfinfo.repository = NULL;
4457     xfinfo.rcs = NULL;
4458     vers = Version_TS (&xfinfo, NULL, NULL, NULL, 0, 0);
4459 
4460     if (vers->entdata)
4461 	filename = vers->entdata->user;
4462     else
4463 	filename = finfo->file;
4464 
4465     if (vers->vn_user)
4466     {
4467 	/* The Entries request.  */
4468 	send_to_server ("Entry /", 0);
4469 	send_to_server (filename, 0);
4470 	send_to_server ("/", 0);
4471 	send_to_server (vers->vn_user, 0);
4472 	send_to_server ("/", 0);
4473 	if (vers->ts_conflict)
4474 	{
4475 	    if (vers->ts_user && !strcmp (vers->ts_conflict, vers->ts_user))
4476 		send_to_server ("+=", 0);
4477 	    else
4478 		send_to_server ("+modified", 0);
4479 	}
4480 	send_to_server ("/", 0);
4481 	send_to_server (vers->entdata ? vers->entdata->options : vers->options,
4482 			0);
4483 	send_to_server ("/", 0);
4484 	if (vers->entdata && vers->entdata->tag)
4485 	{
4486 	    send_to_server ("T", 0);
4487 	    send_to_server (vers->entdata->tag, 0);
4488 	}
4489 	else if (vers->entdata && vers->entdata->date)
4490           {
4491 	    send_to_server ("D", 0);
4492 	    send_to_server (vers->entdata->date, 0);
4493           }
4494 	send_to_server ("\012", 1);
4495     }
4496     else
4497     {
4498 	/* It seems a little silly to re-read this on each file, but
4499 	   send_dirent_proc doesn't get called if filenames are specified
4500 	   explicitly on the command line.  */
4501 	wrap_add_file (CVSDOTWRAPPER, 1);
4502 
4503 	if (wrap_name_has (filename, WRAP_RCSOPTION))
4504 	{
4505 	    /* No "Entry", but the wrappers did give us a kopt so we better
4506 	       send it with "Kopt".  As far as I know this only happens
4507 	       for "cvs add".  Question: is there any reason why checking
4508 	       for options from wrappers isn't done in Version_TS?
4509 
4510 	       Note: it might have been better to just remember all the
4511 	       kopts on the client side, rather than send them to the server,
4512 	       and have it send us back the same kopts.  But that seemed like
4513 	       a bigger change than I had in mind making now.  */
4514 
4515 	    if (supported_request ("Kopt"))
4516 	    {
4517 		char *opt;
4518 
4519 		send_to_server ("Kopt ", 0);
4520 		opt = wrap_rcsoption (filename, 1);
4521 		send_to_server (opt, 0);
4522 		send_to_server ("\012", 1);
4523 		free (opt);
4524 	    }
4525 	    else
4526 		error (0, 0, "\
4527 warning: ignoring -k options due to server limitations");
4528 	}
4529     }
4530 
4531     if (!vers->ts_user)
4532     {
4533 	/*
4534 	 * Do we want to print "file was lost" like normal CVS?
4535 	 * Would it always be appropriate?
4536 	 */
4537 	/* File no longer exists.  Don't do anything, missing files
4538 	   just happen.  */
4539     }
4540     else if (!vers->ts_rcs || args->force
4541 	     || strcmp (vers->ts_conflict
4542 		        ? vers->ts_conflict : vers->ts_rcs, vers->ts_user)
4543 	     || (vers->ts_conflict && !strcmp (cvs_cmd_name, "diff")))
4544     {
4545 	if (args->no_contents
4546 	    && supported_request ("Is-modified"))
4547 	{
4548 	    send_to_server ("Is-modified ", 0);
4549 	    send_to_server (filename, 0);
4550 	    send_to_server ("\012", 1);
4551 	}
4552 	else
4553 	    send_modified (filename, finfo->fullname, vers);
4554 
4555         if (args->backup_modified)
4556         {
4557             char *bakname;
4558             bakname = backup_file (filename, vers->vn_user);
4559             /* This behavior is sufficiently unexpected to
4560                justify overinformativeness, I think. */
4561             if (! really_quiet)
4562                 printf ("(Locally modified %s moved to %s)\n",
4563                         filename, bakname);
4564             free (bakname);
4565         }
4566     }
4567     else
4568     {
4569 	send_to_server ("Unchanged ", 0);
4570 	send_to_server (filename, 0);
4571 	send_to_server ("\012", 1);
4572     }
4573 
4574     /* if this directory has an ignore list, add this file to it */
4575     if (ignlist)
4576     {
4577 	Node *p;
4578 
4579 	p = getnode ();
4580 	p->type = FILES;
4581 	p->key = xstrdup (finfo->file);
4582 	(void) addnode (ignlist, p);
4583     }
4584 
4585     freevers_ts (&vers);
4586     return 0;
4587 }
4588 
4589 
4590 
4591 static void
send_ignproc(const char * file,const char * dir)4592 send_ignproc (const char *file, const char *dir)
4593 {
4594     if (ign_inhibit_server || !supported_request ("Questionable"))
4595     {
4596 	if (dir[0] != '\0')
4597 	    (void) printf ("? %s/%s\n", dir, file);
4598 	else
4599 	    (void) printf ("? %s\n", file);
4600     }
4601     else
4602     {
4603 	send_to_server ("Questionable ", 0);
4604 	send_to_server (file, 0);
4605 	send_to_server ("\012", 1);
4606     }
4607 }
4608 
4609 
4610 
4611 static int
send_filesdoneproc(void * callerdat,int err,const char * repository,const char * update_dir,List * entries)4612 send_filesdoneproc (void *callerdat, int err, const char *repository,
4613                     const char *update_dir, List *entries)
4614 {
4615     /* if this directory has an ignore list, process it then free it */
4616     if (ignlist)
4617     {
4618 	ignore_files (ignlist, entries, update_dir, send_ignproc);
4619 	dellist (&ignlist);
4620     }
4621 
4622     return err;
4623 }
4624 
4625 
4626 
4627 /*
4628  * send_dirent_proc () is called back by the recursion processor before a
4629  * sub-directory is processed for update.
4630  * A return code of 0 indicates the directory should be
4631  * processed by the recursion code.  A return of non-zero indicates the
4632  * recursion code should skip this directory.
4633  *
4634  */
4635 static Dtype
send_dirent_proc(void * callerdat,const char * dir,const char * repository,const char * update_dir,List * entries)4636 send_dirent_proc (void *callerdat, const char *dir, const char *repository,
4637                   const char *update_dir, List *entries)
4638 {
4639     struct send_data *args = callerdat;
4640     int dir_exists;
4641     char *cvsadm_name;
4642 
4643     if (ignore_directory (update_dir))
4644     {
4645 	/* print the warm fuzzy message */
4646 	if (!quiet)
4647 	    error (0, 0, "Ignoring %s", update_dir);
4648         return R_SKIP_ALL;
4649     }
4650 
4651     /*
4652      * If the directory does not exist yet (e.g. "cvs update -d foo"),
4653      * no need to send any files from it.  If the directory does not
4654      * have a CVS directory, then we pretend that it does not exist.
4655      * Otherwise, we will fail when trying to open the Entries file.
4656      * This case will happen when checking out a module defined as
4657      * ``-a .''.
4658      */
4659     cvsadm_name = Xasprintf ("%s/%s", dir, CVSADM);
4660     dir_exists = isdir (cvsadm_name);
4661     free (cvsadm_name);
4662 
4663     /*
4664      * If there is an empty directory (e.g. we are doing `cvs add' on a
4665      * newly-created directory), the server still needs to know about it.
4666      */
4667 
4668     if (dir_exists)
4669     {
4670 	/*
4671 	 * Get the repository from a CVS/Repository file whenever possible.
4672 	 * The repository variable is wrong if the names in the local
4673 	 * directory don't match the names in the repository.
4674 	 */
4675 	char *repos = Name_Repository (dir, update_dir);
4676 	send_a_repository (dir, repos, update_dir);
4677 	free (repos);
4678 
4679 	/* initialize the ignore list for this directory */
4680 	ignlist = getlist ();
4681     }
4682     else
4683     {
4684 	/* It doesn't make sense to send a non-existent directory,
4685 	   because there is no way to get the correct value for
4686 	   the repository (I suppose maybe via the expand-modules
4687 	   request).  In the case where the "obvious" choice for
4688 	   repository is correct, the server can figure out whether
4689 	   to recreate the directory; in the case where it is wrong
4690 	   (that is, does not match what modules give us), we might as
4691 	   well just fail to recreate it.
4692 
4693 	   Checking for noexec is a kludge for "cvs -n add dir".  */
4694 	/* Don't send a non-existent directory unless we are building
4695            new directories (build_dirs is true).  Otherwise, CVS may
4696            see a D line in an Entries file, and recreate a directory
4697            which the user removed by hand.  */
4698 	if (args->build_dirs && noexec)
4699 	    send_a_repository (dir, repository, update_dir);
4700     }
4701 
4702     return dir_exists ? R_PROCESS : R_SKIP_ALL;
4703 }
4704 
4705 
4706 
4707 /*
4708  * send_dirleave_proc () is called back by the recursion code upon leaving
4709  * a directory.  All it does is delete the ignore list if it hasn't already
4710  * been done (by send_filesdone_proc).
4711  */
4712 /* ARGSUSED */
4713 static int
send_dirleave_proc(void * callerdat,const char * dir,int err,const char * update_dir,List * entries)4714 send_dirleave_proc (void *callerdat, const char *dir, int err,
4715                     const char *update_dir, List *entries )
4716 {
4717 
4718     /* Delete the ignore list if it hasn't already been done.  */
4719     if (ignlist)
4720 	dellist (&ignlist);
4721     return err;
4722 }
4723 
4724 
4725 
4726 /*
4727  * Send each option in an array to the server, one by one.
4728  * argv might be "--foo=bar",  "-C", "5", "-y".
4729  */
4730 
4731 void
send_options(int argc,char * const * argv)4732 send_options (int argc, char * const *argv)
4733 {
4734     int i;
4735     for (i = 0; i < argc; i++)
4736 	send_arg (argv[i]);
4737 }
4738 
4739 
4740 
4741 /* Send the names of all the argument files to the server.  */
4742 void
send_file_names(int argc,char ** argv,unsigned int flags)4743 send_file_names (int argc, char **argv, unsigned int flags)
4744 {
4745     int i;
4746 
4747     /* The fact that we do this here as well as start_recursion is a bit
4748        of a performance hit.  Perhaps worth cleaning up someday.  */
4749     if (flags & SEND_EXPAND_WILD)
4750 	expand_wild (argc, argv, &argc, &argv);
4751 
4752     for (i = 0; i < argc; ++i)
4753     {
4754 	char buf[1];
4755 	char *p;
4756 #ifdef FILENAMES_CASE_INSENSITIVE
4757 	char *line = NULL;
4758 #endif /* FILENAMES_CASE_INSENSITIVE */
4759 
4760 	if (arg_should_not_be_sent_to_server (argv[i]))
4761 	    continue;
4762 
4763 #ifdef FILENAMES_CASE_INSENSITIVE
4764 	/* We want to send the path as it appears in the
4765 	   CVS/Entries files.  We put this inside an ifdef
4766 	   to avoid doing all these system calls in
4767 	   cases where fncmp is just strcmp anyway.  */
4768 	/* The isdir (CVSADM) check could more gracefully be replaced
4769 	   with a way of having Entries_Open report back the
4770 	   error to us and letting us ignore existence_error.
4771 	   Or some such.  */
4772 	{
4773 	    List *stack;
4774 	    size_t line_len = 0;
4775 	    char *q, *r;
4776 	    struct saved_cwd sdir;
4777 
4778 	    /* Split the argument onto the stack.  */
4779 	    stack = getlist();
4780 	    r = xstrdup (argv[i]);
4781             /* It's okay to discard the const from the last_component return
4782              * below since we know we passed in an arg that was not const.
4783              */
4784 	    while ((q = (char *)last_component (r)) != r)
4785 	    {
4786 		push (stack, xstrdup (q));
4787 		*--q = '\0';
4788 	    }
4789 	    push (stack, r);
4790 
4791 	    /* Normalize the path into outstr. */
4792 	    save_cwd (&sdir);
4793 	    while (q = pop (stack))
4794 	    {
4795 		Node *node = NULL;
4796 	        if (isdir (CVSADM))
4797 		{
4798 		    List *entries;
4799 
4800 		    /* Note that if we are adding a directory,
4801 		       the following will read the entry
4802 		       that we just wrote there, that is, we
4803 		       will get the case specified on the
4804 		       command line, not the case of the
4805 		       directory in the filesystem.  This
4806 		       is correct behavior.  */
4807 		    entries = Entries_Open (0, NULL);
4808 		    node = findnode_fn (entries, q);
4809 		    if (node)
4810 		    {
4811 			/* Add the slash unless this is our first element. */
4812 			if (line_len)
4813 			    xrealloc_and_strcat (&line, &line_len, "/");
4814 			xrealloc_and_strcat (&line, &line_len, node->key);
4815 			delnode (node);
4816 		    }
4817 		    Entries_Close (entries);
4818 		}
4819 
4820 		/* If node is still NULL then we either didn't find CVSADM or
4821 		 * we didn't find an entry there.
4822 		 */
4823 		if (!node)
4824 		{
4825 		    /* Add the slash unless this is our first element. */
4826 		    if (line_len)
4827 			xrealloc_and_strcat (&line, &line_len, "/");
4828 		    xrealloc_and_strcat (&line, &line_len, q);
4829 		    break;
4830 		}
4831 
4832 		/* And descend the tree. */
4833 		if (isdir (q))
4834 		    CVS_CHDIR (q);
4835 		free (q);
4836 	    }
4837 	    restore_cwd (&sdir);
4838 	    free_cwd (&sdir);
4839 
4840 	    /* Now put everything we didn't find entries for back on. */
4841 	    while (q = pop (stack))
4842 	    {
4843 		if (line_len)
4844 		    xrealloc_and_strcat (&line, &line_len, "/");
4845 		xrealloc_and_strcat (&line, &line_len, q);
4846 		free (q);
4847 	    }
4848 
4849 	    p = line;
4850 
4851 	    dellist (&stack);
4852 	}
4853 #else /* !FILENAMES_CASE_INSENSITIVE */
4854 	p = argv[i];
4855 #endif /* FILENAMES_CASE_INSENSITIVE */
4856 
4857 	send_to_server ("Argument ", 0);
4858 
4859 	while (*p)
4860 	{
4861 	    if (*p == '\n')
4862 	    {
4863 		send_to_server ("\012Argumentx ", 0);
4864 	    }
4865 	    else if (ISSLASH (*p))
4866 	    {
4867 		buf[0] = '/';
4868 		send_to_server (buf, 1);
4869 	    }
4870 	    else
4871 	    {
4872 		buf[0] = *p;
4873 		send_to_server (buf, 1);
4874 	    }
4875 	    ++p;
4876 	}
4877 	send_to_server ("\012", 1);
4878 #ifdef FILENAMES_CASE_INSENSITIVE
4879 	free (line);
4880 #endif /* FILENAMES_CASE_INSENSITIVE */
4881     }
4882 
4883     if (flags & SEND_EXPAND_WILD)
4884     {
4885 	int i;
4886 	for (i = 0; i < argc; ++i)
4887 	    free (argv[i]);
4888 	free (argv);
4889     }
4890 }
4891 
4892 
4893 
4894 /* Calculate and send max-dotdot to the server */
4895 static void
send_max_dotdot(argc,argv)4896 send_max_dotdot (argc, argv)
4897     int argc;
4898     char **argv;
4899 {
4900     int i;
4901     int level = 0;
4902     int max_level = 0;
4903 
4904     /* Send Max-dotdot if needed.  */
4905     for (i = 0; i < argc; ++i)
4906     {
4907         level = pathname_levels (argv[i]);
4908 	if (level > 0)
4909 	{
4910             if (!uppaths) uppaths = getlist();
4911 	    push_string (uppaths, xstrdup (argv[i]));
4912 	}
4913         if (level > max_level)
4914             max_level = level;
4915     }
4916 
4917     if (max_level > 0)
4918     {
4919         if (supported_request ("Max-dotdot"))
4920         {
4921             char buf[10];
4922             sprintf (buf, "%d", max_level);
4923 
4924             send_to_server ("Max-dotdot ", 0);
4925             send_to_server (buf, 0);
4926             send_to_server ("\012", 1);
4927         }
4928         else
4929         {
4930             error (1, 0,
4931 "backreference in path (`..') not supported by old (pre-Max-dotdot) servers");
4932         }
4933     }
4934 }
4935 
4936 
4937 
4938 /* Send Repository, Modified and Entry.  argc and argv contain only
4939   the files to operate on (or empty for everything), not options.
4940   local is nonzero if we should not recurse (-l option).  flags &
4941   SEND_BUILD_DIRS is nonzero if nonexistent directories should be
4942   sent.  flags & SEND_FORCE is nonzero if we should send unmodified
4943   files to the server as though they were modified.  flags &
4944   SEND_NO_CONTENTS means that this command only needs to know
4945   _whether_ a file is modified, not the contents.  Also sends Argument
4946   lines for argc and argv, so should be called after options are sent.  */
4947 void
send_files(int argc,char ** argv,int local,int aflag,unsigned int flags)4948 send_files (int argc, char **argv, int local, int aflag, unsigned int flags)
4949 {
4950     struct send_data args;
4951     int err;
4952 
4953     send_max_dotdot (argc, argv);
4954 
4955     /*
4956      * aflag controls whether the tag/date is copied into the vers_ts.
4957      * But we don't actually use it, so I don't think it matters what we pass
4958      * for aflag here.
4959      */
4960     args.build_dirs = flags & SEND_BUILD_DIRS;
4961     args.force = flags & SEND_FORCE;
4962     args.no_contents = flags & SEND_NO_CONTENTS;
4963     args.backup_modified = flags & BACKUP_MODIFIED_FILES;
4964     err = start_recursion
4965 	(send_fileproc, send_filesdoneproc, send_dirent_proc,
4966          send_dirleave_proc, &args, argc, argv, local, W_LOCAL, aflag,
4967          CVS_LOCK_NONE, NULL, 0, NULL);
4968     if (err)
4969 	exit (EXIT_FAILURE);
4970     if (!toplevel_repos)
4971 	/*
4972 	 * This happens if we are not processing any files,
4973 	 * or for checkouts in directories without any existing stuff
4974 	 * checked out.  The following assignment is correct for the
4975 	 * latter case; I don't think toplevel_repos matters for the
4976 	 * former.
4977 	 */
4978 	toplevel_repos = xstrdup (current_parsed_root->directory);
4979     send_repository ("", toplevel_repos, ".");
4980 }
4981 
4982 
4983 
4984 void
client_import_setup(char * repository)4985 client_import_setup (char *repository)
4986 {
4987     if (!toplevel_repos)		/* should always be true */
4988         send_a_repository ("", repository, "");
4989 }
4990 
4991 
4992 
4993 /*
4994  * Process the argument import file.
4995  */
4996 int
client_process_import_file(char * message,char * vfile,char * vtag,int targc,char * targv[],char * repository,int all_files_binary,int modtime)4997 client_process_import_file (char *message, char *vfile, char *vtag, int targc,
4998                             char *targv[], char *repository,
4999                             int all_files_binary,
5000                             int modtime /* Nonzero for "import -d".  */ )
5001 {
5002     char *update_dir;
5003     char *fullname;
5004     Vers_TS vers;
5005 
5006     assert (toplevel_repos);
5007 
5008     if (strncmp (repository, toplevel_repos, strlen (toplevel_repos)))
5009 	error (1, 0,
5010 	       "internal error: pathname `%s' doesn't specify file in `%s'",
5011 	       repository, toplevel_repos);
5012 
5013     if (!strcmp (repository, toplevel_repos))
5014     {
5015 	update_dir = "";
5016 	fullname = xstrdup (vfile);
5017     }
5018     else
5019     {
5020 	update_dir = repository + strlen (toplevel_repos) + 1;
5021 
5022 	fullname = Xasprintf ("%s/%s", update_dir, vfile);
5023     }
5024 
5025     send_a_repository ("", repository, update_dir);
5026     if (all_files_binary)
5027 	vers.options = xstrdup ("-kb");
5028     else
5029 	vers.options = wrap_rcsoption (vfile, 1);
5030 
5031     if (vers.options)
5032     {
5033 	if (supported_request ("Kopt"))
5034 	{
5035 	    send_to_server ("Kopt ", 0);
5036 	    send_to_server (vers.options, 0);
5037 	    send_to_server ("\012", 1);
5038 	}
5039 	else
5040 	    error (0, 0,
5041 		   "warning: ignoring -k options due to server limitations");
5042     }
5043     if (modtime)
5044     {
5045 	if (supported_request ("Checkin-time"))
5046 	{
5047 	    struct stat sb;
5048 	    char *rcsdate;
5049 	    char netdate[MAXDATELEN];
5050 
5051 	    if (stat (vfile, &sb) < 0)
5052 		error (1, errno, "cannot stat %s", fullname);
5053 	    rcsdate = date_from_time_t (sb.st_mtime);
5054 	    date_to_internet (netdate, rcsdate);
5055 	    free (rcsdate);
5056 
5057 	    send_to_server ("Checkin-time ", 0);
5058 	    send_to_server (netdate, 0);
5059 	    send_to_server ("\012", 1);
5060 	}
5061 	else
5062 	    error (0, 0,
5063 		   "warning: ignoring -d option due to server limitations");
5064     }
5065     send_modified (vfile, fullname, &vers);
5066     if (vers.options)
5067 	free (vers.options);
5068     free (fullname);
5069     return 0;
5070 }
5071 
5072 
5073 
5074 void
client_import_done(void)5075 client_import_done (void)
5076 {
5077     if (!toplevel_repos)
5078 	/*
5079 	 * This happens if we are not processing any files,
5080 	 * or for checkouts in directories without any existing stuff
5081 	 * checked out.  The following assignment is correct for the
5082 	 * latter case; I don't think toplevel_repos matters for the
5083 	 * former.
5084 	 */
5085         /* FIXME: "can't happen" now that we call client_import_setup
5086 	   at the beginning.  */
5087 	toplevel_repos = xstrdup (current_parsed_root->directory);
5088     send_repository ("", toplevel_repos, ".");
5089 }
5090 
5091 
5092 
5093 void
client_notify(const char * repository,const char * update_dir,const char * filename,int notif_type,const char * val)5094 client_notify (const char *repository, const char *update_dir,
5095                const char *filename, int notif_type, const char *val)
5096 {
5097     char buf[2];
5098 
5099     send_a_repository ("", repository, update_dir);
5100     send_to_server ("Notify ", 0);
5101     send_to_server (filename, 0);
5102     send_to_server ("\012", 1);
5103     buf[0] = notif_type;
5104     buf[1] = '\0';
5105     send_to_server (buf, 1);
5106     send_to_server ("\t", 1);
5107     send_to_server (val, 0);
5108 }
5109 
5110 
5111 
5112 /*
5113  * Send an option with an argument, dealing correctly with newlines in
5114  * the argument.  If ARG is NULL, forget the whole thing.
5115  */
5116 void
option_with_arg(const char * option,const char * arg)5117 option_with_arg (const char *option, const char *arg)
5118 {
5119     if (!arg)
5120 	return;
5121 
5122     send_to_server ("Argument ", 0);
5123     send_to_server (option, 0);
5124     send_to_server ("\012", 1);
5125 
5126     send_arg (arg);
5127 }
5128 
5129 
5130 
5131 /* Send a date to the server.  The input DATE is in RCS format.
5132    The time will be GMT.
5133 
5134    We then convert that to the format required in the protocol
5135    (including the "-D" option) and send it.  According to
5136    cvsclient.texi, RFC 822/1123 format is preferred.  */
5137 void
client_senddate(const char * date)5138 client_senddate (const char *date)
5139 {
5140     char buf[MAXDATELEN];
5141 
5142     date_to_internet (buf, date);
5143     option_with_arg ("-D", buf);
5144 }
5145 
5146 
5147 
5148 void
send_init_command(void)5149 send_init_command (void)
5150 {
5151     /* This is here because we need the current_parsed_root->directory variable.  */
5152     send_to_server ("init ", 0);
5153     send_to_server (current_parsed_root->directory, 0);
5154     send_to_server ("\012", 0);
5155 }
5156 
5157 
5158 
5159 #if defined AUTH_CLIENT_SUPPORT || defined HAVE_KERBEROS || defined HAVE_GSSAPI
5160 
5161 static int
connect_to(char * hostname,unsigned int port)5162 connect_to(char *hostname, unsigned int port)
5163 {
5164     struct addrinfo hints, *res, *res0 = NULL;
5165     char pbuf[10];
5166     int e, sock;
5167 
5168     memset(&hints, 0, sizeof(hints));
5169     hints.ai_family = PF_UNSPEC;
5170     hints.ai_socktype = SOCK_STREAM;
5171     hints.ai_flags = AI_CANONNAME;
5172 
5173     snprintf(pbuf, sizeof(pbuf), "%d", port);
5174     e = getaddrinfo(hostname, pbuf, &hints, &res0);
5175     if (e)
5176     {
5177 	error (1, 0, "%s", gai_strerror(e));
5178     }
5179     sock = -1;
5180     for (res = res0; res; res = res->ai_next) {
5181 	sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
5182 	if (sock < 0)
5183 	    continue;
5184 
5185 	TRACE (TRACE_FUNCTION, " -> Connecting to %s\n", hostname);
5186 	if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
5187 	    close(sock);
5188 	    sock = -1;
5189 	    continue;
5190 	}
5191 	break;
5192     }
5193     freeaddrinfo(res0);
5194     return sock;
5195 }
5196 
5197 #endif /* defined AUTH_CLIENT_SUPPORT || defined HAVE_KERBEROS
5198 	* || defined HAVE_GSSAPI
5199 	*/
5200 
5201 #endif /* CLIENT_SUPPORT */
5202