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