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