xref: /openbsd/gnu/usr.bin/cvs/src/server.c (revision 133306f0)
1 /* This program is free software; you can redistribute it and/or modify
2    it under the terms of the GNU General Public License as published by
3    the Free Software Foundation; either version 2, or (at your option)
4    any later version.
5 
6    This program is distributed in the hope that it will be useful,
7    but WITHOUT ANY WARRANTY; without even the implied warranty of
8    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9    GNU General Public License for more details.  */
10 
11 #include <assert.h>
12 #include "cvs.h"
13 #include "watch.h"
14 #include "edit.h"
15 #include "fileattr.h"
16 #include "getline.h"
17 #include "buffer.h"
18 
19 #ifdef SERVER_SUPPORT
20 
21 #ifdef HAVE_WINSOCK_H
22 #include <winsock.h>
23 #endif
24 
25 #if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
26 #include <sys/socket.h>
27 #endif
28 
29 #ifdef HAVE_KERBEROS
30 #  include <netinet/in.h>
31 #  include <krb.h>
32 #  ifndef HAVE_KRB_GET_ERR_TEXT
33 #    define krb_get_err_text(status) krb_err_txt[status]
34 #  endif
35 
36 /* Information we need if we are going to use Kerberos encryption.  */
37 static C_Block kblock;
38 static Key_schedule sched;
39 
40 #endif
41 
42 #ifdef HAVE_GSSAPI
43 
44 #include <netdb.h>
45 
46 #ifdef HAVE_GSSAPI_H
47 #include <gssapi.h>
48 #endif
49 #ifdef HAVE_GSSAPI_GSSAPI_H
50 #include <gssapi/gssapi.h>
51 #endif
52 #ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
53 #include <gssapi/gssapi_generic.h>
54 #endif
55 
56 #ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
57 #define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
58 #endif
59 
60 /* We use Kerberos 5 routines to map the GSSAPI credential to a user
61    name.  */
62 #include <krb5.h>
63 
64 /* We need this to wrap data.  */
65 static gss_ctx_id_t gcontext;
66 
67 static void gserver_authenticate_connection PROTO((void));
68 
69 /* Whether we are already wrapping GSSAPI communication.  */
70 static int cvs_gssapi_wrapping;
71 
72 #  ifdef ENCRYPTION
73 /* Whether to encrypt GSSAPI communication.  We use a global variable
74    like this because we use the same buffer type (gssapi_wrap) to
75    handle both authentication and encryption, and we don't want
76    multiple instances of that buffer in the communication stream.  */
77 int cvs_gssapi_encrypt;
78 #  endif
79 
80 #endif
81 
82 /* for select */
83 #include <sys/types.h>
84 #ifdef HAVE_SYS_BSDTYPES_H
85 #include <sys/bsdtypes.h>
86 #endif
87 
88 #if TIME_WITH_SYS_TIME
89 # include <sys/time.h>
90 # include <time.h>
91 #else
92 # if HAVE_SYS_TIME_H
93 #  include <sys/time.h>
94 # else
95 #  include <time.h>
96 # endif
97 #endif
98 
99 #if HAVE_SYS_SELECT_H
100 #include <sys/select.h>
101 #endif
102 
103 #ifndef O_NONBLOCK
104 #define O_NONBLOCK O_NDELAY
105 #endif
106 
107 /* EWOULDBLOCK is not defined by POSIX, but some BSD systems will
108    return it, rather than EAGAIN, for nonblocking writes.  */
109 #ifdef EWOULDBLOCK
110 #define blocking_error(err) ((err) == EWOULDBLOCK || (err) == EAGAIN)
111 #else
112 #define blocking_error(err) ((err) == EAGAIN)
113 #endif
114 
115 #ifdef AUTH_SERVER_SUPPORT
116 #ifdef HAVE_GETSPNAM
117 #include <shadow.h>
118 #endif
119 #endif /* AUTH_SERVER_SUPPORT */
120 
121 /* For initgroups().  */
122 #if HAVE_INITGROUPS
123 #include <grp.h>
124 #endif /* HAVE_INITGROUPS */
125 
126 #ifdef AUTH_SERVER_SUPPORT
127 
128 /* The cvs username sent by the client, which might or might not be
129    the same as the system username the server eventually switches to
130    run as.  CVS_Username gets set iff password authentication is
131    successful. */
132 char *CVS_Username = NULL;
133 
134 /* Used to check that same repos is transmitted in pserver auth and in
135    later CVS protocol.  Exported because root.c also uses. */
136 static char *Pserver_Repos = NULL;
137 
138 /* Should we check for system usernames/passwords?  Can be changed by
139    CVSROOT/config.  */
140 int system_auth = 1;
141 
142 #endif /* AUTH_SERVER_SUPPORT */
143 
144 
145 /* While processing requests, this buffer accumulates data to be sent to
146    the client, and then once we are in do_cvs_command, we use it
147    for all the data to be sent.  */
148 static struct buffer *buf_to_net;
149 
150 /* This buffer is used to read input from the client.  */
151 static struct buffer *buf_from_net;
152 
153 /*
154  * This is where we stash stuff we are going to use.  Format string
155  * which expects a single directory within it, starting with a slash.
156  */
157 static char *server_temp_dir;
158 
159 /* This is the original value of server_temp_dir, before any possible
160    changes inserted by serve_max_dotdot.  */
161 static char *orig_server_temp_dir;
162 
163 /* Nonzero if we should keep the temp directory around after we exit.  */
164 static int dont_delete_temp;
165 
166 static void server_write_entries PROTO((void));
167 
168 /* All server communication goes through buffer structures.  Most of
169    the buffers are built on top of a file descriptor.  This structure
170    is used as the closure field in a buffer.  */
171 
172 struct fd_buffer
173 {
174     /* The file descriptor.  */
175     int fd;
176     /* Nonzero if the file descriptor is in blocking mode.  */
177     int blocking;
178 };
179 
180 static struct buffer *fd_buffer_initialize
181   PROTO ((int, int, void (*) (struct buffer *)));
182 static int fd_buffer_input PROTO((void *, char *, int, int, int *));
183 static int fd_buffer_output PROTO((void *, const char *, int, int *));
184 static int fd_buffer_flush PROTO((void *));
185 static int fd_buffer_block PROTO((void *, int));
186 
187 /* Initialize a buffer built on a file descriptor.  FD is the file
188    descriptor.  INPUT is nonzero if this is for input, zero if this is
189    for output.  MEMORY is the function to call when a memory error
190    occurs.  */
191 
192 static struct buffer *
193 fd_buffer_initialize (fd, input, memory)
194      int fd;
195      int input;
196      void (*memory) PROTO((struct buffer *));
197 {
198     struct fd_buffer *n;
199 
200     n = (struct fd_buffer *) xmalloc (sizeof *n);
201     n->fd = fd;
202     n->blocking = 1;
203     return buf_initialize (input ? fd_buffer_input : NULL,
204 			   input ? NULL : fd_buffer_output,
205 			   input ? NULL : fd_buffer_flush,
206 			   fd_buffer_block,
207 			   (int (*) PROTO((void *))) NULL,
208 			   memory,
209 			   n);
210 }
211 
212 /* The buffer input function for a buffer built on a file descriptor.  */
213 
214 static int
215 fd_buffer_input (closure, data, need, size, got)
216      void *closure;
217      char *data;
218      int need;
219      int size;
220      int *got;
221 {
222     struct fd_buffer *fd = (struct fd_buffer *) closure;
223     int nbytes;
224 
225     if (! fd->blocking)
226 	nbytes = read (fd->fd, data, size);
227     else
228     {
229 	/* This case is not efficient.  Fortunately, I don't think it
230            ever actually happens.  */
231 	nbytes = read (fd->fd, data, need == 0 ? 1 : need);
232     }
233 
234     if (nbytes > 0)
235     {
236 	*got = nbytes;
237 	return 0;
238     }
239 
240     *got = 0;
241 
242     if (nbytes == 0)
243     {
244 	/* End of file.  This assumes that we are using POSIX or BSD
245            style nonblocking I/O.  On System V we will get a zero
246            return if there is no data, even when not at EOF.  */
247 	return -1;
248     }
249 
250     /* Some error occurred.  */
251 
252     if (blocking_error (errno))
253     {
254 	/* Everything's fine, we just didn't get any data.  */
255 	return 0;
256     }
257 
258     return errno;
259 }
260 
261 /* The buffer output function for a buffer built on a file descriptor.  */
262 
263 static int
264 fd_buffer_output (closure, data, have, wrote)
265      void *closure;
266      const char *data;
267      int have;
268      int *wrote;
269 {
270     struct fd_buffer *fd = (struct fd_buffer *) closure;
271 
272     *wrote = 0;
273 
274     while (have > 0)
275     {
276 	int nbytes;
277 
278 	nbytes = write (fd->fd, data, have);
279 
280 	if (nbytes <= 0)
281 	{
282 	    if (! fd->blocking
283 		&& (nbytes == 0 || blocking_error (errno)))
284 	    {
285 		/* A nonblocking write failed to write any data.  Just
286                    return.  */
287 		return 0;
288 	    }
289 
290 	    /* Some sort of error occurred.  */
291 
292 	    if (nbytes == 0)
293 	        return EIO;
294 
295 	    return errno;
296 	}
297 
298 	*wrote += nbytes;
299 	data += nbytes;
300 	have -= nbytes;
301     }
302 
303     return 0;
304 }
305 
306 /* The buffer flush function for a buffer built on a file descriptor.  */
307 
308 /*ARGSUSED*/
309 static int
310 fd_buffer_flush (closure)
311      void *closure;
312 {
313     /* Nothing to do.  File descriptors are always flushed.  */
314     return 0;
315 }
316 
317 /* The buffer block function for a buffer built on a file descriptor.  */
318 
319 static int
320 fd_buffer_block (closure, block)
321      void *closure;
322      int block;
323 {
324     struct fd_buffer *fd = (struct fd_buffer *) closure;
325     int flags;
326 
327     flags = fcntl (fd->fd, F_GETFL, 0);
328     if (flags < 0)
329 	return errno;
330 
331     if (block)
332 	flags &= ~O_NONBLOCK;
333     else
334 	flags |= O_NONBLOCK;
335 
336     if (fcntl (fd->fd, F_SETFL, flags) < 0)
337         return errno;
338 
339     fd->blocking = block;
340 
341     return 0;
342 }
343 
344 /* Populate all of the directories between BASE_DIR and its relative
345    subdirectory DIR with CVSADM directories.  Return 0 for success or
346    errno value.  */
347 static int create_adm_p PROTO((char *, char *));
348 
349 static int
350 create_adm_p (base_dir, dir)
351     char *base_dir;
352     char *dir;
353 {
354     char *dir_where_cvsadm_lives, *dir_to_register, *p, *tmp;
355     int retval, done;
356     FILE *f;
357 
358     if (strcmp (dir, ".") == 0)
359 	return 0;			/* nothing to do */
360 
361     /* Allocate some space for our directory-munging string. */
362     p = malloc (strlen (dir) + 1);
363     if (p == NULL)
364 	return ENOMEM;
365 
366     dir_where_cvsadm_lives = malloc (strlen (base_dir) + strlen (dir) + 100);
367     if (dir_where_cvsadm_lives == NULL)
368 	return ENOMEM;
369 
370     /* Allocate some space for the temporary string in which we will
371        construct filenames. */
372     tmp = malloc (strlen (base_dir) + strlen (dir) + 100);
373     if (tmp == NULL)
374 	return ENOMEM;
375 
376 
377     /* We make several passes through this loop.  On the first pass,
378        we simply create the CVSADM directory in the deepest directory.
379        For each subsequent pass, we try to remove the last path
380        element from DIR, create the CVSADM directory in the remaining
381        pathname, and register the subdirectory in the newly created
382        CVSADM directory. */
383 
384     retval = done = 0;
385 
386     strcpy (p, dir);
387     strcpy (dir_where_cvsadm_lives, base_dir);
388     strcat (dir_where_cvsadm_lives, "/");
389     strcat (dir_where_cvsadm_lives, p);
390     dir_to_register = NULL;
391 
392     while (1)
393     {
394 	/* Create CVSADM. */
395 	(void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM);
396 	if ((CVS_MKDIR (tmp, 0777) < 0) && (errno != EEXIST))
397 	{
398 	    retval = errno;
399 	    goto finish;
400 	}
401 
402 	/* Create CVSADM_REP. */
403 	(void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM_REP);
404 	if (! isfile (tmp))
405 	{
406 	    /* Use Emptydir as the placeholder until the client sends
407 	       us the real value.  This code is similar to checkout.c
408 	       (emptydir_name), but the code below returns errors
409 	       differently.  */
410 
411 	    char *empty;
412 	    empty = malloc (strlen (CVSroot_directory)
413 			    + sizeof (CVSROOTADM)
414 			    + sizeof (CVSNULLREPOS)
415 			    + 10);
416 	    if (! empty)
417 	    {
418 		retval = ENOMEM;
419 		goto finish;
420 	    }
421 
422 	    /* Create the directory name. */
423 	    (void) sprintf (empty, "%s/%s/%s", CVSroot_directory,
424 			    CVSROOTADM, CVSNULLREPOS);
425 
426 	    /* Create the directory if it doesn't exist. */
427 	    if (! isfile (empty))
428 	    {
429 		mode_t omask;
430 		omask = umask (cvsumask);
431 		if (CVS_MKDIR (empty, 0777) < 0)
432 		{
433 		    retval = errno;
434 		    free (empty);
435 		    goto finish;
436 		}
437 		(void) umask (omask);
438 	    }
439 
440 
441 	    f = CVS_FOPEN (tmp, "w");
442 	    if (f == NULL)
443 	    {
444 		retval = errno;
445 		free (empty);
446 		goto finish;
447 	    }
448 	    /* Write the directory name to CVSADM_REP. */
449 	    if (fprintf (f, "%s\n", empty) < 0)
450 	    {
451 		retval = errno;
452 		fclose (f);
453 		free (empty);
454 		goto finish;
455 	    }
456 	    if (fclose (f) == EOF)
457 	    {
458 		retval = errno;
459 		free (empty);
460 		goto finish;
461 	    }
462 
463 	    /* Clean up after ourselves. */
464 	    free (empty);
465 	}
466 
467 	/* Create CVSADM_ENT.  We open in append mode because we
468 	   don't want to clobber an existing Entries file.  */
469 	(void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM_ENT);
470 	f = CVS_FOPEN (tmp, "a");
471 	if (f == NULL)
472 	{
473 	    retval = errno;
474 	    goto finish;
475 	}
476 	if (fclose (f) == EOF)
477 	{
478 	    retval = errno;
479 	    goto finish;
480 	}
481 
482 	if (dir_to_register != NULL)
483 	{
484 	    /* FIXME: Yes, this results in duplicate entries in the
485 	       Entries.Log file, but it doesn't currently matter.  We
486 	       might need to change this later on to make sure that we
487 	       only write one entry.  */
488 
489 	    Subdir_Register ((List *) NULL, dir_where_cvsadm_lives,
490 			     dir_to_register);
491 	}
492 
493 	if (done)
494 	    break;
495 
496 	dir_to_register = strrchr (p, '/');
497 	if (dir_to_register == NULL)
498 	{
499 	    dir_to_register = p;
500 	    strcpy (dir_where_cvsadm_lives, base_dir);
501 	    done = 1;
502 	}
503 	else
504 	{
505 	    *dir_to_register = '\0';
506 	    dir_to_register++;
507 	    strcpy (dir_where_cvsadm_lives, base_dir);
508 	    strcat (dir_where_cvsadm_lives, "/");
509 	    strcat (dir_where_cvsadm_lives, p);
510 	}
511     }
512 
513   finish:
514     free (tmp);
515     free (dir_where_cvsadm_lives);
516     free (p);
517     return retval;
518 }
519 
520 /*
521  * Make directory DIR, including all intermediate directories if necessary.
522  * Returns 0 for success or errno code.
523  */
524 static int mkdir_p PROTO((char *));
525 
526 static int
527 mkdir_p (dir)
528      char *dir;
529 {
530     char *p;
531     char *q = malloc (strlen (dir) + 1);
532     int retval;
533 
534     if (q == NULL)
535 	return ENOMEM;
536 
537     retval = 0;
538 
539     /*
540      * Skip over leading slash if present.  We won't bother to try to
541      * make '/'.
542      */
543     p = dir + 1;
544     while (1)
545     {
546 	while (*p != '/' && *p != '\0')
547 	    ++p;
548 	if (*p == '/')
549 	{
550 	    strncpy (q, dir, p - dir);
551 	    q[p - dir] = '\0';
552 	    if (q[p - dir - 1] != '/'  &&  CVS_MKDIR (q, 0777) < 0)
553 	    {
554 		int saved_errno = errno;
555 
556 		if (saved_errno != EEXIST
557 		    && ((saved_errno != EACCES && saved_errno != EROFS)
558 			|| !isdir (q)))
559 		{
560 		    retval = saved_errno;
561 		    goto done;
562 		}
563 	    }
564 	    ++p;
565 	}
566 	else
567 	{
568 	    if (CVS_MKDIR (dir, 0777) < 0)
569 		retval = errno;
570 	    goto done;
571 	}
572     }
573   done:
574     free (q);
575     return retval;
576 }
577 
578 /*
579  * Print the error response for error code STATUS.  The caller is
580  * reponsible for making sure we get back to the command loop without
581  * any further output occuring.
582  * Must be called only in contexts where it is OK to send output.
583  */
584 static void
585 print_error (status)
586     int status;
587 {
588     char *msg;
589     buf_output0 (buf_to_net, "error  ");
590     msg = strerror (status);
591     if (msg)
592 	buf_output0 (buf_to_net, msg);
593     buf_append_char (buf_to_net, '\n');
594 
595     buf_flush (buf_to_net, 0);
596 }
597 
598 static int pending_error;
599 /*
600  * Malloc'd text for pending error.  Each line must start with "E ".  The
601  * last line should not end with a newline.
602  */
603 static char *pending_error_text;
604 
605 /* If an error is pending, print it and return 1.  If not, return 0.
606    Must be called only in contexts where it is OK to send output.  */
607 static int
608 print_pending_error ()
609 {
610     if (pending_error_text)
611     {
612 	buf_output0 (buf_to_net, pending_error_text);
613 	buf_append_char (buf_to_net, '\n');
614 	if (pending_error)
615 	    print_error (pending_error);
616 	else
617 	    buf_output0 (buf_to_net, "error  \n");
618 
619 	buf_flush (buf_to_net, 0);
620 
621 	pending_error = 0;
622 	free (pending_error_text);
623 	pending_error_text = NULL;
624 	return 1;
625     }
626     else if (pending_error)
627     {
628 	print_error (pending_error);
629 	pending_error = 0;
630 	return 1;
631     }
632     else
633 	return 0;
634 }
635 
636 /* Is an error pending?  */
637 #define error_pending() (pending_error || pending_error_text)
638 
639 static int alloc_pending PROTO ((size_t size));
640 
641 /* Allocate SIZE bytes for pending_error_text and return nonzero
642    if we could do it.  */
643 static int
644 alloc_pending (size)
645     size_t size;
646 {
647     if (error_pending ())
648 	/* Probably alloc_pending callers will have already checked for
649 	   this case.  But we might as well handle it if they don't, I
650 	   guess.  */
651 	return 0;
652     pending_error_text = malloc (size);
653     if (pending_error_text == NULL)
654     {
655 	pending_error = ENOMEM;
656 	return 0;
657     }
658     return 1;
659 }
660 
661 static void serve_is_modified PROTO ((char *));
662 
663 static int supported_response PROTO ((char *));
664 
665 static int
666 supported_response (name)
667      char *name;
668 {
669     struct response *rs;
670 
671     for (rs = responses; rs->name != NULL; ++rs)
672 	if (strcmp (rs->name, name) == 0)
673 	    return rs->status == rs_supported;
674     error (1, 0, "internal error: testing support for unknown response?");
675     /* NOTREACHED */
676     return 0;
677 }
678 
679 static void
680 serve_valid_responses (arg)
681      char *arg;
682 {
683     char *p = arg;
684     char *q;
685     struct response *rs;
686     do
687     {
688 	q = strchr (p, ' ');
689 	if (q != NULL)
690 	    *q++ = '\0';
691 	for (rs = responses; rs->name != NULL; ++rs)
692 	{
693 	    if (strcmp (rs->name, p) == 0)
694 		break;
695 	}
696 	if (rs->name == NULL)
697 	    /*
698 	     * It is a response we have never heard of (and thus never
699 	     * will want to use).  So don't worry about it.
700 	     */
701 	    ;
702 	else
703 	    rs->status = rs_supported;
704 	p = q;
705     } while (q != NULL);
706     for (rs = responses; rs->name != NULL; ++rs)
707     {
708 	if (rs->status == rs_essential)
709 	{
710 	    buf_output0 (buf_to_net, "E response `");
711 	    buf_output0 (buf_to_net, rs->name);
712 	    buf_output0 (buf_to_net, "' not supported by client\nerror  \n");
713 
714 	    /* FIXME: This call to buf_flush could conceivably
715 	       cause deadlock, as noted in server_cleanup.  */
716 	    buf_flush (buf_to_net, 1);
717 
718 	    /* I'm doing this manually rather than via error_exit ()
719 	       because I'm not sure whether we want to call server_cleanup.
720 	       Needs more investigation....  */
721 
722 #ifdef SYSTEM_CLEANUP
723 	    /* Hook for OS-specific behavior, for example socket subsystems on
724 	       NT and OS2 or dealing with windows and arguments on Mac.  */
725 	    SYSTEM_CLEANUP ();
726 #endif
727 
728 	    exit (EXIT_FAILURE);
729 	}
730 	else if (rs->status == rs_optional)
731 	    rs->status = rs_not_supported;
732     }
733 }
734 
735 static void
736 serve_root (arg)
737     char *arg;
738 {
739     char *env;
740     char *path;
741     int save_errno;
742     char *arg_dup;
743 
744     if (error_pending()) return;
745 
746     if (!isabsolute (arg))
747     {
748 	if (alloc_pending (80 + strlen (arg)))
749 	    sprintf (pending_error_text,
750 		     "E Root %s must be an absolute pathname", arg);
751 	return;
752     }
753 
754     /* Sending "Root" twice is illegal.
755 
756        The other way to handle a duplicate Root requests would be as a
757        request to clear out all state and start over as if it was a
758        new connection.  Doing this would cause interoperability
759        headaches, so it should be a different request, if there is
760        any reason why such a feature is needed.  */
761     if (CVSroot_directory != NULL)
762     {
763 	if (alloc_pending (80 + strlen (arg)))
764 	    sprintf (pending_error_text,
765 		     "E Protocol error: Duplicate Root request, for %s", arg);
766 	return;
767     }
768 
769 #ifdef AUTH_SERVER_SUPPORT
770     if (Pserver_Repos != NULL)
771     {
772 	if (strcmp (Pserver_Repos, arg) != 0)
773 	{
774 	    if (alloc_pending (80 + strlen (Pserver_Repos) + strlen (arg)))
775 		/* The explicitness is to aid people who are writing clients.
776 		   I don't see how this information could help an
777 		   attacker.  */
778 		sprintf (pending_error_text, "\
779 E Protocol error: Root says \"%s\" but pserver says \"%s\"",
780 			 arg, Pserver_Repos);
781 	}
782     }
783 #endif
784     arg_dup = malloc (strlen (arg) + 1);
785     if (arg_dup == NULL)
786     {
787 	pending_error = ENOMEM;
788 	return;
789     }
790     strcpy (arg_dup, arg);
791     set_local_cvsroot (arg_dup);
792 
793     /* For pserver, this will already have happened, and the call will do
794        nothing.  But for rsh, we need to do it now.  */
795     parse_config (CVSroot_directory);
796 
797     path = malloc (strlen (CVSroot_directory)
798 		   + sizeof (CVSROOTADM)
799 		   + sizeof (CVSROOTADM_HISTORY)
800 		   + 10);
801     if (path == NULL)
802     {
803 	pending_error = ENOMEM;
804 	return;
805     }
806     (void) sprintf (path, "%s/%s", CVSroot_directory, CVSROOTADM);
807     if (!isaccessible (path, R_OK | X_OK))
808     {
809 	save_errno = errno;
810 	pending_error_text = malloc (80 + strlen (path));
811 	if (pending_error_text != NULL)
812 	    sprintf (pending_error_text, "E Cannot access %s", path);
813 	pending_error = save_errno;
814     }
815     (void) strcat (path, "/");
816     (void) strcat (path, CVSROOTADM_HISTORY);
817     if (readonlyfs == 0 && isfile (path) && !isaccessible (path, R_OK | W_OK))
818     {
819 	save_errno = errno;
820 	pending_error_text = malloc (80 + strlen (path));
821 	if (pending_error_text != NULL)
822 	    sprintf (pending_error_text, "E \
823 Sorry, you don't have read/write access to the history file %s", path);
824 	pending_error = save_errno;
825     }
826     free (path);
827 
828 #ifdef HAVE_PUTENV
829     env = malloc (strlen (CVSROOT_ENV) + strlen (CVSroot_directory) + 1 + 1);
830     if (env == NULL)
831     {
832 	pending_error = ENOMEM;
833 	return;
834     }
835     (void) sprintf (env, "%s=%s", CVSROOT_ENV, CVSroot_directory);
836     (void) putenv (env);
837     /* do not free env, as putenv has control of it */
838 #endif
839 }
840 
841 static int max_dotdot_limit = 0;
842 
843 /* Is this pathname OK to recurse into when we are running as the server?
844    If not, call error() with a fatal error.  */
845 void
846 server_pathname_check (path)
847     char *path;
848 {
849     /* An absolute pathname is almost surely a path on the *client* machine,
850        and is unlikely to do us any good here.  It also is probably capable
851        of being a security hole in the anonymous readonly case.  */
852     if (isabsolute (path))
853 	/* Giving an error is actually kind of a cop-out, in the sense
854 	   that it would be nice for "cvs co -d /foo/bar/baz" to work.
855 	   A quick fix in the server would be requiring Max-dotdot of
856 	   at least one if pathnames are absolute, and then putting
857 	   /abs/foo/bar/baz in the temp dir beside the /d/d/d stuff.
858 	   A cleaner fix in the server might be to decouple the
859 	   pathnames we pass back to the client from pathnames in our
860 	   temp directory (this would also probably remove the need
861 	   for Max-dotdot).  A fix in the client would have the client
862 	   turn it into "cd /foo/bar; cvs co -d baz" (more or less).
863 	   This probably has some problems with pathnames which appear
864 	   in messages.  */
865 	error (1, 0, "absolute pathname `%s' illegal for server", path);
866     if (pathname_levels (path) > max_dotdot_limit)
867     {
868 	/* Similar to the isabsolute case in security implications.  */
869 	error (0, 0, "protocol error: `%s' contains more leading ..", path);
870 	error (1, 0, "than the %d which Max-dotdot specified",
871 	       max_dotdot_limit);
872     }
873 }
874 
875 static int outside_root PROTO ((char *));
876 
877 /* Is file or directory REPOS an absolute pathname within the
878    CVSroot_directory?  If yes, return 0.  If no, set pending_error
879    and return 1.  */
880 static int
881 outside_root (repos)
882     char *repos;
883 {
884     size_t repos_len = strlen (repos);
885     size_t root_len = strlen (CVSroot_directory);
886 
887     /* I think isabsolute (repos) should always be true, and that
888        any RELATIVE_REPOS stuff should only be in CVS/Repository
889        files, not the protocol (for compatibility), but I'm putting
890        in the isabsolute check just in case.  */
891     if (!isabsolute (repos))
892     {
893 	if (alloc_pending (repos_len + 80))
894 	    sprintf (pending_error_text, "\
895 E protocol error: %s is not absolute", repos);
896 	return 1;
897     }
898 
899     if (repos_len < root_len
900 	|| strncmp (CVSroot_directory, repos, root_len) != 0)
901     {
902     not_within:
903 	if (alloc_pending (strlen (CVSroot_directory)
904 			   + strlen (repos)
905 			   + 80))
906 	    sprintf (pending_error_text, "\
907 E protocol error: directory '%s' not within root '%s'",
908 		     repos, CVSroot_directory);
909 	return 1;
910     }
911     if (repos_len > root_len)
912     {
913 	if (repos[root_len] != '/')
914 	    goto not_within;
915 	if (pathname_levels (repos + root_len + 1) > 0)
916 	    goto not_within;
917     }
918     return 0;
919 }
920 
921 static int outside_dir PROTO ((char *));
922 
923 /* Is file or directory FILE outside the current directory (that is, does
924    it contain '/')?  If no, return 0.  If yes, set pending_error
925    and return 1.  */
926 static int
927 outside_dir (file)
928     char *file;
929 {
930     if (strchr (file, '/') != NULL)
931     {
932 	if (alloc_pending (strlen (file)
933 			   + 80))
934 	    sprintf (pending_error_text, "\
935 E protocol error: directory '%s' not within current directory",
936 		     file);
937 	return 1;
938     }
939     return 0;
940 }
941 
942 /*
943  * Add as many directories to the temp directory as the client tells us it
944  * will use "..", so we never try to access something outside the temp
945  * directory via "..".
946  */
947 static void
948 serve_max_dotdot (arg)
949     char *arg;
950 {
951     int lim = atoi (arg);
952     int i;
953     char *p;
954 
955     if (lim < 0)
956 	return;
957     p = malloc (strlen (server_temp_dir) + 2 * lim + 10);
958     if (p == NULL)
959     {
960 	pending_error = ENOMEM;
961 	return;
962     }
963     strcpy (p, server_temp_dir);
964     for (i = 0; i < lim; ++i)
965 	strcat (p, "/d");
966     if (server_temp_dir != orig_server_temp_dir)
967 	free (server_temp_dir);
968     server_temp_dir = p;
969     max_dotdot_limit = lim;
970 }
971 
972 static char *dir_name;
973 
974 static void
975 dirswitch (dir, repos)
976     char *dir;
977     char *repos;
978 {
979     int status;
980     FILE *f;
981     size_t dir_len;
982 
983     server_write_entries ();
984 
985     if (error_pending()) return;
986 
987     /* Check for bad directory name.
988 
989        FIXME: could/should unify these checks with server_pathname_check
990        except they need to report errors differently.  */
991     if (isabsolute (dir))
992     {
993 	if (alloc_pending (80 + strlen (dir)))
994 	    sprintf (pending_error_text,
995 		     "E absolute pathname `%s' illegal for server", dir);
996 	return;
997     }
998     if (pathname_levels (dir) > max_dotdot_limit)
999     {
1000 	if (alloc_pending (80 + strlen (dir)))
1001 	    sprintf (pending_error_text,
1002 		     "E protocol error: `%s' has too many ..", dir);
1003 	return;
1004     }
1005 
1006     if (dir_name != NULL)
1007 	free (dir_name);
1008 
1009     dir_len = strlen (dir);
1010 
1011     /* Check for a trailing '/'.  This is not ISDIRSEP because \ in the
1012        protocol is an ordinary character, not a directory separator (of
1013        course, it is perhaps unwise to use it in directory names, but that
1014        is another issue).  */
1015     if (dir_len > 0
1016 	&& dir[dir_len - 1] == '/')
1017     {
1018 	if (alloc_pending (80 + dir_len))
1019 	    sprintf (pending_error_text,
1020 		     "E protocol error: invalid directory syntax in %s", dir);
1021 	return;
1022     }
1023 
1024     dir_name = malloc (strlen (server_temp_dir) + dir_len + 40);
1025     if (dir_name == NULL)
1026     {
1027 	pending_error = ENOMEM;
1028 	return;
1029     }
1030 
1031     strcpy (dir_name, server_temp_dir);
1032     strcat (dir_name, "/");
1033     strcat (dir_name, dir);
1034 
1035     status = mkdir_p (dir_name);
1036     if (status != 0
1037 	&& status != EEXIST)
1038     {
1039 	pending_error = status;
1040 	if (alloc_pending (80 + strlen (dir_name)))
1041 	    sprintf (pending_error_text, "E cannot mkdir %s", dir_name);
1042 	return;
1043     }
1044 
1045     /* We need to create adm directories in all path elements because
1046        we want the server to descend them, even if the client hasn't
1047        sent the appropriate "Argument xxx" command to match the
1048        already-sent "Directory xxx" command.  See recurse.c
1049        (start_recursion) for a big discussion of this.  */
1050 
1051     status = create_adm_p (server_temp_dir, dir);
1052     if (status != 0)
1053     {
1054 	pending_error = status;
1055 	if (alloc_pending (80 + strlen (dir_name)))
1056 	    sprintf (pending_error_text, "E cannot create_adm_p %s", dir_name);
1057 	return;
1058     }
1059 
1060     if ( CVS_CHDIR (dir_name) < 0)
1061     {
1062 	pending_error = errno;
1063 	if (alloc_pending (80 + strlen (dir_name)))
1064 	    sprintf (pending_error_text, "E cannot change to %s", dir_name);
1065 	return;
1066     }
1067     /*
1068      * This is pretty much like calling Create_Admin, but Create_Admin doesn't
1069      * report errors in the right way for us.
1070      */
1071     if ((CVS_MKDIR (CVSADM, 0777) < 0) && (errno != EEXIST))
1072     {
1073 	pending_error = errno;
1074 	return;
1075     }
1076 
1077     /* The following will overwrite the contents of CVSADM_REP.  This
1078        is the correct behavior -- mkdir_p may have written a
1079        placeholder value to this file and we need to insert the
1080        correct value. */
1081 
1082     f = CVS_FOPEN (CVSADM_REP, "w");
1083     if (f == NULL)
1084     {
1085 	pending_error = errno;
1086 	return;
1087     }
1088     if (fprintf (f, "%s", repos) < 0)
1089     {
1090 	pending_error = errno;
1091 	fclose (f);
1092 	return;
1093     }
1094     /* Non-remote CVS handles a module representing the entire tree
1095        (e.g., an entry like ``world -a .'') by putting /. at the end
1096        of the Repository file, so we do the same.  */
1097     if (strcmp (dir, ".") == 0
1098 	&& CVSroot_directory != NULL
1099 	&& strcmp (CVSroot_directory, repos) == 0)
1100     {
1101         if (fprintf (f, "/.") < 0)
1102 	{
1103 	    pending_error = errno;
1104 	    fclose (f);
1105 	    return;
1106 	}
1107     }
1108     if (fprintf (f, "\n") < 0)
1109     {
1110 	pending_error = errno;
1111 	fclose (f);
1112 	return;
1113     }
1114     if (fclose (f) == EOF)
1115     {
1116 	pending_error = errno;
1117 	return;
1118     }
1119     /* We open in append mode because we don't want to clobber an
1120        existing Entries file.  */
1121     f = CVS_FOPEN (CVSADM_ENT, "a");
1122     if (f == NULL)
1123     {
1124 	pending_error = errno;
1125 	if (alloc_pending (80 + strlen (CVSADM_ENT)))
1126 	    sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
1127 	return;
1128     }
1129     if (fclose (f) == EOF)
1130     {
1131 	pending_error = errno;
1132 	if (alloc_pending (80 + strlen (CVSADM_ENT)))
1133 	    sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
1134 	return;
1135     }
1136 }
1137 
1138 static void
1139 serve_repository (arg)
1140     char *arg;
1141 {
1142     pending_error_text = malloc (80);
1143     if (pending_error_text == NULL)
1144 	pending_error = ENOMEM;
1145     else
1146 	strcpy (pending_error_text,
1147 		"E Repository request is obsolete; aborted");
1148     return;
1149 }
1150 
1151 static void
1152 serve_directory (arg)
1153     char *arg;
1154 {
1155     int status;
1156     char *repos;
1157 
1158     status = buf_read_line (buf_from_net, &repos, (int *) NULL);
1159     if (status == 0)
1160     {
1161 	if (outside_root (repos))
1162 	    return;
1163 	dirswitch (arg, repos);
1164 	free (repos);
1165     }
1166     else if (status == -2)
1167     {
1168         pending_error = ENOMEM;
1169     }
1170     else
1171     {
1172 	pending_error_text = malloc (80 + strlen (arg));
1173 	if (pending_error_text == NULL)
1174 	{
1175 	    pending_error = ENOMEM;
1176 	}
1177 	else if (status == -1)
1178 	{
1179 	    sprintf (pending_error_text,
1180 		     "E end of file reading mode for %s", arg);
1181 	}
1182 	else
1183 	{
1184 	    sprintf (pending_error_text,
1185 		     "E error reading mode for %s", arg);
1186 	    pending_error = status;
1187 	}
1188     }
1189 }
1190 
1191 static void
1192 serve_static_directory (arg)
1193     char *arg;
1194 {
1195     FILE *f;
1196 
1197     if (error_pending ()) return;
1198 
1199     f = CVS_FOPEN (CVSADM_ENTSTAT, "w+");
1200     if (f == NULL)
1201     {
1202 	pending_error = errno;
1203 	if (alloc_pending (80 + strlen (CVSADM_ENTSTAT)))
1204 	    sprintf (pending_error_text, "E cannot open %s", CVSADM_ENTSTAT);
1205 	return;
1206     }
1207     if (fclose (f) == EOF)
1208     {
1209 	pending_error = errno;
1210 	if (alloc_pending (80 + strlen (CVSADM_ENTSTAT)))
1211 	    sprintf (pending_error_text, "E cannot close %s", CVSADM_ENTSTAT);
1212 	return;
1213     }
1214 }
1215 
1216 static void
1217 serve_sticky (arg)
1218     char *arg;
1219 {
1220     FILE *f;
1221 
1222     if (error_pending ()) return;
1223 
1224     f = CVS_FOPEN (CVSADM_TAG, "w+");
1225     if (f == NULL)
1226     {
1227 	pending_error = errno;
1228 	if (alloc_pending (80 + strlen (CVSADM_TAG)))
1229 	    sprintf (pending_error_text, "E cannot open %s", CVSADM_TAG);
1230 	return;
1231     }
1232     if (fprintf (f, "%s\n", arg) < 0)
1233     {
1234 	pending_error = errno;
1235 	if (alloc_pending (80 + strlen (CVSADM_TAG)))
1236 	    sprintf (pending_error_text, "E cannot write to %s", CVSADM_TAG);
1237 	return;
1238     }
1239     if (fclose (f) == EOF)
1240     {
1241 	pending_error = errno;
1242 	if (alloc_pending (80 + strlen (CVSADM_TAG)))
1243 	    sprintf (pending_error_text, "E cannot close %s", CVSADM_TAG);
1244 	return;
1245     }
1246 }
1247 
1248 /*
1249  * Read SIZE bytes from buf_from_net, write them to FILE.
1250  *
1251  * Currently this isn't really used for receiving parts of a file --
1252  * the file is still sent over in one chunk.  But if/when we get
1253  * spiffy in-process gzip support working, perhaps the compressed
1254  * pieces could be sent over as they're ready, if the network is fast
1255  * enough.  Or something.
1256  */
1257 static void
1258 receive_partial_file (size, file)
1259      int size;
1260      int file;
1261 {
1262     while (size > 0)
1263     {
1264 	int status, nread;
1265 	char *data;
1266 
1267 	status = buf_read_data (buf_from_net, size, &data, &nread);
1268 	if (status != 0)
1269 	{
1270 	    if (status == -2)
1271 		pending_error = ENOMEM;
1272 	    else
1273 	    {
1274 		pending_error_text = malloc (80);
1275 		if (pending_error_text == NULL)
1276 		    pending_error = ENOMEM;
1277 		else if (status == -1)
1278 		{
1279 		    sprintf (pending_error_text,
1280 			     "E premature end of file from client");
1281 		    pending_error = 0;
1282 		}
1283 		else
1284 		{
1285 		    sprintf (pending_error_text,
1286 			     "E error reading from client");
1287 		    pending_error = status;
1288 		}
1289 	    }
1290 	    return;
1291 	}
1292 
1293 	size -= nread;
1294 
1295 	while (nread > 0)
1296 	{
1297 	    int nwrote;
1298 
1299 	    nwrote = write (file, data, nread);
1300 	    if (nwrote < 0)
1301 	    {
1302 		pending_error_text = malloc (40);
1303 		if (pending_error_text != NULL)
1304 		    sprintf (pending_error_text, "E unable to write");
1305 		pending_error = errno;
1306 
1307 		/* Read and discard the file data.  */
1308 		while (size > 0)
1309 		{
1310 		    int status, nread;
1311 		    char *data;
1312 
1313 		    status = buf_read_data (buf_from_net, size, &data, &nread);
1314 		    if (status != 0)
1315 			return;
1316 		    size -= nread;
1317 		}
1318 
1319 		return;
1320 	    }
1321 	    nread -= nwrote;
1322 	    data += nwrote;
1323 	}
1324     }
1325 }
1326 
1327 /* Receive SIZE bytes, write to filename FILE.  */
1328 static void
1329 receive_file (size, file, gzipped)
1330      int size;
1331      char *file;
1332      int gzipped;
1333 {
1334     int fd;
1335     char *arg = file;
1336 
1337     /* Write the file.  */
1338     fd = CVS_OPEN (arg, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1339     if (fd < 0)
1340     {
1341 	pending_error_text = malloc (40 + strlen (arg));
1342 	if (pending_error_text)
1343 	    sprintf (pending_error_text, "E cannot open %s", arg);
1344 	pending_error = errno;
1345 	return;
1346     }
1347 
1348     if (gzipped)
1349     {
1350 	/* Using gunzip_and_write isn't really a high-performance
1351 	   approach, because it keeps the whole thing in memory
1352 	   (contiguous memory, worse yet).  But it seems easier to
1353 	   code than the alternative (and less vulnerable to subtle
1354 	   bugs).  Given that this feature is mainly for
1355 	   compatibility, that is the better tradeoff.  */
1356 
1357 	int toread = size;
1358 	char *filebuf;
1359 	char *p;
1360 
1361 	filebuf = malloc (size);
1362 	p = filebuf;
1363 	/* If NULL, we still want to read the data and discard it.  */
1364 
1365 	while (toread > 0)
1366 	{
1367 	    int status, nread;
1368 	    char *data;
1369 
1370 	    status = buf_read_data (buf_from_net, toread, &data, &nread);
1371 	    if (status != 0)
1372 	    {
1373 		if (status == -2)
1374 		    pending_error = ENOMEM;
1375 		else
1376 		{
1377 		    pending_error_text = malloc (80);
1378 		    if (pending_error_text == NULL)
1379 			pending_error = ENOMEM;
1380 		    else if (status == -1)
1381 		    {
1382 			sprintf (pending_error_text,
1383 				 "E premature end of file from client");
1384 			pending_error = 0;
1385 		    }
1386 		    else
1387 		    {
1388 			sprintf (pending_error_text,
1389 				 "E error reading from client");
1390 			pending_error = status;
1391 		    }
1392 		}
1393 		return;
1394 	    }
1395 
1396 	    toread -= nread;
1397 
1398 	    if (filebuf != NULL)
1399 	    {
1400 		memcpy (p, data, nread);
1401 		p += nread;
1402 	    }
1403 	}
1404 	if (filebuf == NULL)
1405 	{
1406 	    pending_error = ENOMEM;
1407 	    goto out;
1408 	}
1409 
1410 	if (gunzip_and_write (fd, file, filebuf, size))
1411 	{
1412 	    if (alloc_pending (80))
1413 		sprintf (pending_error_text,
1414 			 "E aborting due to compression error");
1415 	}
1416 	free (filebuf);
1417     }
1418     else
1419 	receive_partial_file (size, fd);
1420 
1421     if (pending_error_text)
1422     {
1423 	char *p = realloc (pending_error_text,
1424 			   strlen (pending_error_text) + strlen (arg) + 30);
1425 	if (p)
1426 	{
1427 	    pending_error_text = p;
1428 	    sprintf (p + strlen (p), ", file %s", arg);
1429 	}
1430 	/* else original string is supposed to be unchanged */
1431     }
1432 
1433  out:
1434     if (close (fd) < 0 && !error_pending ())
1435     {
1436 	pending_error_text = malloc (40 + strlen (arg));
1437 	if (pending_error_text)
1438 	    sprintf (pending_error_text, "E cannot close %s", arg);
1439 	pending_error = errno;
1440 	return;
1441     }
1442 }
1443 
1444 /* Kopt for the next file sent in Modified or Is-modified.  */
1445 static char *kopt;
1446 
1447 /* Timestamp (Checkin-time) for next file sent in Modified or
1448    Is-modified.  */
1449 static int checkin_time_valid;
1450 static time_t checkin_time;
1451 
1452 static void serve_modified PROTO ((char *));
1453 
1454 static void
1455 serve_modified (arg)
1456      char *arg;
1457 {
1458     int size, status;
1459     char *size_text;
1460     char *mode_text;
1461 
1462     int gzipped = 0;
1463 
1464     /*
1465      * This used to return immediately if error_pending () was true.
1466      * However, that fails, because it causes each line of the file to
1467      * be echoed back to the client as an unrecognized command.  The
1468      * client isn't reading from the socket, so eventually both
1469      * processes block trying to write to the other.  Now, we try to
1470      * read the file if we can.
1471      */
1472 
1473     status = buf_read_line (buf_from_net, &mode_text, (int *) NULL);
1474     if (status != 0)
1475     {
1476         if (status == -2)
1477 	    pending_error = ENOMEM;
1478 	else
1479 	{
1480 	    pending_error_text = malloc (80 + strlen (arg));
1481 	    if (pending_error_text == NULL)
1482 		pending_error = ENOMEM;
1483 	    else
1484 	    {
1485 		if (status == -1)
1486 		    sprintf (pending_error_text,
1487 			     "E end of file reading mode for %s", arg);
1488 		else
1489 		{
1490 		    sprintf (pending_error_text,
1491 			     "E error reading mode for %s", arg);
1492 		    pending_error = status;
1493 		}
1494 	    }
1495 	}
1496 	return;
1497     }
1498 
1499     status = buf_read_line (buf_from_net, &size_text, (int *) NULL);
1500     if (status != 0)
1501     {
1502 	if (status == -2)
1503 	    pending_error = ENOMEM;
1504 	else
1505 	{
1506 	    pending_error_text = malloc (80 + strlen (arg));
1507 	    if (pending_error_text == NULL)
1508 		pending_error = ENOMEM;
1509 	    else
1510 	    {
1511 		if (status == -1)
1512 		    sprintf (pending_error_text,
1513 			     "E end of file reading size for %s", arg);
1514 		else
1515 		{
1516 		    sprintf (pending_error_text,
1517 			     "E error reading size for %s", arg);
1518 		    pending_error = errno;
1519 		}
1520 	    }
1521 	}
1522 	return;
1523     }
1524     if (size_text[0] == 'z')
1525     {
1526 	gzipped = 1;
1527 	size = atoi (size_text + 1);
1528     }
1529     else
1530 	size = atoi (size_text);
1531     free (size_text);
1532 
1533     if (error_pending ())
1534     {
1535         /* Now that we know the size, read and discard the file data.  */
1536 	while (size > 0)
1537 	{
1538 	    int status, nread;
1539 	    char *data;
1540 
1541 	    status = buf_read_data (buf_from_net, size, &data, &nread);
1542 	    if (status != 0)
1543 		return;
1544 	    size -= nread;
1545 	}
1546 	return;
1547     }
1548 
1549     if (outside_dir (arg))
1550 	return;
1551 
1552     if (size >= 0)
1553     {
1554 	receive_file (size, arg, gzipped);
1555 	if (error_pending ()) return;
1556     }
1557 
1558     if (checkin_time_valid)
1559     {
1560 	struct utimbuf t;
1561 
1562 	memset (&t, 0, sizeof (t));
1563 	t.modtime = t.actime = checkin_time;
1564 	if (utime (arg, &t) < 0)
1565 	{
1566 	    pending_error = errno;
1567 	    if (alloc_pending (80 + strlen (arg)))
1568 		sprintf (pending_error_text, "E cannot utime %s", arg);
1569 	    return;
1570 	}
1571 	checkin_time_valid = 0;
1572     }
1573 
1574     {
1575 	int status = change_mode (arg, mode_text, 0);
1576 	free (mode_text);
1577 	if (status)
1578 	{
1579 	    pending_error_text = malloc (40 + strlen (arg));
1580 	    if (pending_error_text)
1581 		sprintf (pending_error_text,
1582 			 "E cannot change mode for %s", arg);
1583 	    pending_error = status;
1584 	    return;
1585 	}
1586     }
1587 
1588     /* Make sure that the Entries indicate the right kopt.  We probably
1589        could do this even in the non-kopt case and, I think, save a stat()
1590        call in time_stamp_server.  But for conservatism I'm leaving the
1591        non-kopt case alone.  */
1592     if (kopt != NULL)
1593 	serve_is_modified (arg);
1594 }
1595 
1596 
1597 static void
1598 serve_enable_unchanged (arg)
1599      char *arg;
1600 {
1601 }
1602 
1603 struct an_entry {
1604     struct an_entry *next;
1605     char *entry;
1606 };
1607 
1608 static struct an_entry *entries;
1609 
1610 static void serve_unchanged PROTO ((char *));
1611 
1612 static void
1613 serve_unchanged (arg)
1614     char *arg;
1615 {
1616     struct an_entry *p;
1617     char *name;
1618     char *cp;
1619     char *timefield;
1620 
1621     if (error_pending ())
1622 	return;
1623 
1624     if (outside_dir (arg))
1625 	return;
1626 
1627     /* Rewrite entries file to have `=' in timestamp field.  */
1628     for (p = entries; p != NULL; p = p->next)
1629     {
1630 	name = p->entry + 1;
1631 	cp = strchr (name, '/');
1632 	if (cp != NULL
1633 	    && strlen (arg) == cp - name
1634 	    && strncmp (arg, name, cp - name) == 0)
1635 	{
1636 	    timefield = strchr (cp + 1, '/') + 1;
1637 	    if (*timefield != '=')
1638 	    {
1639 		cp = timefield + strlen (timefield);
1640 		cp[1] = '\0';
1641 		while (cp > timefield)
1642 		{
1643 		    *cp = cp[-1];
1644 		    --cp;
1645 		}
1646 		*timefield = '=';
1647 	    }
1648 	    break;
1649 	}
1650     }
1651 }
1652 
1653 static void
1654 serve_is_modified (arg)
1655     char *arg;
1656 {
1657     struct an_entry *p;
1658     char *name;
1659     char *cp;
1660     char *timefield;
1661     /* Have we found this file in "entries" yet.  */
1662     int found;
1663 
1664     if (error_pending ())
1665 	return;
1666 
1667     if (outside_dir (arg))
1668 	return;
1669 
1670     /* Rewrite entries file to have `M' in timestamp field.  */
1671     found = 0;
1672     for (p = entries; p != NULL; p = p->next)
1673     {
1674 	name = p->entry + 1;
1675 	cp = strchr (name, '/');
1676 	if (cp != NULL
1677 	    && strlen (arg) == cp - name
1678 	    && strncmp (arg, name, cp - name) == 0)
1679 	{
1680 	    timefield = strchr (cp + 1, '/') + 1;
1681 	    if (!(timefield[0] == 'M' && timefield[1] == '/'))
1682 	    {
1683 		cp = timefield + strlen (timefield);
1684 		cp[1] = '\0';
1685 		while (cp > timefield)
1686 		{
1687 		    *cp = cp[-1];
1688 		    --cp;
1689 		}
1690 		*timefield = 'M';
1691 	    }
1692 	    if (kopt != NULL)
1693 	    {
1694 		if (alloc_pending (strlen (name) + 80))
1695 		    sprintf (pending_error_text,
1696 			     "E protocol error: both Kopt and Entry for %s",
1697 			     arg);
1698 		free (kopt);
1699 		kopt = NULL;
1700 		return;
1701 	    }
1702 	    found = 1;
1703 	    break;
1704 	}
1705     }
1706     if (!found)
1707     {
1708 	/* We got Is-modified but no Entry.  Add a dummy entry.
1709 	   The "D" timestamp is what makes it a dummy.  */
1710 	p = (struct an_entry *) malloc (sizeof (struct an_entry));
1711 	if (p == NULL)
1712 	{
1713 	    pending_error = ENOMEM;
1714 	    return;
1715 	}
1716 	p->entry = malloc (strlen (arg) + 80);
1717 	if (p->entry == NULL)
1718 	{
1719 	    pending_error = ENOMEM;
1720 	    free (p);
1721 	    return;
1722 	}
1723 	strcpy (p->entry, "/");
1724 	strcat (p->entry, arg);
1725 	strcat (p->entry, "//D/");
1726 	if (kopt != NULL)
1727 	{
1728 	    strcat (p->entry, kopt);
1729 	    free (kopt);
1730 	    kopt = NULL;
1731 	}
1732 	strcat (p->entry, "/");
1733 	p->next = entries;
1734 	entries = p;
1735     }
1736 }
1737 
1738 static void serve_entry PROTO ((char *));
1739 
1740 static void
1741 serve_entry (arg)
1742      char *arg;
1743 {
1744     struct an_entry *p;
1745     char *cp;
1746     if (error_pending()) return;
1747     p = (struct an_entry *) malloc (sizeof (struct an_entry));
1748     if (p == NULL)
1749     {
1750 	pending_error = ENOMEM;
1751 	return;
1752     }
1753     /* Leave space for serve_unchanged to write '=' if it wants.  */
1754     cp = malloc (strlen (arg) + 2);
1755     if (cp == NULL)
1756     {
1757 	pending_error = ENOMEM;
1758 	return;
1759     }
1760     strcpy (cp, arg);
1761     p->next = entries;
1762     p->entry = cp;
1763     entries = p;
1764 }
1765 
1766 static void serve_kopt PROTO ((char *));
1767 
1768 static void
1769 serve_kopt (arg)
1770      char *arg;
1771 {
1772     if (error_pending ())
1773 	return;
1774 
1775     if (kopt != NULL)
1776     {
1777 	if (alloc_pending (80 + strlen (arg)))
1778 	    sprintf (pending_error_text,
1779 		     "E protocol error: duplicate Kopt request: %s", arg);
1780 	return;
1781     }
1782 
1783     /* Do some sanity checks.  In particular, that it is not too long.
1784        This lets the rest of the code not worry so much about buffer
1785        overrun attacks.  Probably should call RCS_check_kflag here,
1786        but that would mean changing RCS_check_kflag to handle errors
1787        other than via exit(), fprintf(), and such.  */
1788     if (strlen (arg) > 10)
1789     {
1790 	if (alloc_pending (80 + strlen (arg)))
1791 	    sprintf (pending_error_text,
1792 		     "E protocol error: invalid Kopt request: %s", arg);
1793 	return;
1794     }
1795 
1796     kopt = malloc (strlen (arg) + 1);
1797     if (kopt == NULL)
1798     {
1799 	pending_error = ENOMEM;
1800 	return;
1801     }
1802     strcpy (kopt, arg);
1803 }
1804 
1805 static void serve_checkin_time PROTO ((char *));
1806 
1807 static void
1808 serve_checkin_time (arg)
1809      char *arg;
1810 {
1811     if (error_pending ())
1812 	return;
1813 
1814     if (checkin_time_valid)
1815     {
1816 	if (alloc_pending (80 + strlen (arg)))
1817 	    sprintf (pending_error_text,
1818 		     "E protocol error: duplicate Checkin-time request: %s",
1819 		     arg);
1820 	return;
1821     }
1822 
1823     checkin_time = get_date (arg, NULL);
1824     if (checkin_time == (time_t)-1)
1825     {
1826 	if (alloc_pending (80 + strlen (arg)))
1827 	    sprintf (pending_error_text, "E cannot parse date %s", arg);
1828 	return;
1829     }
1830     checkin_time_valid = 1;
1831 }
1832 
1833 static void
1834 server_write_entries ()
1835 {
1836     FILE *f;
1837     struct an_entry *p;
1838     struct an_entry *q;
1839 
1840     if (entries == NULL)
1841 	return;
1842 
1843     f = NULL;
1844     /* Note that we free all the entries regardless of errors.  */
1845     if (!error_pending ())
1846     {
1847 	/* We open in append mode because we don't want to clobber an
1848            existing Entries file.  If we are checking out a module
1849            which explicitly lists more than one file in a particular
1850            directory, then we will wind up calling
1851            server_write_entries for each such file.  */
1852 	f = CVS_FOPEN (CVSADM_ENT, "a");
1853 	if (f == NULL)
1854 	{
1855 	    pending_error = errno;
1856 	    if (alloc_pending (80 + strlen (CVSADM_ENT)))
1857 		sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
1858 	}
1859     }
1860     for (p = entries; p != NULL;)
1861     {
1862 	if (!error_pending ())
1863 	{
1864 	    if (fprintf (f, "%s\n", p->entry) < 0)
1865 	    {
1866 		pending_error = errno;
1867 		if (alloc_pending (80 + strlen(CVSADM_ENT)))
1868 		    sprintf (pending_error_text,
1869 			     "E cannot write to %s", CVSADM_ENT);
1870 	    }
1871 	}
1872 	free (p->entry);
1873 	q = p->next;
1874 	free (p);
1875 	p = q;
1876     }
1877     entries = NULL;
1878     if (f != NULL && fclose (f) == EOF && !error_pending ())
1879     {
1880 	pending_error = errno;
1881 	if (alloc_pending (80 + strlen (CVSADM_ENT)))
1882 	    sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
1883     }
1884 }
1885 
1886 struct notify_note {
1887     /* Directory in which this notification happens.  malloc'd*/
1888     char *dir;
1889 
1890     /* malloc'd.  */
1891     char *filename;
1892 
1893     /* The following three all in one malloc'd block, pointed to by TYPE.
1894        Each '\0' terminated.  */
1895     /* "E" or "U".  */
1896     char *type;
1897     /* time+host+dir */
1898     char *val;
1899     char *watches;
1900 
1901     struct notify_note *next;
1902 };
1903 
1904 static struct notify_note *notify_list;
1905 /* Used while building list, to point to the last node that already exists.  */
1906 static struct notify_note *last_node;
1907 
1908 static void serve_notify PROTO ((char *));
1909 
1910 static void
1911 serve_notify (arg)
1912     char *arg;
1913 {
1914     struct notify_note *new;
1915     char *data;
1916     int status;
1917 
1918     if (error_pending ()) return;
1919 
1920     if (outside_dir (arg))
1921 	return;
1922 
1923     new = (struct notify_note *) malloc (sizeof (struct notify_note));
1924     if (new == NULL)
1925     {
1926 	pending_error = ENOMEM;
1927 	return;
1928     }
1929     if (dir_name == NULL)
1930 	goto error;
1931     new->dir = malloc (strlen (dir_name) + 1);
1932     if (new->dir == NULL)
1933     {
1934 	pending_error = ENOMEM;
1935 	return;
1936     }
1937     strcpy (new->dir, dir_name);
1938     new->filename = malloc (strlen (arg) + 1);
1939     if (new->filename == NULL)
1940     {
1941 	pending_error = ENOMEM;
1942 	return;
1943     }
1944     strcpy (new->filename, arg);
1945 
1946     status = buf_read_line (buf_from_net, &data, (int *) NULL);
1947     if (status != 0)
1948     {
1949 	if (status == -2)
1950 	    pending_error = ENOMEM;
1951 	else
1952 	{
1953 	    pending_error_text = malloc (80 + strlen (arg));
1954 	    if (pending_error_text == NULL)
1955 		pending_error = ENOMEM;
1956 	    else
1957 	    {
1958 		if (status == -1)
1959 		    sprintf (pending_error_text,
1960 			     "E end of file reading notification for %s", arg);
1961 		else
1962 		{
1963 		    sprintf (pending_error_text,
1964 			     "E error reading notification for %s", arg);
1965 		    pending_error = status;
1966 		}
1967 	    }
1968 	}
1969     }
1970     else
1971     {
1972 	char *cp;
1973 
1974 	if (strchr (data, '+'))
1975 	    goto error;
1976 
1977 	new->type = data;
1978 	if (data[1] != '\t')
1979 	    goto error;
1980 	data[1] = '\0';
1981 	cp = data + 2;
1982 	new->val = cp;
1983 	cp = strchr (cp, '\t');
1984 	if (cp == NULL)
1985 	    goto error;
1986 	*cp++ = '+';
1987 	cp = strchr (cp, '\t');
1988 	if (cp == NULL)
1989 	    goto error;
1990 	*cp++ = '+';
1991 	cp = strchr (cp, '\t');
1992 	if (cp == NULL)
1993 	    goto error;
1994 	*cp++ = '\0';
1995 	new->watches = cp;
1996 	/* If there is another tab, ignore everything after it,
1997 	   for future expansion.  */
1998 	cp = strchr (cp, '\t');
1999 	if (cp != NULL)
2000 	{
2001 	    *cp = '\0';
2002 	}
2003 
2004 	new->next = NULL;
2005 
2006 	if (last_node == NULL)
2007 	{
2008 	    notify_list = new;
2009 	}
2010 	else
2011 	    last_node->next = new;
2012 	last_node = new;
2013     }
2014     return;
2015   error:
2016     pending_error_text = malloc (80);
2017     if (pending_error_text)
2018 	strcpy (pending_error_text,
2019 		"E Protocol error; misformed Notify request");
2020     pending_error = 0;
2021     return;
2022 }
2023 
2024 /* Process all the Notify requests that we have stored up.  Returns 0
2025    if successful, if not prints error message (via error()) and
2026    returns negative value.  */
2027 static int
2028 server_notify ()
2029 {
2030     struct notify_note *p;
2031     char *repos;
2032 
2033     while (notify_list != NULL)
2034     {
2035 	if ( CVS_CHDIR (notify_list->dir) < 0)
2036 	{
2037 	    error (0, errno, "cannot change to %s", notify_list->dir);
2038 	    return -1;
2039 	}
2040 	repos = Name_Repository (NULL, NULL);
2041 
2042 	lock_dir_for_write (repos);
2043 
2044 	fileattr_startdir (repos);
2045 
2046 	notify_do (*notify_list->type, notify_list->filename, getcaller(),
2047 		   notify_list->val, notify_list->watches, repos);
2048 
2049 	buf_output0 (buf_to_net, "Notified ");
2050 	{
2051 	    char *dir = notify_list->dir + strlen (server_temp_dir) + 1;
2052 	    if (dir[0] == '\0')
2053 	        buf_append_char (buf_to_net, '.');
2054 	    else
2055 	        buf_output0 (buf_to_net, dir);
2056 	    buf_append_char (buf_to_net, '/');
2057 	    buf_append_char (buf_to_net, '\n');
2058 	}
2059 	buf_output0 (buf_to_net, repos);
2060 	buf_append_char (buf_to_net, '/');
2061 	buf_output0 (buf_to_net, notify_list->filename);
2062 	buf_append_char (buf_to_net, '\n');
2063 
2064 	p = notify_list->next;
2065 	free (notify_list->filename);
2066 	free (notify_list->dir);
2067 	free (notify_list->type);
2068 	free (notify_list);
2069 	notify_list = p;
2070 
2071 	fileattr_write ();
2072 	fileattr_free ();
2073 
2074 	Lock_Cleanup ();
2075     }
2076 
2077     last_node = NULL;
2078 
2079     /* The code used to call fflush (stdout) here, but that is no
2080        longer necessary.  The data is now buffered in buf_to_net,
2081        which will be flushed by the caller, do_cvs_command.  */
2082 
2083     return 0;
2084 }
2085 
2086 static int argument_count;
2087 static char **argument_vector;
2088 static int argument_vector_size;
2089 
2090 static void
2091 serve_argument (arg)
2092      char *arg;
2093 {
2094     char *p;
2095 
2096     if (error_pending()) return;
2097 
2098     if (argument_vector_size <= argument_count)
2099     {
2100 	argument_vector_size *= 2;
2101 	argument_vector =
2102 	    (char **) realloc ((char *)argument_vector,
2103 			       argument_vector_size * sizeof (char *));
2104 	if (argument_vector == NULL)
2105 	{
2106 	    pending_error = ENOMEM;
2107 	    return;
2108 	}
2109     }
2110     p = malloc (strlen (arg) + 1);
2111     if (p == NULL)
2112     {
2113 	pending_error = ENOMEM;
2114 	return;
2115     }
2116     strcpy (p, arg);
2117     argument_vector[argument_count++] = p;
2118 }
2119 
2120 static void
2121 serve_argumentx (arg)
2122      char *arg;
2123 {
2124     char *p;
2125 
2126     if (error_pending()) return;
2127 
2128     p = argument_vector[argument_count - 1];
2129     p = realloc (p, strlen (p) + 1 + strlen (arg) + 1);
2130     if (p == NULL)
2131     {
2132 	pending_error = ENOMEM;
2133 	return;
2134     }
2135     strcat (p, "\n");
2136     strcat (p, arg);
2137     argument_vector[argument_count - 1] = p;
2138 }
2139 
2140 static void
2141 serve_global_option (arg)
2142     char *arg;
2143 {
2144     if (arg[0] != '-' || arg[1] == '\0' || arg[2] != '\0')
2145     {
2146     error_return:
2147 	if (alloc_pending (strlen (arg) + 80))
2148 	    sprintf (pending_error_text,
2149 		     "E Protocol error: bad global option %s",
2150 		     arg);
2151 	return;
2152     }
2153     switch (arg[1])
2154     {
2155 	case 'n':
2156 	    noexec = 1;
2157 	    break;
2158 	case 'q':
2159 	    quiet = 1;
2160 	    break;
2161 	case 'r':
2162 	    cvswrite = 0;
2163 	    break;
2164 	case 'Q':
2165 	    really_quiet = 1;
2166 	    break;
2167 	case 'l':
2168 	    logoff = 1;
2169 	    break;
2170 	case 't':
2171 	    trace = 1;
2172 	    break;
2173 	default:
2174 	    goto error_return;
2175     }
2176 }
2177 
2178 static void
2179 serve_set (arg)
2180     char *arg;
2181 {
2182     /* FIXME: This sends errors immediately (I think); they should be
2183        put into pending_error.  */
2184     variable_set (arg);
2185 }
2186 
2187 #ifdef ENCRYPTION
2188 
2189 #ifdef HAVE_KERBEROS
2190 
2191 static void
2192 serve_kerberos_encrypt (arg)
2193      char *arg;
2194 {
2195     /* All future communication with the client will be encrypted.  */
2196 
2197     buf_to_net = krb_encrypt_buffer_initialize (buf_to_net, 0, sched,
2198 						kblock,
2199 						buf_to_net->memory_error);
2200     buf_from_net = krb_encrypt_buffer_initialize (buf_from_net, 1, sched,
2201 						  kblock,
2202 						  buf_from_net->memory_error);
2203 }
2204 
2205 #endif /* HAVE_KERBEROS */
2206 
2207 #ifdef HAVE_GSSAPI
2208 
2209 static void
2210 serve_gssapi_encrypt (arg)
2211      char *arg;
2212 {
2213     if (cvs_gssapi_wrapping)
2214     {
2215 	/* We're already using a gssapi_wrap buffer for stream
2216            authentication.  Flush everything we've output so far, and
2217            turn on encryption for future data.  On the input side, we
2218            should only have unwrapped as far as the Gssapi-encrypt
2219            command, so future unwrapping will become encrypted.  */
2220 	buf_flush (buf_to_net, 1);
2221 	cvs_gssapi_encrypt = 1;
2222 	return;
2223     }
2224 
2225     /* All future communication with the client will be encrypted.  */
2226 
2227     cvs_gssapi_encrypt = 1;
2228 
2229     buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0,
2230 						    gcontext,
2231 						    buf_to_net->memory_error);
2232     buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1,
2233 						      gcontext,
2234 						      buf_from_net->memory_error);
2235 
2236     cvs_gssapi_wrapping = 1;
2237 }
2238 
2239 #endif /* HAVE_GSSAPI */
2240 
2241 #endif /* ENCRYPTION */
2242 
2243 #ifdef HAVE_GSSAPI
2244 
2245 static void
2246 serve_gssapi_authenticate (arg)
2247      char *arg;
2248 {
2249     if (cvs_gssapi_wrapping)
2250     {
2251 	/* We're already using a gssapi_wrap buffer for encryption.
2252            That includes authentication, so we don't have to do
2253            anything further.  */
2254 	return;
2255     }
2256 
2257     buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0,
2258 						    gcontext,
2259 						    buf_to_net->memory_error);
2260     buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1,
2261 						      gcontext,
2262 						      buf_from_net->memory_error);
2263 
2264     cvs_gssapi_wrapping = 1;
2265 }
2266 
2267 #endif /* HAVE_GSSAPI */
2268 
2269 #ifdef SERVER_FLOWCONTROL
2270 /* The maximum we'll queue to the remote client before blocking.  */
2271 # ifndef SERVER_HI_WATER
2272 #  define SERVER_HI_WATER (2 * 1024 * 1024)
2273 # endif /* SERVER_HI_WATER */
2274 /* When the buffer drops to this, we restart the child */
2275 # ifndef SERVER_LO_WATER
2276 #  define SERVER_LO_WATER (1 * 1024 * 1024)
2277 # endif /* SERVER_LO_WATER */
2278 
2279 static int set_nonblock_fd PROTO((int));
2280 
2281 /*
2282  * Set buffer BUF to non-blocking I/O.  Returns 0 for success or errno
2283  * code.
2284  */
2285 
2286 static int
2287 set_nonblock_fd (fd)
2288      int fd;
2289 {
2290     int flags;
2291 
2292     flags = fcntl (fd, F_GETFL, 0);
2293     if (flags < 0)
2294 	return errno;
2295     if (fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0)
2296 	return errno;
2297     return 0;
2298 }
2299 
2300 #endif /* SERVER_FLOWCONTROL */
2301 
2302 static void serve_questionable PROTO((char *));
2303 
2304 static void
2305 serve_questionable (arg)
2306     char *arg;
2307 {
2308     static int initted;
2309 
2310     if (!initted)
2311     {
2312 	/* Pick up ignores from CVSROOTADM_IGNORE, $HOME/.cvsignore on server,
2313 	   and CVSIGNORE on server.  */
2314 	ign_setup ();
2315 	initted = 1;
2316     }
2317 
2318     if (dir_name == NULL)
2319     {
2320 	buf_output0 (buf_to_net, "E Protocol error: 'Directory' missing");
2321 	return;
2322     }
2323 
2324     if (outside_dir (arg))
2325 	return;
2326 
2327     if (!ign_name (arg))
2328     {
2329 	char *update_dir;
2330 
2331 	buf_output (buf_to_net, "M ? ", 4);
2332 	update_dir = dir_name + strlen (server_temp_dir) + 1;
2333 	if (!(update_dir[0] == '.' && update_dir[1] == '\0'))
2334 	{
2335 	    buf_output0 (buf_to_net, update_dir);
2336 	    buf_output (buf_to_net, "/", 1);
2337 	}
2338 	buf_output0 (buf_to_net, arg);
2339 	buf_output (buf_to_net, "\n", 1);
2340     }
2341 }
2342 
2343 static void serve_case PROTO ((char *));
2344 
2345 static void
2346 serve_case (arg)
2347     char *arg;
2348 {
2349     ign_case = 1;
2350 }
2351 
2352 static struct buffer *protocol;
2353 
2354 /* This is the output which we are saving up to send to the server, in the
2355    child process.  We will push it through, via the `protocol' buffer, when
2356    we have a complete line.  */
2357 static struct buffer *saved_output;
2358 /* Likewise, but stuff which will go to stderr.  */
2359 static struct buffer *saved_outerr;
2360 
2361 static void
2362 protocol_memory_error (buf)
2363     struct buffer *buf;
2364 {
2365     error (1, ENOMEM, "Virtual memory exhausted");
2366 }
2367 
2368 /*
2369  * Process IDs of the subprocess, or negative if that subprocess
2370  * does not exist.
2371  */
2372 static pid_t command_pid;
2373 
2374 static void
2375 outbuf_memory_error (buf)
2376     struct buffer *buf;
2377 {
2378     static const char msg[] = "E Fatal server error\n\
2379 error ENOMEM Virtual memory exhausted.\n";
2380     if (command_pid > 0)
2381 	kill (command_pid, SIGTERM);
2382 
2383     /*
2384      * We have arranged things so that printing this now either will
2385      * be legal, or the "E fatal error" line will get glommed onto the
2386      * end of an existing "E" or "M" response.
2387      */
2388 
2389     /* If this gives an error, not much we could do.  syslog() it?  */
2390     write (STDOUT_FILENO, msg, sizeof (msg) - 1);
2391     error_exit ();
2392 }
2393 
2394 static void
2395 input_memory_error (buf)
2396      struct buffer *buf;
2397 {
2398     outbuf_memory_error (buf);
2399 }
2400 
2401 
2402 
2403 /* If command is legal, return 1.
2404  * Else if command is illegal and croak_on_illegal is set, then die.
2405  * Else just return 0 to indicate that command is illegal.
2406  */
2407 static int
2408 check_command_legal_p (cmd_name)
2409     char *cmd_name;
2410 {
2411     /* Right now, only pserver notices illegal commands -- namely,
2412      * write attempts by a read-only user.  Therefore, if CVS_Username
2413      * is not set, this just returns 1, because CVS_Username unset
2414      * means pserver is not active.
2415      */
2416 #ifdef AUTH_SERVER_SUPPORT
2417     if (CVS_Username == NULL)
2418         return 1;
2419 
2420     if (lookup_command_attribute (cmd_name) & CVS_CMD_MODIFIES_REPOSITORY)
2421     {
2422         /* This command has the potential to modify the repository, so
2423          * we check if the user have permission to do that.
2424          *
2425          * (Only relevant for remote users -- local users can do
2426          * whatever normal Unix file permissions allow them to do.)
2427          *
2428          * The decision method:
2429          *
2430          *    If $CVSROOT/CVSADMROOT_READERS exists and user is listed
2431          *    in it, then read-only access for user.
2432          *
2433          *    Or if $CVSROOT/CVSADMROOT_WRITERS exists and user NOT
2434          *    listed in it, then also read-only access for user.
2435          *
2436          *    Else read-write access for user.
2437          */
2438 
2439          char *linebuf = NULL;
2440          int num_red = 0;
2441          size_t linebuf_len = 0;
2442          char *fname;
2443          size_t flen;
2444          FILE *fp;
2445          int found_it = 0;
2446 
2447          /* else */
2448          flen = strlen (CVSroot_directory)
2449                 + strlen (CVSROOTADM)
2450                 + strlen (CVSROOTADM_READERS)
2451                 + 3;
2452 
2453          fname = xmalloc (flen);
2454          (void) sprintf (fname, "%s/%s/%s", CVSroot_directory,
2455 			CVSROOTADM, CVSROOTADM_READERS);
2456 
2457          fp = fopen (fname, "r");
2458 
2459          if (fp == NULL)
2460 	 {
2461 	     if (!existence_error (errno))
2462 	     {
2463 		 /* Need to deny access, so that attackers can't fool
2464 		    us with some sort of denial of service attack.  */
2465 		 error (0, errno, "cannot open %s", fname);
2466 		 free (fname);
2467 		 return 0;
2468 	     }
2469 	 }
2470          else  /* successfully opened readers file */
2471          {
2472              while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
2473              {
2474                  /* Hmmm, is it worth importing my own readline
2475                     library into CVS?  It takes care of chopping
2476                     leading and trailing whitespace, "#" comments, and
2477                     newlines automatically when so requested.  Would
2478                     save some code here...  -kff */
2479 
2480                  /* Chop newline by hand, for strcmp()'s sake. */
2481                  if (linebuf[num_red - 1] == '\n')
2482                      linebuf[num_red - 1] = '\0';
2483 
2484                  if (strcmp (linebuf, CVS_Username) == 0)
2485                      goto handle_illegal;
2486              }
2487 	     if (num_red < 0 && !feof (fp))
2488 		 error (0, errno, "cannot read %s", fname);
2489 
2490              /* If not listed specifically as a reader, then this user
2491                 has write access by default unless writers are also
2492                 specified in a file . */
2493 	     if (fclose (fp) < 0)
2494 		 error (0, errno, "cannot close %s", fname);
2495          }
2496 	 free (fname);
2497 
2498 	 /* Now check the writers file.  */
2499 
2500          flen = strlen (CVSroot_directory)
2501                 + strlen (CVSROOTADM)
2502                 + strlen (CVSROOTADM_WRITERS)
2503                 + 3;
2504 
2505          fname = xmalloc (flen);
2506          (void) sprintf (fname, "%s/%s/%s", CVSroot_directory,
2507 			CVSROOTADM, CVSROOTADM_WRITERS);
2508 
2509          fp = fopen (fname, "r");
2510 
2511          if (fp == NULL)
2512          {
2513 	     if (linebuf)
2514 	         free (linebuf);
2515 	     if (existence_error (errno))
2516 	     {
2517 		 /* Writers file does not exist, so everyone is a writer,
2518 		    by default.  */
2519 		 free (fname);
2520 		 return 1;
2521 	     }
2522 	     else
2523 	     {
2524 		 /* Need to deny access, so that attackers can't fool
2525 		    us with some sort of denial of service attack.  */
2526 		 error (0, errno, "cannot read %s", fname);
2527 		 free (fname);
2528 		 return 0;
2529 	     }
2530          }
2531 
2532          found_it = 0;
2533          while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
2534          {
2535              /* Chop newline by hand, for strcmp()'s sake. */
2536              if (linebuf[num_red - 1] == '\n')
2537                  linebuf[num_red - 1] = '\0';
2538 
2539              if (strcmp (linebuf, CVS_Username) == 0)
2540              {
2541                  found_it = 1;
2542                  break;
2543              }
2544          }
2545 	 if (num_red < 0 && !feof (fp))
2546 	     error (0, errno, "cannot read %s", fname);
2547 
2548          if (found_it)
2549          {
2550              if (fclose (fp) < 0)
2551 		 error (0, errno, "cannot close %s", fname);
2552              if (linebuf)
2553                  free (linebuf);
2554 	     free (fname);
2555              return 1;
2556          }
2557          else   /* writers file exists, but this user not listed in it */
2558          {
2559          handle_illegal:
2560              if (fclose (fp) < 0)
2561 		 error (0, errno, "cannot close %s", fname);
2562              if (linebuf)
2563                  free (linebuf);
2564 	     free (fname);
2565 	     return 0;
2566          }
2567     }
2568 #endif /* AUTH_SERVER_SUPPORT */
2569 
2570     /* If ever reach end of this function, command must be legal. */
2571     return 1;
2572 }
2573 
2574 
2575 
2576 /* Execute COMMAND in a subprocess with the approriate funky things done.  */
2577 
2578 static struct fd_set_wrapper { fd_set fds; } command_fds_to_drain;
2579 static int max_command_fd;
2580 
2581 #ifdef SERVER_FLOWCONTROL
2582 static int flowcontrol_pipe[2];
2583 #endif /* SERVER_FLOWCONTROL */
2584 
2585 static void
2586 do_cvs_command (cmd_name, command)
2587     char *cmd_name;
2588     int (*command) PROTO((int argc, char **argv));
2589 {
2590     /*
2591      * The following file descriptors are set to -1 if that file is not
2592      * currently open.
2593      */
2594 
2595     /* Data on these pipes is a series of '\n'-terminated lines.  */
2596     int stdout_pipe[2];
2597     int stderr_pipe[2];
2598 
2599     /*
2600      * Data on this pipe is a series of counted (see buf_send_counted)
2601      * packets.  Each packet must be processed atomically (i.e. not
2602      * interleaved with data from stdout_pipe or stderr_pipe).
2603      */
2604     int protocol_pipe[2];
2605 
2606     int dev_null_fd = -1;
2607 
2608     int errs;
2609 
2610     command_pid = -1;
2611     stdout_pipe[0] = -1;
2612     stdout_pipe[1] = -1;
2613     stderr_pipe[0] = -1;
2614     stderr_pipe[1] = -1;
2615     protocol_pipe[0] = -1;
2616     protocol_pipe[1] = -1;
2617 
2618     server_write_entries ();
2619 
2620     if (print_pending_error ())
2621 	goto free_args_and_return;
2622 
2623     /* Global `command_name' is probably "server" right now -- only
2624        serve_export() sets it to anything else.  So we will use local
2625        parameter `cmd_name' to determine if this command is legal for
2626        this user.  */
2627     if (!check_command_legal_p (cmd_name))
2628     {
2629 	buf_output0 (buf_to_net, "E ");
2630 	buf_output0 (buf_to_net, program_name);
2631 	buf_output0 (buf_to_net, " [server aborted]: \"");
2632 	buf_output0 (buf_to_net, cmd_name);
2633 	buf_output0 (buf_to_net, "\" requires write access to the repository\n\
2634 error  \n");
2635 	goto free_args_and_return;
2636     }
2637 
2638     (void) server_notify ();
2639 
2640     /*
2641      * We use a child process which actually does the operation.  This
2642      * is so we can intercept its standard output.  Even if all of CVS
2643      * were written to go to some special routine instead of writing
2644      * to stdout or stderr, we would still need to do the same thing
2645      * for the RCS commands.
2646      */
2647 
2648     if (pipe (stdout_pipe) < 0)
2649     {
2650 	print_error (errno);
2651 	goto error_exit;
2652     }
2653     if (pipe (stderr_pipe) < 0)
2654     {
2655 	print_error (errno);
2656 	goto error_exit;
2657     }
2658     if (pipe (protocol_pipe) < 0)
2659     {
2660 	print_error (errno);
2661 	goto error_exit;
2662     }
2663 #ifdef SERVER_FLOWCONTROL
2664     if (pipe (flowcontrol_pipe) < 0)
2665     {
2666 	print_error (errno);
2667 	goto error_exit;
2668     }
2669     set_nonblock_fd (flowcontrol_pipe[0]);
2670     set_nonblock_fd (flowcontrol_pipe[1]);
2671 #endif /* SERVER_FLOWCONTROL */
2672 
2673     dev_null_fd = CVS_OPEN (DEVNULL, O_RDONLY);
2674     if (dev_null_fd < 0)
2675     {
2676 	print_error (errno);
2677 	goto error_exit;
2678     }
2679 
2680     /* We shouldn't have any partial lines from cvs_output and
2681        cvs_outerr, but we handle them here in case there is a bug.  */
2682     /* FIXME: appending a newline, rather than using "MT" as we
2683        do in the child process, is probably not really a very good
2684        way to "handle" them.  */
2685     if (! buf_empty_p (saved_output))
2686     {
2687 	buf_append_char (saved_output, '\n');
2688 	buf_copy_lines (buf_to_net, saved_output, 'M');
2689     }
2690     if (! buf_empty_p (saved_outerr))
2691     {
2692 	buf_append_char (saved_outerr, '\n');
2693 	buf_copy_lines (buf_to_net, saved_outerr, 'E');
2694     }
2695 
2696     /* Flush out any pending data.  */
2697     buf_flush (buf_to_net, 1);
2698 
2699     /* Don't use vfork; we're not going to exec().  */
2700     command_pid = fork ();
2701     if (command_pid < 0)
2702     {
2703 	print_error (errno);
2704 	goto error_exit;
2705     }
2706     if (command_pid == 0)
2707     {
2708 	int exitstatus;
2709 
2710 	/* Since we're in the child, and the parent is going to take
2711 	   care of packaging up our error messages, we can clear this
2712 	   flag.  */
2713 	error_use_protocol = 0;
2714 
2715 	protocol = fd_buffer_initialize (protocol_pipe[1], 0,
2716 					 protocol_memory_error);
2717 
2718 	/* At this point we should no longer be using buf_to_net and
2719            buf_from_net.  Instead, everything should go through
2720            protocol.  */
2721 	buf_to_net = NULL;
2722 	buf_from_net = NULL;
2723 
2724 	/* These were originally set up to use outbuf_memory_error.
2725            Since we're now in the child, we should use the simpler
2726            protocol_memory_error function.  */
2727 	saved_output->memory_error = protocol_memory_error;
2728 	saved_outerr->memory_error = protocol_memory_error;
2729 
2730 	if (dup2 (dev_null_fd, STDIN_FILENO) < 0)
2731 	    error (1, errno, "can't set up pipes");
2732 	if (dup2 (stdout_pipe[1], STDOUT_FILENO) < 0)
2733 	    error (1, errno, "can't set up pipes");
2734 	if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
2735 	    error (1, errno, "can't set up pipes");
2736 	close (stdout_pipe[0]);
2737 	close (stderr_pipe[0]);
2738 	close (protocol_pipe[0]);
2739 #ifdef SERVER_FLOWCONTROL
2740 	close (flowcontrol_pipe[1]);
2741 #endif /* SERVER_FLOWCONTROL */
2742 
2743 	/*
2744 	 * Set this in .bashrc if you want to give yourself time to attach
2745 	 * to the subprocess with a debugger.
2746 	 */
2747 	if (getenv ("CVS_SERVER_SLEEP"))
2748 	{
2749 	    int secs = atoi (getenv ("CVS_SERVER_SLEEP"));
2750 	    sleep (secs);
2751 	}
2752 
2753 	exitstatus = (*command) (argument_count, argument_vector);
2754 
2755 	/* Output any partial lines.  If the client doesn't support
2756 	   "MT", we just throw out the partial line, like old versions
2757 	   of CVS did, since the protocol can't support this.  */
2758 	if (supported_response ("MT") && ! buf_empty_p (saved_output))
2759 	{
2760 	    buf_output0 (protocol, "MT text ");
2761 	    buf_append_buffer (protocol, saved_output);
2762 	    buf_output (protocol, "\n", 1);
2763 	    buf_send_counted (protocol);
2764 	}
2765 	/* For now we just discard partial lines on stderr.  I suspect
2766 	   that CVS can't write such lines unless there is a bug.  */
2767 
2768 	/*
2769 	 * When we exit, that will close the pipes, giving an EOF to
2770 	 * the parent.
2771 	 */
2772 	exit (exitstatus);
2773     }
2774 
2775     /* OK, sit around getting all the input from the child.  */
2776     {
2777 	struct buffer *stdoutbuf;
2778 	struct buffer *stderrbuf;
2779 	struct buffer *protocol_inbuf;
2780 	/* Number of file descriptors to check in select ().  */
2781 	int num_to_check;
2782 	int count_needed = 0;
2783 #ifdef SERVER_FLOWCONTROL
2784 	int have_flowcontrolled = 0;
2785 #endif /* SERVER_FLOWCONTROL */
2786 
2787 	FD_ZERO (&command_fds_to_drain.fds);
2788 	num_to_check = stdout_pipe[0];
2789 	FD_SET (stdout_pipe[0], &command_fds_to_drain.fds);
2790 	if (stderr_pipe[0] > num_to_check)
2791 	  num_to_check = stderr_pipe[0];
2792 	FD_SET (stderr_pipe[0], &command_fds_to_drain.fds);
2793 	if (protocol_pipe[0] > num_to_check)
2794 	  num_to_check = protocol_pipe[0];
2795 	FD_SET (protocol_pipe[0], &command_fds_to_drain.fds);
2796 	if (STDOUT_FILENO > num_to_check)
2797 	  num_to_check = STDOUT_FILENO;
2798 	max_command_fd = num_to_check;
2799 	/*
2800 	 * File descriptors are numbered from 0, so num_to_check needs to
2801 	 * be one larger than the largest descriptor.
2802 	 */
2803 	++num_to_check;
2804 	if (num_to_check > FD_SETSIZE)
2805 	{
2806 	    buf_output0 (buf_to_net,
2807 			 "E internal error: FD_SETSIZE not big enough.\n\
2808 error  \n");
2809 	    goto error_exit;
2810 	}
2811 
2812 	stdoutbuf = fd_buffer_initialize (stdout_pipe[0], 1,
2813 					  input_memory_error);
2814 
2815 	stderrbuf = fd_buffer_initialize (stderr_pipe[0], 1,
2816 					  input_memory_error);
2817 
2818 	protocol_inbuf = fd_buffer_initialize (protocol_pipe[0], 1,
2819 					       input_memory_error);
2820 
2821 	set_nonblock (buf_to_net);
2822 	set_nonblock (stdoutbuf);
2823 	set_nonblock (stderrbuf);
2824 	set_nonblock (protocol_inbuf);
2825 
2826 	if (close (stdout_pipe[1]) < 0)
2827 	{
2828 	    print_error (errno);
2829 	    goto error_exit;
2830 	}
2831 	stdout_pipe[1] = -1;
2832 
2833 	if (close (stderr_pipe[1]) < 0)
2834 	{
2835 	    print_error (errno);
2836 	    goto error_exit;
2837 	}
2838 	stderr_pipe[1] = -1;
2839 
2840 	if (close (protocol_pipe[1]) < 0)
2841 	{
2842 	    print_error (errno);
2843 	    goto error_exit;
2844 	}
2845 	protocol_pipe[1] = -1;
2846 
2847 #ifdef SERVER_FLOWCONTROL
2848 	if (close (flowcontrol_pipe[0]) < 0)
2849 	{
2850 	    print_error (errno);
2851 	    goto error_exit;
2852 	}
2853 	flowcontrol_pipe[0] = -1;
2854 #endif /* SERVER_FLOWCONTROL */
2855 
2856 	if (close (dev_null_fd) < 0)
2857 	{
2858 	    print_error (errno);
2859 	    goto error_exit;
2860 	}
2861 	dev_null_fd = -1;
2862 
2863 	while (stdout_pipe[0] >= 0
2864 	       || stderr_pipe[0] >= 0
2865 	       || protocol_pipe[0] >= 0)
2866 	{
2867 	    fd_set readfds;
2868 	    fd_set writefds;
2869 	    int numfds;
2870 #ifdef SERVER_FLOWCONTROL
2871 	    int bufmemsize;
2872 
2873 	    /*
2874 	     * See if we are swamping the remote client and filling our VM.
2875 	     * Tell child to hold off if we do.
2876 	     */
2877 	    bufmemsize = buf_count_mem (buf_to_net);
2878 	    if (!have_flowcontrolled && (bufmemsize > SERVER_HI_WATER))
2879 	    {
2880 		if (write(flowcontrol_pipe[1], "S", 1) == 1)
2881 		    have_flowcontrolled = 1;
2882 	    }
2883 	    else if (have_flowcontrolled && (bufmemsize < SERVER_LO_WATER))
2884 	    {
2885 		if (write(flowcontrol_pipe[1], "G", 1) == 1)
2886 		    have_flowcontrolled = 0;
2887 	    }
2888 #endif /* SERVER_FLOWCONTROL */
2889 
2890 	    FD_ZERO (&readfds);
2891 	    FD_ZERO (&writefds);
2892 	    if (! buf_empty_p (buf_to_net))
2893 	        FD_SET (STDOUT_FILENO, &writefds);
2894 
2895 	    if (stdout_pipe[0] >= 0)
2896 	    {
2897 		FD_SET (stdout_pipe[0], &readfds);
2898 	    }
2899 	    if (stderr_pipe[0] >= 0)
2900 	    {
2901 		FD_SET (stderr_pipe[0], &readfds);
2902 	    }
2903 	    if (protocol_pipe[0] >= 0)
2904 	    {
2905 		FD_SET (protocol_pipe[0], &readfds);
2906 	    }
2907 
2908 	    /* This process of selecting on the three pipes means that
2909 	       we might not get output in the same order in which it
2910 	       was written, thus producing the well-known
2911 	       "out-of-order" bug.  If the child process uses
2912 	       cvs_output and cvs_outerr, it will send everything on
2913 	       the protocol_pipe and avoid this problem, so the
2914 	       solution is to use cvs_output and cvs_outerr in the
2915 	       child process.  */
2916 	    do {
2917 		/* This used to select on exceptions too, but as far
2918                    as I know there was never any reason to do that and
2919                    SCO doesn't let you select on exceptions on pipes.  */
2920 		numfds = select (num_to_check, &readfds, &writefds,
2921 				 (fd_set *)0, (struct timeval *)NULL);
2922 		if (numfds < 0
2923 		    && errno != EINTR)
2924 		{
2925 		    print_error (errno);
2926 		    goto error_exit;
2927 		}
2928 	    } while (numfds < 0);
2929 
2930 	    if (FD_ISSET (STDOUT_FILENO, &writefds))
2931 	    {
2932 		/* What should we do with errors?  syslog() them?  */
2933 		buf_send_output (buf_to_net);
2934 	    }
2935 
2936 	    if (stdout_pipe[0] >= 0
2937 		&& (FD_ISSET (stdout_pipe[0], &readfds)))
2938 	    {
2939 	        int status;
2940 
2941 	        status = buf_input_data (stdoutbuf, (int *) NULL);
2942 
2943 		buf_copy_lines (buf_to_net, stdoutbuf, 'M');
2944 
2945 		if (status == -1)
2946 		    stdout_pipe[0] = -1;
2947 		else if (status > 0)
2948 		{
2949 		    print_error (status);
2950 		    goto error_exit;
2951 		}
2952 
2953 		/* What should we do with errors?  syslog() them?  */
2954 		buf_send_output (buf_to_net);
2955 	    }
2956 
2957 	    if (stderr_pipe[0] >= 0
2958 		&& (FD_ISSET (stderr_pipe[0], &readfds)))
2959 	    {
2960 	        int status;
2961 
2962 	        status = buf_input_data (stderrbuf, (int *) NULL);
2963 
2964 		buf_copy_lines (buf_to_net, stderrbuf, 'E');
2965 
2966 		if (status == -1)
2967 		    stderr_pipe[0] = -1;
2968 		else if (status > 0)
2969 		{
2970 		    print_error (status);
2971 		    goto error_exit;
2972 		}
2973 
2974 		/* What should we do with errors?  syslog() them?  */
2975 		buf_send_output (buf_to_net);
2976 	    }
2977 
2978 	    if (protocol_pipe[0] >= 0
2979 		&& (FD_ISSET (protocol_pipe[0], &readfds)))
2980 	    {
2981 		int status;
2982 		int count_read;
2983 		int special;
2984 
2985 		status = buf_input_data (protocol_inbuf, &count_read);
2986 
2987 		if (status == -1)
2988 		    protocol_pipe[0] = -1;
2989 		else if (status > 0)
2990 		{
2991 		    print_error (status);
2992 		    goto error_exit;
2993 		}
2994 
2995 		/*
2996 		 * We only call buf_copy_counted if we have read
2997 		 * enough bytes to make it worthwhile.  This saves us
2998 		 * from continually recounting the amount of data we
2999 		 * have.
3000 		 */
3001 		count_needed -= count_read;
3002 		while (count_needed <= 0)
3003 		{
3004 		    count_needed = buf_copy_counted (buf_to_net,
3005 						     protocol_inbuf,
3006 						     &special);
3007 
3008 		    /* What should we do with errors?  syslog() them?  */
3009 		    buf_send_output (buf_to_net);
3010 
3011 		    /* If SPECIAL got set to -1, it means that the child
3012 		       wants us to flush the pipe.  We don't want to block
3013 		       on the network, but we flush what we can.  If the
3014 		       client supports the 'F' command, we send it.  */
3015 		    if (special == -1)
3016 		    {
3017 			if (supported_response ("F"))
3018 			{
3019 			    buf_append_char (buf_to_net, 'F');
3020 			    buf_append_char (buf_to_net, '\n');
3021 			}
3022 
3023 			cvs_flusherr ();
3024 		    }
3025 		}
3026 	    }
3027 	}
3028 
3029 	/*
3030 	 * OK, we've gotten EOF on all the pipes.  If there is
3031 	 * anything left on stdoutbuf or stderrbuf (this could only
3032 	 * happen if there was no trailing newline), send it over.
3033 	 */
3034 	if (! buf_empty_p (stdoutbuf))
3035 	{
3036 	    buf_append_char (stdoutbuf, '\n');
3037 	    buf_copy_lines (buf_to_net, stdoutbuf, 'M');
3038 	}
3039 	if (! buf_empty_p (stderrbuf))
3040 	{
3041 	    buf_append_char (stderrbuf, '\n');
3042 	    buf_copy_lines (buf_to_net, stderrbuf, 'E');
3043 	}
3044 	if (! buf_empty_p (protocol_inbuf))
3045 	    buf_output0 (buf_to_net,
3046 			 "E Protocol error: uncounted data discarded\n");
3047 
3048 	errs = 0;
3049 
3050 	while (command_pid > 0)
3051 	{
3052 	    int status;
3053 	    pid_t waited_pid;
3054 	    waited_pid = waitpid (command_pid, &status, 0);
3055 	    if (waited_pid < 0)
3056 	    {
3057 		/*
3058 		 * Intentionally ignoring EINTR.  Other errors
3059 		 * "can't happen".
3060 		 */
3061 		continue;
3062 	    }
3063 
3064 	    if (WIFEXITED (status))
3065 		errs += WEXITSTATUS (status);
3066 	    else
3067 	    {
3068 	        int sig = WTERMSIG (status);
3069 	        char buf[50];
3070 		/*
3071 		 * This is really evil, because signals might be numbered
3072 		 * differently on the two systems.  We should be using
3073 		 * signal names (either of the "Terminated" or the "SIGTERM"
3074 		 * variety).  But cvs doesn't currently use libiberty...we
3075 		 * could roll our own....  FIXME.
3076 		 */
3077 		buf_output0 (buf_to_net, "E Terminated with fatal signal ");
3078 		sprintf (buf, "%d\n", sig);
3079 		buf_output0 (buf_to_net, buf);
3080 
3081 		/* Test for a core dump.  Is this portable?  */
3082 		if (status & 0x80)
3083 		{
3084 		    buf_output0 (buf_to_net, "E Core dumped; preserving ");
3085 		    buf_output0 (buf_to_net, orig_server_temp_dir);
3086 		    buf_output0 (buf_to_net, " on server.\n\
3087 E CVS locks may need cleaning up.\n");
3088 		    dont_delete_temp = 1;
3089 		}
3090 		++errs;
3091 	    }
3092 	    if (waited_pid == command_pid)
3093 		command_pid = -1;
3094 	}
3095 
3096 	/*
3097 	 * OK, we've waited for the child.  By now all CVS locks are free
3098 	 * and it's OK to block on the network.
3099 	 */
3100 	set_block (buf_to_net);
3101 	buf_flush (buf_to_net, 1);
3102     }
3103 
3104     if (errs)
3105 	/* We will have printed an error message already.  */
3106 	buf_output0 (buf_to_net, "error  \n");
3107     else
3108 	buf_output0 (buf_to_net, "ok\n");
3109     goto free_args_and_return;
3110 
3111  error_exit:
3112     if (command_pid > 0)
3113 	kill (command_pid, SIGTERM);
3114 
3115     while (command_pid > 0)
3116     {
3117 	pid_t waited_pid;
3118 	waited_pid = waitpid (command_pid, (int *) 0, 0);
3119 	if (waited_pid < 0 && errno == EINTR)
3120 	    continue;
3121 	if (waited_pid == command_pid)
3122 	    command_pid = -1;
3123     }
3124 
3125     close (dev_null_fd);
3126     close (protocol_pipe[0]);
3127     close (protocol_pipe[1]);
3128     close (stderr_pipe[0]);
3129     close (stderr_pipe[1]);
3130     close (stdout_pipe[0]);
3131     close (stdout_pipe[1]);
3132 
3133  free_args_and_return:
3134     /* Now free the arguments.  */
3135     {
3136 	/* argument_vector[0] is a dummy argument, we don't mess with it.  */
3137 	char **cp;
3138 	for (cp = argument_vector + 1;
3139 	     cp < argument_vector + argument_count;
3140 	     ++cp)
3141 	    free (*cp);
3142 
3143 	argument_count = 1;
3144     }
3145 
3146     /* Flush out any data not yet sent.  */
3147     set_block (buf_to_net);
3148     buf_flush (buf_to_net, 1);
3149 
3150     return;
3151 }
3152 
3153 #ifdef SERVER_FLOWCONTROL
3154 /*
3155  * Called by the child at convenient points in the server's execution for
3156  * the server child to block.. ie: when it has no locks active.
3157  */
3158 void
3159 server_pause_check()
3160 {
3161     int paused = 0;
3162     char buf[1];
3163 
3164     while (read (flowcontrol_pipe[0], buf, 1) == 1)
3165     {
3166 	if (*buf == 'S')	/* Stop */
3167 	    paused = 1;
3168 	else if (*buf == 'G')	/* Go */
3169 	    paused = 0;
3170 	else
3171 	    return;		/* ??? */
3172     }
3173     while (paused) {
3174 	int numfds, numtocheck;
3175 	fd_set fds;
3176 
3177 	FD_ZERO (&fds);
3178 	FD_SET (flowcontrol_pipe[0], &fds);
3179 	numtocheck = flowcontrol_pipe[0] + 1;
3180 
3181 	do {
3182 	    numfds = select (numtocheck, &fds, (fd_set *)0,
3183 			     (fd_set *)0, (struct timeval *)NULL);
3184 	    if (numfds < 0
3185 		&& errno != EINTR)
3186 	    {
3187 		print_error (errno);
3188 		return;
3189 	    }
3190 	} while (numfds < 0);
3191 
3192 	if (FD_ISSET (flowcontrol_pipe[0], &fds))
3193 	{
3194 	    int got;
3195 
3196 	    while ((got = read (flowcontrol_pipe[0], buf, 1)) == 1)
3197 	    {
3198 		if (*buf == 'S')	/* Stop */
3199 		    paused = 1;
3200 		else if (*buf == 'G')	/* Go */
3201 		    paused = 0;
3202 		else
3203 		    return;		/* ??? */
3204 	    }
3205 
3206 	    /* This assumes that we are using BSD or POSIX nonblocking
3207                I/O.  System V nonblocking I/O returns zero if there is
3208                nothing to read.  */
3209 	    if (got == 0)
3210 	        error (1, 0, "flow control EOF");
3211 	    if (got < 0 && ! blocking_error (errno))
3212 	    {
3213 	        error (1, errno, "flow control read failed");
3214 	    }
3215 	}
3216     }
3217 }
3218 #endif /* SERVER_FLOWCONTROL */
3219 
3220 /* This variable commented in server.h.  */
3221 char *server_dir = NULL;
3222 
3223 static void output_dir PROTO((char *, char *));
3224 
3225 static void
3226 output_dir (update_dir, repository)
3227     char *update_dir;
3228     char *repository;
3229 {
3230     if (server_dir != NULL)
3231     {
3232 	buf_output0 (protocol, server_dir);
3233 	buf_output0 (protocol, "/");
3234     }
3235     if (update_dir[0] == '\0')
3236 	buf_output0 (protocol, ".");
3237     else
3238 	buf_output0 (protocol, update_dir);
3239     buf_output0 (protocol, "/\n");
3240     buf_output0 (protocol, repository);
3241     buf_output0 (protocol, "/");
3242 }
3243 
3244 /*
3245  * Entries line that we are squirreling away to send to the client when
3246  * we are ready.
3247  */
3248 static char *entries_line;
3249 
3250 /*
3251  * File which has been Scratch_File'd, we are squirreling away that fact
3252  * to inform the client when we are ready.
3253  */
3254 static char *scratched_file;
3255 
3256 /*
3257  * The scratched_file will need to be removed as well as having its entry
3258  * removed.
3259  */
3260 static int kill_scratched_file;
3261 
3262 void
3263 server_register (name, version, timestamp, options, tag, date, conflict)
3264     char *name;
3265     char *version;
3266     char *timestamp;
3267     char *options;
3268     char *tag;
3269     char *date;
3270     char *conflict;
3271 {
3272     int len;
3273 
3274     if (options == NULL)
3275 	options = "";
3276 
3277     if (trace)
3278     {
3279 	(void) fprintf (stderr,
3280 			"%s-> server_register(%s, %s, %s, %s, %s, %s, %s)\n",
3281 			CLIENT_SERVER_STR,
3282 			name, version, timestamp ? timestamp : "", options,
3283 			tag ? tag : "", date ? date : "",
3284 			conflict ? conflict : "");
3285     }
3286 
3287     if (entries_line != NULL)
3288     {
3289 	/*
3290 	 * If CVS decides to Register it more than once (which happens
3291 	 * on "cvs update foo/foo.c" where foo and foo.c are already
3292 	 * checked out), use the last of the entries lines Register'd.
3293 	 */
3294 	free (entries_line);
3295     }
3296 
3297     /*
3298      * I have reports of Scratch_Entry and Register both happening, in
3299      * two different cases.  Using the last one which happens is almost
3300      * surely correct; I haven't tracked down why they both happen (or
3301      * even verified that they are for the same file).
3302      */
3303     if (scratched_file != NULL)
3304     {
3305 	free (scratched_file);
3306 	scratched_file = NULL;
3307     }
3308 
3309     len = (strlen (name) + strlen (version) + strlen (options) + 80);
3310     if (tag)
3311 	len += strlen (tag);
3312     if (date)
3313 	len += strlen (date);
3314 
3315     entries_line = xmalloc (len);
3316     sprintf (entries_line, "/%s/%s/", name, version);
3317     if (conflict != NULL)
3318     {
3319 	strcat (entries_line, "+=");
3320     }
3321     strcat (entries_line, "/");
3322     strcat (entries_line, options);
3323     strcat (entries_line, "/");
3324     if (tag != NULL)
3325     {
3326 	strcat (entries_line, "T");
3327 	strcat (entries_line, tag);
3328     }
3329     else if (date != NULL)
3330     {
3331 	strcat (entries_line, "D");
3332 	strcat (entries_line, date);
3333     }
3334 }
3335 
3336 void
3337 server_scratch (fname)
3338     char *fname;
3339 {
3340     /*
3341      * I have reports of Scratch_Entry and Register both happening, in
3342      * two different cases.  Using the last one which happens is almost
3343      * surely correct; I haven't tracked down why they both happen (or
3344      * even verified that they are for the same file).
3345      */
3346     if (entries_line != NULL)
3347     {
3348 	free (entries_line);
3349 	entries_line = NULL;
3350     }
3351 
3352     if (scratched_file != NULL)
3353     {
3354 	buf_output0 (protocol,
3355 		     "E CVS server internal error: duplicate Scratch_Entry\n");
3356 	buf_send_counted (protocol);
3357 	return;
3358     }
3359     scratched_file = xstrdup (fname);
3360     kill_scratched_file = 1;
3361 }
3362 
3363 void
3364 server_scratch_entry_only ()
3365 {
3366     kill_scratched_file = 0;
3367 }
3368 
3369 /* Print a new entries line, from a previous server_register.  */
3370 static void
3371 new_entries_line ()
3372 {
3373     if (entries_line)
3374     {
3375 	buf_output0 (protocol, entries_line);
3376 	buf_output (protocol, "\n", 1);
3377     }
3378     else
3379 	/* Return the error message as the Entries line.  */
3380 	buf_output0 (protocol,
3381 		     "CVS server internal error: Register missing\n");
3382     free (entries_line);
3383     entries_line = NULL;
3384 }
3385 
3386 
3387 static void
3388 serve_ci (arg)
3389     char *arg;
3390 {
3391     do_cvs_command ("commit", commit);
3392 }
3393 
3394 static void
3395 checked_in_response (file, update_dir, repository)
3396     char *file;
3397     char *update_dir;
3398     char *repository;
3399 {
3400     if (supported_response ("Mode"))
3401     {
3402 	struct stat sb;
3403 	char *mode_string;
3404 
3405 	if ( CVS_STAT (file, &sb) < 0)
3406 	{
3407 	    /* Not clear to me why the file would fail to exist, but it
3408 	       was happening somewhere in the testsuite.  */
3409 	    if (!existence_error (errno))
3410 		error (0, errno, "cannot stat %s", file);
3411 	}
3412 	else
3413 	{
3414 	    buf_output0 (protocol, "Mode ");
3415 	    mode_string = mode_to_string (sb.st_mode);
3416 	    buf_output0 (protocol, mode_string);
3417 	    buf_output0 (protocol, "\n");
3418 	    free (mode_string);
3419 	}
3420     }
3421 
3422     buf_output0 (protocol, "Checked-in ");
3423     output_dir (update_dir, repository);
3424     buf_output0 (protocol, file);
3425     buf_output (protocol, "\n", 1);
3426     new_entries_line ();
3427 }
3428 
3429 void
3430 server_checked_in (file, update_dir, repository)
3431     char *file;
3432     char *update_dir;
3433     char *repository;
3434 {
3435     if (noexec)
3436 	return;
3437     if (scratched_file != NULL && entries_line == NULL)
3438     {
3439 	/*
3440 	 * This happens if we are now doing a "cvs remove" after a previous
3441 	 * "cvs add" (without a "cvs ci" in between).
3442 	 */
3443 	buf_output0 (protocol, "Remove-entry ");
3444 	output_dir (update_dir, repository);
3445 	buf_output0 (protocol, file);
3446 	buf_output (protocol, "\n", 1);
3447 	free (scratched_file);
3448 	scratched_file = NULL;
3449     }
3450     else
3451     {
3452 	checked_in_response (file, update_dir, repository);
3453     }
3454     buf_send_counted (protocol);
3455 }
3456 
3457 void
3458 server_update_entries (file, update_dir, repository, updated)
3459     char *file;
3460     char *update_dir;
3461     char *repository;
3462     enum server_updated_arg4 updated;
3463 {
3464     if (noexec)
3465 	return;
3466     if (updated == SERVER_UPDATED)
3467 	checked_in_response (file, update_dir, repository);
3468     else
3469     {
3470 	if (!supported_response ("New-entry"))
3471 	    return;
3472 	buf_output0 (protocol, "New-entry ");
3473 	output_dir (update_dir, repository);
3474 	buf_output0 (protocol, file);
3475 	buf_output (protocol, "\n", 1);
3476 	new_entries_line ();
3477     }
3478 
3479     buf_send_counted (protocol);
3480 }
3481 
3482 static void
3483 serve_update (arg)
3484     char *arg;
3485 {
3486     do_cvs_command ("update", update);
3487 }
3488 
3489 static void
3490 serve_diff (arg)
3491     char *arg;
3492 {
3493     do_cvs_command ("diff", diff);
3494 }
3495 
3496 static void
3497 serve_log (arg)
3498     char *arg;
3499 {
3500     do_cvs_command ("log", cvslog);
3501 }
3502 
3503 static void
3504 serve_add (arg)
3505     char *arg;
3506 {
3507     do_cvs_command ("add", add);
3508 }
3509 
3510 static void
3511 serve_remove (arg)
3512     char *arg;
3513 {
3514     do_cvs_command ("remove", cvsremove);
3515 }
3516 
3517 static void
3518 serve_status (arg)
3519     char *arg;
3520 {
3521     do_cvs_command ("status", cvsstatus);
3522 }
3523 
3524 static void
3525 serve_rdiff (arg)
3526     char *arg;
3527 {
3528     do_cvs_command ("rdiff", patch);
3529 }
3530 
3531 static void
3532 serve_tag (arg)
3533     char *arg;
3534 {
3535     do_cvs_command ("cvstag", cvstag);
3536 }
3537 
3538 static void
3539 serve_rtag (arg)
3540     char *arg;
3541 {
3542     do_cvs_command ("rtag", rtag);
3543 }
3544 
3545 static void
3546 serve_import (arg)
3547     char *arg;
3548 {
3549     do_cvs_command ("import", import);
3550 }
3551 
3552 static void
3553 serve_admin (arg)
3554     char *arg;
3555 {
3556     do_cvs_command ("admin", admin);
3557 }
3558 
3559 static void
3560 serve_history (arg)
3561     char *arg;
3562 {
3563     do_cvs_command ("history", history);
3564 }
3565 
3566 static void
3567 serve_release (arg)
3568     char *arg;
3569 {
3570     do_cvs_command ("release", release);
3571 }
3572 
3573 static void serve_watch_on PROTO ((char *));
3574 
3575 static void
3576 serve_watch_on (arg)
3577     char *arg;
3578 {
3579     do_cvs_command ("watch_on", watch_on);
3580 }
3581 
3582 static void serve_watch_off PROTO ((char *));
3583 
3584 static void
3585 serve_watch_off (arg)
3586     char *arg;
3587 {
3588     do_cvs_command ("watch_off", watch_off);
3589 }
3590 
3591 static void serve_watch_add PROTO ((char *));
3592 
3593 static void
3594 serve_watch_add (arg)
3595     char *arg;
3596 {
3597     do_cvs_command ("watch_add", watch_add);
3598 }
3599 
3600 static void serve_watch_remove PROTO ((char *));
3601 
3602 static void
3603 serve_watch_remove (arg)
3604     char *arg;
3605 {
3606     do_cvs_command ("watch_remove", watch_remove);
3607 }
3608 
3609 static void serve_watchers PROTO ((char *));
3610 
3611 static void
3612 serve_watchers (arg)
3613     char *arg;
3614 {
3615     do_cvs_command ("watchers", watchers);
3616 }
3617 
3618 static void serve_editors PROTO ((char *));
3619 
3620 static void
3621 serve_editors (arg)
3622     char *arg;
3623 {
3624     do_cvs_command ("editors", editors);
3625 }
3626 
3627 static int noop PROTO ((int, char **));
3628 
3629 static int
3630 noop (argc, argv)
3631     int argc;
3632     char **argv;
3633 {
3634     return 0;
3635 }
3636 
3637 static void serve_noop PROTO ((char *));
3638 
3639 static void
3640 serve_noop (arg)
3641     char *arg;
3642 {
3643     do_cvs_command ("noop", noop);
3644 }
3645 
3646 static void serve_init PROTO ((char *));
3647 
3648 static void
3649 serve_init (arg)
3650     char *arg;
3651 {
3652     if (!isabsolute (arg))
3653     {
3654 	if (alloc_pending (80 + strlen (arg)))
3655 	    sprintf (pending_error_text,
3656 		     "E Root %s must be an absolute pathname", arg);
3657 	/* Fall through to do_cvs_command which will return the
3658 	   actual error.  */
3659     }
3660     set_local_cvsroot (arg);
3661 
3662     do_cvs_command ("init", init);
3663 }
3664 
3665 static void serve_annotate PROTO ((char *));
3666 
3667 static void
3668 serve_annotate (arg)
3669     char *arg;
3670 {
3671     do_cvs_command ("annotate", annotate);
3672 }
3673 
3674 static void
3675 serve_co (arg)
3676     char *arg;
3677 {
3678     char *tempdir;
3679     int status;
3680 
3681     if (print_pending_error ())
3682 	return;
3683 
3684     if (!isdir (CVSADM))
3685     {
3686 	/*
3687 	 * The client has not sent a "Repository" line.  Check out
3688 	 * into a pristine directory.
3689 	 */
3690 	tempdir = malloc (strlen (server_temp_dir) + 80);
3691 	if (tempdir == NULL)
3692 	{
3693 	    buf_output0 (buf_to_net, "E Out of memory\n");
3694 	    return;
3695 	}
3696 	strcpy (tempdir, server_temp_dir);
3697 	strcat (tempdir, "/checkout-dir");
3698 	status = mkdir_p (tempdir);
3699 	if (status != 0 && status != EEXIST)
3700 	{
3701 	    buf_output0 (buf_to_net, "E Cannot create ");
3702 	    buf_output0 (buf_to_net, tempdir);
3703 	    buf_append_char (buf_to_net, '\n');
3704 	    print_error (errno);
3705 	    free (tempdir);
3706 	    return;
3707 	}
3708 
3709 	if ( CVS_CHDIR (tempdir) < 0)
3710 	{
3711 	    buf_output0 (buf_to_net, "E Cannot change to directory ");
3712 	    buf_output0 (buf_to_net, tempdir);
3713 	    buf_append_char (buf_to_net, '\n');
3714 	    print_error (errno);
3715 	    free (tempdir);
3716 	    return;
3717 	}
3718 	free (tempdir);
3719     }
3720 
3721     /* Compensate for server_export()'s setting of command_name.
3722      *
3723      * [It probably doesn't matter if do_cvs_command() gets "export"
3724      *  or "checkout", but we ought to be accurate where possible.]
3725      */
3726     do_cvs_command ((strcmp (command_name, "export") == 0) ?
3727                     "export" : "checkout",
3728                     checkout);
3729 }
3730 
3731 static void
3732 serve_export (arg)
3733     char *arg;
3734 {
3735     /* Tell checkout() to behave like export not checkout.  */
3736     command_name = "export";
3737     serve_co (arg);
3738 }
3739 
3740 void
3741 server_copy_file (file, update_dir, repository, newfile)
3742     char *file;
3743     char *update_dir;
3744     char *repository;
3745     char *newfile;
3746 {
3747     /* At least for now, our practice is to have the server enforce
3748        noexec for the repository and the client enforce it for the
3749        working directory.  This might want more thought, and/or
3750        documentation in cvsclient.texi (other responses do it
3751        differently).  */
3752 
3753     if (!supported_response ("Copy-file"))
3754 	return;
3755     buf_output0 (protocol, "Copy-file ");
3756     output_dir (update_dir, repository);
3757     buf_output0 (protocol, file);
3758     buf_output0 (protocol, "\n");
3759     buf_output0 (protocol, newfile);
3760     buf_output0 (protocol, "\n");
3761 }
3762 
3763 /* See server.h for description.  */
3764 
3765 void
3766 server_modtime (finfo, vers_ts)
3767     struct file_info *finfo;
3768     Vers_TS *vers_ts;
3769 {
3770     char date[MAXDATELEN];
3771     char outdate[MAXDATELEN];
3772 
3773     assert (vers_ts->vn_rcs != NULL);
3774 
3775     if (!supported_response ("Mod-time"))
3776 	return;
3777 
3778     if (RCS_getrevtime (finfo->rcs, vers_ts->vn_rcs, date, 0) == (time_t) -1)
3779 	/* FIXME? should we be printing some kind of warning?  For one
3780 	   thing I'm not 100% sure whether this happens in non-error
3781 	   circumstances.  */
3782 	return;
3783     date_to_internet (outdate, date);
3784     buf_output0 (protocol, "Mod-time ");
3785     buf_output0 (protocol, outdate);
3786     buf_output0 (protocol, "\n");
3787 }
3788 
3789 /* See server.h for description.  */
3790 
3791 #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
3792 /* Need to prototype because mode_t might be smaller than int.  */
3793 void
3794 server_updated (
3795     struct file_info *finfo,
3796     Vers_TS *vers,
3797     enum server_updated_arg4 updated,
3798     mode_t mode,
3799     unsigned char *checksum,
3800     struct buffer *filebuf)
3801 #else
3802 void
3803 server_updated (finfo, vers, updated, mode, checksum, filebuf)
3804     struct file_info *finfo;
3805     Vers_TS *vers;
3806     enum server_updated_arg4 updated;
3807     mode_t mode;
3808     unsigned char *checksum;
3809     struct buffer *filebuf;
3810 #endif
3811 {
3812     if (noexec)
3813     {
3814 	/* Hmm, maybe if we did the same thing for entries_file, we
3815 	   could get rid of the kludges in server_register and
3816 	   server_scratch which refrain from warning if both
3817 	   Scratch_Entry and Register get called.  Maybe.  */
3818 	if (scratched_file)
3819 	{
3820 	    free (scratched_file);
3821 	    scratched_file = NULL;
3822 	}
3823 	return;
3824     }
3825 
3826     if (entries_line != NULL && scratched_file == NULL)
3827     {
3828 	FILE *f;
3829 	struct buffer_data *list, *last;
3830 	unsigned long size;
3831 	char size_text[80];
3832 
3833 	/* The contents of the file will be in one of filebuf,
3834 	   list/last, or here.  */
3835 	unsigned char *file;
3836 	size_t file_allocated;
3837 	size_t file_used;
3838 
3839 	if (filebuf != NULL)
3840 	{
3841 	    size = buf_length (filebuf);
3842 	    if (mode == (mode_t) -1)
3843 		error (1, 0, "\
3844 CVS server internal error: no mode in server_updated");
3845 	}
3846 	else
3847 	{
3848 	    struct stat sb;
3849 
3850 	    if ( CVS_STAT (finfo->file, &sb) < 0)
3851 	    {
3852 		if (existence_error (errno))
3853 		{
3854 		    /* If we have a sticky tag for a branch on which
3855 		       the file is dead, and cvs update the directory,
3856 		       it gets a T_CHECKOUT but no file.  So in this
3857 		       case just forget the whole thing.  */
3858 		    free (entries_line);
3859 		    entries_line = NULL;
3860 		    goto done;
3861 		}
3862 		error (1, errno, "reading %s", finfo->fullname);
3863 	    }
3864 	    size = sb.st_size;
3865 	    if (mode == (mode_t) -1)
3866 	    {
3867 		/* FIXME: When we check out files the umask of the
3868 		   server (set in .bashrc if rsh is in use) affects
3869 		   what mode we send, and it shouldn't.  */
3870 		mode = sb.st_mode;
3871 	    }
3872 	}
3873 
3874 	if (checksum != NULL)
3875 	{
3876 	    static int checksum_supported = -1;
3877 
3878 	    if (checksum_supported == -1)
3879 	    {
3880 		checksum_supported = supported_response ("Checksum");
3881 	    }
3882 
3883 	    if (checksum_supported)
3884 	    {
3885 	        int i;
3886 		char buf[3];
3887 
3888 	        buf_output0 (protocol, "Checksum ");
3889 		for (i = 0; i < 16; i++)
3890 		{
3891 		    sprintf (buf, "%02x", (unsigned int) checksum[i]);
3892 		    buf_output0 (protocol, buf);
3893 		}
3894 		buf_append_char (protocol, '\n');
3895 	    }
3896 	}
3897 
3898 	if (updated == SERVER_UPDATED)
3899 	{
3900 	    Node *node;
3901 	    Entnode *entnode;
3902 
3903 	    if (!(supported_response ("Created")
3904 		  && supported_response ("Update-existing")))
3905 		buf_output0 (protocol, "Updated ");
3906 	    else
3907 	    {
3908 		assert (vers != NULL);
3909 		if (vers->ts_user == NULL)
3910 		    buf_output0 (protocol, "Created ");
3911 		else
3912 		    buf_output0 (protocol, "Update-existing ");
3913 	    }
3914 
3915 	    /* Now munge the entries to say that the file is unmodified,
3916 	       in case we end up processing it again (e.g. modules3-6
3917 	       in the testsuite).  */
3918 	    node = findnode_fn (finfo->entries, finfo->file);
3919 	    entnode = (Entnode *)node->data;
3920 	    free (entnode->timestamp);
3921 	    entnode->timestamp = xstrdup ("=");
3922 	}
3923 	else if (updated == SERVER_MERGED)
3924 	    buf_output0 (protocol, "Merged ");
3925 	else if (updated == SERVER_PATCHED)
3926 	    buf_output0 (protocol, "Patched ");
3927 	else if (updated == SERVER_RCS_DIFF)
3928 	    buf_output0 (protocol, "Rcs-diff ");
3929 	else
3930 	    abort ();
3931 	output_dir (finfo->update_dir, finfo->repository);
3932 	buf_output0 (protocol, finfo->file);
3933 	buf_output (protocol, "\n", 1);
3934 
3935 	new_entries_line ();
3936 
3937         {
3938 	    char *mode_string;
3939 
3940 	    mode_string = mode_to_string (mode);
3941 	    buf_output0 (protocol, mode_string);
3942 	    buf_output0 (protocol, "\n");
3943 	    free (mode_string);
3944 	}
3945 
3946 	list = last = NULL;
3947 
3948 	file = NULL;
3949 	file_allocated = 0;
3950 	file_used = 0;
3951 
3952 	if (size > 0)
3953 	{
3954 	    /* Throughout this section we use binary mode to read the
3955 	       file we are sending.  The client handles any line ending
3956 	       translation if necessary.  */
3957 
3958 	    if (file_gzip_level
3959 		/*
3960 		 * For really tiny files, the gzip process startup
3961 		 * time will outweigh the compression savings.  This
3962 		 * might be computable somehow; using 100 here is just
3963 		 * a first approximation.
3964 		 */
3965 		&& size > 100)
3966 	    {
3967 		/* Basing this routine on read_and_gzip is not a
3968 		   high-performance approach.  But it seems easier
3969 		   to code than the alternative (and less
3970 		   vulnerable to subtle bugs).  Given that this feature
3971 		   is mainly for compatibility, that is the better
3972 		   tradeoff.  */
3973 
3974 		int fd;
3975 
3976 		/* Callers must avoid passing us a buffer if
3977                    file_gzip_level is set.  We could handle this case,
3978                    but it's not worth it since this case never arises
3979                    with a current client and server.  */
3980 		if (filebuf != NULL)
3981 		    error (1, 0, "\
3982 CVS server internal error: unhandled case in server_updated");
3983 
3984 		fd = CVS_OPEN (finfo->file, O_RDONLY | OPEN_BINARY, 0);
3985 		if (fd < 0)
3986 		    error (1, errno, "reading %s", finfo->fullname);
3987 		if (read_and_gzip (fd, finfo->fullname, &file,
3988 				   &file_allocated, &file_used,
3989 				   file_gzip_level))
3990 		    error (1, 0, "aborting due to compression error");
3991 		size = file_used;
3992 		if (close (fd) < 0)
3993 		    error (1, errno, "reading %s", finfo->fullname);
3994 		/* Prepending length with "z" is flag for using gzip here.  */
3995 		buf_output0 (protocol, "z");
3996 	    }
3997 	    else if (filebuf == NULL)
3998 	    {
3999 		long status;
4000 
4001 		f = CVS_FOPEN (finfo->file, "rb");
4002 		if (f == NULL)
4003 		    error (1, errno, "reading %s", finfo->fullname);
4004 		status = buf_read_file (f, size, &list, &last);
4005 		if (status == -2)
4006 		    (*protocol->memory_error) (protocol);
4007 		else if (status != 0)
4008 		    error (1, ferror (f) ? errno : 0, "reading %s",
4009 			   finfo->fullname);
4010 		if (fclose (f) == EOF)
4011 		    error (1, errno, "reading %s", finfo->fullname);
4012 	    }
4013 	}
4014 
4015 	sprintf (size_text, "%lu\n", size);
4016 	buf_output0 (protocol, size_text);
4017 
4018 	if (file != NULL)
4019 	{
4020 	    buf_output (protocol, file, file_used);
4021 	    free (file);
4022 	    file = NULL;
4023 	}
4024 	else if (filebuf == NULL)
4025 	    buf_append_data (protocol, list, last);
4026 	else
4027 	{
4028 	    buf_append_buffer (protocol, filebuf);
4029 	    buf_free (filebuf);
4030 	}
4031 	/* Note we only send a newline here if the file ended with one.  */
4032 
4033 	/*
4034 	 * Avoid using up too much disk space for temporary files.
4035 	 * A file which does not exist indicates that the file is up-to-date,
4036 	 * which is now the case.  If this is SERVER_MERGED, the file is
4037 	 * not up-to-date, and we indicate that by leaving the file there.
4038 	 * I'm thinking of cases like "cvs update foo/foo.c foo".
4039 	 */
4040 	if ((updated == SERVER_UPDATED
4041 	     || updated == SERVER_PATCHED
4042 	     || updated == SERVER_RCS_DIFF)
4043 	    && filebuf == NULL
4044 	    /* But if we are joining, we'll need the file when we call
4045 	       join_file.  */
4046 	    && !joining ())
4047 	{
4048 	    if (CVS_UNLINK (finfo->file) < 0)
4049 		error (0, errno, "cannot remove temp file for %s",
4050 		       finfo->fullname);
4051 	}
4052     }
4053     else if (scratched_file != NULL && entries_line == NULL)
4054     {
4055 	if (strcmp (scratched_file, finfo->file) != 0)
4056 	    error (1, 0,
4057 		   "CVS server internal error: `%s' vs. `%s' scratched",
4058 		   scratched_file,
4059 		   finfo->file);
4060 	free (scratched_file);
4061 	scratched_file = NULL;
4062 
4063 	if (kill_scratched_file)
4064 	    buf_output0 (protocol, "Removed ");
4065 	else
4066 	    buf_output0 (protocol, "Remove-entry ");
4067 	output_dir (finfo->update_dir, finfo->repository);
4068 	buf_output0 (protocol, finfo->file);
4069 	buf_output (protocol, "\n", 1);
4070     }
4071     else if (scratched_file == NULL && entries_line == NULL)
4072     {
4073 	/*
4074 	 * This can happen with death support if we were processing
4075 	 * a dead file in a checkout.
4076 	 */
4077     }
4078     else
4079 	error (1, 0,
4080 	       "CVS server internal error: Register *and* Scratch_Entry.\n");
4081     buf_send_counted (protocol);
4082   done:;
4083 }
4084 
4085 /* Return whether we should send patches in RCS format.  */
4086 
4087 int
4088 server_use_rcs_diff ()
4089 {
4090     return supported_response ("Rcs-diff");
4091 }
4092 
4093 void
4094 server_set_entstat (update_dir, repository)
4095     char *update_dir;
4096     char *repository;
4097 {
4098     static int set_static_supported = -1;
4099     if (set_static_supported == -1)
4100 	set_static_supported = supported_response ("Set-static-directory");
4101     if (!set_static_supported) return;
4102 
4103     buf_output0 (protocol, "Set-static-directory ");
4104     output_dir (update_dir, repository);
4105     buf_output0 (protocol, "\n");
4106     buf_send_counted (protocol);
4107 }
4108 
4109 void
4110 server_clear_entstat (update_dir, repository)
4111      char *update_dir;
4112      char *repository;
4113 {
4114     static int clear_static_supported = -1;
4115     if (clear_static_supported == -1)
4116 	clear_static_supported = supported_response ("Clear-static-directory");
4117     if (!clear_static_supported) return;
4118 
4119     if (noexec)
4120 	return;
4121 
4122     buf_output0 (protocol, "Clear-static-directory ");
4123     output_dir (update_dir, repository);
4124     buf_output0 (protocol, "\n");
4125     buf_send_counted (protocol);
4126 }
4127 
4128 void
4129 server_set_sticky (update_dir, repository, tag, date, nonbranch)
4130     char *update_dir;
4131     char *repository;
4132     char *tag;
4133     char *date;
4134     int nonbranch;
4135 {
4136     static int set_sticky_supported = -1;
4137 
4138     assert (update_dir != NULL);
4139 
4140     if (set_sticky_supported == -1)
4141 	set_sticky_supported = supported_response ("Set-sticky");
4142     if (!set_sticky_supported) return;
4143 
4144     if (noexec)
4145 	return;
4146 
4147     if (tag == NULL && date == NULL)
4148     {
4149 	buf_output0 (protocol, "Clear-sticky ");
4150 	output_dir (update_dir, repository);
4151 	buf_output0 (protocol, "\n");
4152     }
4153     else
4154     {
4155 	buf_output0 (protocol, "Set-sticky ");
4156 	output_dir (update_dir, repository);
4157 	buf_output0 (protocol, "\n");
4158 	if (tag != NULL)
4159 	{
4160 	    if (nonbranch)
4161 		buf_output0 (protocol, "N");
4162 	    else
4163 		buf_output0 (protocol, "T");
4164 	    buf_output0 (protocol, tag);
4165 	}
4166 	else
4167 	{
4168 	    buf_output0 (protocol, "D");
4169 	    buf_output0 (protocol, date);
4170 	}
4171 	buf_output0 (protocol, "\n");
4172     }
4173     buf_send_counted (protocol);
4174 }
4175 
4176 struct template_proc_data
4177 {
4178     char *update_dir;
4179     char *repository;
4180 };
4181 
4182 /* Here as a static until we get around to fixing Parse_Info to pass along
4183    a void * for it.  */
4184 static struct template_proc_data *tpd;
4185 
4186 static int
4187 template_proc (repository, template)
4188     char *repository;
4189     char *template;
4190 {
4191     FILE *fp;
4192     char buf[1024];
4193     size_t n;
4194     struct stat sb;
4195     struct template_proc_data *data = tpd;
4196 
4197     if (!supported_response ("Template"))
4198 	/* Might want to warn the user that the rcsinfo feature won't work.  */
4199 	return 0;
4200     buf_output0 (protocol, "Template ");
4201     output_dir (data->update_dir, data->repository);
4202     buf_output0 (protocol, "\n");
4203 
4204     fp = CVS_FOPEN (template, "rb");
4205     if (fp == NULL)
4206     {
4207 	error (0, errno, "Couldn't open rcsinfo template file %s", template);
4208 	return 1;
4209     }
4210     if (fstat (fileno (fp), &sb) < 0)
4211     {
4212 	error (0, errno, "cannot stat rcsinfo template file %s", template);
4213 	return 1;
4214     }
4215     sprintf (buf, "%ld\n", (long) sb.st_size);
4216     buf_output0 (protocol, buf);
4217     while (!feof (fp))
4218     {
4219 	n = fread (buf, 1, sizeof buf, fp);
4220 	buf_output (protocol, buf, n);
4221 	if (ferror (fp))
4222 	{
4223 	    error (0, errno, "cannot read rcsinfo template file %s", template);
4224 	    (void) fclose (fp);
4225 	    return 1;
4226 	}
4227     }
4228     if (fclose (fp) < 0)
4229 	error (0, errno, "cannot close rcsinfo template file %s", template);
4230     return 0;
4231 }
4232 
4233 void
4234 server_template (update_dir, repository)
4235     char *update_dir;
4236     char *repository;
4237 {
4238     struct template_proc_data data;
4239     data.update_dir = update_dir;
4240     data.repository = repository;
4241     tpd = &data;
4242     (void) Parse_Info (CVSROOTADM_RCSINFO, repository, template_proc, 1);
4243 }
4244 
4245 static void
4246 serve_gzip_contents (arg)
4247      char *arg;
4248 {
4249     int level;
4250     level = atoi (arg);
4251     if (level == 0)
4252 	level = 6;
4253     file_gzip_level = level;
4254 }
4255 
4256 static void
4257 serve_gzip_stream (arg)
4258      char *arg;
4259 {
4260     int level;
4261     level = atoi (arg);
4262     if (level == 0)
4263 	level = 6;
4264 
4265     /* All further communication with the client will be compressed.  */
4266 
4267     buf_to_net = compress_buffer_initialize (buf_to_net, 0, level,
4268 					     buf_to_net->memory_error);
4269     buf_from_net = compress_buffer_initialize (buf_from_net, 1, level,
4270 					       buf_from_net->memory_error);
4271 }
4272 
4273 /* Tell the client about RCS options set in CVSROOT/cvswrappers. */
4274 static void
4275 serve_wrapper_sendme_rcs_options (arg)
4276      char *arg;
4277 {
4278     /* Actually, this is kind of sdrawkcab-ssa: the client wants
4279      * verbatim lines from a cvswrappers file, but the server has
4280      * already parsed the cvswrappers file into the wrap_list struct.
4281      * Therefore, the server loops over wrap_list, unparsing each
4282      * entry before sending it.
4283      */
4284     char *wrapper_line = NULL;
4285 
4286     wrap_setup ();
4287 
4288     for (wrap_unparse_rcs_options (&wrapper_line, 1);
4289          wrapper_line;
4290          wrap_unparse_rcs_options (&wrapper_line, 0))
4291     {
4292 	buf_output0 (buf_to_net, "Wrapper-rcsOption ");
4293 	buf_output0 (buf_to_net, wrapper_line);
4294 	buf_output0 (buf_to_net, "\012");;
4295 	free (wrapper_line);
4296     }
4297 
4298     buf_output0 (buf_to_net, "ok\012");
4299 
4300     /* The client is waiting for us, so we better send the data now.  */
4301     buf_flush (buf_to_net, 1);
4302 }
4303 
4304 
4305 static void
4306 serve_ignore (arg)
4307     char *arg;
4308 {
4309     /*
4310      * Just ignore this command.  This is used to support the
4311      * update-patches command, which is not a real command, but a signal
4312      * to the client that update will accept the -u argument.
4313      */
4314 }
4315 
4316 static int
4317 expand_proc (pargc, argv, where, mwhere, mfile, shorten,
4318 	     local_specified, omodule, msg)
4319     int *pargc;
4320     char **argv;
4321     char *where;
4322     char *mwhere;
4323     char *mfile;
4324     int shorten;
4325     int local_specified;
4326     char *omodule;
4327     char *msg;
4328 {
4329     int i;
4330     char *dir = argv[0];
4331 
4332     /* If mwhere has been specified, the thing we're expanding is a
4333        module -- just return its name so the client will ask for the
4334        right thing later.  If it is an alias or a real directory,
4335        mwhere will not be set, so send out the appropriate
4336        expansion. */
4337 
4338     if (mwhere != NULL)
4339     {
4340 	buf_output0 (buf_to_net, "Module-expansion ");
4341 	if (server_dir != NULL)
4342 	{
4343 	    buf_output0 (buf_to_net, server_dir);
4344 	    buf_output0 (buf_to_net, "/");
4345 	}
4346 	buf_output0 (buf_to_net, mwhere);
4347 	if (mfile != NULL)
4348 	{
4349 	    buf_append_char (buf_to_net, '/');
4350 	    buf_output0 (buf_to_net, mfile);
4351 	}
4352 	buf_append_char (buf_to_net, '\n');
4353     }
4354     else
4355     {
4356 	/* We may not need to do this anymore -- check the definition
4357            of aliases before removing */
4358 	if (*pargc == 1)
4359 	{
4360 	    buf_output0 (buf_to_net, "Module-expansion ");
4361 	    if (server_dir != NULL)
4362 	    {
4363 		buf_output0 (buf_to_net, server_dir);
4364 		buf_output0 (buf_to_net, "/");
4365 	    }
4366 	    buf_output0 (buf_to_net, dir);
4367 	    buf_append_char (buf_to_net, '\n');
4368 	}
4369 	else
4370 	{
4371 	    for (i = 1; i < *pargc; ++i)
4372 	    {
4373 	        buf_output0 (buf_to_net, "Module-expansion ");
4374 		if (server_dir != NULL)
4375 		{
4376 		    buf_output0 (buf_to_net, server_dir);
4377 		    buf_output0 (buf_to_net, "/");
4378 		}
4379 		buf_output0 (buf_to_net, dir);
4380 		buf_append_char (buf_to_net, '/');
4381 		buf_output0 (buf_to_net, argv[i]);
4382 		buf_append_char (buf_to_net, '\n');
4383 	    }
4384 	}
4385     }
4386     return 0;
4387 }
4388 
4389 static void
4390 serve_expand_modules (arg)
4391     char *arg;
4392 {
4393     int i;
4394     int err;
4395     DBM *db;
4396     err = 0;
4397 
4398     server_expanding = 1;
4399     db = open_module ();
4400     for (i = 1; i < argument_count; i++)
4401 	err += do_module (db, argument_vector[i],
4402 			  CHECKOUT, "Updating", expand_proc,
4403 			  NULL, 0, 0, 0,
4404 			  (char *) NULL);
4405     close_module (db);
4406     server_expanding = 0;
4407     {
4408 	/* argument_vector[0] is a dummy argument, we don't mess with it.  */
4409 	char **cp;
4410 	for (cp = argument_vector + 1;
4411 	     cp < argument_vector + argument_count;
4412 	     ++cp)
4413 	    free (*cp);
4414 
4415 	argument_count = 1;
4416     }
4417     if (err)
4418 	/* We will have printed an error message already.  */
4419 	buf_output0 (buf_to_net, "error  \n");
4420     else
4421 	buf_output0 (buf_to_net, "ok\n");
4422 
4423     /* The client is waiting for the module expansions, so we must
4424        send the output now.  */
4425     buf_flush (buf_to_net, 1);
4426 }
4427 
4428 void
4429 server_prog (dir, name, which)
4430     char *dir;
4431     char *name;
4432     enum progs which;
4433 {
4434     if (!supported_response ("Set-checkin-prog"))
4435     {
4436 	buf_output0 (buf_to_net, "E \
4437 warning: this client does not support -i or -u flags in the modules file.\n");
4438 	return;
4439     }
4440     switch (which)
4441     {
4442 	case PROG_CHECKIN:
4443 	    buf_output0 (buf_to_net, "Set-checkin-prog ");
4444 	    break;
4445 	case PROG_UPDATE:
4446 	    buf_output0 (buf_to_net, "Set-update-prog ");
4447 	    break;
4448     }
4449     buf_output0 (buf_to_net, dir);
4450     buf_append_char (buf_to_net, '\n');
4451     buf_output0 (buf_to_net, name);
4452     buf_append_char (buf_to_net, '\n');
4453 }
4454 
4455 static void
4456 serve_checkin_prog (arg)
4457     char *arg;
4458 {
4459     FILE *f;
4460     f = CVS_FOPEN (CVSADM_CIPROG, "w+");
4461     if (f == NULL)
4462     {
4463 	pending_error = errno;
4464 	if (alloc_pending (80 + strlen (CVSADM_CIPROG)))
4465 	    sprintf (pending_error_text, "E cannot open %s", CVSADM_CIPROG);
4466 	return;
4467     }
4468     if (fprintf (f, "%s\n", arg) < 0)
4469     {
4470 	pending_error = errno;
4471 	if (alloc_pending (80 + strlen (CVSADM_CIPROG)))
4472 	    sprintf (pending_error_text,
4473 		     "E cannot write to %s", CVSADM_CIPROG);
4474 	return;
4475     }
4476     if (fclose (f) == EOF)
4477     {
4478 	pending_error = errno;
4479 	if (alloc_pending (80 + strlen (CVSADM_CIPROG)))
4480 	    sprintf (pending_error_text, "E cannot close %s", CVSADM_CIPROG);
4481 	return;
4482     }
4483 }
4484 
4485 static void
4486 serve_update_prog (arg)
4487     char *arg;
4488 {
4489     FILE *f;
4490 
4491     /* Before we do anything we need to make sure we are not in readonly
4492        mode.  */
4493     if (!check_command_legal_p ("commit"))
4494     {
4495 	/* I might be willing to make this a warning, except we lack the
4496 	   machinery to do so.  */
4497 	if (alloc_pending (80))
4498 	    sprintf (pending_error_text, "\
4499 E Flag -u in modules not allowed in readonly mode");
4500 	return;
4501     }
4502 
4503     f = CVS_FOPEN (CVSADM_UPROG, "w+");
4504     if (f == NULL)
4505     {
4506 	pending_error = errno;
4507 	if (alloc_pending (80 + strlen (CVSADM_UPROG)))
4508 	    sprintf (pending_error_text, "E cannot open %s", CVSADM_UPROG);
4509 	return;
4510     }
4511     if (fprintf (f, "%s\n", arg) < 0)
4512     {
4513 	pending_error = errno;
4514 	if (alloc_pending (80 + strlen (CVSADM_UPROG)))
4515 	    sprintf (pending_error_text, "E cannot write to %s", CVSADM_UPROG);
4516 	return;
4517     }
4518     if (fclose (f) == EOF)
4519     {
4520 	pending_error = errno;
4521 	if (alloc_pending (80 + strlen (CVSADM_UPROG)))
4522 	    sprintf (pending_error_text, "E cannot close %s", CVSADM_UPROG);
4523 	return;
4524     }
4525 }
4526 
4527 static void serve_valid_requests PROTO((char *arg));
4528 
4529 #endif /* SERVER_SUPPORT */
4530 #if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
4531 
4532 /*
4533  * Parts of this table are shared with the client code,
4534  * but the client doesn't need to know about the handler
4535  * functions.
4536  */
4537 
4538 struct request requests[] =
4539 {
4540 #ifdef SERVER_SUPPORT
4541 #define REQ_LINE(n, f, s) {n, f, s}
4542 #else
4543 #define REQ_LINE(n, f, s) {n, s}
4544 #endif
4545 
4546   REQ_LINE("Root", serve_root, RQ_ESSENTIAL | RQ_ROOTLESS),
4547   REQ_LINE("Valid-responses", serve_valid_responses,
4548 	   RQ_ESSENTIAL | RQ_ROOTLESS),
4549   REQ_LINE("valid-requests", serve_valid_requests,
4550 	   RQ_ESSENTIAL | RQ_ROOTLESS),
4551   REQ_LINE("Repository", serve_repository, 0),
4552   REQ_LINE("Directory", serve_directory, RQ_ESSENTIAL),
4553   REQ_LINE("Max-dotdot", serve_max_dotdot, 0),
4554   REQ_LINE("Static-directory", serve_static_directory, 0),
4555   REQ_LINE("Sticky", serve_sticky, 0),
4556   REQ_LINE("Checkin-prog", serve_checkin_prog, 0),
4557   REQ_LINE("Update-prog", serve_update_prog, 0),
4558   REQ_LINE("Entry", serve_entry, RQ_ESSENTIAL),
4559   REQ_LINE("Kopt", serve_kopt, 0),
4560   REQ_LINE("Checkin-time", serve_checkin_time, 0),
4561   REQ_LINE("Modified", serve_modified, RQ_ESSENTIAL),
4562   REQ_LINE("Is-modified", serve_is_modified, 0),
4563 
4564   /* The client must send this request to interoperate with CVS 1.5
4565      through 1.9 servers.  The server must support it (although it can
4566      be and is a noop) to interoperate with CVS 1.5 to 1.9 clients.  */
4567   REQ_LINE("UseUnchanged", serve_enable_unchanged, RQ_ENABLEME | RQ_ROOTLESS),
4568 
4569   REQ_LINE("Unchanged", serve_unchanged, RQ_ESSENTIAL),
4570   REQ_LINE("Notify", serve_notify, 0),
4571   REQ_LINE("Questionable", serve_questionable, 0),
4572   REQ_LINE("Case", serve_case, 0),
4573   REQ_LINE("Argument", serve_argument, RQ_ESSENTIAL),
4574   REQ_LINE("Argumentx", serve_argumentx, RQ_ESSENTIAL),
4575   REQ_LINE("Global_option", serve_global_option, 0),
4576   REQ_LINE("Gzip-stream", serve_gzip_stream, 0),
4577   REQ_LINE("wrapper-sendme-rcsOptions",
4578            serve_wrapper_sendme_rcs_options,
4579            0),
4580   REQ_LINE("Set", serve_set, RQ_ROOTLESS),
4581 #ifdef ENCRYPTION
4582 #  ifdef HAVE_KERBEROS
4583   REQ_LINE("Kerberos-encrypt", serve_kerberos_encrypt, 0),
4584 #  endif
4585 #  ifdef HAVE_GSSAPI
4586   REQ_LINE("Gssapi-encrypt", serve_gssapi_encrypt, 0),
4587 #  endif
4588 #endif
4589 #ifdef HAVE_GSSAPI
4590   REQ_LINE("Gssapi-authenticate", serve_gssapi_authenticate, 0),
4591 #endif
4592   REQ_LINE("expand-modules", serve_expand_modules, 0),
4593   REQ_LINE("ci", serve_ci, RQ_ESSENTIAL),
4594   REQ_LINE("co", serve_co, RQ_ESSENTIAL),
4595   REQ_LINE("update", serve_update, RQ_ESSENTIAL),
4596   REQ_LINE("diff", serve_diff, 0),
4597   REQ_LINE("log", serve_log, 0),
4598   REQ_LINE("add", serve_add, 0),
4599   REQ_LINE("remove", serve_remove, 0),
4600   REQ_LINE("update-patches", serve_ignore, 0),
4601   REQ_LINE("gzip-file-contents", serve_gzip_contents, 0),
4602   REQ_LINE("status", serve_status, 0),
4603   REQ_LINE("rdiff", serve_rdiff, 0),
4604   REQ_LINE("tag", serve_tag, 0),
4605   REQ_LINE("rtag", serve_rtag, 0),
4606   REQ_LINE("import", serve_import, 0),
4607   REQ_LINE("admin", serve_admin, 0),
4608   REQ_LINE("export", serve_export, 0),
4609   REQ_LINE("history", serve_history, 0),
4610   REQ_LINE("release", serve_release, 0),
4611   REQ_LINE("watch-on", serve_watch_on, 0),
4612   REQ_LINE("watch-off", serve_watch_off, 0),
4613   REQ_LINE("watch-add", serve_watch_add, 0),
4614   REQ_LINE("watch-remove", serve_watch_remove, 0),
4615   REQ_LINE("watchers", serve_watchers, 0),
4616   REQ_LINE("editors", serve_editors, 0),
4617   REQ_LINE("init", serve_init, RQ_ROOTLESS),
4618   REQ_LINE("annotate", serve_annotate, 0),
4619   REQ_LINE("noop", serve_noop, 0),
4620   REQ_LINE(NULL, NULL, 0)
4621 
4622 #undef REQ_LINE
4623 };
4624 
4625 #endif /* SERVER_SUPPORT or CLIENT_SUPPORT */
4626 #ifdef SERVER_SUPPORT
4627 
4628 static void
4629 serve_valid_requests (arg)
4630      char *arg;
4631 {
4632     struct request *rq;
4633     if (print_pending_error ())
4634 	return;
4635     buf_output0 (buf_to_net, "Valid-requests");
4636     for (rq = requests; rq->name != NULL; rq++)
4637     {
4638 	if (rq->func != NULL)
4639 	{
4640 	    buf_append_char (buf_to_net, ' ');
4641 	    buf_output0 (buf_to_net, rq->name);
4642 	}
4643     }
4644     buf_output0 (buf_to_net, "\nok\n");
4645 
4646     /* The client is waiting for the list of valid requests, so we
4647        must send the output now.  */
4648     buf_flush (buf_to_net, 1);
4649 }
4650 
4651 #ifdef sun
4652 /*
4653  * Delete temporary files.  SIG is the signal making this happen, or
4654  * 0 if not called as a result of a signal.
4655  */
4656 static int command_pid_is_dead;
4657 static void wait_sig (sig)
4658      int sig;
4659 {
4660     int status;
4661     int save_errno = errno;
4662 
4663     pid_t r = wait (&status);
4664     if (r == command_pid)
4665 	command_pid_is_dead++;
4666     errno = save_errno;
4667 }
4668 #endif
4669 
4670 void
4671 server_cleanup (sig)
4672     int sig;
4673 {
4674     /* Do "rm -rf" on the temp directory.  */
4675     int status;
4676     int save_noexec;
4677 
4678     if (buf_to_net != NULL)
4679     {
4680 	/* FIXME: If this is not the final call from server, this
4681 	   could deadlock, because the client might be blocked writing
4682 	   to us.  This should not be a problem in practice, because
4683 	   we do not generate much output when the client is not
4684 	   waiting for it.  */
4685 	set_block (buf_to_net);
4686 	buf_flush (buf_to_net, 1);
4687 
4688 	/* The calls to buf_shutdown are currently only meaningful
4689 	   when we are using compression.  First we shut down
4690 	   BUF_FROM_NET.  That will pick up the checksum generated
4691 	   when the client shuts down its buffer.  Then, after we have
4692 	   generated any final output, we shut down BUF_TO_NET.  */
4693 
4694 	status = buf_shutdown (buf_from_net);
4695 	if (status != 0)
4696 	{
4697 	    error (0, status, "shutting down buffer from client");
4698 	    buf_flush (buf_to_net, 1);
4699 	}
4700     }
4701 
4702     if (dont_delete_temp)
4703     {
4704 	if (buf_to_net != NULL)
4705 	    (void) buf_shutdown (buf_to_net);
4706 	return;
4707     }
4708 
4709     /* What a bogus kludge.  This disgusting code makes all kinds of
4710        assumptions about SunOS, and is only for a bug in that system.
4711        So only enable it on Suns.  */
4712 #ifdef sun
4713     if (command_pid > 0)
4714     {
4715 	/* To avoid crashes on SunOS due to bugs in SunOS tmpfs
4716 	   triggered by the use of rename() in RCS, wait for the
4717 	   subprocess to die.  Unfortunately, this means draining output
4718 	   while waiting for it to unblock the signal we sent it.  Yuck!  */
4719 	int status;
4720 	pid_t r;
4721 
4722 	signal (SIGCHLD, wait_sig);
4723 	if (sig)
4724 	    /* Perhaps SIGTERM would be more correct.  But the child
4725 	       process will delay the SIGINT delivery until its own
4726 	       children have exited.  */
4727 	    kill (command_pid, SIGINT);
4728 	/* The caller may also have sent a signal to command_pid, so
4729 	   always try waiting.  First, though, check and see if it's still
4730 	   there....  */
4731     do_waitpid:
4732 	r = waitpid (command_pid, &status, WNOHANG);
4733 	if (r == 0)
4734 	    ;
4735 	else if (r == command_pid)
4736 	    command_pid_is_dead++;
4737 	else if (r == -1)
4738 	    switch (errno)
4739 	    {
4740 		case ECHILD:
4741 		    command_pid_is_dead++;
4742 		    break;
4743 		case EINTR:
4744 		    goto do_waitpid;
4745 	    }
4746 	else
4747 	    /* waitpid should always return one of the above values */
4748 	    abort ();
4749 	while (!command_pid_is_dead)
4750 	{
4751 	    struct timeval timeout;
4752 	    struct fd_set_wrapper readfds;
4753 	    char buf[100];
4754 	    int i;
4755 
4756 	    /* Use a non-zero timeout to avoid eating up CPU cycles.  */
4757 	    timeout.tv_sec = 2;
4758 	    timeout.tv_usec = 0;
4759 	    readfds = command_fds_to_drain;
4760 	    switch (select (max_command_fd + 1, &readfds.fds,
4761 			    (fd_set *)0, (fd_set *)0,
4762 			    &timeout))
4763 	    {
4764 		case -1:
4765 		    if (errno != EINTR)
4766 			abort ();
4767 		case 0:
4768 		    /* timeout */
4769 		    break;
4770 		case 1:
4771 		    for (i = 0; i <= max_command_fd; i++)
4772 		    {
4773 			if (!FD_ISSET (i, &readfds.fds))
4774 			    continue;
4775 			/* this fd is non-blocking */
4776 			while (read (i, buf, sizeof (buf)) >= 1)
4777 			    ;
4778 		    }
4779 		    break;
4780 		default:
4781 		    abort ();
4782 	    }
4783 	}
4784     }
4785 #endif
4786 
4787     CVS_CHDIR (Tmpdir);
4788     /* Temporarily clear noexec, so that we clean up our temp directory
4789        regardless of it (this could more cleanly be handled by moving
4790        the noexec check to all the unlink_file_dir callers from
4791        unlink_file_dir itself).  */
4792     save_noexec = noexec;
4793     noexec = 0;
4794     /* FIXME?  Would be nice to not ignore errors.  But what should we do?
4795        We could try to do this before we shut down the network connection,
4796        and try to notify the client (but the client might not be waiting
4797        for responses).  We could try something like syslog() or our own
4798        log file.  */
4799     unlink_file_dir (orig_server_temp_dir);
4800     noexec = save_noexec;
4801 
4802     if (buf_to_net != NULL)
4803 	(void) buf_shutdown (buf_to_net);
4804 }
4805 
4806 int server_active = 0;
4807 int server_expanding = 0;
4808 
4809 int
4810 server (argc, argv)
4811      int argc;
4812      char **argv;
4813 {
4814     if (argc == -1)
4815     {
4816 	static const char *const msg[] =
4817 	{
4818 	    "Usage: %s %s\n",
4819 	    "  Normally invoked by a cvs client on a remote machine.\n",
4820 	    NULL
4821 	};
4822 	usage (msg);
4823     }
4824     /* Ignore argc and argv.  They might be from .cvsrc.  */
4825 
4826     buf_to_net = fd_buffer_initialize (STDOUT_FILENO, 0,
4827 				       outbuf_memory_error);
4828     buf_from_net = stdio_buffer_initialize (stdin, 1, outbuf_memory_error);
4829 
4830     saved_output = buf_nonio_initialize (outbuf_memory_error);
4831     saved_outerr = buf_nonio_initialize (outbuf_memory_error);
4832 
4833     /* Since we're in the server parent process, error should use the
4834        protocol to report error messages.  */
4835     error_use_protocol = 1;
4836 
4837     /* OK, now figure out where we stash our temporary files.  */
4838     {
4839 	char *p;
4840 
4841 	/* The code which wants to chdir into server_temp_dir is not set
4842 	   up to deal with it being a relative path.  So give an error
4843 	   for that case.  */
4844 	if (!isabsolute (Tmpdir))
4845 	{
4846 	    pending_error_text = malloc (80 + strlen (Tmpdir));
4847 	    if (pending_error_text == NULL)
4848 	    {
4849 		pending_error = ENOMEM;
4850 	    }
4851 	    else
4852 	    {
4853 		sprintf (pending_error_text,
4854 			 "E Value of %s for TMPDIR is not absolute", Tmpdir);
4855 	    }
4856 	    /* FIXME: we would like this error to be persistent, that
4857 	       is, not cleared by print_pending_error.  The current client
4858 	       will exit as soon as it gets an error, but the protocol spec
4859 	       does not require a client to do so.  */
4860 	}
4861 	else
4862 	{
4863 	    int status;
4864 
4865 	    server_temp_dir = malloc (strlen (Tmpdir) + 80);
4866 	    if (server_temp_dir == NULL)
4867 	    {
4868 		/*
4869 		 * Strictly speaking, we're not supposed to output anything
4870 		 * now.  But we're about to exit(), give it a try.
4871 		 */
4872 		printf ("E Fatal server error, aborting.\n\
4873 error ENOMEM Virtual memory exhausted.\n");
4874 
4875 		/* I'm doing this manually rather than via error_exit ()
4876 		   because I'm not sure whether we want to call server_cleanup.
4877 		   Needs more investigation....  */
4878 
4879 #ifdef SYSTEM_CLEANUP
4880 		/* Hook for OS-specific behavior, for example socket
4881 		   subsystems on NT and OS2 or dealing with windows
4882 		   and arguments on Mac.  */
4883 		SYSTEM_CLEANUP ();
4884 #endif
4885 
4886 		exit (EXIT_FAILURE);
4887 	    }
4888 	    strcpy (server_temp_dir, Tmpdir);
4889 
4890 	    /* Remove a trailing slash from TMPDIR if present.  */
4891 	    p = server_temp_dir + strlen (server_temp_dir) - 1;
4892 	    if (*p == '/')
4893 		*p = '\0';
4894 
4895 	    /*
4896 	     * I wanted to use cvs-serv/PID, but then you have to worry about
4897 	     * the permissions on the cvs-serv directory being right.  So
4898 	     * use cvs-servPID.
4899 	     */
4900 	    strcat (server_temp_dir, "/cvs-serv");
4901 
4902 	    p = server_temp_dir + strlen (server_temp_dir);
4903 	    sprintf (p, "%ld", (long) getpid ());
4904 
4905 	    orig_server_temp_dir = server_temp_dir;
4906 
4907 	    /* Create the temporary directory, and set the mode to
4908                700, to discourage random people from tampering with
4909                it.  */
4910 	    status = mkdir_p (server_temp_dir);
4911 	    if (status != 0 && status != EEXIST)
4912 	    {
4913 		if (alloc_pending (80))
4914 		    strcpy (pending_error_text,
4915 			    "E can't create temporary directory");
4916 		pending_error = status;
4917 	    }
4918 #ifndef CHMOD_BROKEN
4919 	    else
4920 	    {
4921 		if (chmod (server_temp_dir, S_IRWXU) < 0)
4922 		{
4923 		    int save_errno = errno;
4924 		    if (alloc_pending (80))
4925 			strcpy (pending_error_text, "\
4926 E cannot change permissions on temporary directory");
4927 		    pending_error = save_errno;
4928 		}
4929 	    }
4930 #endif
4931 	}
4932     }
4933 
4934 #ifdef SIGHUP
4935     (void) SIG_register (SIGHUP, server_cleanup);
4936 #endif
4937 #ifdef SIGINT
4938     (void) SIG_register (SIGINT, server_cleanup);
4939 #endif
4940 #ifdef SIGQUIT
4941     (void) SIG_register (SIGQUIT, server_cleanup);
4942 #endif
4943 #ifdef SIGPIPE
4944     (void) SIG_register (SIGPIPE, server_cleanup);
4945 #endif
4946 #ifdef SIGTERM
4947     (void) SIG_register (SIGTERM, server_cleanup);
4948 #endif
4949 
4950     /* Now initialize our argument vector (for arguments from the client).  */
4951 
4952     /* Small for testing.  */
4953     argument_vector_size = 1;
4954     argument_vector =
4955 	(char **) malloc (argument_vector_size * sizeof (char *));
4956     if (argument_vector == NULL)
4957     {
4958 	/*
4959 	 * Strictly speaking, we're not supposed to output anything
4960 	 * now.  But we're about to exit(), give it a try.
4961 	 */
4962 	printf ("E Fatal server error, aborting.\n\
4963 error ENOMEM Virtual memory exhausted.\n");
4964 
4965 	/* I'm doing this manually rather than via error_exit ()
4966 	   because I'm not sure whether we want to call server_cleanup.
4967 	   Needs more investigation....  */
4968 
4969 #ifdef SYSTEM_CLEANUP
4970 	/* Hook for OS-specific behavior, for example socket subsystems on
4971 	   NT and OS2 or dealing with windows and arguments on Mac.  */
4972 	SYSTEM_CLEANUP ();
4973 #endif
4974 
4975 	exit (EXIT_FAILURE);
4976     }
4977 
4978     argument_count = 1;
4979     /* This gets printed if the client supports an option which the
4980        server doesn't, causing the server to print a usage message.
4981        FIXME: probably should be using program_name here.
4982        FIXME: just a nit, I suppose, but the usage message the server
4983        prints isn't literally true--it suggests "cvs server" followed
4984        by options which are for a particular command.  Might be nice to
4985        say something like "client apparently supports an option not supported
4986        by this server" or something like that instead of usage message.  */
4987     argument_vector[0] = "cvs server";
4988 
4989     while (1)
4990     {
4991 	char *cmd, *orig_cmd;
4992 	struct request *rq;
4993 	int status;
4994 
4995 	status = buf_read_line (buf_from_net, &cmd, (int *) NULL);
4996 	if (status == -2)
4997 	{
4998 	    buf_output0 (buf_to_net, "E Fatal server error, aborting.\n\
4999 error ENOMEM Virtual memory exhausted.\n");
5000 	    break;
5001 	}
5002 	if (status != 0)
5003 	    break;
5004 
5005 	orig_cmd = cmd;
5006 	for (rq = requests; rq->name != NULL; ++rq)
5007 	    if (strncmp (cmd, rq->name, strlen (rq->name)) == 0)
5008 	    {
5009 		int len = strlen (rq->name);
5010 		if (cmd[len] == '\0')
5011 		    cmd += len;
5012 		else if (cmd[len] == ' ')
5013 		    cmd += len + 1;
5014 		else
5015 		    /*
5016 		     * The first len characters match, but it's a different
5017 		     * command.  e.g. the command is "cooperate" but we matched
5018 		     * "co".
5019 		     */
5020 		    continue;
5021 
5022 		if (!(rq->flags & RQ_ROOTLESS)
5023 		    && CVSroot_directory == NULL)
5024 		{
5025 		    /* For commands which change the way in which data
5026 		       is sent and received, for example Gzip-stream,
5027 		       this does the wrong thing.  Since the client
5028 		       assumes that everything is being compressed,
5029 		       unconditionally, there is no way to give this
5030 		       error to the client without turning on
5031 		       compression.  The obvious fix would be to make
5032 		       Gzip-stream RQ_ROOTLESS (with the corresponding
5033 		       change to the spec), and that might be a good
5034 		       idea but then again I can see some settings in
5035 		       CVSROOT about what compression level to allow.
5036 		       I suppose a more baroque answer would be to
5037 		       turn on compression (say, at level 1), just
5038 		       enough to give the "Root request missing"
5039 		       error.  For now we just lose.  */
5040 		    if (alloc_pending (80))
5041 			sprintf (pending_error_text,
5042 				 "E Protocol error: Root request missing");
5043 		}
5044 		else
5045 		    (*rq->func) (cmd);
5046 		break;
5047 	    }
5048 	if (rq->name == NULL)
5049 	{
5050 	    if (!print_pending_error ())
5051 	    {
5052 	        buf_output0 (buf_to_net, "error  unrecognized request `");
5053 		buf_output0 (buf_to_net, cmd);
5054 		buf_append_char (buf_to_net, '\'');
5055 		buf_append_char (buf_to_net, '\n');
5056 	    }
5057 	}
5058 	free (orig_cmd);
5059     }
5060     server_cleanup (0);
5061     return 0;
5062 }
5063 
5064 
5065 #if defined (HAVE_KERBEROS) || defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
5066 static void switch_to_user PROTO((const char *));
5067 
5068 static void
5069 switch_to_user (username)
5070     const char *username;
5071 {
5072     struct passwd *pw;
5073 
5074     pw = getpwnam (username);
5075     if (pw == NULL)
5076     {
5077 	/* Normally this won't be reached; check_password contains
5078 	   a similar check.  */
5079 
5080 	printf ("E Fatal error, aborting.\n\
5081 error 0 %s: no such user\n", username);
5082 	/* Don't worry about server_cleanup; server_active isn't set yet.  */
5083 	error_exit ();
5084     }
5085 
5086 #if HAVE_INITGROUPS
5087     if (initgroups (pw->pw_name, pw->pw_gid) < 0
5088 #  ifdef EPERM
5089 	/* At least on the system I tried, initgroups() only works as root.
5090 	   But we do still want to report ENOMEM and whatever other
5091 	   errors initgroups() might dish up.  */
5092 	&& errno != EPERM
5093 #  endif
5094 	)
5095     {
5096 	/* This could be a warning, but I'm not sure I see the point
5097 	   in doing that instead of an error given that it would happen
5098 	   on every connection.  We could log it somewhere and not tell
5099 	   the user.  But at least for now make it an error.  */
5100 	printf ("error 0 initgroups failed: %s\n", strerror (errno));
5101 	/* Don't worry about server_cleanup; server_active isn't set yet.  */
5102 	error_exit ();
5103     }
5104 #endif /* HAVE_INITGROUPS */
5105 
5106 #ifdef SETXID_SUPPORT
5107     /* honor the setgid bit iff set*/
5108     if (getgid() != getegid())
5109     {
5110 	if (setgid (getegid ()) < 0)
5111 	{
5112 	    /* See comments at setuid call below for more discussion.  */
5113 	    printf ("error 0 setuid failed: %s\n", strerror (errno));
5114 	    /* Don't worry about server_cleanup;
5115 	       server_active isn't set yet.  */
5116 	    error_exit ();
5117 	}
5118     }
5119     else
5120 #endif
5121     {
5122 	if (setgid (pw->pw_gid) < 0)
5123 	{
5124 	    /* See comments at setuid call below for more discussion.  */
5125 	    printf ("error 0 setuid failed: %s\n", strerror (errno));
5126 	    /* Don't worry about server_cleanup;
5127 	       server_active isn't set yet.  */
5128 	    error_exit ();
5129 	}
5130     }
5131 
5132     if (setuid (pw->pw_uid) < 0)
5133     {
5134 	/* Note that this means that if run as a non-root user,
5135 	   CVSROOT/passwd must contain the user we are running as
5136 	   (e.g. "joe:FsEfVcu:cvs" if run as "cvs" user).  This seems
5137 	   cleaner than ignoring the error like CVS 1.10 and older but
5138 	   it does mean that some people might need to update their
5139 	   CVSROOT/passwd file.  */
5140 	printf ("error 0 setuid failed: %s\n", strerror (errno));
5141 	/* Don't worry about server_cleanup; server_active isn't set yet.  */
5142 	error_exit ();
5143     }
5144 
5145     /* We don't want our umask to change file modes.  The modes should
5146        be set by the modes used in the repository, and by the umask of
5147        the client.  */
5148     umask (0);
5149 
5150 #if HAVE_PUTENV
5151     /* Set LOGNAME and USER in the environment, in case they are
5152        already set to something else.  */
5153     {
5154 	char *env;
5155 
5156 	env = xmalloc (sizeof "LOGNAME=" + strlen (username));
5157 	(void) sprintf (env, "LOGNAME=%s", username);
5158 	(void) putenv (env);
5159 
5160 	env = xmalloc (sizeof "USER=" + strlen (username));
5161 	(void) sprintf (env, "USER=%s", username);
5162 	(void) putenv (env);
5163     }
5164 #endif /* HAVE_PUTENV */
5165 }
5166 #endif
5167 
5168 #ifdef AUTH_SERVER_SUPPORT
5169 
5170 extern char *crypt PROTO((const char *, const char *));
5171 
5172 
5173 /*
5174  * 0 means no entry found for this user.
5175  * 1 means entry found and password matches.
5176  * 2 means entry found, but password does not match.
5177  *
5178  * If success, host_user_ptr will be set to point at the system
5179  * username (i.e., the "real" identity, which may or may not be the
5180  * CVS username) of this user; caller may free this.  Global
5181  * CVS_Username will point at an allocated copy of cvs username (i.e.,
5182  * the username argument below).
5183  */
5184 static int
5185 check_repository_password (username, password, repository, host_user_ptr)
5186      char *username, *password, *repository, **host_user_ptr;
5187 {
5188     int retval = 0;
5189     FILE *fp;
5190     char *filename;
5191     char *linebuf = NULL;
5192     size_t linebuf_len;
5193     int found_it = 0;
5194     int namelen;
5195 
5196     /* We don't use CVSroot_directory because it hasn't been set yet
5197      * -- our `repository' argument came from the authentication
5198      * protocol, not the regular CVS protocol.
5199      */
5200 
5201     filename = xmalloc (strlen (repository)
5202 			+ 1
5203 			+ strlen (CVSROOTADM)
5204 			+ 1
5205 			+ strlen (CVSROOTADM_PASSWD)
5206 			+ 1);
5207 
5208     (void) sprintf (filename, "%s/%s/%s", repository,
5209                     CVSROOTADM, CVSROOTADM_PASSWD);
5210 
5211     fp = CVS_FOPEN (filename, "r");
5212     if (fp == NULL)
5213     {
5214 	if (!existence_error (errno))
5215 	    error (0, errno, "cannot open %s", filename);
5216 	return 0;
5217     }
5218 
5219     /* Look for a relevant line -- one with this user's name. */
5220     namelen = strlen (username);
5221     while (getline (&linebuf, &linebuf_len, fp) >= 0)
5222     {
5223 	if ((strncmp (linebuf, username, namelen) == 0)
5224 	    && (linebuf[namelen] == ':'))
5225         {
5226 	    found_it = 1;
5227 	    break;
5228         }
5229     }
5230     if (ferror (fp))
5231 	error (0, errno, "cannot read %s", filename);
5232     if (fclose (fp) < 0)
5233 	error (0, errno, "cannot close %s", filename);
5234 
5235     /* If found_it != 0, then linebuf contains the information we need. */
5236     if (found_it)
5237     {
5238 	char *found_password, *host_user_tmp;
5239 
5240 	strtok (linebuf, ":");
5241 	found_password = strtok (NULL, ": \n");
5242 	host_user_tmp = strtok (NULL, ": \n");
5243 	if (host_user_tmp == NULL)
5244             host_user_tmp = username;
5245 
5246 	if (strcmp (found_password, crypt (password, found_password)) == 0)
5247         {
5248             /* Give host_user_ptr permanent storage. */
5249             *host_user_ptr = xstrdup (host_user_tmp);
5250 	    retval = 1;
5251         }
5252 	else
5253         {
5254             *host_user_ptr = NULL;
5255 	    retval         = 2;
5256         }
5257     }
5258     else
5259     {
5260 	*host_user_ptr = NULL;
5261 	retval = 0;
5262     }
5263 
5264     free (filename);
5265     if (linebuf)
5266         free (linebuf);
5267 
5268     return retval;
5269 }
5270 
5271 
5272 /* Return a hosting username if password matches, else NULL. */
5273 static char *
5274 check_password (username, password, repository)
5275     char *username, *password, *repository;
5276 {
5277     int rc;
5278     char *host_user = NULL;
5279 
5280     /* First we see if this user has a password in the CVS-specific
5281        password file.  If so, that's enough to authenticate with.  If
5282        not, we'll check /etc/passwd. */
5283 
5284     rc = check_repository_password (username, password, repository,
5285 				    &host_user);
5286 
5287     if (rc == 2)
5288 	return NULL;
5289 
5290     /* else */
5291 
5292     if (rc == 1)
5293     {
5294         /* host_user already set by reference, so just return. */
5295         goto handle_return;
5296     }
5297     else if (rc == 0 && system_auth)
5298     {
5299 	/* No cvs password found, so try /etc/passwd. */
5300 
5301 	const char *found_passwd = NULL;
5302 	struct passwd *pw;
5303 #ifdef HAVE_GETSPNAM
5304 	struct spwd *spw;
5305 
5306 	spw = getspnam (username);
5307 	if (spw != NULL)
5308 	{
5309 	    found_passwd = spw->sp_pwdp;
5310 	}
5311 #endif
5312 
5313 	if (found_passwd == NULL && (pw = getpwnam (username)) != NULL)
5314 	{
5315 	    found_passwd = pw->pw_passwd;
5316 	}
5317 
5318 	if (found_passwd == NULL)
5319 	{
5320 	    printf ("E Fatal error, aborting.\n\
5321 error 0 %s: no such user\n", username);
5322 
5323 	    /* I'm doing this manually rather than via error_exit ()
5324 	       because I'm not sure whether we want to call server_cleanup.
5325 	       Needs more investigation....  */
5326 
5327 #ifdef SYSTEM_CLEANUP
5328 	    /* Hook for OS-specific behavior, for example socket subsystems on
5329 	       NT and OS2 or dealing with windows and arguments on Mac.  */
5330 	    SYSTEM_CLEANUP ();
5331 #endif
5332 
5333 	    exit (EXIT_FAILURE);
5334 	}
5335 
5336 	if (*found_passwd)
5337         {
5338 	    /* user exists and has a password */
5339 	    host_user = ((! strcmp (found_passwd,
5340                                     crypt (password, found_passwd)))
5341                          ? username : NULL);
5342             goto handle_return;
5343         }
5344 	else if (password && *password)
5345         {
5346 	    /* user exists and has no system password, but we got
5347 	       one as parameter */
5348 	    host_user = username;
5349             goto handle_return;
5350         }
5351 	else
5352         {
5353 	    /* user exists but has no password at all */
5354 	    host_user = NULL;
5355             goto handle_return;
5356         }
5357     }
5358     else if (rc == 0)
5359     {
5360 	/* Note that the message _does_ distinguish between the case in
5361 	   which we check for a system password and the case in which
5362 	   we do not.  It is a real pain to track down why it isn't
5363 	   letting you in if it won't say why, and I am not convinced
5364 	   that the potential information disclosure to an attacker
5365 	   outweighs this.  */
5366 	printf ("error 0 no such user %s in CVSROOT/passwd\n", username);
5367 
5368 	/* I'm doing this manually rather than via error_exit ()
5369 	   because I'm not sure whether we want to call server_cleanup.
5370 	   Needs more investigation....  */
5371 
5372 #ifdef SYSTEM_CLEANUP
5373 	/* Hook for OS-specific behavior, for example socket subsystems on
5374 	   NT and OS2 or dealing with windows and arguments on Mac.  */
5375 	SYSTEM_CLEANUP ();
5376 #endif
5377 	exit (EXIT_FAILURE);
5378     }
5379     else
5380     {
5381 	/* Something strange happened.  We don't know what it was, but
5382 	   we certainly won't grant authorization. */
5383 	host_user = NULL;
5384         goto handle_return;
5385     }
5386 
5387 handle_return:
5388     if (host_user)
5389     {
5390         /* Set CVS_Username here, in allocated space.
5391            It might or might not be the same as host_user. */
5392         CVS_Username = xmalloc (strlen (username) + 1);
5393         strcpy (CVS_Username, username);
5394     }
5395 
5396     return host_user;
5397 }
5398 
5399 #endif /* AUTH_SERVER_SUPPORT */
5400 
5401 #if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
5402 
5403 /* Read username and password from client (i.e., stdin).
5404    If correct, then switch to run as that user and send an ACK to the
5405    client via stdout, else send NACK and die. */
5406 void
5407 pserver_authenticate_connection ()
5408 {
5409     char *tmp = NULL;
5410     size_t tmp_allocated = 0;
5411 #ifdef AUTH_SERVER_SUPPORT
5412     char *repository = NULL;
5413     size_t repository_allocated = 0;
5414     char *username = NULL;
5415     size_t username_allocated = 0;
5416     char *password = NULL;
5417     size_t password_allocated = 0;
5418 
5419     char *host_user;
5420     char *descrambled_password;
5421 #endif /* AUTH_SERVER_SUPPORT */
5422     int verify_and_exit = 0;
5423 
5424     /* The Authentication Protocol.  Client sends:
5425      *
5426      *   BEGIN AUTH REQUEST\n
5427      *   <REPOSITORY>\n
5428      *   <USERNAME>\n
5429      *   <PASSWORD>\n
5430      *   END AUTH REQUEST\n
5431      *
5432      * Server uses above information to authenticate, then sends
5433      *
5434      *   I LOVE YOU\n
5435      *
5436      * if it grants access, else
5437      *
5438      *   I HATE YOU\n
5439      *
5440      * if it denies access (and it exits if denying).
5441      *
5442      * When the client is "cvs login", the user does not desire actual
5443      * repository access, but would like to confirm the password with
5444      * the server.  In this case, the start and stop strings are
5445      *
5446      *   BEGIN VERIFICATION REQUEST\n
5447      *
5448      *            and
5449      *
5450      *   END VERIFICATION REQUEST\n
5451      *
5452      * On a verification request, the server's responses are the same
5453      * (with the obvious semantics), but it exits immediately after
5454      * sending the response in both cases.
5455      *
5456      * Why is the repository sent?  Well, note that the actual
5457      * client/server protocol can't start up until authentication is
5458      * successful.  But in order to perform authentication, the server
5459      * needs to look up the password in the special CVS passwd file,
5460      * before trying /etc/passwd.  So the client transmits the
5461      * repository as part of the "authentication protocol".  The
5462      * repository will be redundantly retransmitted later, but that's no
5463      * big deal.
5464      */
5465 
5466 #ifdef SO_KEEPALIVE
5467     /* Set SO_KEEPALIVE on the socket, so that we don't hang forever
5468        if the client dies while we are waiting for input.  */
5469     {
5470 	int on = 1;
5471 
5472 	(void) setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
5473 			   (char *) &on, sizeof on);
5474     }
5475 #endif
5476 
5477     /* Make sure the protocol starts off on the right foot... */
5478     if (getline (&tmp, &tmp_allocated, stdin) < 0)
5479 	/* FIXME: what?  We could try writing error/eof, but chances
5480 	   are the network connection is dead bidirectionally.  log it
5481 	   somewhere?  */
5482 	;
5483 
5484     if (strcmp (tmp, "BEGIN VERIFICATION REQUEST\n") == 0)
5485 	verify_and_exit = 1;
5486     else if (strcmp (tmp, "BEGIN AUTH REQUEST\n") == 0)
5487 	;
5488     else if (strcmp (tmp, "BEGIN GSSAPI REQUEST\n") == 0)
5489     {
5490 #ifdef HAVE_GSSAPI
5491 	free (tmp);
5492 	gserver_authenticate_connection ();
5493 	return;
5494 #else
5495 	error (1, 0, "GSSAPI authentication not supported by this server");
5496 #endif
5497     }
5498     else
5499 	error (1, 0, "bad auth protocol start: %s", tmp);
5500 
5501 #ifndef AUTH_SERVER_SUPPORT
5502 
5503     error (1, 0, "Password authentication not supported by this server");
5504 
5505 #else /* AUTH_SERVER_SUPPORT */
5506 
5507     /* Get the three important pieces of information in order. */
5508     /* See above comment about error handling.  */
5509     getline (&repository, &repository_allocated, stdin);
5510     getline (&username, &username_allocated, stdin);
5511     getline (&password, &password_allocated, stdin);
5512 
5513     /* Make them pure. */
5514     strip_trailing_newlines (repository);
5515     strip_trailing_newlines (username);
5516     strip_trailing_newlines (password);
5517 
5518     /* ... and make sure the protocol ends on the right foot. */
5519     /* See above comment about error handling.  */
5520     getline (&tmp, &tmp_allocated, stdin);
5521     if (strcmp (tmp,
5522 		verify_and_exit ?
5523 		"END VERIFICATION REQUEST\n" : "END AUTH REQUEST\n")
5524 	!= 0)
5525     {
5526 	error (1, 0, "bad auth protocol end: %s", tmp);
5527     }
5528     if (!root_allow_ok (repository))
5529 	/* Just give a generic I HATE YOU.  This is because CVS 1.9.10
5530 	   and older clients do not support "error".  Once more recent
5531 	   clients are more widespread, probably want to fix this (it is
5532 	   a real pain to track down why it isn't letting you in if it
5533 	   won't say why, and I am not convinced that the potential
5534 	   information disclosure to an attacker outweighs this).  */
5535 	goto i_hate_you;
5536 
5537     /* OK, now parse the config file, so we can use it to control how
5538        to check passwords.  If there was an error parsing the config
5539        file, parse_config already printed an error.  We keep going.
5540        Why?  Because if we didn't, then there would be no way to check
5541        in a new CVSROOT/config file to fix the broken one!  */
5542     parse_config (repository);
5543 
5544     /* We need the real cleartext before we hash it. */
5545     descrambled_password = descramble (password);
5546     host_user = check_password (username, descrambled_password, repository);
5547     memset (descrambled_password, 0, strlen (descrambled_password));
5548     free (descrambled_password);
5549     if (host_user == NULL)
5550     {
5551     i_hate_you:
5552 	printf ("I HATE YOU\n");
5553 	fflush (stdout);
5554 
5555 	/* Don't worry about server_cleanup, server_active isn't set
5556 	   yet.  */
5557 	error_exit ();
5558     }
5559 
5560     /* Don't go any farther if we're just responding to "cvs login". */
5561     if (verify_and_exit)
5562     {
5563 	printf ("I LOVE YOU\n");
5564 	fflush (stdout);
5565 
5566 #ifdef SYSTEM_CLEANUP
5567 	/* Hook for OS-specific behavior, for example socket subsystems on
5568 	   NT and OS2 or dealing with windows and arguments on Mac.  */
5569 	SYSTEM_CLEANUP ();
5570 #endif
5571 
5572 	exit (0);
5573     }
5574 
5575     /* Set Pserver_Repos so that we can check later that the same
5576        repository is sent in later client/server protocol. */
5577     Pserver_Repos = xmalloc (strlen (repository) + 1);
5578     strcpy (Pserver_Repos, repository);
5579 
5580     /* Switch to run as this user. */
5581     switch_to_user (host_user);
5582     free (tmp);
5583     free (repository);
5584     free (username);
5585     free (password);
5586 
5587     printf ("I LOVE YOU\n");
5588     fflush (stdout);
5589 #endif /* AUTH_SERVER_SUPPORT */
5590 }
5591 
5592 #endif /* AUTH_SERVER_SUPPORT || HAVE_GSSAPI */
5593 
5594 
5595 #ifdef HAVE_KERBEROS
5596 void
5597 kserver_authenticate_connection ()
5598 {
5599     int status;
5600     char instance[INST_SZ];
5601     struct sockaddr_in peer;
5602     struct sockaddr_in laddr;
5603     int len;
5604     KTEXT_ST ticket;
5605     AUTH_DAT auth;
5606     char version[KRB_SENDAUTH_VLEN];
5607     char user[ANAME_SZ];
5608 
5609     strcpy (instance, "*");
5610     len = sizeof peer;
5611     if (getpeername (STDIN_FILENO, (struct sockaddr *) &peer, &len) < 0
5612 	|| getsockname (STDIN_FILENO, (struct sockaddr *) &laddr,
5613 			&len) < 0)
5614     {
5615 	printf ("E Fatal error, aborting.\n\
5616 error %s getpeername or getsockname failed\n", strerror (errno));
5617 #ifdef SYSTEM_CLEANUP
5618 	/* Hook for OS-specific behavior, for example socket subsystems on
5619 	   NT and OS2 or dealing with windows and arguments on Mac.  */
5620 	SYSTEM_CLEANUP ();
5621 #endif
5622 	exit (EXIT_FAILURE);
5623     }
5624 
5625 #ifdef SO_KEEPALIVE
5626     /* Set SO_KEEPALIVE on the socket, so that we don't hang forever
5627        if the client dies while we are waiting for input.  */
5628     {
5629 	int on = 1;
5630 
5631 	(void) setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
5632 			   (char *) &on, sizeof on);
5633     }
5634 #endif
5635 
5636     status = krb_recvauth (KOPT_DO_MUTUAL, STDIN_FILENO, &ticket, "rcmd",
5637 			   instance, &peer, &laddr, &auth, "", sched,
5638 			   version);
5639     if (status != KSUCCESS)
5640     {
5641 	printf ("E Fatal error, aborting.\n\
5642 error 0 kerberos: %s\n", krb_get_err_text(status));
5643 #ifdef SYSTEM_CLEANUP
5644 	/* Hook for OS-specific behavior, for example socket subsystems on
5645 	   NT and OS2 or dealing with windows and arguments on Mac.  */
5646 	SYSTEM_CLEANUP ();
5647 #endif
5648 	exit (EXIT_FAILURE);
5649     }
5650 
5651     memcpy (kblock, auth.session, sizeof (C_Block));
5652 
5653     /* Get the local name.  */
5654     status = krb_kntoln (&auth, user);
5655     if (status != KSUCCESS)
5656     {
5657 	printf ("E Fatal error, aborting.\n\
5658 error 0 kerberos: can't get local name: %s\n", krb_get_err_text(status));
5659 #ifdef SYSTEM_CLEANUP
5660 	/* Hook for OS-specific behavior, for example socket subsystems on
5661 	   NT and OS2 or dealing with windows and arguments on Mac.  */
5662 	SYSTEM_CLEANUP ();
5663 #endif
5664 	exit (EXIT_FAILURE);
5665     }
5666 
5667     /* Switch to run as this user. */
5668     switch_to_user (user);
5669 }
5670 #endif /* HAVE_KERBEROS */
5671 
5672 #ifdef HAVE_GSSAPI
5673 
5674 #ifndef MAXHOSTNAMELEN
5675 #define MAXHOSTNAMELEN (256)
5676 #endif
5677 
5678 /* Authenticate a GSSAPI connection.  This is called from
5679    pserver_authenticate_connection, and it handles success and failure
5680    the same way.  */
5681 
5682 static void
5683 gserver_authenticate_connection ()
5684 {
5685     char hostname[MAXHOSTNAMELEN];
5686     struct hostent *hp;
5687     gss_buffer_desc tok_in, tok_out;
5688     char buf[1024];
5689     OM_uint32 stat_min, ret;
5690     gss_name_t server_name, client_name;
5691     gss_cred_id_t server_creds;
5692     int nbytes;
5693     gss_OID mechid;
5694 
5695     gethostname (hostname, sizeof hostname);
5696     hp = gethostbyname (hostname);
5697     if (hp == NULL)
5698 	error (1, 0, "can't get canonical hostname");
5699 
5700     sprintf (buf, "cvs@%s", hp->h_name);
5701     tok_in.value = buf;
5702     tok_in.length = strlen (buf);
5703 
5704     if (gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE,
5705 			 &server_name) != GSS_S_COMPLETE)
5706 	error (1, 0, "could not import GSSAPI service name %s", buf);
5707 
5708     /* Acquire the server credential to verify the client's
5709        authentication.  */
5710     if (gss_acquire_cred (&stat_min, server_name, 0, GSS_C_NULL_OID_SET,
5711 			  GSS_C_ACCEPT, &server_creds,
5712 			  NULL, NULL) != GSS_S_COMPLETE)
5713 	error (1, 0, "could not acquire GSSAPI server credentials");
5714 
5715     gss_release_name (&stat_min, &server_name);
5716 
5717     /* The client will send us a two byte length followed by that many
5718        bytes.  */
5719     if (fread (buf, 1, 2, stdin) != 2)
5720 	error (1, errno, "read of length failed");
5721 
5722     nbytes = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
5723     assert (nbytes <= sizeof buf);
5724 
5725     if (fread (buf, 1, nbytes, stdin) != nbytes)
5726 	error (1, errno, "read of data failed");
5727 
5728     gcontext = GSS_C_NO_CONTEXT;
5729     tok_in.length = nbytes;
5730     tok_in.value = buf;
5731 
5732     if (gss_accept_sec_context (&stat_min,
5733                                 &gcontext,	/* context_handle */
5734                                 server_creds,	/* verifier_cred_handle */
5735                                 &tok_in,	/* input_token */
5736                                 NULL,		/* channel bindings */
5737                                 &client_name,	/* src_name */
5738                                 &mechid,	/* mech_type */
5739                                 &tok_out,	/* output_token */
5740                                 &ret,
5741                                 NULL,	 	/* ignore time_rec */
5742                                 NULL)		/* ignore del_cred_handle */
5743 	!= GSS_S_COMPLETE)
5744     {
5745 	error (1, 0, "could not verify credentials");
5746     }
5747 
5748     /* FIXME: Use Kerberos v5 specific code to authenticate to a user.
5749        We could instead use an authentication to access mapping.  */
5750     {
5751 	krb5_context kc;
5752 	krb5_principal p;
5753 	gss_buffer_desc desc;
5754 
5755 	krb5_init_context (&kc);
5756 	if (gss_display_name (&stat_min, client_name, &desc,
5757 			      &mechid) != GSS_S_COMPLETE
5758 	    || krb5_parse_name (kc, ((gss_buffer_t) &desc)->value, &p) != 0
5759 	    || krb5_aname_to_localname (kc, p, sizeof buf, buf) != 0
5760 	    || krb5_kuserok (kc, p, buf) != TRUE)
5761 	{
5762 	    error (1, 0, "access denied");
5763 	}
5764 	krb5_free_principal (kc, p);
5765 	krb5_free_context (kc);
5766     }
5767 
5768     if (tok_out.length != 0)
5769     {
5770 	char cbuf[2];
5771 
5772 	cbuf[0] = (tok_out.length >> 8) & 0xff;
5773 	cbuf[1] = tok_out.length & 0xff;
5774 	if (fwrite (cbuf, 1, 2, stdout) != 2
5775 	    || (fwrite (tok_out.value, 1, tok_out.length, stdout)
5776 		!= tok_out.length))
5777 	    error (1, errno, "fwrite failed");
5778     }
5779 
5780     switch_to_user (buf);
5781 
5782     printf ("I LOVE YOU\n");
5783     fflush (stdout);
5784 }
5785 
5786 #endif /* HAVE_GSSAPI */
5787 
5788 #endif /* SERVER_SUPPORT */
5789 
5790 #if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
5791 
5792 /* This global variable is non-zero if the user requests encryption on
5793    the command line.  */
5794 int cvsencrypt;
5795 
5796 /* This global variable is non-zero if the users requests stream
5797    authentication on the command line.  */
5798 int cvsauthenticate;
5799 
5800 #ifdef HAVE_GSSAPI
5801 
5802 /* An buffer interface using GSSAPI.  This is built on top of a
5803    packetizing buffer.  */
5804 
5805 /* This structure is the closure field of the GSSAPI translation
5806    routines.  */
5807 
5808 struct cvs_gssapi_wrap_data
5809 {
5810     /* The GSSAPI context.  */
5811     gss_ctx_id_t gcontext;
5812 };
5813 
5814 static int cvs_gssapi_wrap_input PROTO((void *, const char *, char *, int));
5815 static int cvs_gssapi_wrap_output PROTO((void *, const char *, char *, int,
5816 					 int *));
5817 
5818 /* Create a GSSAPI wrapping buffer.  We use a packetizing buffer with
5819    GSSAPI wrapping routines.  */
5820 
5821 struct buffer *
5822 cvs_gssapi_wrap_buffer_initialize (buf, input, gcontext, memory)
5823      struct buffer *buf;
5824      int input;
5825      gss_ctx_id_t gcontext;
5826      void (*memory) PROTO((struct buffer *));
5827 {
5828     struct cvs_gssapi_wrap_data *gd;
5829 
5830     gd = (struct cvs_gssapi_wrap_data *) xmalloc (sizeof *gd);
5831     gd->gcontext = gcontext;
5832 
5833     return (packetizing_buffer_initialize
5834 	    (buf,
5835 	     input ? cvs_gssapi_wrap_input : NULL,
5836 	     input ? NULL : cvs_gssapi_wrap_output,
5837 	     gd,
5838 	     memory));
5839 }
5840 
5841 /* Unwrap data using GSSAPI.  */
5842 
5843 static int
5844 cvs_gssapi_wrap_input (fnclosure, input, output, size)
5845      void *fnclosure;
5846      const char *input;
5847      char *output;
5848      int size;
5849 {
5850     struct cvs_gssapi_wrap_data *gd =
5851 	(struct cvs_gssapi_wrap_data *) fnclosure;
5852     gss_buffer_desc inbuf, outbuf;
5853     OM_uint32 stat_min;
5854     int conf;
5855 
5856     inbuf.value = (void *) input;
5857     inbuf.length = size;
5858 
5859     if (gss_unwrap (&stat_min, gd->gcontext, &inbuf, &outbuf, &conf, NULL)
5860 	!= GSS_S_COMPLETE)
5861     {
5862 	error (1, 0, "gss_unwrap failed");
5863     }
5864 
5865     if (outbuf.length > size)
5866 	abort ();
5867 
5868     memcpy (output, outbuf.value, outbuf.length);
5869 
5870     /* The real packet size is stored in the data, so we don't need to
5871        remember outbuf.length.  */
5872 
5873     gss_release_buffer (&stat_min, &outbuf);
5874 
5875     return 0;
5876 }
5877 
5878 /* Wrap data using GSSAPI.  */
5879 
5880 static int
5881 cvs_gssapi_wrap_output (fnclosure, input, output, size, translated)
5882      void *fnclosure;
5883      const char *input;
5884      char *output;
5885      int size;
5886      int *translated;
5887 {
5888     struct cvs_gssapi_wrap_data *gd =
5889 	(struct cvs_gssapi_wrap_data *) fnclosure;
5890     gss_buffer_desc inbuf, outbuf;
5891     OM_uint32 stat_min;
5892     int conf_req, conf;
5893 
5894     inbuf.value = (void *) input;
5895     inbuf.length = size;
5896 
5897 #ifdef ENCRYPTION
5898     conf_req = cvs_gssapi_encrypt;
5899 #else
5900     conf_req = 0;
5901 #endif
5902 
5903     if (gss_wrap (&stat_min, gd->gcontext, conf_req, GSS_C_QOP_DEFAULT,
5904 		  &inbuf, &conf, &outbuf) != GSS_S_COMPLETE)
5905 	error (1, 0, "gss_wrap failed");
5906 
5907     /* The packetizing buffer only permits us to add 100 bytes.
5908        FIXME: I don't know what, if anything, is guaranteed by GSSAPI.
5909        This may need to be increased for a different GSSAPI
5910        implementation, or we may need a different algorithm.  */
5911     if (outbuf.length > size + 100)
5912 	abort ();
5913 
5914     memcpy (output, outbuf.value, outbuf.length);
5915 
5916     *translated = outbuf.length;
5917 
5918     gss_release_buffer (&stat_min, &outbuf);
5919 
5920     return 0;
5921 }
5922 
5923 #endif /* HAVE_GSSAPI */
5924 
5925 #ifdef ENCRYPTION
5926 
5927 #ifdef HAVE_KERBEROS
5928 
5929 /* An encryption interface using Kerberos.  This is built on top of a
5930    packetizing buffer.  */
5931 
5932 /* This structure is the closure field of the Kerberos translation
5933    routines.  */
5934 
5935 struct krb_encrypt_data
5936 {
5937     /* The Kerberos key schedule.  */
5938     Key_schedule sched;
5939     /* The Kerberos DES block.  */
5940     C_Block block;
5941 };
5942 
5943 static int krb_encrypt_input PROTO((void *, const char *, char *, int));
5944 static int krb_encrypt_output PROTO((void *, const char *, char *, int,
5945 				     int *));
5946 
5947 /* Create a Kerberos encryption buffer.  We use a packetizing buffer
5948    with Kerberos encryption translation routines.  */
5949 
5950 struct buffer *
5951 krb_encrypt_buffer_initialize (buf, input, sched, block, memory)
5952      struct buffer *buf;
5953      int input;
5954      Key_schedule sched;
5955      C_Block block;
5956      void (*memory) PROTO((struct buffer *));
5957 {
5958     struct krb_encrypt_data *kd;
5959 
5960     kd = (struct krb_encrypt_data *) xmalloc (sizeof *kd);
5961     memcpy (kd->sched, sched, sizeof (Key_schedule));
5962     memcpy (kd->block, block, sizeof (C_Block));
5963 
5964     return packetizing_buffer_initialize (buf,
5965 					  input ? krb_encrypt_input : NULL,
5966 					  input ? NULL : krb_encrypt_output,
5967 					  kd,
5968 					  memory);
5969 }
5970 
5971 /* Decrypt Kerberos data.  */
5972 
5973 static int
5974 krb_encrypt_input (fnclosure, input, output, size)
5975      void *fnclosure;
5976      const char *input;
5977      char *output;
5978      int size;
5979 {
5980     struct krb_encrypt_data *kd = (struct krb_encrypt_data *) fnclosure;
5981     int tcount;
5982 
5983     des_cbc_encrypt ((C_Block *) input, (C_Block *) output,
5984 		     size, kd->sched, &kd->block, 0);
5985 
5986     /* SIZE is the size of the buffer, which is set by the encryption
5987        routine.  The packetizing buffer will arrange for the first two
5988        bytes in the decrypted buffer to be the real (unaligned)
5989        length.  As a safety check, make sure that the length in the
5990        buffer corresponds to SIZE.  Note that the length in the buffer
5991        is just the length of the data.  We must add 2 to account for
5992        the buffer count itself.  */
5993     tcount = ((output[0] & 0xff) << 8) + (output[1] & 0xff);
5994     if (((tcount + 2 + 7) & ~7) != size)
5995       error (1, 0, "Decryption failure");
5996 
5997     return 0;
5998 }
5999 
6000 /* Encrypt Kerberos data.  */
6001 
6002 static int
6003 krb_encrypt_output (fnclosure, input, output, size, translated)
6004      void *fnclosure;
6005      const char *input;
6006      char *output;
6007      int size;
6008      int *translated;
6009 {
6010     struct krb_encrypt_data *kd = (struct krb_encrypt_data *) fnclosure;
6011     int aligned;
6012 
6013     /* For security against a known plaintext attack, we should
6014        initialize any padding bytes to random values.  Instead, we
6015        just pick up whatever is on the stack, which is at least better
6016        than using zero.  */
6017 
6018     /* Align SIZE to an 8 byte boundary.  Note that SIZE includes the
6019        two byte buffer count at the start of INPUT which was added by
6020        the packetizing buffer.  */
6021     aligned = (size + 7) & ~7;
6022 
6023     /* We use des_cbc_encrypt rather than krb_mk_priv because the
6024        latter sticks a timestamp in the block, and krb_rd_priv expects
6025        that timestamp to be within five minutes of the current time.
6026        Given the way the CVS server buffers up data, that can easily
6027        fail over a long network connection.  We trust krb_recvauth to
6028        guard against a replay attack.  */
6029 
6030     des_cbc_encrypt ((C_Block *) input, (C_Block *) output, aligned,
6031 		     kd->sched, &kd->block, 1);
6032 
6033     *translated = aligned;
6034 
6035     return 0;
6036 }
6037 
6038 #endif /* HAVE_KERBEROS */
6039 #endif /* ENCRYPTION */
6040 #endif /* defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT) */
6041 
6042 /* Output LEN bytes at STR.  If LEN is zero, then output up to (not including)
6043    the first '\0' byte.  */
6044 
6045 void
6046 cvs_output (str, len)
6047     const char *str;
6048     size_t len;
6049 {
6050     if (len == 0)
6051 	len = strlen (str);
6052 #ifdef SERVER_SUPPORT
6053     if (error_use_protocol)
6054     {
6055 	buf_output (saved_output, str, len);
6056 	buf_copy_lines (buf_to_net, saved_output, 'M');
6057     }
6058     else if (server_active)
6059     {
6060 	buf_output (saved_output, str, len);
6061 	buf_copy_lines (protocol, saved_output, 'M');
6062 	buf_send_counted (protocol);
6063     }
6064     else
6065 #endif
6066     {
6067 	size_t written;
6068 	size_t to_write = len;
6069 	const char *p = str;
6070 
6071 	/* For symmetry with cvs_outerr we would call fflush (stderr)
6072 	   here.  I guess the assumption is that stderr will be
6073 	   unbuffered, so we don't need to.  That sounds like a sound
6074 	   assumption from the manpage I looked at, but if there was
6075 	   something fishy about it, my guess is that calling fflush
6076 	   would not produce a significant performance problem.  */
6077 
6078 	while (to_write > 0)
6079 	{
6080 	    written = fwrite (p, 1, to_write, stdout);
6081 	    if (written == 0)
6082 		break;
6083 	    p += written;
6084 	    to_write -= written;
6085 	}
6086     }
6087 }
6088 
6089 /* Output LEN bytes at STR in binary mode.  If LEN is zero, then
6090    output zero bytes.  */
6091 
6092 void
6093 cvs_output_binary (str, len)
6094     char *str;
6095     size_t len;
6096 {
6097 #ifdef SERVER_SUPPORT
6098     if (error_use_protocol || server_active)
6099     {
6100 	struct buffer *buf;
6101 	char size_text[40];
6102 
6103 	if (error_use_protocol)
6104 	    buf = buf_to_net;
6105 	else
6106 	    buf = protocol;
6107 
6108 	if (!supported_response ("Mbinary"))
6109 	{
6110 	    error (0, 0, "\
6111 this client does not support writing binary files to stdout");
6112 	    return;
6113 	}
6114 
6115 	buf_output0 (buf, "Mbinary\012");
6116 	sprintf (size_text, "%lu\012", (unsigned long) len);
6117 	buf_output0 (buf, size_text);
6118 
6119 	/* Not sure what would be involved in using buf_append_data here
6120 	   without stepping on the toes of our caller (which is responsible
6121 	   for the memory allocation of STR).  */
6122 	buf_output (buf, str, len);
6123 
6124 	if (!error_use_protocol)
6125 	    buf_send_counted (protocol);
6126     }
6127     else
6128 #endif
6129     {
6130 	size_t written;
6131 	size_t to_write = len;
6132 	const char *p = str;
6133 
6134 	/* For symmetry with cvs_outerr we would call fflush (stderr)
6135 	   here.  I guess the assumption is that stderr will be
6136 	   unbuffered, so we don't need to.  That sounds like a sound
6137 	   assumption from the manpage I looked at, but if there was
6138 	   something fishy about it, my guess is that calling fflush
6139 	   would not produce a significant performance problem.  */
6140 #ifdef USE_SETMODE_STDOUT
6141 	int oldmode;
6142 
6143 	/* It is possible that this should be the same ifdef as
6144 	   USE_SETMODE_BINARY but at least for the moment we keep them
6145 	   separate.  Mostly this is just laziness and/or a question
6146 	   of what has been tested where.  Also there might be an
6147 	   issue of setmode vs. _setmode.  */
6148 	/* The Windows doc says to call setmode only right after startup.
6149 	   I assume that what they are talking about can also be helped
6150 	   by flushing the stream before changing the mode.  */
6151 	fflush (stdout);
6152 	oldmode = _setmode (_fileno (stdout), OPEN_BINARY);
6153 	if (oldmode < 0)
6154 	    error (0, errno, "failed to setmode on stdout");
6155 #endif
6156 
6157 	while (to_write > 0)
6158 	{
6159 	    written = fwrite (p, 1, to_write, stdout);
6160 	    if (written == 0)
6161 		break;
6162 	    p += written;
6163 	    to_write -= written;
6164 	}
6165 #ifdef USE_SETMODE_STDOUT
6166 	fflush (stdout);
6167 	if (_setmode (_fileno (stdout), oldmode) != OPEN_BINARY)
6168 	    error (0, errno, "failed to setmode on stdout");
6169 #endif
6170     }
6171 }
6172 
6173 /* Like CVS_OUTPUT but output is for stderr not stdout.  */
6174 
6175 void
6176 cvs_outerr (str, len)
6177     const char *str;
6178     size_t len;
6179 {
6180     if (len == 0)
6181 	len = strlen (str);
6182 #ifdef SERVER_SUPPORT
6183     if (error_use_protocol)
6184     {
6185 	buf_output (saved_outerr, str, len);
6186 	buf_copy_lines (buf_to_net, saved_outerr, 'E');
6187     }
6188     else if (server_active)
6189     {
6190 	buf_output (saved_outerr, str, len);
6191 	buf_copy_lines (protocol, saved_outerr, 'E');
6192 	buf_send_counted (protocol);
6193     }
6194     else
6195 #endif
6196     {
6197 	size_t written;
6198 	size_t to_write = len;
6199 	const char *p = str;
6200 
6201 	/* Make sure that output appears in order if stdout and stderr
6202 	   point to the same place.  For the server case this is taken
6203 	   care of by the fact that saved_outerr always holds less
6204 	   than a line.  */
6205 	fflush (stdout);
6206 
6207 	while (to_write > 0)
6208 	{
6209 	    written = fwrite (p, 1, to_write, stderr);
6210 	    if (written == 0)
6211 		break;
6212 	    p += written;
6213 	    to_write -= written;
6214 	}
6215     }
6216 }
6217 
6218 /* Flush stderr.  stderr is normally flushed automatically, of course,
6219    but this function is used to flush information from the server back
6220    to the client.  */
6221 
6222 void
6223 cvs_flusherr ()
6224 {
6225 #ifdef SERVER_SUPPORT
6226     if (error_use_protocol)
6227     {
6228 	/* Flush what we can to the network, but don't block.  */
6229 	buf_flush (buf_to_net, 0);
6230     }
6231     else if (server_active)
6232     {
6233 	/* Send a special count to tell the parent to flush.  */
6234 	buf_send_special_count (protocol, -1);
6235     }
6236     else
6237 #endif
6238 	fflush (stderr);
6239 }
6240 
6241 /* Make it possible for the user to see what has been written to
6242    stdout (it is up to the implementation to decide exactly how far it
6243    should go to ensure this).  */
6244 
6245 void
6246 cvs_flushout ()
6247 {
6248 #ifdef SERVER_SUPPORT
6249     if (error_use_protocol)
6250     {
6251 	/* Flush what we can to the network, but don't block.  */
6252 	buf_flush (buf_to_net, 0);
6253     }
6254     else if (server_active)
6255     {
6256 	/* Just do nothing.  This is because the code which
6257 	   cvs_flushout replaces, setting stdout to line buffering in
6258 	   main.c, didn't get called in the server child process.  But
6259 	   in the future it is quite plausible that we'll want to make
6260 	   this case work analogously to cvs_flusherr.  */
6261     }
6262     else
6263 #endif
6264 	fflush (stdout);
6265 }
6266 
6267 /* Output TEXT, tagging it according to TAG.  There are lots more
6268    details about what TAG means in cvsclient.texi but for the simple
6269    case (e.g. non-client/server), TAG is just "newline" to output a
6270    newline (in which case TEXT must be NULL), and any other tag to
6271    output normal text.
6272 
6273    Note that there is no way to output either \0 or \n as part of TEXT.  */
6274 
6275 void
6276 cvs_output_tagged (tag, text)
6277     char *tag;
6278     char *text;
6279 {
6280     if (text != NULL && strchr (text, '\n') != NULL)
6281 	/* Uh oh.  The protocol has no way to cope with this.  For now
6282 	   we dump core, although that really isn't such a nice
6283 	   response given that this probably can be caused by newlines
6284 	   in filenames and other causes other than bugs in CVS.  Note
6285 	   that we don't want to turn this into "MT newline" because
6286 	   this case is a newline within a tagged item, not a newline
6287 	   as extraneous sugar for the user.  */
6288 	assert (0);
6289 
6290     /* Start and end tags don't take any text, per cvsclient.texi.  */
6291     if (tag[0] == '+' || tag[0] == '-')
6292 	assert (text == NULL);
6293 
6294 #ifdef SERVER_SUPPORT
6295     if (server_active && supported_response ("MT"))
6296     {
6297 	struct buffer *buf;
6298 
6299 	if (error_use_protocol)
6300 	    buf = buf_to_net;
6301 	else
6302 	    buf = protocol;
6303 
6304 	buf_output0 (buf, "MT ");
6305 	buf_output0 (buf, tag);
6306 	if (text != NULL)
6307 	{
6308 	    buf_output (buf, " ", 1);
6309 	    buf_output0 (buf, text);
6310 	}
6311 	buf_output (buf, "\n", 1);
6312 
6313 	if (!error_use_protocol)
6314 	    buf_send_counted (protocol);
6315     }
6316     else
6317 #endif
6318     {
6319 	if (strcmp (tag, "newline") == 0)
6320 	    cvs_output ("\n", 1);
6321 	else if (text != NULL)
6322 	    cvs_output (text, 0);
6323     }
6324 }
6325