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