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