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