xref: /netbsd/external/gpl2/xcvs/dist/src/client.c (revision 3cd63638)
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.5 2016/05/17 14:00:09 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     if (toplevel_wd)
2293     {
2294 	if (CVS_CHDIR (toplevel_wd) < 0)
2295 	    error (1, errno, "could not chdir to %s", toplevel_wd);
2296     }
2297     for (p = prune_candidates; p; )
2298     {
2299 	if (isemptydir (p->dir, 1))
2300 	{
2301 	    char *b;
2302 
2303 	    if (unlink_file_dir (p->dir) < 0)
2304 		error (0, errno, "cannot remove %s", p->dir);
2305 	    b = strrchr (p->dir, '/');
2306 	    if (!b)
2307 		Subdir_Deregister (NULL, NULL, p->dir);
2308 	    else
2309 	    {
2310 		*b = '\0';
2311 		Subdir_Deregister (NULL, p->dir, b + 1);
2312 	    }
2313 	}
2314 	free (p->dir);
2315 	q = p->next;
2316 	free (p);
2317 	p = q;
2318     }
2319     prune_candidates = NULL;
2320 }
2321 
2322 
2323 
2324 /* Send a Repository line.  */
2325 static char *last_repos;
2326 static char *last_update_dir;
2327 static void
send_repository(const char * dir,const char * repos,const char * update_dir)2328 send_repository (const char *dir, const char *repos, const char *update_dir)
2329 {
2330     char *adm_name;
2331 
2332     /* FIXME: this is probably not the best place to check; I wish I
2333      * knew where in here's callers to really trap this bug.  To
2334      * reproduce the bug, just do this:
2335      *
2336      *       mkdir junk
2337      *       cd junk
2338      *       cvs -d some_repos update foo
2339      *
2340      * Poof, CVS seg faults and dies!  It's because it's trying to
2341      * send a NULL string to the server but dies in send_to_server.
2342      * That string was supposed to be the repository, but it doesn't
2343      * get set because there's no CVSADM dir, and somehow it's not
2344      * getting set from the -d argument either... ?
2345      */
2346     if (!repos)
2347     {
2348         /* Lame error.  I want a real fix but can't stay up to track
2349            this down right now. */
2350         error (1, 0, "no repository");
2351     }
2352 
2353     if (!update_dir || update_dir[0] == '\0')
2354 	update_dir = ".";
2355 
2356     if (last_repos && !strcmp (repos, last_repos)
2357 	&& last_update_dir && !strcmp (update_dir, last_update_dir))
2358 	/* We've already sent it.  */
2359 	return;
2360 
2361     if (client_prune_dirs)
2362 	add_prune_candidate (update_dir);
2363 
2364     /* Add a directory name to the list of those sent to the
2365        server. */
2366     if (update_dir && *update_dir != '\0' && strcmp (update_dir, ".")
2367 	&& !findnode (dirs_sent_to_server, update_dir))
2368     {
2369 	Node *n;
2370 	n = getnode ();
2371 	n->type = NT_UNKNOWN;
2372 	n->key = xstrdup (update_dir);
2373 	n->data = NULL;
2374 
2375 	if (addnode (dirs_sent_to_server, n))
2376 	    error (1, 0, "cannot add directory %s to list", n->key);
2377     }
2378 
2379     /* 80 is large enough for any of CVSADM_*.  */
2380     adm_name = xmalloc (strlen (dir) + 80);
2381 
2382     send_to_server ("Directory ", 0);
2383     {
2384 	/* Send the directory name.  I know that this
2385 	   sort of duplicates code elsewhere, but each
2386 	   case seems slightly different...  */
2387 	char buf[1];
2388 	const char *p = update_dir;
2389 	while (*p != '\0')
2390 	{
2391 	    assert (*p != '\012');
2392 	    if (ISSLASH (*p))
2393 	    {
2394 		buf[0] = '/';
2395 		send_to_server (buf, 1);
2396 	    }
2397 	    else
2398 	    {
2399 		buf[0] = *p;
2400 		send_to_server (buf, 1);
2401 	    }
2402 	    ++p;
2403 	}
2404     }
2405     send_to_server ("\012", 1);
2406     if (supported_request ("Relative-directory"))
2407     {
2408 	const char *short_repos = Short_Repository (repos);
2409 	send_to_server (short_repos, 0);
2410     }
2411     else
2412 	send_to_server (repos, 0);
2413     send_to_server ("\012", 1);
2414 
2415     if (supported_request ("Static-directory"))
2416     {
2417 	adm_name[0] = '\0';
2418 	if (dir[0] != '\0')
2419 	{
2420 	    strcat (adm_name, dir);
2421 	    strcat (adm_name, "/");
2422 	}
2423 	strcat (adm_name, CVSADM_ENTSTAT);
2424 	if (isreadable (adm_name))
2425 	{
2426 	    send_to_server ("Static-directory\012", 0);
2427 	}
2428     }
2429     if (supported_request ("Sticky"))
2430     {
2431 	FILE *f;
2432 	if (dir[0] == '\0')
2433 	    strcpy (adm_name, CVSADM_TAG);
2434 	else
2435 	    sprintf (adm_name, "%s/%s", dir, CVSADM_TAG);
2436 
2437 	f = CVS_FOPEN (adm_name, "r");
2438 	if (!f)
2439 	{
2440 	    if (! existence_error (errno))
2441 		error (1, errno, "reading %s", adm_name);
2442 	}
2443 	else
2444 	{
2445 	    char line[80];
2446 	    char *nl = NULL;
2447 	    send_to_server ("Sticky ", 0);
2448 	    while (fgets (line, sizeof (line), f))
2449 	    {
2450 		send_to_server (line, 0);
2451 		nl = strchr (line, '\n');
2452 		if (nl)
2453 		    break;
2454 	    }
2455 	    if (!nl)
2456                 send_to_server ("\012", 1);
2457 	    if (fclose (f) == EOF)
2458 		error (0, errno, "closing %s", adm_name);
2459 	}
2460     }
2461     free (adm_name);
2462     if (last_repos) free (last_repos);
2463     if (last_update_dir) free (last_update_dir);
2464     last_repos = xstrdup (repos);
2465     last_update_dir = xstrdup (update_dir);
2466 }
2467 
2468 
2469 
2470 /* Send a Repository line and set toplevel_repos.  */
2471 void
send_a_repository(const char * dir,const char * repository,const char * update_dir_in)2472 send_a_repository (const char *dir, const char *repository,
2473                    const char *update_dir_in)
2474 {
2475     char *update_dir = xstrdup (update_dir_in);
2476 
2477     if (!toplevel_repos && repository)
2478     {
2479 	if (update_dir[0] == '\0'
2480 	    || (update_dir[0] == '.' && update_dir[1] == '\0'))
2481 	    toplevel_repos = xstrdup (repository);
2482 	else
2483 	{
2484 	    /*
2485 	     * Get the repository from a CVS/Repository file if update_dir
2486 	     * is absolute.  This is not correct in general, because
2487 	     * the CVS/Repository file might not be the top-level one.
2488 	     * This is for cases like "cvs update /foo/bar" (I'm not
2489 	     * sure it matters what toplevel_repos we get, but it does
2490 	     * matter that we don't hit the "internal error" code below).
2491 	     */
2492 	    if (update_dir[0] == '/')
2493 		toplevel_repos = Name_Repository (update_dir, update_dir);
2494 	    else
2495 	    {
2496 		/*
2497 		 * Guess the repository of that directory by looking at a
2498 		 * subdirectory and removing as many pathname components
2499 		 * as are in update_dir.  I think that will always (or at
2500 		 * least almost always) be 1.
2501 		 *
2502 		 * So this deals with directories which have been
2503 		 * renamed, though it doesn't necessarily deal with
2504 		 * directories which have been put inside other
2505 		 * directories (and cvs invoked on the containing
2506 		 * directory).  I'm not sure the latter case needs to
2507 		 * work.
2508 		 *
2509 		 * 21 Aug 1998: Well, Mr. Above-Comment-Writer, it
2510 		 * does need to work after all.  When we are using the
2511 		 * client in a multi-cvsroot environment, it will be
2512 		 * fairly common that we have the above case (e.g.,
2513 		 * cwd checked out from one repository but
2514 		 * subdirectory checked out from another).  We can't
2515 		 * assume that by walking up a directory in our wd we
2516 		 * necessarily walk up a directory in the repository.
2517 		 */
2518 		/*
2519 		 * This gets toplevel_repos wrong for "cvs update ../foo"
2520 		 * but I'm not sure toplevel_repos matters in that case.
2521 		 */
2522 
2523 		int repository_len, update_dir_len;
2524 
2525 		strip_trailing_slashes (update_dir);
2526 
2527 		repository_len = strlen (repository);
2528 		update_dir_len = strlen (update_dir);
2529 
2530 		/* Try to remove the path components in UPDATE_DIR
2531                    from REPOSITORY.  If the path elements don't exist
2532                    in REPOSITORY, or the removal of those path
2533                    elements mean that we "step above"
2534                    current_parsed_root->directory, set toplevel_repos to
2535                    current_parsed_root->directory. */
2536 		if (repository_len > update_dir_len
2537 		    && !strcmp (repository + repository_len - update_dir_len,
2538 				update_dir)
2539 		    /* TOPLEVEL_REPOS shouldn't be above current_parsed_root->directory */
2540 		    && ((size_t)(repository_len - update_dir_len)
2541 			> strlen (current_parsed_root->directory)))
2542 		{
2543 		    /* The repository name contains UPDATE_DIR.  Set
2544                        toplevel_repos to the repository name without
2545                        UPDATE_DIR. */
2546 
2547 		    toplevel_repos = xmalloc (repository_len - update_dir_len);
2548 		    /* Note that we don't copy the trailing '/'.  */
2549 		    strncpy (toplevel_repos, repository,
2550 			     repository_len - update_dir_len - 1);
2551 		    toplevel_repos[repository_len - update_dir_len - 1] = '\0';
2552 		}
2553 		else
2554 		{
2555 		    toplevel_repos = xstrdup (current_parsed_root->directory);
2556 		}
2557 	    }
2558 	}
2559     }
2560 
2561     send_repository (dir, repository, update_dir);
2562     free (update_dir);
2563 }
2564 
2565 
2566 
2567 static void
notified_a_file(void * data,List * ent_list,const char * short_pathname,const char * filename)2568 notified_a_file (void *data, List *ent_list, const char *short_pathname,
2569                  const char *filename)
2570 {
2571     FILE *fp;
2572     FILE *newf;
2573     size_t line_len = 8192;
2574     char *line = xmalloc (line_len);
2575     char *cp;
2576     int nread;
2577     int nwritten;
2578     char *p;
2579 
2580     fp = xfopen (CVSADM_NOTIFY, "r");
2581     if (getline (&line, &line_len, fp) < 0)
2582     {
2583 	if (feof (fp))
2584 	    error (0, 0, "cannot read %s: end of file", CVSADM_NOTIFY);
2585 	else
2586 	    error (0, errno, "cannot read %s", CVSADM_NOTIFY);
2587 	goto error_exit;
2588     }
2589     cp = strchr (line, '\t');
2590     if (!cp)
2591     {
2592 	error (0, 0, "malformed %s file", CVSADM_NOTIFY);
2593 	goto error_exit;
2594     }
2595     *cp = '\0';
2596     if (strcmp (filename, line + 1))
2597 	error (0, 0, "protocol error: notified %s, expected %s", filename,
2598 	       line + 1);
2599 
2600     if (getline (&line, &line_len, fp) < 0)
2601     {
2602 	if (feof (fp))
2603 	{
2604 	    free (line);
2605 	    if (fclose (fp) < 0)
2606 		error (0, errno, "cannot close %s", CVSADM_NOTIFY);
2607 	    if ( CVS_UNLINK (CVSADM_NOTIFY) < 0)
2608 		error (0, errno, "cannot remove %s", CVSADM_NOTIFY);
2609 	    return;
2610 	}
2611 	else
2612 	{
2613 	    error (0, errno, "cannot read %s", CVSADM_NOTIFY);
2614 	    goto error_exit;
2615 	}
2616     }
2617     newf = xfopen (CVSADM_NOTIFYTMP, "w");
2618     if (fputs (line, newf) < 0)
2619     {
2620 	error (0, errno, "cannot write %s", CVSADM_NOTIFYTMP);
2621 	goto error2;
2622     }
2623     while ((nread = fread (line, 1, line_len, fp)) > 0)
2624     {
2625 	p = line;
2626 	while ((nwritten = fwrite (p, sizeof *p, nread, newf)) > 0)
2627 	{
2628 	    nread -= nwritten;
2629 	    p += nwritten;
2630 	}
2631 	if (ferror (newf))
2632 	{
2633 	    error (0, errno, "cannot write %s", CVSADM_NOTIFYTMP);
2634 	    goto error2;
2635 	}
2636     }
2637     if (ferror (fp))
2638     {
2639 	error (0, errno, "cannot read %s", CVSADM_NOTIFY);
2640 	goto error2;
2641     }
2642     if (fclose (newf) < 0)
2643     {
2644 	error (0, errno, "cannot close %s", CVSADM_NOTIFYTMP);
2645 	goto error_exit;
2646     }
2647     free (line);
2648     if (fclose (fp) < 0)
2649     {
2650 	error (0, errno, "cannot close %s", CVSADM_NOTIFY);
2651 	return;
2652     }
2653 
2654     {
2655         /* In this case, we want rename_file() to ignore noexec. */
2656         int saved_noexec = noexec;
2657         noexec = 0;
2658         rename_file (CVSADM_NOTIFYTMP, CVSADM_NOTIFY);
2659         noexec = saved_noexec;
2660     }
2661 
2662     return;
2663   error2:
2664     (void)fclose (newf);
2665   error_exit:
2666     free (line);
2667     (void)fclose (fp);
2668 }
2669 
2670 
2671 
2672 static void
handle_notified(char * args,size_t len)2673 handle_notified (char *args, size_t len)
2674 {
2675     call_in_directory (args, notified_a_file, NULL);
2676 }
2677 
2678 
2679 
2680 /* The "expanded" modules.  */
2681 static int modules_count;
2682 static int modules_allocated;
2683 static char **modules_vector;
2684 
2685 static void
handle_module_expansion(char * args,size_t len)2686 handle_module_expansion (char *args, size_t len)
2687 {
2688     if (!modules_vector)
2689     {
2690 	modules_allocated = 1; /* Small for testing */
2691 	modules_vector = xnmalloc (modules_allocated,
2692 				   sizeof (modules_vector[0]));
2693     }
2694     else if (modules_count >= modules_allocated)
2695     {
2696 	modules_allocated *= 2;
2697 	modules_vector = xnrealloc (modules_vector,
2698 				    modules_allocated,
2699 				    sizeof (modules_vector[0]));
2700     }
2701     modules_vector[modules_count] = xstrdup (args);
2702     ++modules_count;
2703 }
2704 
2705 
2706 
2707 /* Original, not "expanded" modules.  */
2708 static int module_argc;
2709 static char **module_argv;
2710 
2711 void
client_expand_modules(int argc,char ** argv,int local)2712 client_expand_modules (int argc, char **argv, int local)
2713 {
2714     int errs;
2715     int i;
2716 
2717     module_argc = argc;
2718     module_argv = xnmalloc (argc + 1, sizeof (module_argv[0]));
2719     for (i = 0; i < argc; ++i)
2720 	module_argv[i] = xstrdup (argv[i]);
2721     module_argv[argc] = NULL;
2722 
2723     for (i = 0; i < argc; ++i)
2724 	send_arg (argv[i]);
2725     send_a_repository ("", current_parsed_root->directory, "");
2726 
2727     send_to_server ("expand-modules\012", 0);
2728 
2729     errs = get_server_responses ();
2730 
2731     if (last_repos) free (last_repos);
2732     last_repos = NULL;
2733 
2734     if (last_update_dir) free (last_update_dir);
2735     last_update_dir = NULL;
2736 
2737     if (errs)
2738 	error (errs, 0, "cannot expand modules");
2739 }
2740 
2741 
2742 
2743 void
client_send_expansions(int local,char * where,int build_dirs)2744 client_send_expansions (int local, char *where, int build_dirs)
2745 {
2746     int i;
2747     char *argv[1];
2748 
2749     /* Send the original module names.  The "expanded" module name might
2750        not be suitable as an argument to a co request (e.g. it might be
2751        the result of a -d argument in the modules file).  It might be
2752        cleaner if we genuinely expanded module names, all the way to a
2753        local directory and repository, but that isn't the way it works
2754        now.  */
2755     send_file_names (module_argc, module_argv, 0);
2756 
2757     for (i = 0; i < modules_count; ++i)
2758     {
2759 	argv[0] = where ? where : modules_vector[i];
2760 	if (isfile (argv[0]))
2761 	    send_files (1, argv, local, 0, build_dirs ? SEND_BUILD_DIRS : 0);
2762     }
2763     send_a_repository ("", current_parsed_root->directory, "");
2764 }
2765 
2766 
2767 
2768 void
client_nonexpanded_setup(void)2769 client_nonexpanded_setup (void)
2770 {
2771     send_a_repository ("", current_parsed_root->directory, "");
2772 }
2773 
2774 
2775 
2776 /* Receive a cvswrappers line from the server; it must be a line
2777    containing an RCS option (e.g., "*.exe   -k 'b'").
2778 
2779    Note that this doesn't try to handle -t/-f options (which are a
2780    whole separate issue which noone has thought much about, as far
2781    as I know).
2782 
2783    We need to know the keyword expansion mode so we know whether to
2784    read the file in text or binary mode.  */
2785 static void
handle_wrapper_rcs_option(char * args,size_t len)2786 handle_wrapper_rcs_option (char *args, size_t len)
2787 {
2788     char *p;
2789 
2790     /* Enforce the notes in cvsclient.texi about how the response is not
2791        as free-form as it looks.  */
2792     p = strchr (args, ' ');
2793     if (!p)
2794 	goto handle_error;
2795     if (*++p != '-'
2796 	|| *++p != 'k'
2797 	|| *++p != ' '
2798 	|| *++p != '\'')
2799 	goto handle_error;
2800     if (!strchr (p, '\''))
2801 	goto handle_error;
2802 
2803     /* Add server-side cvswrappers line to our wrapper list. */
2804     wrap_add (args, 0);
2805     return;
2806  handle_error:
2807     error (0, errno, "protocol error: ignoring invalid wrappers %s", args);
2808 }
2809 
2810 
2811 
2812 
2813 static void
handle_m(char * args,size_t len)2814 handle_m (char *args, size_t len)
2815 {
2816     /* In the case where stdout and stderr point to the same place,
2817        fflushing stderr will make output happen in the correct order.
2818        Often stderr will be line-buffered and this won't be needed,
2819        but not always (is that true?  I think the comment is probably
2820        based on being confused between default buffering between
2821        stdout and stderr.  But I'm not sure).  */
2822     fflush (stderr);
2823     fwrite (args, sizeof *args, len, stdout);
2824     putc ('\n', stdout);
2825 }
2826 
2827 
2828 
2829 static void
handle_mbinary(char * args,size_t len)2830 handle_mbinary (char *args, size_t len)
2831 {
2832     char *size_string;
2833     size_t size;
2834     size_t totalread;
2835     size_t nread;
2836     size_t toread;
2837     char buf[8192];
2838 
2839     /* See comment at handle_m about (non)flush of stderr.  */
2840 
2841     /* Get the size.  */
2842     read_line (&size_string);
2843     size = atoi (size_string);
2844     free (size_string);
2845 
2846     /* OK, now get all the data.  The algorithm here is that we read
2847        as much as the network wants to give us in
2848        try_read_from_server, and then we output it all, and then
2849        repeat, until we get all the data.  */
2850     totalread = 0;
2851     while (totalread < size)
2852     {
2853 	toread = size - totalread;
2854 	if (toread > sizeof buf)
2855 	    toread = sizeof buf;
2856 
2857 	nread = try_read_from_server (buf, toread);
2858 	cvs_output_binary (buf, nread);
2859 	totalread += nread;
2860     }
2861 }
2862 
2863 
2864 
2865 static void
handle_e(char * args,size_t len)2866 handle_e (char *args, size_t len)
2867 {
2868     /* In the case where stdout and stderr point to the same place,
2869        fflushing stdout will make output happen in the correct order.  */
2870     fflush (stdout);
2871     fwrite (args, sizeof *args, len, stderr);
2872     putc ('\n', stderr);
2873 }
2874 
2875 
2876 
2877 /*ARGSUSED*/
2878 static void
handle_f(char * args,size_t len)2879 handle_f  (char *args, size_t len)
2880 {
2881     fflush (stderr);
2882 }
2883 
2884 
2885 
2886 static void
handle_mt(char * args,size_t len)2887 handle_mt (char *args, size_t len)
2888 {
2889     char *p;
2890     char *tag = args;
2891     char *text;
2892 
2893     /* See comment at handle_m for more details.  */
2894     fflush (stderr);
2895 
2896     p = strchr (args, ' ');
2897     if (!p)
2898 	text = NULL;
2899     else
2900     {
2901 	*p++ = '\0';
2902 	text = p;
2903     }
2904 
2905     switch (tag[0])
2906     {
2907 	case '+':
2908 	    if (!strcmp (tag, "+updated"))
2909 		updated_seen = 1;
2910 	    else if (!strcmp (tag, "+importmergecmd"))
2911 		importmergecmd.seen = 1;
2912 	    break;
2913 	case '-':
2914 	    if (!strcmp (tag, "-updated"))
2915 		updated_seen = 0;
2916 	    else if (!strcmp (tag, "-importmergecmd"))
2917 	    {
2918 		char buf[80];
2919 
2920 		/* Now that we have gathered the information, we can
2921                    output the suggested merge command.  */
2922 
2923 		if (importmergecmd.conflicts == 0
2924 		    || !importmergecmd.mergetag1
2925 		    || !importmergecmd.mergetag2
2926 		    || !importmergecmd.repository)
2927 		{
2928 		    error (0, 0,
2929 			   "invalid server: incomplete importmergecmd tags");
2930 		    break;
2931 		}
2932 
2933 		if (importmergecmd.conflicts == -1)
2934  		    sprintf (buf, "\nNo conflicts created by this import.\n");
2935 		else
2936 		    sprintf (buf, "\n%d conflicts created by this import.\n",
2937 			     importmergecmd.conflicts);
2938 		cvs_output (buf, 0);
2939 		cvs_output ("Use the following command to help the merge:\n\n",
2940 			    0);
2941 		cvs_output ("\t", 1);
2942 		cvs_output (program_name, 0);
2943 		if (CVSroot_cmdline)
2944 		{
2945 		    cvs_output (" -d ", 0);
2946 		    cvs_output (CVSroot_cmdline, 0);
2947 		}
2948 		cvs_output (" checkout -j", 0);
2949 		cvs_output (importmergecmd.mergetag1, 0);
2950 		cvs_output (" -j", 0);
2951 		cvs_output (importmergecmd.mergetag2, 0);
2952 		cvs_output (" ", 1);
2953 		cvs_output (importmergecmd.repository, 0);
2954 		cvs_output ("\n\n", 0);
2955 
2956 		/* Clear the static variables so that everything is
2957                    ready for any subsequent importmergecmd tag.  */
2958 		importmergecmd.conflicts = 0;
2959 		free (importmergecmd.mergetag1);
2960 		importmergecmd.mergetag1 = NULL;
2961 		free (importmergecmd.mergetag2);
2962 		importmergecmd.mergetag2 = NULL;
2963 		free (importmergecmd.repository);
2964 		importmergecmd.repository = NULL;
2965 
2966 		importmergecmd.seen = 0;
2967 	    }
2968 	    break;
2969 	default:
2970 	    if (updated_seen)
2971 	    {
2972 		if (!strcmp (tag, "fname"))
2973 		{
2974 		    if (updated_fname)
2975 		    {
2976 			/* Output the previous message now.  This can happen
2977 			   if there was no Update-existing or other such
2978 			   response, due to the -n global option.  */
2979 			cvs_output ("U ", 0);
2980 			cvs_output (updated_fname, 0);
2981 			cvs_output ("\n", 1);
2982 			free (updated_fname);
2983 		    }
2984 		    updated_fname = xstrdup (text);
2985 		}
2986 		/* Swallow all other tags.  Either they are extraneous
2987 		   or they reflect future extensions that we can
2988 		   safely ignore.  */
2989 	    }
2990 	    else if (importmergecmd.seen)
2991 	    {
2992 		if (!strcmp (tag, "conflicts"))
2993 		{
2994 		    if (!strcmp (text, "No"))
2995 			importmergecmd.conflicts = -1;
2996 		    else
2997 			importmergecmd.conflicts = atoi (text);
2998 		}
2999 		else if (!strcmp (tag, "mergetag1"))
3000 		    importmergecmd.mergetag1 = xstrdup (text);
3001 		else if (!strcmp (tag, "mergetag2"))
3002 		    importmergecmd.mergetag2 = xstrdup (text);
3003 		else if (!strcmp (tag, "repository"))
3004 		    importmergecmd.repository = xstrdup (text);
3005 		/* Swallow all other tags.  Either they are text for
3006                    which we are going to print our own version when we
3007                    see -importmergecmd, or they are future extensions
3008                    we can safely ignore.  */
3009 	    }
3010 	    else if (!strcmp (tag, "newline"))
3011 		printf ("\n");
3012 	    else if (!strcmp (tag, "date"))
3013 	    {
3014 		char *date = format_date_alloc (text);
3015 		printf ("%s", date);
3016 		free (date);
3017 	    }
3018 	    else if (text)
3019 		printf ("%s", text);
3020     }
3021 }
3022 
3023 
3024 
3025 #endif /* CLIENT_SUPPORT */
3026 #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
3027 
3028 /* This table must be writeable if the server code is included.  */
3029 struct response responses[] =
3030 {
3031 #ifdef CLIENT_SUPPORT
3032 #define RSP_LINE(n, f, t, s) {n, f, t, s}
3033 #else /* ! CLIENT_SUPPORT */
3034 #define RSP_LINE(n, f, t, s) {n, s}
3035 #endif /* CLIENT_SUPPORT */
3036 
3037     RSP_LINE("ok", handle_ok, response_type_ok, rs_essential),
3038     RSP_LINE("error", handle_error, response_type_error, rs_essential),
3039     RSP_LINE("Valid-requests", handle_valid_requests, response_type_normal,
3040        rs_essential),
3041     RSP_LINE("Force-gzip", handle_force_gzip, response_type_normal,
3042        rs_optional),
3043     RSP_LINE("Referrer", handle_referrer, response_type_normal, rs_optional),
3044     RSP_LINE("Redirect", handle_redirect, response_type_redirect, rs_optional),
3045     RSP_LINE("Checked-in", handle_checked_in, response_type_normal,
3046        rs_essential),
3047     RSP_LINE("New-entry", handle_new_entry, response_type_normal, rs_optional),
3048     RSP_LINE("Checksum", handle_checksum, response_type_normal, rs_optional),
3049     RSP_LINE("Copy-file", handle_copy_file, response_type_normal, rs_optional),
3050     RSP_LINE("Updated", handle_updated, response_type_normal, rs_essential),
3051     RSP_LINE("Created", handle_created, response_type_normal, rs_optional),
3052     RSP_LINE("Update-existing", handle_update_existing, response_type_normal,
3053        rs_optional),
3054     RSP_LINE("Merged", handle_merged, response_type_normal, rs_essential),
3055     RSP_LINE("Patched", handle_patched, response_type_normal, rs_optional),
3056     RSP_LINE("Rcs-diff", handle_rcs_diff, response_type_normal, rs_optional),
3057     RSP_LINE("Mode", handle_mode, response_type_normal, rs_optional),
3058     RSP_LINE("Mod-time", handle_mod_time, response_type_normal, rs_optional),
3059     RSP_LINE("Removed", handle_removed, response_type_normal, rs_essential),
3060     RSP_LINE("Remove-entry", handle_remove_entry, response_type_normal,
3061        rs_optional),
3062     RSP_LINE("Set-static-directory", handle_set_static_directory,
3063        response_type_normal,
3064        rs_optional),
3065     RSP_LINE("Clear-static-directory", handle_clear_static_directory,
3066        response_type_normal,
3067        rs_optional),
3068     RSP_LINE("Set-sticky", handle_set_sticky, response_type_normal,
3069        rs_optional),
3070     RSP_LINE("Clear-sticky", handle_clear_sticky, response_type_normal,
3071        rs_optional),
3072     RSP_LINE("Edit-file", handle_edit_file, response_type_normal,
3073        rs_optional),
3074     RSP_LINE("Template", handle_template, response_type_normal,
3075        rs_optional),
3076     RSP_LINE("Clear-template", handle_clear_template, response_type_normal,
3077        rs_optional),
3078     RSP_LINE("Notified", handle_notified, response_type_normal, rs_optional),
3079     RSP_LINE("Module-expansion", handle_module_expansion, response_type_normal,
3080        rs_optional),
3081     RSP_LINE("Wrapper-rcsOption", handle_wrapper_rcs_option,
3082        response_type_normal,
3083        rs_optional),
3084     RSP_LINE("M", handle_m, response_type_normal, rs_essential),
3085     RSP_LINE("Mbinary", handle_mbinary, response_type_normal, rs_optional),
3086     RSP_LINE("E", handle_e, response_type_normal, rs_essential),
3087     RSP_LINE("F", handle_f, response_type_normal, rs_optional),
3088     RSP_LINE("MT", handle_mt, response_type_normal, rs_optional),
3089     /* Possibly should be response_type_error.  */
3090     RSP_LINE(NULL, NULL, response_type_normal, rs_essential)
3091 
3092 #undef RSP_LINE
3093 };
3094 
3095 #endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
3096 #ifdef CLIENT_SUPPORT
3097 
3098 
3099 
3100 /*
3101  * If LEN is 0, then send_to_server_via() computes string's length itself.
3102  *
3103  * Therefore, pass the real length when transmitting data that might
3104  * contain 0's.
3105  */
3106 void
send_to_server_via(struct buffer * via_buffer,const char * str,size_t len)3107 send_to_server_via (struct buffer *via_buffer, const char *str, size_t len)
3108 {
3109     static int nbytes;
3110 
3111     if (len == 0)
3112 	len = strlen (str);
3113 
3114     buf_output (via_buffer, str, len);
3115 
3116     /* There is no reason not to send data to the server, so do it
3117        whenever we've accumulated enough information in the buffer to
3118        make it worth sending.  */
3119     nbytes += len;
3120     if (nbytes >= 2 * BUFFER_DATA_SIZE)
3121     {
3122 	int status;
3123 
3124         status = buf_send_output (via_buffer);
3125 	if (status != 0)
3126 	    error (1, status, "error writing to server");
3127 	nbytes = 0;
3128     }
3129 }
3130 
3131 
3132 
3133 void
send_to_server(const char * str,size_t len)3134 send_to_server (const char *str, size_t len)
3135 {
3136   send_to_server_via (global_to_server, str, len);
3137 }
3138 
3139 
3140 
3141 /* Read up to LEN bytes from the server.  Returns actual number of
3142    bytes read, which will always be at least one; blocks if there is
3143    no data available at all.  Gives a fatal error on EOF or error.  */
3144 static size_t
try_read_from_server(char * buf,size_t len)3145 try_read_from_server( char *buf, size_t len )
3146 {
3147     int status;
3148     size_t nread;
3149     char *data;
3150 
3151     status = buf_read_data (global_from_server, len, &data, &nread);
3152     if (status != 0)
3153     {
3154 	if (status == -1)
3155 	    error (1, 0,
3156 		   "end of file from server (consult above messages if any)");
3157 	else if (status == -2)
3158 	    error (1, 0, "out of memory");
3159 	else
3160 	    error (1, status, "reading from server");
3161     }
3162 
3163     memcpy (buf, data, nread);
3164 
3165     return nread;
3166 }
3167 
3168 
3169 
3170 /*
3171  * Read LEN bytes from the server or die trying.
3172  */
3173 void
read_from_server(char * buf,size_t len)3174 read_from_server (char *buf, size_t len)
3175 {
3176     size_t red = 0;
3177     while (red < len)
3178     {
3179 	red += try_read_from_server (buf + red, len - red);
3180 	if (red == len)
3181 	    break;
3182     }
3183 }
3184 
3185 
3186 
3187 /* Get some server responses and process them.
3188  *
3189  * RETURNS
3190  *   0		Success
3191  *   1		Error
3192  *   2		Redirect
3193  */
3194 int
get_server_responses(void)3195 get_server_responses (void)
3196 {
3197     struct response *rs;
3198     do
3199     {
3200 	char *cmd;
3201 	size_t len;
3202 
3203 	len = read_line (&cmd);
3204 	for (rs = responses; rs->name; ++rs)
3205 	    if (!strncmp (cmd, rs->name, strlen (rs->name)))
3206 	    {
3207 		size_t cmdlen = strlen (rs->name);
3208 		if (cmd[cmdlen] == '\0')
3209 		    ;
3210 		else if (cmd[cmdlen] == ' ')
3211 		    ++cmdlen;
3212 		else
3213 		    /*
3214 		     * The first len characters match, but it's a different
3215 		     * response.  e.g. the response is "oklahoma" but we
3216 		     * matched "ok".
3217 		     */
3218 		    continue;
3219 		(*rs->func) (cmd + cmdlen, len - cmdlen);
3220 		break;
3221 	    }
3222 	if (!rs->name)
3223 	    /* It's OK to print just to the first '\0'.  */
3224 	    /* We might want to handle control characters and the like
3225 	       in some other way other than just sending them to stdout.
3226 	       One common reason for this error is if people use :ext:
3227 	       with a version of rsh which is doing CRLF translation or
3228 	       something, and so the client gets "ok^M" instead of "ok".
3229 	       Right now that will tend to print part of this error
3230 	       message over the other part of it.  It seems like we could
3231 	       do better (either in general, by quoting or omitting all
3232 	       control characters, and/or specifically, by detecting the CRLF
3233 	       case and printing a specific error message).  */
3234 	    error (0, 0,
3235 		   "warning: unrecognized response `%s' from cvs server",
3236 		   cmd);
3237 	free (cmd);
3238     } while (rs->type == response_type_normal);
3239 
3240     if (updated_fname)
3241     {
3242 	/* Output the previous message now.  This can happen
3243 	   if there was no Update-existing or other such
3244 	   response, due to the -n global option.  */
3245 	cvs_output ("U ", 0);
3246 	cvs_output (updated_fname, 0);
3247 	cvs_output ("\n", 1);
3248 	free (updated_fname);
3249 	updated_fname = NULL;
3250     }
3251 
3252     if (rs->type == response_type_redirect) return 2;
3253     if (rs->type == response_type_error) return 1;
3254     if (failure_exit) return 1;
3255     return 0;
3256 }
3257 
3258 
3259 
3260 static inline void
close_connection_to_server(struct buffer ** to,struct buffer ** from)3261 close_connection_to_server (struct buffer **to, struct buffer **from)
3262 {
3263     int status;
3264 
3265     /* First we shut down GLOBAL_TO_SERVER.  That tells the server that its
3266      * input is finished.  It then shuts down the buffer it is sending to us,
3267      * at which point our shut down of GLOBAL_FROM_SERVER will complete.
3268      */
3269 
3270     TRACE (TRACE_FUNCTION, "close_connection_to_server ()");
3271 
3272     status = buf_shutdown (*to);
3273     if (status != 0)
3274 	error (0, status, "shutting down buffer to server");
3275     buf_free (*to);
3276     *to = NULL;
3277 
3278     status = buf_shutdown (*from);
3279     if (status != 0)
3280 	error (0, status, "shutting down buffer from server");
3281     buf_free (*from);
3282     *from = NULL;
3283 }
3284 
3285 
3286 
3287 /* Get the responses and then close the connection.  */
3288 
3289 /*
3290  * Flag var; we'll set it in start_server() and not one of its
3291  * callees, such as start_rsh_server().  This means that there might
3292  * be a small window between the starting of the server and the
3293  * setting of this var, but all the code in that window shouldn't care
3294  * because it's busy checking return values to see if the server got
3295  * started successfully anyway.
3296  */
3297 int server_started = 0;
3298 
3299 int
get_responses_and_close(void)3300 get_responses_and_close (void)
3301 {
3302     int errs = get_server_responses ();
3303 
3304     /* The following is necessary when working with multiple cvsroots, at least
3305      * with commit.  It used to be buried nicely in do_deferred_progs() before
3306      * that function was removed.  I suspect it wouldn't be necessary if
3307      * call_in_directory() saved its working directory via save_cwd() before
3308      * changing its directory and restored the saved working directory via
3309      * restore_cwd() before exiting.  Of course, calling CVS_CHDIR only once,
3310      * here, may be more efficient.
3311      */
3312     if (toplevel_wd)
3313     {
3314 	if (CVS_CHDIR (toplevel_wd) < 0)
3315 	    error (1, errno, "could not chdir to %s", toplevel_wd);
3316     }
3317 
3318     if (client_prune_dirs)
3319 	process_prune_candidates ();
3320 
3321     close_connection_to_server (&global_to_server, &global_from_server);
3322     server_started = 0;
3323 
3324     /* see if we need to sleep before returning to avoid time-stamp races */
3325     if (last_register_time)
3326 	sleep_past (last_register_time);
3327 
3328     return errs;
3329 }
3330 
3331 
3332 
3333 bool
supported_request(const char * name)3334 supported_request (const char *name)
3335 {
3336     struct request *rq;
3337 
3338     for (rq = requests; rq->name; rq++)
3339 	if (!strcmp (rq->name, name))
3340 	    return (rq->flags & RQ_SUPPORTED) != 0;
3341     error (1, 0, "internal error: testing support for unknown request?");
3342     /* NOTREACHED */
3343     return 0;
3344 }
3345 
3346 
3347 
3348 #if defined (AUTH_CLIENT_SUPPORT) || defined (SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
3349 
3350 
3351 /* Generic function to do port number lookup tasks.
3352  *
3353  * In order of precedence, will return:
3354  * 	getenv (envname), if defined
3355  * 	getservbyname (portname), if defined
3356  * 	defaultport
3357  */
3358 static int
get_port_number(const char * envname,const char * portname,int defaultport)3359 get_port_number (const char *envname, const char *portname, int defaultport)
3360 {
3361     struct servent *s;
3362     char *port_s;
3363 
3364     if (envname && (port_s = getenv (envname)))
3365     {
3366 	int port = atoi (port_s);
3367 	if (port <= 0)
3368 	{
3369 	    error (0, 0, "%s must be a positive integer!  If you", envname);
3370 	    error (0, 0, "are trying to force a connection via rsh, please");
3371 	    error (0, 0, "put \":server:\" at the beginning of your CVSROOT");
3372 	    error (1, 0, "variable.");
3373 	}
3374 	return port;
3375     }
3376     else if (portname && (s = getservbyname (portname, "tcp")))
3377 	return ntohs (s->s_port);
3378     else
3379 	return defaultport;
3380 }
3381 
3382 
3383 
3384 /* get the port number for a client to connect to based on the port
3385  * and method of a cvsroot_t.
3386  *
3387  * we do this here instead of in parse_cvsroot so that we can keep network
3388  * code confined to a localized area and also to delay the lookup until the
3389  * last possible moment so it remains possible to run cvs client commands that
3390  * skip opening connections to the server (i.e. skip network operations
3391  * entirely)
3392  *
3393  * and yes, I know none of the commands do that now, but here's to planning
3394  * for the future, eh?  cheers.
3395  */
3396 int
get_cvs_port_number(const cvsroot_t * root)3397 get_cvs_port_number (const cvsroot_t *root)
3398 {
3399 
3400     if (root->port) return root->port;
3401 
3402     switch (root->method)
3403     {
3404 # ifdef HAVE_GSSAPI
3405 	case gserver_method:
3406 # endif /* HAVE_GSSAPI */
3407 # ifdef AUTH_CLIENT_SUPPORT
3408 	case pserver_method:
3409 # endif /* AUTH_CLIENT_SUPPORT */
3410 # if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_GSSAPI)
3411 	    return get_port_number ("CVS_CLIENT_PORT", "cvspserver",
3412                                     CVS_AUTH_PORT);
3413 # endif /* defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_GSSAPI) */
3414 # ifdef HAVE_KERBEROS
3415 	case kserver_method:
3416 	    return get_port_number ("CVS_CLIENT_PORT", "cvs", CVS_PORT);
3417 # endif /* HAVE_KERBEROS */
3418 	default:
3419 	    error(1, EINVAL,
3420 "internal error: get_cvs_port_number called for invalid connection method (%s)",
3421 		  method_names[root->method]);
3422 	    break;
3423     }
3424     /* NOTREACHED */
3425     return -1;
3426 }
3427 
3428 
3429 
3430 /* get the port number for a client to connect to based on the proxy port
3431  * of a cvsroot_t.
3432  */
3433 static int
get_proxy_port_number(const cvsroot_t * root)3434 get_proxy_port_number (const cvsroot_t *root)
3435 {
3436 
3437     if (root->proxy_port) return root->proxy_port;
3438 
3439     return get_port_number ("CVS_PROXY_PORT", NULL, CVS_PROXY_PORT);
3440 }
3441 
3442 
3443 
3444 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)3445 make_bufs_from_fds(int tofd, int fromfd, int child_pid, cvsroot_t *root,
3446                    struct buffer **to_server_p,
3447                    struct buffer **from_server_p, int is_sock)
3448 {
3449 # ifdef NO_SOCKET_TO_FD
3450     if (is_sock)
3451     {
3452 	assert (tofd == fromfd);
3453 	*to_server_p = socket_buffer_initialize (tofd, 0, NULL);
3454 	*from_server_p = socket_buffer_initialize (tofd, 1, NULL);
3455     }
3456     else
3457 # endif /* NO_SOCKET_TO_FD */
3458     {
3459 	/* todo: some OS's don't need these calls... */
3460 	close_on_exec (tofd);
3461 	close_on_exec (fromfd);
3462 
3463 	/* SCO 3 and AIX have a nasty bug in the I/O libraries which precludes
3464 	   fdopening the same file descriptor twice, so dup it if it is the
3465 	   same.  */
3466 	if (tofd == fromfd)
3467 	{
3468 	    fromfd = dup (tofd);
3469 	    if (fromfd < 0)
3470 		error (1, errno, "cannot dup net connection");
3471 	}
3472 
3473 	/* These will use binary mode on systems which have it.  */
3474 	/*
3475 	 * Also, we know that from_server is shut down second, so we pass
3476 	 * child_pid in there.  In theory, it should be stored in both
3477 	 * buffers with a ref count...
3478 	 */
3479 	*to_server_p = fd_buffer_initialize (tofd, 0, root, false, NULL);
3480 	*from_server_p = fd_buffer_initialize (fromfd, child_pid, root,
3481                                                true, NULL);
3482     }
3483 }
3484 #endif /* defined (AUTH_CLIENT_SUPPORT) || defined (SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined(HAVE_GSSAPI) */
3485 
3486 
3487 
3488 #if defined (AUTH_CLIENT_SUPPORT) || defined(HAVE_GSSAPI)
3489 /* Connect to the authenticating server.
3490 
3491    If VERIFY_ONLY is non-zero, then just verify that the password is
3492    correct and then shutdown the connection.
3493 
3494    If VERIFY_ONLY is 0, then really connect to the server.
3495 
3496    If DO_GSSAPI is non-zero, then we use GSSAPI authentication rather
3497    than the pserver password authentication.
3498 
3499    If we fail to connect or if access is denied, then die with fatal
3500    error.  */
3501 void
connect_to_pserver(cvsroot_t * root,struct buffer ** to_server_p,struct buffer ** from_server_p,int verify_only,int do_gssapi)3502 connect_to_pserver (cvsroot_t *root, struct buffer **to_server_p,
3503                     struct buffer **from_server_p, int verify_only,
3504                     int do_gssapi)
3505 {
3506     int sock;
3507     int port_number,
3508 	proxy_port_number = 0; /* Initialize to silence -Wall.  Dumb.  */
3509     char no_passwd = 0;   /* gets set if no password found */
3510     struct buffer *to_server, *from_server;
3511 
3512     port_number = get_cvs_port_number (root);
3513 
3514     /* if we have a proxy connect to that instead */
3515     if (root->proxy_hostname)
3516     {
3517         TRACE (TRACE_FUNCTION, "Connecting to %s:%d via proxy %s:%d.",
3518                root->hostname, port_number, root->proxy_hostname,
3519 	       proxy_port_number);
3520         proxy_port_number = get_proxy_port_number (root);
3521 	sock = connect_to(root->proxy_hostname, proxy_port_number);
3522     }
3523     else
3524     {
3525         TRACE (TRACE_FUNCTION, "Connecting to %s:%d.",
3526                root->hostname, port_number);
3527 	sock = connect_to(root->hostname, port_number);
3528     }
3529 
3530     if (sock == -1)
3531 	error (1, 0, "connect to %s:%d failed: %s",
3532 	       root->proxy_hostname ? root->proxy_hostname : root->hostname,
3533 	       root->proxy_hostname ? proxy_port_number : port_number,
3534                SOCK_STRERROR (SOCK_ERRNO));
3535 
3536     make_bufs_from_fds (sock, sock, 0, root, &to_server, &from_server, 1);
3537 
3538     /* if we have proxy then connect to the proxy first */
3539     if (root->proxy_hostname)
3540     {
3541 #define CONNECT_STRING "CONNECT %s:%d HTTP/1.0\r\n\r\n"
3542 	/* Send a "CONNECT" command to proxy: */
3543 	char* read_buf;
3544 	int codenum;
3545 	size_t count;
3546 	/* 4 characters for port covered by the length of %s & %d */
3547 	char* write_buf = Xasnprintf (NULL, &count, CONNECT_STRING,
3548                                       root->hostname, port_number);
3549 	send_to_server_via (to_server, write_buf, count);
3550 
3551 	/* Wait for HTTP status code, bail out if you don't get back a 2xx
3552          * code.
3553          */
3554 	read_line_via (from_server, to_server, &read_buf);
3555 	count = sscanf (read_buf, "%*s %d", &codenum);
3556 
3557 	if (count != 1 || (codenum / 100) != 2)
3558 	    error (1, 0, "proxy server %s:%d does not support http tunnelling",
3559 		   root->proxy_hostname, proxy_port_number);
3560 	free (read_buf);
3561 	free (write_buf);
3562 
3563 	/* Skip through remaining part of MIME header, recv_line
3564            consumes the trailing \n */
3565 	while (read_line_via (from_server, to_server, &read_buf) > 0)
3566 	{
3567 	    if (read_buf[0] == '\r' || read_buf[0] == 0)
3568 	    {
3569 		free (read_buf);
3570 		break;
3571 	    }
3572 	    free (read_buf);
3573 	}
3574     }
3575 
3576     auth_server (root, to_server, from_server, verify_only, do_gssapi);
3577 
3578     if (verify_only)
3579     {
3580 	int status;
3581 
3582 	status = buf_shutdown (to_server);
3583 	if (status != 0)
3584 	    error (0, status, "shutting down buffer to server");
3585 	buf_free (to_server);
3586 	to_server = NULL;
3587 
3588 	status = buf_shutdown (from_server);
3589 	if (status != 0)
3590 	    error (0, status, "shutting down buffer from server");
3591 	buf_free (from_server);
3592 	from_server = NULL;
3593 
3594 	/* Don't need to set server_started = 0 since we don't set it to 1
3595 	 * until returning from this call.
3596 	 */
3597     }
3598     else
3599     {
3600 	*to_server_p = to_server;
3601 	*from_server_p = from_server;
3602     }
3603 
3604     return;
3605 }
3606 
3607 
3608 
3609 static void
auth_server(cvsroot_t * root,struct buffer * to_server,struct buffer * from_server,int verify_only,int do_gssapi)3610 auth_server (cvsroot_t *root, struct buffer *to_server,
3611              struct buffer *from_server, int verify_only, int do_gssapi)
3612 {
3613     char *username = NULL;		/* the username we use to connect */
3614     char no_passwd = 0;			/* gets set if no password found */
3615 
3616     /* Run the authorization mini-protocol before anything else. */
3617     if (do_gssapi)
3618     {
3619 # ifdef HAVE_GSSAPI
3620 	int fd = buf_get_fd (to_server);
3621 	struct stat s;
3622 
3623 	if ((fd < 0) || (fstat (fd, &s) < 0) || !S_ISSOCK(s.st_mode))
3624 	{
3625 	    error (1, 0,
3626                    "gserver currently only enabled for socket connections");
3627 	}
3628 
3629 	if (! connect_to_gserver (root, fd, root->hostname))
3630 	{
3631 	    error (1, 0,
3632 		    "authorization failed: server %s rejected access to %s",
3633 		    root->hostname, root->directory);
3634 	}
3635 # else /* ! HAVE_GSSAPI */
3636 	error (1, 0,
3637 "INTERNAL ERROR: This client does not support GSSAPI authentication");
3638 # endif /* HAVE_GSSAPI */
3639     }
3640     else /* ! do_gssapi */
3641     {
3642 # ifdef AUTH_CLIENT_SUPPORT
3643 	char *begin      = NULL;
3644 	char *password   = NULL;
3645 	char *end        = NULL;
3646 
3647 	if (verify_only)
3648 	{
3649 	    begin = "BEGIN VERIFICATION REQUEST";
3650 	    end   = "END VERIFICATION REQUEST";
3651 	}
3652 	else
3653 	{
3654 	    begin = "BEGIN AUTH REQUEST";
3655 	    end   = "END AUTH REQUEST";
3656 	}
3657 
3658 	/* Get the password, probably from ~/.cvspass. */
3659 	password = get_cvs_password ();
3660 	username = root->username ? root->username : getcaller();
3661 
3662 	/* Send the empty string by default.  This is so anonymous CVS
3663 	   access doesn't require client to have done "cvs login". */
3664 	if (!password)
3665 	{
3666 	    no_passwd = 1;
3667 	    password = scramble ("");
3668 	}
3669 
3670 	/* Announce that we're starting the authorization protocol. */
3671 	send_to_server_via(to_server, begin, 0);
3672 	send_to_server_via(to_server, "\012", 1);
3673 
3674 	/* Send the data the server needs. */
3675 	send_to_server_via(to_server, root->directory, 0);
3676 	send_to_server_via(to_server, "\012", 1);
3677 	send_to_server_via(to_server, username, 0);
3678 	send_to_server_via(to_server, "\012", 1);
3679 	send_to_server_via(to_server, password, 0);
3680 	send_to_server_via(to_server, "\012", 1);
3681 
3682 	/* Announce that we're ending the authorization protocol. */
3683 	send_to_server_via(to_server, end, 0);
3684 	send_to_server_via(to_server, "\012", 1);
3685 
3686         /* Paranoia. */
3687         free_cvs_password (password);
3688 	password = NULL;
3689 # else /* ! AUTH_CLIENT_SUPPORT */
3690 	error (1, 0, "INTERNAL ERROR: This client does not support pserver authentication");
3691 # endif /* AUTH_CLIENT_SUPPORT */
3692     } /* if (do_gssapi) */
3693 
3694     {
3695 	char *read_buf;
3696 
3697 	/* Loop, getting responses from the server.  */
3698 	while (1)
3699 	{
3700 	    read_line_via (from_server, to_server, &read_buf);
3701 
3702 	    if (!strcmp (read_buf, "I HATE YOU"))
3703 	    {
3704 		/* Authorization not granted.
3705 		 *
3706 		 * This is a little confusing since we can reach this while
3707 		 * loop in GSSAPI mode, but if GSSAPI authentication failed,
3708 		 * we already jumped to the rejected label (there is no case
3709 		 * where the connect_to_gserver function can return 1 and we
3710 		 * will not receive "I LOVE YOU" from the server, barring
3711 		 * broken connections and garbled messages, of course).  The
3712 		 * GSSAPI case is also the case where username can be NULL
3713 		 * since username is initialized in the !gssapi section.
3714 		 *
3715 		 * i.e. This is a pserver specific error message and should be
3716 		 * since GSSAPI doesn't use username.
3717 		 */
3718 		error (0, 0,
3719 "authorization failed: server %s rejected access to %s for user %s",
3720 		       root->hostname, root->directory,
3721 		       username ? username : "(null)");
3722 
3723 		/* Output a special error message if authentication was attempted
3724 		with no password -- the user should be made aware that they may
3725 		have missed a step. */
3726 		if (no_passwd)
3727 		{
3728 		    error (0, 0,
3729 "used empty password; try \"cvs login\" with a real password");
3730 		}
3731 		exit (EXIT_FAILURE);
3732 	    }
3733 	    else if (!strncmp (read_buf, "E ", 2))
3734 	    {
3735 		fprintf (stderr, "%s\n", read_buf + 2);
3736 
3737 		/* Continue with the authentication protocol.  */
3738 	    }
3739 	    else if (!strncmp (read_buf, "error ", 6))
3740 	    {
3741 		char *p;
3742 
3743 		/* First skip the code.  */
3744 		p = read_buf + 6;
3745 		while (*p != ' ' && *p != '\0')
3746 		    ++p;
3747 
3748 		/* Skip the space that follows the code.  */
3749 		if (*p == ' ')
3750 		    ++p;
3751 
3752 		/* Now output the text.  */
3753 		fprintf (stderr, "%s\n", p);
3754 		exit (EXIT_FAILURE);
3755 	    }
3756 	    else if (!strcmp (read_buf, "I LOVE YOU"))
3757 	    {
3758 		free (read_buf);
3759 		break;
3760 	    }
3761 	    else
3762 	    {
3763 		error (1, 0,
3764 		       "unrecognized auth response from %s: %s",
3765 		       root->hostname, read_buf);
3766 	    }
3767 	    free (read_buf);
3768 	}
3769     }
3770 }
3771 #endif /* defined (AUTH_CLIENT_SUPPORT) || defined(HAVE_GSSAPI) */
3772 
3773 
3774 
3775 #if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
3776 /*
3777  * Connect to a forked server process.
3778  */
3779 static void
connect_to_forked_server(cvsroot_t * root,struct buffer ** to_server_p,struct buffer ** from_server_p)3780 connect_to_forked_server (cvsroot_t *root, struct buffer **to_server_p,
3781                           struct buffer **from_server_p)
3782 {
3783     int tofd, fromfd;
3784     int child_pid;
3785 
3786     /* This is pretty simple.  All we need to do is choose the correct
3787        cvs binary and call piped_child. */
3788 
3789      char *command[3];
3790 
3791     command[0] = (root->cvs_server
3792 		  ? root->cvs_server : getenv ("CVS_SERVER"));
3793     if (!command[0])
3794 # ifdef SERVER_SUPPORT
3795         /* FIXME:
3796          * I'm casting out the const below because I know that piped_child, the
3797          * only function we pass COMMAND to, accepts COMMAND as a
3798          * (char *const *) and won't alter it, and we don't alter it in this
3799          * function.  This is yucky, there should be a way to declare COMMAND
3800          * such that this casting isn't needed, but I don't know how.  If I
3801          * declare it as (const char *command[]), the compiler complains about
3802          * an incompatible arg 1 being passed to piped_child and if I declare
3803          * it as (char *const command[3]), then the compiler complains when I
3804          * assign values to command[i].
3805          */
3806 	command[0] = (char *)program_path;
3807 # else /* SERVER_SUPPORT */
3808     {
3809 	error( 0, 0, "You must set the CVS_SERVER environment variable when" );
3810 	error( 0, 0, "using the :fork: access method." );
3811 	error( 1, 0, "This CVS was not compiled with server support." );
3812     }
3813 # endif /* SERVER_SUPPORT */
3814 
3815     command[1] = "server";
3816     command[2] = NULL;
3817 
3818     TRACE (TRACE_FUNCTION, "Forking server: %s %s",
3819 	   command[0] ? command[0] : "(null)", command[1]);
3820 
3821     child_pid = piped_child (command, &tofd, &fromfd, false);
3822     if (child_pid < 0)
3823 	error (1, 0, "could not fork server process");
3824 
3825     make_bufs_from_fds (tofd, fromfd, child_pid, root, to_server_p,
3826                         from_server_p, 0);
3827 }
3828 #endif /* CLIENT_SUPPORT || SERVER_SUPPORT */
3829 
3830 
3831 
3832 static int
send_variable_proc(Node * node,void * closure)3833 send_variable_proc (Node *node, void *closure)
3834 {
3835     send_to_server ("Set ", 0);
3836     send_to_server (node->key, 0);
3837     send_to_server ("=", 1);
3838     send_to_server (node->data, 0);
3839     send_to_server ("\012", 1);
3840     return 0;
3841 }
3842 
3843 
3844 
3845 /* Open up the connection to the server and perform any necessary
3846  * authentication.
3847  */
3848 void
open_connection_to_server(cvsroot_t * root,struct buffer ** to_server_p,struct buffer ** from_server_p)3849 open_connection_to_server (cvsroot_t *root, struct buffer **to_server_p,
3850                            struct buffer **from_server_p)
3851 {
3852     /* Note that generally speaking we do *not* fall back to a different
3853        way of connecting if the first one does not work.  This is slow
3854        (*really* slow on a 14.4kbps link); the clean way to have a CVS
3855        which supports several ways of connecting is with access methods.  */
3856 
3857     TRACE (TRACE_FUNCTION, "open_connection_to_server (%s)", root->original);
3858 
3859     switch (root->method)
3860     {
3861 	case pserver_method:
3862 #ifdef AUTH_CLIENT_SUPPORT
3863 	    /* Toss the return value.  It will die with an error message if
3864 	     * anything goes wrong anyway.
3865 	     */
3866 	    connect_to_pserver (root, to_server_p, from_server_p, 0, 0);
3867 #else /* AUTH_CLIENT_SUPPORT */
3868 	    error (0, 0, "CVSROOT is set for a pserver access method but your");
3869 	    error (1, 0, "CVS executable doesn't support it.");
3870 #endif /* AUTH_CLIENT_SUPPORT */
3871 	    break;
3872 
3873 	case kserver_method:
3874 #if HAVE_KERBEROS
3875 	    start_kerberos4_server (root, to_server_p,
3876                                     from_server_p);
3877 #else /* !HAVE_KERBEROS */
3878 	    error (0, 0,
3879 	           "CVSROOT is set for a kerberos access method but your");
3880 	    error (1, 0, "CVS executable doesn't support it.");
3881 #endif /* HAVE_KERBEROS */
3882 	    break;
3883 
3884 	case gserver_method:
3885 #ifdef HAVE_GSSAPI
3886 	    /* GSSAPI authentication is handled by the pserver.  */
3887 	    connect_to_pserver (root, to_server_p, from_server_p, 0, 1);
3888 #else /* !HAVE_GSSAPI */
3889 	    error (0, 0, "CVSROOT is set for a GSSAPI access method but your");
3890 	    error (1, 0, "CVS executable doesn't support it.");
3891 #endif /* HAVE_GSSAPI */
3892 	    break;
3893 
3894 	case ext_method:
3895 #ifdef NO_EXT_METHOD
3896 	    error (0, 0, ":ext: method not supported by this port of CVS");
3897 	    error (1, 0, "try :server: instead");
3898 #else /* ! NO_EXT_METHOD */
3899 	    start_rsh_server (root, to_server_p,
3900                               from_server_p);
3901 #endif /* NO_EXT_METHOD */
3902 	    break;
3903 
3904 	case server_method:
3905 #ifdef START_SERVER
3906 	    {
3907 	    int tofd, fromfd;
3908 	    START_SERVER (&tofd, &fromfd, getcaller (),
3909 			  root->username,
3910                           root->hostname,
3911 			  root->directory);
3912 # ifdef START_SERVER_RETURNS_SOCKET
3913 	    make_bufs_from_fds (tofd, fromfd, 0, root, to_server_p,
3914                                 from_server_p, 1);
3915 # else /* ! START_SERVER_RETURNS_SOCKET */
3916 	    make_bufs_from_fds (tofd, fromfd, 0, root, to_server_p,
3917                                 from_server_p, 0);
3918 # endif /* START_SERVER_RETURNS_SOCKET */
3919 	    }
3920 #else /* ! START_SERVER */
3921 	    /* FIXME: It should be possible to implement this portably,
3922 	       like pserver, which would get rid of the duplicated code
3923 	       in {vms,windows-NT,...}/startserver.c.  */
3924 	    error (1, 0,
3925 "the :server: access method is not supported by this port of CVS");
3926 #endif /* START_SERVER */
3927 	    break;
3928 
3929         case fork_method:
3930 	    connect_to_forked_server (root, to_server_p, from_server_p);
3931 	    break;
3932 
3933 	default:
3934 	    error (1, 0,
3935                    "(start_server internal error): unknown access method");
3936 	    break;
3937     }
3938 
3939     /* "Hi, I'm Darlene and I'll be your server tonight..." */
3940     server_started = 1;
3941 }
3942 
3943 
3944 
3945 /* Contact the server.  */
3946 void
start_server(void)3947 start_server (void)
3948 {
3949     bool rootless;
3950     int status;
3951     bool have_global;
3952 
3953     do
3954     {
3955 	/* Clear our static variables for this invocation. */
3956 	if (toplevel_repos)
3957 	    free (toplevel_repos);
3958 	toplevel_repos = NULL;
3959 
3960 	open_connection_to_server (current_parsed_root, &global_to_server,
3961 				   &global_from_server);
3962 	setup_logfiles ("CVS_CLIENT_LOG", &global_to_server,
3963 			&global_from_server);
3964 
3965 	/* Clear static variables.  */
3966 	if (toplevel_repos)
3967 	{
3968 	    free (toplevel_repos);
3969 	    toplevel_repos = NULL;
3970 	}
3971 	if (last_repos)
3972 	{
3973 	    free (last_repos);
3974 	    last_repos = NULL;
3975 	}
3976 	if (last_update_dir)
3977 	{
3978 	    free (last_update_dir);
3979 	    last_update_dir = NULL;
3980 	}
3981 	stored_checksum_valid = 0;
3982 	if (stored_mode)
3983 	{
3984 	    free (stored_mode);
3985 	    stored_mode = NULL;
3986 	}
3987 
3988 	rootless = !strcmp (cvs_cmd_name, "init");
3989 	if (!rootless)
3990 	{
3991 	    send_to_server ("Root ", 0);
3992 	    send_to_server (current_parsed_root->directory, 0);
3993 	    send_to_server ("\012", 1);
3994 	}
3995 
3996 	{
3997 	    struct response *rs;
3998 	    bool suppress_redirect = !current_parsed_root->redirect;
3999 
4000 	    send_to_server ("Valid-responses", 0);
4001 
4002 	    for (rs = responses; rs->name; ++rs)
4003 	    {
4004 		if (suppress_redirect && !strcmp (rs->name, "Redirect"))
4005 		    continue;
4006 
4007 		send_to_server (" ", 0);
4008 		send_to_server (rs->name, 0);
4009 	    }
4010 	    send_to_server ("\012", 1);
4011 	}
4012 	send_to_server ("valid-requests\012", 0);
4013 
4014 	if (get_server_responses ())
4015 	    exit (EXIT_FAILURE);
4016 
4017 	have_global = supported_request ("Global_option");
4018 
4019 	/* Encryption needs to come before compression.  Good encryption can
4020 	 * render compression useless in the other direction.
4021 	 */
4022 	if (cvsencrypt && !rootless)
4023 	{
4024 #ifdef ENCRYPTION
4025 	    /* Turn on encryption before turning on compression.  We do
4026 	     * not want to try to compress the encrypted stream.  Instead,
4027 	     * we want to encrypt the compressed stream.  If we can't turn
4028 	     * on encryption, bomb out; don't let the user think the data
4029 	     * is being encrypted when it is not.
4030 	     */
4031 #  ifdef HAVE_KERBEROS
4032 	    if (current_parsed_root->method == kserver_method)
4033 	    {
4034 		if (!supported_request ("Kerberos-encrypt"))
4035 		    error (1, 0, "This server does not support encryption");
4036 		send_to_server ("Kerberos-encrypt\012", 0);
4037 	       initialize_kerberos4_encryption_buffers (&global_to_server,
4038 							&global_from_server);
4039 	    }
4040 	    else
4041 #  endif /* HAVE_KERBEROS */
4042 #  ifdef HAVE_GSSAPI
4043 	    if (current_parsed_root->method == gserver_method)
4044 	    {
4045 		if (!supported_request ("Gssapi-encrypt"))
4046 		    error (1, 0, "This server does not support encryption");
4047 		send_to_server ("Gssapi-encrypt\012", 0);
4048 		initialize_gssapi_buffers (&global_to_server,
4049 					   &global_from_server);
4050 		cvs_gssapi_encrypt = 1;
4051 	    }
4052 	    else
4053 #  endif /* HAVE_GSSAPI */
4054 		error (1, 0,
4055 "Encryption is only supported when using GSSAPI or Kerberos");
4056 #else /* ! ENCRYPTION */
4057 	    error (1, 0, "This client does not support encryption");
4058 #endif /* ! ENCRYPTION */
4059 	}
4060 
4061 	if (nolock && !noexec)
4062 	{
4063 	    if (have_global)
4064 	    {
4065 		send_to_server ("Global_option -u\012", 0);
4066 	    }
4067 	    else
4068 		error (1, 0,
4069 		       "This server does not support the global -u option.");
4070 	}
4071 	/* Send this before compression to enable supression of the
4072 	 * "Forcing compression level Z" messages.
4073 	 */
4074 	if (quiet)
4075 	{
4076 	    if (have_global)
4077 	    {
4078 		send_to_server ("Global_option -q\012", 0);
4079 	    }
4080 	    else
4081 		error (1, 0,
4082 		       "This server does not support the global -q option.");
4083 	}
4084 	if (really_quiet)
4085 	{
4086 	    if (have_global)
4087 	    {
4088 		send_to_server ("Global_option -Q\012", 0);
4089 	    }
4090 	    else
4091 		error (1, 0,
4092 		       "This server does not support the global -Q option.");
4093 	}
4094 
4095 	/* Compression needs to come before any of the rooted requests to
4096 	 * work with compression limits.
4097 	 */
4098 	if (!rootless && (gzip_level || force_gzip))
4099 	{
4100 	    if (supported_request ("Gzip-stream"))
4101 	    {
4102 		char *gzip_level_buf = Xasprintf ("%d", gzip_level);
4103 		send_to_server ("Gzip-stream ", 0);
4104 		send_to_server (gzip_level_buf, 0);
4105 		free (gzip_level_buf);
4106 		send_to_server ("\012", 1);
4107 
4108 		/* All further communication with the server will be
4109 		   compressed.  */
4110 
4111 		global_to_server =
4112 		    compress_buffer_initialize (global_to_server, 0,
4113 					        gzip_level, NULL);
4114 		global_from_server =
4115 		    compress_buffer_initialize (global_from_server, 1,
4116 						gzip_level, NULL);
4117 	    }
4118 #ifndef NO_CLIENT_GZIP_PROCESS
4119 	    else if (supported_request ("gzip-file-contents"))
4120 	    {
4121 		char *gzip_level_buf = Xasprintf ("%d", gzip_level);
4122 		send_to_server ("gzip-file-contents ", 0);
4123 		send_to_server (gzip_level_buf, 0);
4124 		free (gzip_level_buf);
4125 		send_to_server ("\012", 1);
4126 
4127 		file_gzip_level = gzip_level;
4128 	    }
4129 #endif
4130 	    else
4131 	    {
4132 		fprintf (stderr, "server doesn't support gzip-file-contents\n");
4133 		/* Setting gzip_level to 0 prevents us from giving the
4134 		   error twice if update has to contact the server again
4135 		   to fetch unpatchable files.  */
4136 		gzip_level = 0;
4137 	    }
4138 	}
4139 
4140 	if (client_referrer && supported_request ("Referrer"))
4141 	{
4142 	    send_to_server ("Referrer ", 0);
4143 	    send_to_server (client_referrer->original, 0);
4144 	    send_to_server ("\012", 0);
4145 	}
4146 
4147 	/* FIXME: I think we should still be sending this for init.  */
4148 	if (!rootless && supported_request ("Command-prep"))
4149 	{
4150 	    send_to_server ("Command-prep ", 0);
4151 	    send_to_server (cvs_cmd_name, 0);
4152 	    send_to_server ("\012", 0);
4153 	    status = get_server_responses ();
4154 	    if (status == 1) exit (EXIT_FAILURE);
4155 	    if (status == 2) close_connection_to_server (&global_to_server,
4156 							 &global_from_server);
4157 	}
4158 	else status = 0;
4159     } while (status == 2);
4160 
4161 
4162     /*
4163      * Now handle global options.
4164      *
4165      * -H, -f, -d, -e should be handled OK locally.
4166      *
4167      * -b we ignore (treating it as a server installation issue).
4168      * FIXME: should be an error message.
4169      *
4170      * -v we print local version info; FIXME: Add a protocol request to get
4171      * the version from the server so we can print that too.
4172      *
4173      * -l -t -r -w -q -n and -Q need to go to the server.
4174      */
4175     if (noexec)
4176     {
4177 	if (have_global)
4178 	{
4179 	    send_to_server ("Global_option -n\012", 0);
4180 	}
4181 	else
4182 	    error (1, 0,
4183 		   "This server does not support the global -n option.");
4184     }
4185     if (!cvswrite)
4186     {
4187 	if (have_global)
4188 	{
4189 	    send_to_server ("Global_option -r\012", 0);
4190 	}
4191 	else
4192 	    error (1, 0,
4193 		   "This server does not support the global -r option.");
4194     }
4195     if (trace)
4196     {
4197 	if (have_global)
4198 	{
4199 	    int count = trace;
4200 	    while (count--) send_to_server ("Global_option -t\012", 0);
4201 	}
4202 	else
4203 	    error (1, 0,
4204 		   "This server does not support the global -t option.");
4205     }
4206 
4207     /* Find out about server-side cvswrappers.  An extra network
4208        turnaround for cvs import seems to be unavoidable, unless we
4209        want to add some kind of client-side place to configure which
4210        filenames imply binary.  For cvs add, we could avoid the
4211        problem by keeping a copy of the wrappers in CVSADM (the main
4212        reason to bother would be so we could make add work without
4213        contacting the server, I suspect).  */
4214 
4215     if (!strcmp (cvs_cmd_name, "import") || !strcmp (cvs_cmd_name, "add"))
4216     {
4217 	if (supported_request ("wrapper-sendme-rcsOptions"))
4218 	{
4219 	    int err;
4220 	    send_to_server ("wrapper-sendme-rcsOptions\012", 0);
4221 	    err = get_server_responses ();
4222 	    if (err != 0)
4223 		error (err, 0, "error reading from server");
4224 	}
4225     }
4226 
4227     if (cvsauthenticate && ! cvsencrypt && !rootless)
4228     {
4229 	/* Turn on authentication after turning on compression, so
4230 	   that we can compress the authentication information.  We
4231 	   assume that encrypted data is always authenticated--the
4232 	   ability to decrypt the data stream is itself a form of
4233 	   authentication.  */
4234 #ifdef HAVE_GSSAPI
4235 	if (current_parsed_root->method == gserver_method)
4236 	{
4237 	    if (! supported_request ("Gssapi-authenticate"))
4238 		error (1, 0,
4239 		       "This server does not support stream authentication");
4240 	    send_to_server ("Gssapi-authenticate\012", 0);
4241 	    initialize_gssapi_buffers(&global_to_server, &global_from_server);
4242 
4243 	}
4244 	else
4245 	    error (1, 0, "Stream authentication is only supported when using GSSAPI");
4246 #else /* ! HAVE_GSSAPI */
4247 	error (1, 0, "This client does not support stream authentication");
4248 #endif /* ! HAVE_GSSAPI */
4249     }
4250 
4251     /* If "Set" is not supported, just silently fail to send the variables.
4252        Users with an old server should get a useful error message when it
4253        fails to recognize the ${=foo} syntax.  This way if someone uses
4254        several servers, some of which are new and some old, they can still
4255        set user variables in their .cvsrc without trouble.  */
4256     if (supported_request ("Set"))
4257 	walklist (variable_list, send_variable_proc, NULL);
4258 }
4259 
4260 
4261 
4262 /* Send an argument STRING.  */
4263 void
send_arg(const char * string)4264 send_arg (const char *string)
4265 {
4266     const char *p = string;
4267 
4268     send_to_server ("Argument ", 0);
4269 
4270     while (*p)
4271     {
4272 	if (*p == '\n')
4273 	    send_to_server ("\012Argumentx ", 0);
4274 	else
4275 	    send_to_server (p, 1);
4276 	++p;
4277     }
4278     send_to_server ("\012", 1);
4279 }
4280 
4281 
4282 
4283 /* VERS->OPTIONS specifies whether the file is binary or not.  NOTE: BEFORE
4284    using any other fields of the struct vers, we would need to fix
4285    client_process_import_file to set them up.  */
4286 static void
send_modified(const char * file,const char * short_pathname,Vers_TS * vers)4287 send_modified (const char *file, const char *short_pathname, Vers_TS *vers)
4288 {
4289     /* File was modified, send it.  */
4290     struct stat sb;
4291     int fd;
4292     unsigned char *buf;
4293     char *mode_string;
4294     size_t bufsize;
4295     int bin;
4296 
4297     TRACE (TRACE_FUNCTION, "Sending file `%s' to server", file);
4298 
4299     /* Don't think we can assume fstat exists.  */
4300     if (stat (file, &sb) < 0)
4301 	error (1, errno, "reading %s", short_pathname);
4302 
4303     mode_string = mode_to_string (sb.st_mode);
4304 
4305     /* Beware: on systems using CRLF line termination conventions,
4306        the read and write functions will convert CRLF to LF, so the
4307        number of characters read is not the same as sb.st_size.  Text
4308        files should always be transmitted using the LF convention, so
4309        we don't want to disable this conversion.  */
4310     bufsize = sb.st_size;
4311     buf = xmalloc (bufsize);
4312 
4313     /* Is the file marked as containing binary data by the "-kb" flag?
4314        If so, make sure to open it in binary mode: */
4315 
4316     if (vers && vers->options)
4317       bin = !strcmp (vers->options, "-kb");
4318     else
4319       bin = 0;
4320 
4321 #ifdef BROKEN_READWRITE_CONVERSION
4322     if (!bin)
4323     {
4324 	/* If only stdio, not open/write/etc., do text/binary
4325 	   conversion, use convert_file which can compensate
4326 	   (FIXME: we could just use stdio instead which would
4327 	   avoid the whole problem).  */
4328 	char *tfile = Xasprintf ("%s.CVSBFCTMP", file);
4329 	convert_file (file, O_RDONLY,
4330 		      tfile, O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY);
4331 	fd = CVS_OPEN (tfile, O_RDONLY | OPEN_BINARY);
4332 	if (fd < 0)
4333 	    error (1, errno, "reading %s", short_pathname);
4334 	free (tfile);
4335     }
4336     else
4337 	fd = CVS_OPEN (file, O_RDONLY | OPEN_BINARY);
4338 #else
4339     fd = CVS_OPEN (file, O_RDONLY | (bin ? OPEN_BINARY : 0));
4340 #endif
4341 
4342     if (fd < 0)
4343 	error (1, errno, "reading %s", short_pathname);
4344 
4345     if (file_gzip_level && sb.st_size > 100)
4346     {
4347 	size_t newsize = 0;
4348 
4349 	if (read_and_gzip (fd, short_pathname, &buf,
4350 			   &bufsize, &newsize,
4351 			   file_gzip_level))
4352 	    error (1, 0, "aborting due to compression error");
4353 
4354 	if (close (fd) < 0)
4355 	    error (0, errno, "warning: can't close %s", short_pathname);
4356 
4357         {
4358           char tmp[80];
4359 
4360 	  send_to_server ("Modified ", 0);
4361 	  send_to_server (file, 0);
4362 	  send_to_server ("\012", 1);
4363 	  send_to_server (mode_string, 0);
4364 	  send_to_server ("\012z", 2);
4365 	  sprintf (tmp, "%lu\n", (unsigned long) newsize);
4366 	  send_to_server (tmp, 0);
4367 
4368           send_to_server (buf, newsize);
4369         }
4370     }
4371     else
4372     {
4373     	int newsize;
4374 
4375         {
4376 	    unsigned char *bufp = buf;
4377 	    int len;
4378 
4379 	    /* FIXME: This is gross.  It assumes that we might read
4380 	       less than st_size bytes (true on NT), but not more.
4381 	       Instead of this we should just be reading a block of
4382 	       data (e.g. 8192 bytes), writing it to the network, and
4383 	       so on until EOF.  */
4384 	    while ((len = read (fd, bufp, (buf + sb.st_size) - bufp)) > 0)
4385 	        bufp += len;
4386 
4387 	    if (len < 0)
4388 	        error (1, errno, "reading %s", short_pathname);
4389 
4390 	    newsize = bufp - buf;
4391 	}
4392 	if (close (fd) < 0)
4393 	    error (0, errno, "warning: can't close %s", short_pathname);
4394 
4395         {
4396           char tmp[80];
4397 
4398 	  send_to_server ("Modified ", 0);
4399 	  send_to_server (file, 0);
4400 	  send_to_server ("\012", 1);
4401 	  send_to_server (mode_string, 0);
4402 	  send_to_server ("\012", 1);
4403           sprintf (tmp, "%lu\012", (unsigned long) newsize);
4404           send_to_server (tmp, 0);
4405         }
4406 #ifdef BROKEN_READWRITE_CONVERSION
4407 	if (!bin)
4408 	{
4409 	    char *tfile = Xasprintf ("%s.CVSBFCTMP", file);
4410 	    if (CVS_UNLINK (tfile) < 0)
4411 		error (0, errno, "warning: can't remove temp file %s", tfile);
4412 	    free (tfile);
4413 	}
4414 #endif
4415 
4416 	/*
4417 	 * Note that this only ends with a newline if the file ended with
4418 	 * one.
4419 	 */
4420 	if (newsize > 0)
4421 	    send_to_server (buf, newsize);
4422     }
4423     free (buf);
4424     free (mode_string);
4425 }
4426 
4427 
4428 
4429 /* The address of an instance of this structure is passed to
4430    send_fileproc, send_filesdoneproc, and send_direntproc, as the
4431    callerdat parameter.  */
4432 struct send_data
4433 {
4434     /* Each of the following flags are zero for clear or nonzero for set.  */
4435     int build_dirs;
4436     int force;
4437     int no_contents;
4438     int backup_modified;
4439 };
4440 
4441 /* Deal with one file.  */
4442 static int
send_fileproc(void * callerdat,struct file_info * finfo)4443 send_fileproc (void *callerdat, struct file_info *finfo)
4444 {
4445     struct send_data *args = callerdat;
4446     Vers_TS *vers;
4447     struct file_info xfinfo;
4448     /* File name to actually use.  Might differ in case from
4449        finfo->file.  */
4450     const char *filename;
4451 
4452     send_a_repository ("", finfo->repository, finfo->update_dir);
4453 
4454     xfinfo = *finfo;
4455     xfinfo.repository = NULL;
4456     xfinfo.rcs = NULL;
4457     vers = Version_TS (&xfinfo, NULL, NULL, NULL, 0, 0);
4458 
4459     if (vers->entdata)
4460 	filename = vers->entdata->user;
4461     else
4462 	filename = finfo->file;
4463 
4464     if (vers->vn_user)
4465     {
4466 	/* The Entries request.  */
4467 	send_to_server ("Entry /", 0);
4468 	send_to_server (filename, 0);
4469 	send_to_server ("/", 0);
4470 	send_to_server (vers->vn_user, 0);
4471 	send_to_server ("/", 0);
4472 	if (vers->ts_conflict)
4473 	{
4474 	    if (vers->ts_user && !strcmp (vers->ts_conflict, vers->ts_user))
4475 		send_to_server ("+=", 0);
4476 	    else
4477 		send_to_server ("+modified", 0);
4478 	}
4479 	send_to_server ("/", 0);
4480 	send_to_server (vers->entdata ? vers->entdata->options : vers->options,
4481 			0);
4482 	send_to_server ("/", 0);
4483 	if (vers->entdata && vers->entdata->tag)
4484 	{
4485 	    send_to_server ("T", 0);
4486 	    send_to_server (vers->entdata->tag, 0);
4487 	}
4488 	else if (vers->entdata && vers->entdata->date)
4489           {
4490 	    send_to_server ("D", 0);
4491 	    send_to_server (vers->entdata->date, 0);
4492           }
4493 	send_to_server ("\012", 1);
4494     }
4495     else
4496     {
4497 	/* It seems a little silly to re-read this on each file, but
4498 	   send_dirent_proc doesn't get called if filenames are specified
4499 	   explicitly on the command line.  */
4500 	wrap_add_file (CVSDOTWRAPPER, 1);
4501 
4502 	if (wrap_name_has (filename, WRAP_RCSOPTION))
4503 	{
4504 	    /* No "Entry", but the wrappers did give us a kopt so we better
4505 	       send it with "Kopt".  As far as I know this only happens
4506 	       for "cvs add".  Question: is there any reason why checking
4507 	       for options from wrappers isn't done in Version_TS?
4508 
4509 	       Note: it might have been better to just remember all the
4510 	       kopts on the client side, rather than send them to the server,
4511 	       and have it send us back the same kopts.  But that seemed like
4512 	       a bigger change than I had in mind making now.  */
4513 
4514 	    if (supported_request ("Kopt"))
4515 	    {
4516 		char *opt;
4517 
4518 		send_to_server ("Kopt ", 0);
4519 		opt = wrap_rcsoption (filename, 1);
4520 		send_to_server (opt, 0);
4521 		send_to_server ("\012", 1);
4522 		free (opt);
4523 	    }
4524 	    else
4525 		error (0, 0, "\
4526 warning: ignoring -k options due to server limitations");
4527 	}
4528     }
4529 
4530     if (!vers->ts_user)
4531     {
4532 	/*
4533 	 * Do we want to print "file was lost" like normal CVS?
4534 	 * Would it always be appropriate?
4535 	 */
4536 	/* File no longer exists.  Don't do anything, missing files
4537 	   just happen.  */
4538     }
4539     else if (!vers->ts_rcs || args->force
4540 	     || strcmp (vers->ts_conflict
4541 		        ? vers->ts_conflict : vers->ts_rcs, vers->ts_user)
4542 	     || (vers->ts_conflict && !strcmp (cvs_cmd_name, "diff")))
4543     {
4544 	if (args->no_contents
4545 	    && supported_request ("Is-modified"))
4546 	{
4547 	    send_to_server ("Is-modified ", 0);
4548 	    send_to_server (filename, 0);
4549 	    send_to_server ("\012", 1);
4550 	}
4551 	else
4552 	    send_modified (filename, finfo->fullname, vers);
4553 
4554         if (args->backup_modified)
4555         {
4556             char *bakname;
4557             bakname = backup_file (filename, vers->vn_user);
4558             /* This behavior is sufficiently unexpected to
4559                justify overinformativeness, I think. */
4560             if (! really_quiet)
4561                 printf ("(Locally modified %s moved to %s)\n",
4562                         filename, bakname);
4563             free (bakname);
4564         }
4565     }
4566     else
4567     {
4568 	send_to_server ("Unchanged ", 0);
4569 	send_to_server (filename, 0);
4570 	send_to_server ("\012", 1);
4571     }
4572 
4573     /* if this directory has an ignore list, add this file to it */
4574     if (ignlist)
4575     {
4576 	Node *p;
4577 
4578 	p = getnode ();
4579 	p->type = FILES;
4580 	p->key = xstrdup (finfo->file);
4581 	(void) addnode (ignlist, p);
4582     }
4583 
4584     freevers_ts (&vers);
4585     return 0;
4586 }
4587 
4588 
4589 
4590 static void
send_ignproc(const char * file,const char * dir)4591 send_ignproc (const char *file, const char *dir)
4592 {
4593     if (ign_inhibit_server || !supported_request ("Questionable"))
4594     {
4595 	if (dir[0] != '\0')
4596 	    (void) printf ("? %s/%s\n", dir, file);
4597 	else
4598 	    (void) printf ("? %s\n", file);
4599     }
4600     else
4601     {
4602 	send_to_server ("Questionable ", 0);
4603 	send_to_server (file, 0);
4604 	send_to_server ("\012", 1);
4605     }
4606 }
4607 
4608 
4609 
4610 static int
send_filesdoneproc(void * callerdat,int err,const char * repository,const char * update_dir,List * entries)4611 send_filesdoneproc (void *callerdat, int err, const char *repository,
4612                     const char *update_dir, List *entries)
4613 {
4614     /* if this directory has an ignore list, process it then free it */
4615     if (ignlist)
4616     {
4617 	ignore_files (ignlist, entries, update_dir, send_ignproc);
4618 	dellist (&ignlist);
4619     }
4620 
4621     return err;
4622 }
4623 
4624 
4625 
4626 /*
4627  * send_dirent_proc () is called back by the recursion processor before a
4628  * sub-directory is processed for update.
4629  * A return code of 0 indicates the directory should be
4630  * processed by the recursion code.  A return of non-zero indicates the
4631  * recursion code should skip this directory.
4632  *
4633  */
4634 static Dtype
send_dirent_proc(void * callerdat,const char * dir,const char * repository,const char * update_dir,List * entries)4635 send_dirent_proc (void *callerdat, const char *dir, const char *repository,
4636                   const char *update_dir, List *entries)
4637 {
4638     struct send_data *args = callerdat;
4639     int dir_exists;
4640     char *cvsadm_name;
4641 
4642     if (ignore_directory (update_dir))
4643     {
4644 	/* print the warm fuzzy message */
4645 	if (!quiet)
4646 	    error (0, 0, "Ignoring %s", update_dir);
4647         return R_SKIP_ALL;
4648     }
4649 
4650     /*
4651      * If the directory does not exist yet (e.g. "cvs update -d foo"),
4652      * no need to send any files from it.  If the directory does not
4653      * have a CVS directory, then we pretend that it does not exist.
4654      * Otherwise, we will fail when trying to open the Entries file.
4655      * This case will happen when checking out a module defined as
4656      * ``-a .''.
4657      */
4658     cvsadm_name = Xasprintf ("%s/%s", dir, CVSADM);
4659     dir_exists = isdir (cvsadm_name);
4660     free (cvsadm_name);
4661 
4662     /*
4663      * If there is an empty directory (e.g. we are doing `cvs add' on a
4664      * newly-created directory), the server still needs to know about it.
4665      */
4666 
4667     if (dir_exists)
4668     {
4669 	/*
4670 	 * Get the repository from a CVS/Repository file whenever possible.
4671 	 * The repository variable is wrong if the names in the local
4672 	 * directory don't match the names in the repository.
4673 	 */
4674 	char *repos = Name_Repository (dir, update_dir);
4675 	send_a_repository (dir, repos, update_dir);
4676 	free (repos);
4677 
4678 	/* initialize the ignore list for this directory */
4679 	ignlist = getlist ();
4680     }
4681     else
4682     {
4683 	/* It doesn't make sense to send a non-existent directory,
4684 	   because there is no way to get the correct value for
4685 	   the repository (I suppose maybe via the expand-modules
4686 	   request).  In the case where the "obvious" choice for
4687 	   repository is correct, the server can figure out whether
4688 	   to recreate the directory; in the case where it is wrong
4689 	   (that is, does not match what modules give us), we might as
4690 	   well just fail to recreate it.
4691 
4692 	   Checking for noexec is a kludge for "cvs -n add dir".  */
4693 	/* Don't send a non-existent directory unless we are building
4694            new directories (build_dirs is true).  Otherwise, CVS may
4695            see a D line in an Entries file, and recreate a directory
4696            which the user removed by hand.  */
4697 	if (args->build_dirs && noexec)
4698 	    send_a_repository (dir, repository, update_dir);
4699     }
4700 
4701     return dir_exists ? R_PROCESS : R_SKIP_ALL;
4702 }
4703 
4704 
4705 
4706 /*
4707  * send_dirleave_proc () is called back by the recursion code upon leaving
4708  * a directory.  All it does is delete the ignore list if it hasn't already
4709  * been done (by send_filesdone_proc).
4710  */
4711 /* ARGSUSED */
4712 static int
send_dirleave_proc(void * callerdat,const char * dir,int err,const char * update_dir,List * entries)4713 send_dirleave_proc (void *callerdat, const char *dir, int err,
4714                     const char *update_dir, List *entries )
4715 {
4716 
4717     /* Delete the ignore list if it hasn't already been done.  */
4718     if (ignlist)
4719 	dellist (&ignlist);
4720     return err;
4721 }
4722 
4723 
4724 
4725 /*
4726  * Send each option in an array to the server, one by one.
4727  * argv might be "--foo=bar",  "-C", "5", "-y".
4728  */
4729 
4730 void
send_options(int argc,char * const * argv)4731 send_options (int argc, char * const *argv)
4732 {
4733     int i;
4734     for (i = 0; i < argc; i++)
4735 	send_arg (argv[i]);
4736 }
4737 
4738 
4739 
4740 /* Send the names of all the argument files to the server.  */
4741 void
send_file_names(int argc,char ** argv,unsigned int flags)4742 send_file_names (int argc, char **argv, unsigned int flags)
4743 {
4744     int i;
4745 
4746     /* The fact that we do this here as well as start_recursion is a bit
4747        of a performance hit.  Perhaps worth cleaning up someday.  */
4748     if (flags & SEND_EXPAND_WILD)
4749 	expand_wild (argc, argv, &argc, &argv);
4750 
4751     for (i = 0; i < argc; ++i)
4752     {
4753 	char buf[1];
4754 	char *p;
4755 #ifdef FILENAMES_CASE_INSENSITIVE
4756 	char *line = NULL;
4757 #endif /* FILENAMES_CASE_INSENSITIVE */
4758 
4759 	if (arg_should_not_be_sent_to_server (argv[i]))
4760 	    continue;
4761 
4762 #ifdef FILENAMES_CASE_INSENSITIVE
4763 	/* We want to send the path as it appears in the
4764 	   CVS/Entries files.  We put this inside an ifdef
4765 	   to avoid doing all these system calls in
4766 	   cases where fncmp is just strcmp anyway.  */
4767 	/* The isdir (CVSADM) check could more gracefully be replaced
4768 	   with a way of having Entries_Open report back the
4769 	   error to us and letting us ignore existence_error.
4770 	   Or some such.  */
4771 	{
4772 	    List *stack;
4773 	    size_t line_len = 0;
4774 	    char *q, *r;
4775 	    struct saved_cwd sdir;
4776 
4777 	    /* Split the argument onto the stack.  */
4778 	    stack = getlist();
4779 	    r = xstrdup (argv[i]);
4780             /* It's okay to discard the const from the last_component return
4781              * below since we know we passed in an arg that was not const.
4782              */
4783 	    while ((q = (char *)last_component (r)) != r)
4784 	    {
4785 		push (stack, xstrdup (q));
4786 		*--q = '\0';
4787 	    }
4788 	    push (stack, r);
4789 
4790 	    /* Normalize the path into outstr. */
4791 	    save_cwd (&sdir);
4792 	    while (q = pop (stack))
4793 	    {
4794 		Node *node = NULL;
4795 	        if (isdir (CVSADM))
4796 		{
4797 		    List *entries;
4798 
4799 		    /* Note that if we are adding a directory,
4800 		       the following will read the entry
4801 		       that we just wrote there, that is, we
4802 		       will get the case specified on the
4803 		       command line, not the case of the
4804 		       directory in the filesystem.  This
4805 		       is correct behavior.  */
4806 		    entries = Entries_Open (0, NULL);
4807 		    node = findnode_fn (entries, q);
4808 		    if (node)
4809 		    {
4810 			/* Add the slash unless this is our first element. */
4811 			if (line_len)
4812 			    xrealloc_and_strcat (&line, &line_len, "/");
4813 			xrealloc_and_strcat (&line, &line_len, node->key);
4814 			delnode (node);
4815 		    }
4816 		    Entries_Close (entries);
4817 		}
4818 
4819 		/* If node is still NULL then we either didn't find CVSADM or
4820 		 * we didn't find an entry there.
4821 		 */
4822 		if (!node)
4823 		{
4824 		    /* Add the slash unless this is our first element. */
4825 		    if (line_len)
4826 			xrealloc_and_strcat (&line, &line_len, "/");
4827 		    xrealloc_and_strcat (&line, &line_len, q);
4828 		    break;
4829 		}
4830 
4831 		/* And descend the tree. */
4832 		if (isdir (q))
4833 		    CVS_CHDIR (q);
4834 		free (q);
4835 	    }
4836 	    restore_cwd (&sdir);
4837 	    free_cwd (&sdir);
4838 
4839 	    /* Now put everything we didn't find entries for back on. */
4840 	    while (q = pop (stack))
4841 	    {
4842 		if (line_len)
4843 		    xrealloc_and_strcat (&line, &line_len, "/");
4844 		xrealloc_and_strcat (&line, &line_len, q);
4845 		free (q);
4846 	    }
4847 
4848 	    p = line;
4849 
4850 	    dellist (&stack);
4851 	}
4852 #else /* !FILENAMES_CASE_INSENSITIVE */
4853 	p = argv[i];
4854 #endif /* FILENAMES_CASE_INSENSITIVE */
4855 
4856 	send_to_server ("Argument ", 0);
4857 
4858 	while (*p)
4859 	{
4860 	    if (*p == '\n')
4861 	    {
4862 		send_to_server ("\012Argumentx ", 0);
4863 	    }
4864 	    else if (ISSLASH (*p))
4865 	    {
4866 		buf[0] = '/';
4867 		send_to_server (buf, 1);
4868 	    }
4869 	    else
4870 	    {
4871 		buf[0] = *p;
4872 		send_to_server (buf, 1);
4873 	    }
4874 	    ++p;
4875 	}
4876 	send_to_server ("\012", 1);
4877 #ifdef FILENAMES_CASE_INSENSITIVE
4878 	free (line);
4879 #endif /* FILENAMES_CASE_INSENSITIVE */
4880     }
4881 
4882     if (flags & SEND_EXPAND_WILD)
4883     {
4884 	int i;
4885 	for (i = 0; i < argc; ++i)
4886 	    free (argv[i]);
4887 	free (argv);
4888     }
4889 }
4890 
4891 
4892 
4893 /* Calculate and send max-dotdot to the server */
4894 static void
send_max_dotdot(argc,argv)4895 send_max_dotdot (argc, argv)
4896     int argc;
4897     char **argv;
4898 {
4899     int i;
4900     int level = 0;
4901     int max_level = 0;
4902 
4903     /* Send Max-dotdot if needed.  */
4904     for (i = 0; i < argc; ++i)
4905     {
4906         level = pathname_levels (argv[i]);
4907 	if (level > 0)
4908 	{
4909             if (!uppaths) uppaths = getlist();
4910 	    push_string (uppaths, xstrdup (argv[i]));
4911 	}
4912         if (level > max_level)
4913             max_level = level;
4914     }
4915 
4916     if (max_level > 0)
4917     {
4918         if (supported_request ("Max-dotdot"))
4919         {
4920             char buf[10];
4921             sprintf (buf, "%d", max_level);
4922 
4923             send_to_server ("Max-dotdot ", 0);
4924             send_to_server (buf, 0);
4925             send_to_server ("\012", 1);
4926         }
4927         else
4928         {
4929             error (1, 0,
4930 "backreference in path (`..') not supported by old (pre-Max-dotdot) servers");
4931         }
4932     }
4933 }
4934 
4935 
4936 
4937 /* Send Repository, Modified and Entry.  argc and argv contain only
4938   the files to operate on (or empty for everything), not options.
4939   local is nonzero if we should not recurse (-l option).  flags &
4940   SEND_BUILD_DIRS is nonzero if nonexistent directories should be
4941   sent.  flags & SEND_FORCE is nonzero if we should send unmodified
4942   files to the server as though they were modified.  flags &
4943   SEND_NO_CONTENTS means that this command only needs to know
4944   _whether_ a file is modified, not the contents.  Also sends Argument
4945   lines for argc and argv, so should be called after options are sent.  */
4946 void
send_files(int argc,char ** argv,int local,int aflag,unsigned int flags)4947 send_files (int argc, char **argv, int local, int aflag, unsigned int flags)
4948 {
4949     struct send_data args;
4950     int err;
4951 
4952     send_max_dotdot (argc, argv);
4953 
4954     /*
4955      * aflag controls whether the tag/date is copied into the vers_ts.
4956      * But we don't actually use it, so I don't think it matters what we pass
4957      * for aflag here.
4958      */
4959     args.build_dirs = flags & SEND_BUILD_DIRS;
4960     args.force = flags & SEND_FORCE;
4961     args.no_contents = flags & SEND_NO_CONTENTS;
4962     args.backup_modified = flags & BACKUP_MODIFIED_FILES;
4963     err = start_recursion
4964 	(send_fileproc, send_filesdoneproc, send_dirent_proc,
4965          send_dirleave_proc, &args, argc, argv, local, W_LOCAL, aflag,
4966          CVS_LOCK_NONE, NULL, 0, NULL);
4967     if (err)
4968 	exit (EXIT_FAILURE);
4969     if (!toplevel_repos)
4970 	/*
4971 	 * This happens if we are not processing any files,
4972 	 * or for checkouts in directories without any existing stuff
4973 	 * checked out.  The following assignment is correct for the
4974 	 * latter case; I don't think toplevel_repos matters for the
4975 	 * former.
4976 	 */
4977 	toplevel_repos = xstrdup (current_parsed_root->directory);
4978     send_repository ("", toplevel_repos, ".");
4979 }
4980 
4981 
4982 
4983 void
client_import_setup(char * repository)4984 client_import_setup (char *repository)
4985 {
4986     if (!toplevel_repos)		/* should always be true */
4987         send_a_repository ("", repository, "");
4988 }
4989 
4990 
4991 
4992 /*
4993  * Process the argument import file.
4994  */
4995 int
client_process_import_file(char * message,char * vfile,char * vtag,int targc,char * targv[],char * repository,int all_files_binary,int modtime)4996 client_process_import_file (char *message, char *vfile, char *vtag, int targc,
4997                             char *targv[], char *repository,
4998                             int all_files_binary,
4999                             int modtime /* Nonzero for "import -d".  */ )
5000 {
5001     char *update_dir;
5002     char *fullname;
5003     Vers_TS vers;
5004 
5005     assert (toplevel_repos);
5006 
5007     if (strncmp (repository, toplevel_repos, strlen (toplevel_repos)))
5008 	error (1, 0,
5009 	       "internal error: pathname `%s' doesn't specify file in `%s'",
5010 	       repository, toplevel_repos);
5011 
5012     if (!strcmp (repository, toplevel_repos))
5013     {
5014 	update_dir = "";
5015 	fullname = xstrdup (vfile);
5016     }
5017     else
5018     {
5019 	update_dir = repository + strlen (toplevel_repos) + 1;
5020 
5021 	fullname = Xasprintf ("%s/%s", update_dir, vfile);
5022     }
5023 
5024     send_a_repository ("", repository, update_dir);
5025     if (all_files_binary)
5026 	vers.options = xstrdup ("-kb");
5027     else
5028 	vers.options = wrap_rcsoption (vfile, 1);
5029 
5030     if (vers.options)
5031     {
5032 	if (supported_request ("Kopt"))
5033 	{
5034 	    send_to_server ("Kopt ", 0);
5035 	    send_to_server (vers.options, 0);
5036 	    send_to_server ("\012", 1);
5037 	}
5038 	else
5039 	    error (0, 0,
5040 		   "warning: ignoring -k options due to server limitations");
5041     }
5042     if (modtime)
5043     {
5044 	if (supported_request ("Checkin-time"))
5045 	{
5046 	    struct stat sb;
5047 	    char *rcsdate;
5048 	    char netdate[MAXDATELEN];
5049 
5050 	    if (stat (vfile, &sb) < 0)
5051 		error (1, errno, "cannot stat %s", fullname);
5052 	    rcsdate = date_from_time_t (sb.st_mtime);
5053 	    date_to_internet (netdate, rcsdate);
5054 	    free (rcsdate);
5055 
5056 	    send_to_server ("Checkin-time ", 0);
5057 	    send_to_server (netdate, 0);
5058 	    send_to_server ("\012", 1);
5059 	}
5060 	else
5061 	    error (0, 0,
5062 		   "warning: ignoring -d option due to server limitations");
5063     }
5064     send_modified (vfile, fullname, &vers);
5065     if (vers.options)
5066 	free (vers.options);
5067     free (fullname);
5068     return 0;
5069 }
5070 
5071 
5072 
5073 void
client_import_done(void)5074 client_import_done (void)
5075 {
5076     if (!toplevel_repos)
5077 	/*
5078 	 * This happens if we are not processing any files,
5079 	 * or for checkouts in directories without any existing stuff
5080 	 * checked out.  The following assignment is correct for the
5081 	 * latter case; I don't think toplevel_repos matters for the
5082 	 * former.
5083 	 */
5084         /* FIXME: "can't happen" now that we call client_import_setup
5085 	   at the beginning.  */
5086 	toplevel_repos = xstrdup (current_parsed_root->directory);
5087     send_repository ("", toplevel_repos, ".");
5088 }
5089 
5090 
5091 
5092 void
client_notify(const char * repository,const char * update_dir,const char * filename,int notif_type,const char * val)5093 client_notify (const char *repository, const char *update_dir,
5094                const char *filename, int notif_type, const char *val)
5095 {
5096     char buf[2];
5097 
5098     send_a_repository ("", repository, update_dir);
5099     send_to_server ("Notify ", 0);
5100     send_to_server (filename, 0);
5101     send_to_server ("\012", 1);
5102     buf[0] = notif_type;
5103     buf[1] = '\0';
5104     send_to_server (buf, 1);
5105     send_to_server ("\t", 1);
5106     send_to_server (val, 0);
5107 }
5108 
5109 
5110 
5111 /*
5112  * Send an option with an argument, dealing correctly with newlines in
5113  * the argument.  If ARG is NULL, forget the whole thing.
5114  */
5115 void
option_with_arg(const char * option,const char * arg)5116 option_with_arg (const char *option, const char *arg)
5117 {
5118     if (!arg)
5119 	return;
5120 
5121     send_to_server ("Argument ", 0);
5122     send_to_server (option, 0);
5123     send_to_server ("\012", 1);
5124 
5125     send_arg (arg);
5126 }
5127 
5128 
5129 
5130 /* Send a date to the server.  The input DATE is in RCS format.
5131    The time will be GMT.
5132 
5133    We then convert that to the format required in the protocol
5134    (including the "-D" option) and send it.  According to
5135    cvsclient.texi, RFC 822/1123 format is preferred.  */
5136 void
client_senddate(const char * date)5137 client_senddate (const char *date)
5138 {
5139     char buf[MAXDATELEN];
5140 
5141     date_to_internet (buf, date);
5142     option_with_arg ("-D", buf);
5143 }
5144 
5145 
5146 
5147 void
send_init_command(void)5148 send_init_command (void)
5149 {
5150     /* This is here because we need the current_parsed_root->directory variable.  */
5151     send_to_server ("init ", 0);
5152     send_to_server (current_parsed_root->directory, 0);
5153     send_to_server ("\012", 0);
5154 }
5155 
5156 
5157 
5158 #if defined AUTH_CLIENT_SUPPORT || defined HAVE_KERBEROS || defined HAVE_GSSAPI
5159 
5160 static int
connect_to(char * hostname,unsigned int port)5161 connect_to(char *hostname, unsigned int port)
5162 {
5163     struct addrinfo hints, *res, *res0 = NULL;
5164     char pbuf[10];
5165     int e, sock;
5166 
5167     memset(&hints, 0, sizeof(hints));
5168     hints.ai_family = PF_UNSPEC;
5169     hints.ai_socktype = SOCK_STREAM;
5170     hints.ai_flags = AI_CANONNAME;
5171 
5172     snprintf(pbuf, sizeof(pbuf), "%d", port);
5173     e = getaddrinfo(hostname, pbuf, &hints, &res0);
5174     if (e)
5175     {
5176 	error (1, 0, "%s", gai_strerror(e));
5177     }
5178     sock = -1;
5179     for (res = res0; res; res = res->ai_next) {
5180 	sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
5181 	if (sock < 0)
5182 	    continue;
5183 
5184 	TRACE (TRACE_FUNCTION, " -> Connecting to %s\n", hostname);
5185 	if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
5186 	    close(sock);
5187 	    sock = -1;
5188 	    continue;
5189 	}
5190 	break;
5191     }
5192     freeaddrinfo(res0);
5193     return sock;
5194 }
5195 
5196 #endif /* defined AUTH_CLIENT_SUPPORT || defined HAVE_KERBEROS
5197 	* || defined HAVE_GSSAPI
5198 	*/
5199 
5200 #endif /* CLIENT_SUPPORT */
5201