xref: /openbsd-src/gnu/usr.bin/cvs/src/server.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
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 || lim > 10000)
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 ()) return;
1639 
1640     if (outside_dir (arg))
1641 	return;
1642 
1643     /* Rewrite entries file to have `=' in timestamp field.  */
1644     for (p = entries; p != NULL; p = p->next)
1645     {
1646 	name = p->entry + 1;
1647 	cp = strchr (name, '/');
1648 	if (cp != NULL
1649 	    && strlen (arg) == cp - name
1650 	    && strncmp (arg, name, cp - name) == 0)
1651 	{
1652 	    if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0')
1653 	    {
1654 		/* We didn't find the record separator or it is followed by
1655 		 * the end of the string, so just exit.
1656 		 */
1657 		if (alloc_pending (80))
1658 		    sprintf (pending_error_text,
1659 		             "E Malformed Entry encountered.");
1660 		return;
1661 	    }
1662 	    /* If the time field is not currently empty, then one of
1663 	     * serve_modified, serve_is_modified, & serve_unchanged were
1664 	     * already called for this file.  We would like to ignore the
1665 	     * reinvocation silently or, better yet, exit with an error
1666 	     * message, but we just avoid the copy-forward and overwrite the
1667 	     * value from the last invocation instead.  See the comment below
1668 	     * for more.
1669 	     */
1670 	    if (*timefield == '/')
1671 	    {
1672 		/* Copy forward one character.  Space was allocated for this
1673 		 * already in serve_entry().  */
1674 		cp = timefield + strlen (timefield);
1675 		cp[1] = '\0';
1676 		while (cp > timefield)
1677 		{
1678 		    *cp = cp[-1];
1679 		    --cp;
1680 		}
1681 	    }
1682 	    /* If *TIMEFIELD wasn't "/", we assume that it was because of
1683 	     * multiple calls to Is-Modified & Unchanged by the client and
1684 	     * just overwrite the value from the last call.  Technically, we
1685 	     * should probably either ignore calls after the first or send the
1686 	     * client an error, since the client/server protocol specification
1687 	     * specifies that only one call to either Is-Modified or Unchanged
1688 	     * is allowed, but broken versions of WinCVS & TortoiseCVS rely on
1689 	     * this behavior.
1690 	     */
1691 	    *timefield = '=';
1692 	    break;
1693 	}
1694     }
1695 }
1696 
1697 static void
1698 serve_is_modified (arg)
1699     char *arg;
1700 {
1701     struct an_entry *p;
1702     char *name;
1703     char *cp;
1704     char *timefield;
1705     /* Have we found this file in "entries" yet.  */
1706     int found;
1707 
1708     if (error_pending ()) return;
1709 
1710     if (outside_dir (arg))
1711 	return;
1712 
1713     /* Rewrite entries file to have `M' in timestamp field.  */
1714     found = 0;
1715     for (p = entries; p != NULL; p = p->next)
1716     {
1717 	name = p->entry + 1;
1718 	cp = strchr (name, '/');
1719 	if (cp != NULL
1720 	    && strlen (arg) == cp - name
1721 	    && strncmp (arg, name, cp - name) == 0)
1722 	{
1723 	    if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0')
1724 	    {
1725 		/* We didn't find the record separator or it is followed by
1726 		 * the end of the string, so just exit.
1727 		 */
1728 		if (alloc_pending (80))
1729 		    sprintf (pending_error_text,
1730 		             "E Malformed Entry encountered.");
1731 		return;
1732 	    }
1733 	    /* If the time field is not currently empty, then one of
1734 	     * serve_modified, serve_is_modified, & serve_unchanged were
1735 	     * already called for this file.  We would like to ignore the
1736 	     * reinvocation silently or, better yet, exit with an error
1737 	     * message, but we just avoid the copy-forward and overwrite the
1738 	     * value from the last invocation instead.  See the comment below
1739 	     * for more.
1740 	     */
1741 	    if (*timefield == '/')
1742 	    {
1743 		/* Copy forward one character.  Space was allocated for this
1744 		 * already in serve_entry().  */
1745 		cp = timefield + strlen (timefield);
1746 		cp[1] = '\0';
1747 		while (cp > timefield)
1748 		{
1749 		    *cp = cp[-1];
1750 		    --cp;
1751 		}
1752 	    }
1753 	    /* If *TIMEFIELD wasn't "/", we assume that it was because of
1754 	     * multiple calls to Is-Modified & Unchanged by the client and
1755 	     * just overwrite the value from the last call.  Technically, we
1756 	     * should probably either ignore calls after the first or send the
1757 	     * client an error, since the client/server protocol specification
1758 	     * specifies that only one call to either Is-Modified or Unchanged
1759 	     * is allowed, but broken versions of WinCVS & TortoiseCVS rely on
1760 	     * this behavior.
1761 	     */
1762 	    *timefield = 'M';
1763 	    if (kopt != NULL)
1764 	    {
1765 		if (alloc_pending (strlen (name) + 80))
1766 		    sprintf (pending_error_text,
1767 			     "E protocol error: both Kopt and Entry for %s",
1768 			     arg);
1769 		free (kopt);
1770 		kopt = NULL;
1771 		return;
1772 	    }
1773 	    found = 1;
1774 	    break;
1775 	}
1776     }
1777     if (!found)
1778     {
1779 	/* We got Is-modified but no Entry.  Add a dummy entry.
1780 	   The "D" timestamp is what makes it a dummy.  */
1781 	p = (struct an_entry *) malloc (sizeof (struct an_entry));
1782 	if (p == NULL)
1783 	{
1784 	    pending_error = ENOMEM;
1785 	    return;
1786 	}
1787 	p->entry = malloc (strlen (arg) + 80);
1788 	if (p->entry == NULL)
1789 	{
1790 	    pending_error = ENOMEM;
1791 	    free (p);
1792 	    return;
1793 	}
1794 	strcpy (p->entry, "/");
1795 	strcat (p->entry, arg);
1796 	strcat (p->entry, "//D/");
1797 	if (kopt != NULL)
1798 	{
1799 	    strcat (p->entry, kopt);
1800 	    free (kopt);
1801 	    kopt = NULL;
1802 	}
1803 	strcat (p->entry, "/");
1804 	p->next = entries;
1805 	entries = p;
1806     }
1807 }
1808 
1809 static void serve_entry PROTO ((char *));
1810 
1811 static void
1812 serve_entry (arg)
1813      char *arg;
1814 {
1815     struct an_entry *p;
1816     char *cp;
1817     int i = 0;
1818     if (error_pending()) return;
1819 
1820     /* Verify that the entry is well-formed.  This can avoid problems later.
1821      * At the moment we only check that the Entry contains five slashes in
1822      * approximately the correct locations since some of the code makes
1823      * assumptions about this.
1824      */
1825     cp = arg;
1826     if (*cp == 'D') cp++;
1827     while (i++ < 5)
1828     {
1829       if (!cp || *cp != '/')
1830       {
1831           if (alloc_pending (80))
1832               sprintf (pending_error_text,
1833                        "E protocol error: Malformed Entry");
1834            return;
1835       }
1836     cp = strchr (cp + 1, '/');
1837     }
1838 
1839     p = xmalloc (sizeof (struct an_entry));
1840     if (p == NULL)
1841     {
1842 	pending_error = ENOMEM;
1843 	return;
1844     }
1845     /* Leave space for serve_unchanged to write '=' if it wants.  */
1846     cp = malloc (strlen (arg) + 2);
1847     if (cp == NULL)
1848     {
1849 	pending_error = ENOMEM;
1850 	return;
1851     }
1852     strcpy (cp, arg);
1853     p->next = entries;
1854     p->entry = cp;
1855     entries = p;
1856 }
1857 
1858 static void serve_kopt PROTO ((char *));
1859 
1860 static void
1861 serve_kopt (arg)
1862      char *arg;
1863 {
1864     if (error_pending ())
1865 	return;
1866 
1867     if (kopt != NULL)
1868     {
1869 	if (alloc_pending (80 + strlen (arg)))
1870 	    sprintf (pending_error_text,
1871 		     "E protocol error: duplicate Kopt request: %s", arg);
1872 	return;
1873     }
1874 
1875     /* Do some sanity checks.  In particular, that it is not too long.
1876        This lets the rest of the code not worry so much about buffer
1877        overrun attacks.  Probably should call RCS_check_kflag here,
1878        but that would mean changing RCS_check_kflag to handle errors
1879        other than via exit(), fprintf(), and such.  */
1880     if (strlen (arg) > 10)
1881     {
1882 	if (alloc_pending (80 + strlen (arg)))
1883 	    sprintf (pending_error_text,
1884 		     "E protocol error: invalid Kopt request: %s", arg);
1885 	return;
1886     }
1887 
1888     kopt = malloc (strlen (arg) + 1);
1889     if (kopt == NULL)
1890     {
1891 	pending_error = ENOMEM;
1892 	return;
1893     }
1894     strcpy (kopt, arg);
1895 }
1896 
1897 static void serve_checkin_time PROTO ((char *));
1898 
1899 static void
1900 serve_checkin_time (arg)
1901      char *arg;
1902 {
1903     if (error_pending ())
1904 	return;
1905 
1906     if (checkin_time_valid)
1907     {
1908 	if (alloc_pending (80 + strlen (arg)))
1909 	    sprintf (pending_error_text,
1910 		     "E protocol error: duplicate Checkin-time request: %s",
1911 		     arg);
1912 	return;
1913     }
1914 
1915     checkin_time = get_date (arg, NULL);
1916     if (checkin_time == (time_t)-1)
1917     {
1918 	if (alloc_pending (80 + strlen (arg)))
1919 	    sprintf (pending_error_text, "E cannot parse date %s", arg);
1920 	return;
1921     }
1922     checkin_time_valid = 1;
1923 }
1924 
1925 static void
1926 server_write_entries ()
1927 {
1928     FILE *f;
1929     struct an_entry *p;
1930     struct an_entry *q;
1931 
1932     if (entries == NULL)
1933 	return;
1934 
1935     f = NULL;
1936     /* Note that we free all the entries regardless of errors.  */
1937     if (!error_pending ())
1938     {
1939 	/* We open in append mode because we don't want to clobber an
1940            existing Entries file.  If we are checking out a module
1941            which explicitly lists more than one file in a particular
1942            directory, then we will wind up calling
1943            server_write_entries for each such file.  */
1944 	f = CVS_FOPEN (CVSADM_ENT, "a");
1945 	if (f == NULL)
1946 	{
1947 	    int save_errno = errno;
1948 	    if (alloc_pending (80 + strlen (CVSADM_ENT)))
1949 		sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
1950 	    pending_error = save_errno;
1951 	}
1952     }
1953     for (p = entries; p != NULL;)
1954     {
1955 	if (!error_pending ())
1956 	{
1957 	    if (fprintf (f, "%s\n", p->entry) < 0)
1958 	    {
1959 		int save_errno = errno;
1960 		if (alloc_pending (80 + strlen(CVSADM_ENT)))
1961 		    sprintf (pending_error_text,
1962 			     "E cannot write to %s", CVSADM_ENT);
1963 		pending_error = save_errno;
1964 	    }
1965 	}
1966 	free (p->entry);
1967 	q = p->next;
1968 	free (p);
1969 	p = q;
1970     }
1971     entries = NULL;
1972     if (f != NULL && fclose (f) == EOF && !error_pending ())
1973     {
1974 	int save_errno = errno;
1975 	if (alloc_pending (80 + strlen (CVSADM_ENT)))
1976 	    sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
1977 	pending_error = save_errno;
1978     }
1979 }
1980 
1981 struct notify_note {
1982     /* Directory in which this notification happens.  malloc'd*/
1983     char *dir;
1984 
1985     /* malloc'd.  */
1986     char *filename;
1987 
1988     /* The following three all in one malloc'd block, pointed to by TYPE.
1989        Each '\0' terminated.  */
1990     /* "E" or "U".  */
1991     char *type;
1992     /* time+host+dir */
1993     char *val;
1994     char *watches;
1995 
1996     struct notify_note *next;
1997 };
1998 
1999 static struct notify_note *notify_list;
2000 /* Used while building list, to point to the last node that already exists.  */
2001 static struct notify_note *last_node;
2002 
2003 static void serve_notify PROTO ((char *));
2004 
2005 static void
2006 serve_notify (arg)
2007     char *arg;
2008 {
2009     struct notify_note *new = NULL;
2010     char *data = NULL;
2011     int status;
2012 
2013     if (error_pending ()) return;
2014 
2015     if (outside_dir (arg))
2016 	return;
2017 
2018     if (dir_name == NULL)
2019 	goto error;
2020 
2021     new = (struct notify_note *) malloc (sizeof (struct notify_note));
2022     if (new == NULL)
2023     {
2024 	pending_error = ENOMEM;
2025 	return;
2026     }
2027     new->dir = malloc (strlen (dir_name) + 1);
2028     new->filename = malloc (strlen (arg) + 1);
2029     if (new->dir == NULL || new->filename == NULL)
2030     {
2031 	pending_error = ENOMEM;
2032 	if (new->dir != NULL)
2033 	    free (new->dir);
2034 	free (new);
2035 	return;
2036     }
2037     strcpy (new->dir, dir_name);
2038     strcpy (new->filename, arg);
2039 
2040     status = buf_read_line (buf_from_net, &data, (int *) NULL);
2041     if (status != 0)
2042     {
2043 	if (status == -2)
2044 	    pending_error = ENOMEM;
2045 	else
2046 	{
2047 	    pending_error_text = malloc (80 + strlen (arg));
2048 	    if (pending_error_text == NULL)
2049 		pending_error = ENOMEM;
2050 	    else
2051 	    {
2052 		if (status == -1)
2053 		    sprintf (pending_error_text,
2054 			     "E end of file reading notification for %s", arg);
2055 		else
2056 		{
2057 		    sprintf (pending_error_text,
2058 			     "E error reading notification for %s", arg);
2059 		    pending_error = status;
2060 		}
2061 	    }
2062 	}
2063 	free (new->filename);
2064 	free (new->dir);
2065 	free (new);
2066     }
2067     else
2068     {
2069 	char *cp;
2070 
2071 	if (!data[0])
2072 	    goto error;
2073 
2074 	if (strchr (data, '+'))
2075 	    goto error;
2076 
2077 	new->type = data;
2078 	if (data[1] != '\t')
2079 	    goto error;
2080 	data[1] = '\0';
2081 	cp = data + 2;
2082 	new->val = cp;
2083 	cp = strchr (cp, '\t');
2084 	if (cp == NULL)
2085 	    goto error;
2086 	*cp++ = '+';
2087 	cp = strchr (cp, '\t');
2088 	if (cp == NULL)
2089 	    goto error;
2090 	*cp++ = '+';
2091 	cp = strchr (cp, '\t');
2092 	if (cp == NULL)
2093 	    goto error;
2094 	*cp++ = '\0';
2095 	new->watches = cp;
2096 	/* If there is another tab, ignore everything after it,
2097 	   for future expansion.  */
2098 	cp = strchr (cp, '\t');
2099 	if (cp != NULL)
2100 	{
2101 	    *cp = '\0';
2102 	}
2103 
2104 	new->next = NULL;
2105 
2106 	if (last_node == NULL)
2107 	{
2108 	    notify_list = new;
2109 	}
2110 	else
2111 	    last_node->next = new;
2112 	last_node = new;
2113     }
2114     return;
2115   error:
2116     pending_error = 0;
2117     if (alloc_pending (80))
2118 	strcpy (pending_error_text,
2119 		"E Protocol error; misformed Notify request");
2120     if (data != NULL)
2121 	free (data);
2122     if (new != NULL)
2123     {
2124 	free (new->filename);
2125 	free (new->dir);
2126 	free (new);
2127     }
2128     return;
2129 }
2130 
2131 /* Process all the Notify requests that we have stored up.  Returns 0
2132    if successful, if not prints error message (via error()) and
2133    returns negative value.  */
2134 static int
2135 server_notify ()
2136 {
2137     struct notify_note *p;
2138     char *repos;
2139 
2140     while (notify_list != NULL)
2141     {
2142 	if ( CVS_CHDIR (notify_list->dir) < 0)
2143 	{
2144 	    error (0, errno, "cannot change to %s", notify_list->dir);
2145 	    return -1;
2146 	}
2147 	repos = Name_Repository (NULL, NULL);
2148 
2149 	lock_dir_for_write (repos);
2150 
2151 	fileattr_startdir (repos);
2152 
2153 	notify_do (*notify_list->type, notify_list->filename, getcaller(),
2154 		   notify_list->val, notify_list->watches, repos);
2155 
2156 	buf_output0 (buf_to_net, "Notified ");
2157 	{
2158 	    char *dir = notify_list->dir + strlen (server_temp_dir) + 1;
2159 	    if (dir[0] == '\0')
2160 	        buf_append_char (buf_to_net, '.');
2161 	    else
2162 	        buf_output0 (buf_to_net, dir);
2163 	    buf_append_char (buf_to_net, '/');
2164 	    buf_append_char (buf_to_net, '\n');
2165 	}
2166 	buf_output0 (buf_to_net, repos);
2167 	buf_append_char (buf_to_net, '/');
2168 	buf_output0 (buf_to_net, notify_list->filename);
2169 	buf_append_char (buf_to_net, '\n');
2170 	free (repos);
2171 
2172 	p = notify_list->next;
2173 	free (notify_list->filename);
2174 	free (notify_list->dir);
2175 	free (notify_list->type);
2176 	free (notify_list);
2177 	notify_list = p;
2178 
2179 	fileattr_write ();
2180 	fileattr_free ();
2181 
2182 	Lock_Cleanup ();
2183     }
2184 
2185     last_node = NULL;
2186 
2187     /* The code used to call fflush (stdout) here, but that is no
2188        longer necessary.  The data is now buffered in buf_to_net,
2189        which will be flushed by the caller, do_cvs_command.  */
2190 
2191     return 0;
2192 }
2193 
2194 static int argument_count;
2195 static char **argument_vector;
2196 static int argument_vector_size;
2197 
2198 static void
2199 serve_argument (arg)
2200      char *arg;
2201 {
2202     char *p;
2203 
2204     if (error_pending()) return;
2205 
2206     if (argument_count >= 10000)
2207     {
2208        if (alloc_pending (80))
2209            sprintf (pending_error_text,
2210                     "E Protocol error: too many arguments");
2211        return;
2212     }
2213 
2214 
2215     if (argument_vector_size <= argument_count)
2216     {
2217 	argument_vector_size *= 2;
2218 	argument_vector =
2219 	    (char **) realloc ((char *)argument_vector,
2220 			       argument_vector_size * sizeof (char *));
2221 	if (argument_vector == NULL)
2222 	{
2223 	    pending_error = ENOMEM;
2224 	    return;
2225 	}
2226     }
2227     p = malloc (strlen (arg) + 1);
2228     if (p == NULL)
2229     {
2230 	pending_error = ENOMEM;
2231 	return;
2232     }
2233     strcpy (p, arg);
2234     argument_vector[argument_count++] = p;
2235 }
2236 
2237 static void
2238 serve_argumentx (arg)
2239      char *arg;
2240 {
2241     char *p;
2242 
2243     if (error_pending()) return;
2244 
2245     if (argument_count <= 1)
2246     {
2247         if (alloc_pending (80))
2248             sprintf (pending_error_text,
2249                      "E Protocol error: called argumentx without prior call to argument");
2250         return;
2251     }
2252 
2253 
2254     p = argument_vector[argument_count - 1];
2255     p = realloc (p, strlen (p) + 1 + strlen (arg) + 1);
2256     if (p == NULL)
2257     {
2258 	pending_error = ENOMEM;
2259 	return;
2260     }
2261     strcat (p, "\n");
2262     strcat (p, arg);
2263     argument_vector[argument_count - 1] = p;
2264 }
2265 
2266 static void
2267 serve_global_option (arg)
2268     char *arg;
2269 {
2270     if (arg[0] != '-' || arg[1] == '\0' || arg[2] != '\0')
2271     {
2272     error_return:
2273 	if (alloc_pending (strlen (arg) + 80))
2274 	    sprintf (pending_error_text,
2275 		     "E Protocol error: bad global option %s",
2276 		     arg);
2277 	return;
2278     }
2279     switch (arg[1])
2280     {
2281 	case 'n':
2282 	    noexec = 1;
2283 	    break;
2284 	case 'q':
2285 	    quiet = 1;
2286 	    break;
2287 	case 'r':
2288 	    cvswrite = 0;
2289 	    break;
2290 	case 'Q':
2291 	    really_quiet = 1;
2292 	    break;
2293 	case 'l':
2294 	    logoff = 1;
2295 	    break;
2296 	case 't':
2297 	    trace = 1;
2298 	    break;
2299 	default:
2300 	    goto error_return;
2301     }
2302 }
2303 
2304 static void
2305 serve_set (arg)
2306     char *arg;
2307 {
2308     /* FIXME: This sends errors immediately (I think); they should be
2309        put into pending_error.  */
2310     variable_set (arg);
2311 }
2312 
2313 #ifdef ENCRYPTION
2314 
2315 #ifdef HAVE_KERBEROS
2316 
2317 static void
2318 serve_kerberos_encrypt (arg)
2319      char *arg;
2320 {
2321     /* All future communication with the client will be encrypted.  */
2322 
2323     buf_to_net = krb_encrypt_buffer_initialize (buf_to_net, 0, sched,
2324 						kblock,
2325 						buf_to_net->memory_error);
2326     buf_from_net = krb_encrypt_buffer_initialize (buf_from_net, 1, sched,
2327 						  kblock,
2328 						  buf_from_net->memory_error);
2329 }
2330 
2331 #endif /* HAVE_KERBEROS */
2332 
2333 #ifdef HAVE_GSSAPI
2334 
2335 static void
2336 serve_gssapi_encrypt (arg)
2337      char *arg;
2338 {
2339     if (cvs_gssapi_wrapping)
2340     {
2341 	/* We're already using a gssapi_wrap buffer for stream
2342            authentication.  Flush everything we've output so far, and
2343            turn on encryption for future data.  On the input side, we
2344            should only have unwrapped as far as the Gssapi-encrypt
2345            command, so future unwrapping will become encrypted.  */
2346 	buf_flush (buf_to_net, 1);
2347 	cvs_gssapi_encrypt = 1;
2348 	return;
2349     }
2350 
2351     /* All future communication with the client will be encrypted.  */
2352 
2353     cvs_gssapi_encrypt = 1;
2354 
2355     buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0,
2356 						    gcontext,
2357 						    buf_to_net->memory_error);
2358     buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1,
2359 						      gcontext,
2360 						      buf_from_net->memory_error);
2361 
2362     cvs_gssapi_wrapping = 1;
2363 }
2364 
2365 #endif /* HAVE_GSSAPI */
2366 
2367 #endif /* ENCRYPTION */
2368 
2369 #ifdef HAVE_GSSAPI
2370 
2371 static void
2372 serve_gssapi_authenticate (arg)
2373      char *arg;
2374 {
2375     if (cvs_gssapi_wrapping)
2376     {
2377 	/* We're already using a gssapi_wrap buffer for encryption.
2378            That includes authentication, so we don't have to do
2379            anything further.  */
2380 	return;
2381     }
2382 
2383     buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0,
2384 						    gcontext,
2385 						    buf_to_net->memory_error);
2386     buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1,
2387 						      gcontext,
2388 						      buf_from_net->memory_error);
2389 
2390     cvs_gssapi_wrapping = 1;
2391 }
2392 
2393 #endif /* HAVE_GSSAPI */
2394 
2395 #ifdef SERVER_FLOWCONTROL
2396 /* The maximum we'll queue to the remote client before blocking.  */
2397 # ifndef SERVER_HI_WATER
2398 #  define SERVER_HI_WATER (2 * 1024 * 1024)
2399 # endif /* SERVER_HI_WATER */
2400 /* When the buffer drops to this, we restart the child */
2401 # ifndef SERVER_LO_WATER
2402 #  define SERVER_LO_WATER (1 * 1024 * 1024)
2403 # endif /* SERVER_LO_WATER */
2404 
2405 static int set_nonblock_fd PROTO((int));
2406 
2407 /*
2408  * Set buffer BUF to non-blocking I/O.  Returns 0 for success or errno
2409  * code.
2410  */
2411 
2412 static int
2413 set_nonblock_fd (fd)
2414      int fd;
2415 {
2416     int flags;
2417 
2418     flags = fcntl (fd, F_GETFL, 0);
2419     if (flags < 0)
2420 	return errno;
2421     if (fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0)
2422 	return errno;
2423     return 0;
2424 }
2425 
2426 #endif /* SERVER_FLOWCONTROL */
2427 
2428 static void serve_questionable PROTO((char *));
2429 
2430 static void
2431 serve_questionable (arg)
2432     char *arg;
2433 {
2434     static int initted;
2435 
2436     if (!initted)
2437     {
2438 	/* Pick up ignores from CVSROOTADM_IGNORE, $HOME/.cvsignore on server,
2439 	   and CVSIGNORE on server.  */
2440 	ign_setup ();
2441 	initted = 1;
2442     }
2443 
2444     if (dir_name == NULL)
2445     {
2446 	buf_output0 (buf_to_net, "E Protocol error: 'Directory' missing");
2447 	return;
2448     }
2449 
2450     if (outside_dir (arg))
2451 	return;
2452 
2453     if (!ign_name (arg))
2454     {
2455 	char *update_dir;
2456 
2457 	buf_output (buf_to_net, "M ? ", 4);
2458 	update_dir = dir_name + strlen (server_temp_dir) + 1;
2459 	if (!(update_dir[0] == '.' && update_dir[1] == '\0'))
2460 	{
2461 	    buf_output0 (buf_to_net, update_dir);
2462 	    buf_output (buf_to_net, "/", 1);
2463 	}
2464 	buf_output0 (buf_to_net, arg);
2465 	buf_output (buf_to_net, "\n", 1);
2466     }
2467 }
2468 
2469 static void serve_case PROTO ((char *));
2470 
2471 static void
2472 serve_case (arg)
2473     char *arg;
2474 {
2475     ign_case = 1;
2476 }
2477 
2478 static struct buffer *protocol;
2479 
2480 /* This is the output which we are saving up to send to the server, in the
2481    child process.  We will push it through, via the `protocol' buffer, when
2482    we have a complete line.  */
2483 static struct buffer *saved_output;
2484 /* Likewise, but stuff which will go to stderr.  */
2485 static struct buffer *saved_outerr;
2486 
2487 static void
2488 protocol_memory_error (buf)
2489     struct buffer *buf;
2490 {
2491     error (1, ENOMEM, "Virtual memory exhausted");
2492 }
2493 
2494 /*
2495  * Process IDs of the subprocess, or negative if that subprocess
2496  * does not exist.
2497  */
2498 static pid_t command_pid;
2499 
2500 static void
2501 outbuf_memory_error (buf)
2502     struct buffer *buf;
2503 {
2504     static const char msg[] = "E Fatal server error\n\
2505 error ENOMEM Virtual memory exhausted.\n";
2506     if (command_pid > 0)
2507 	kill (command_pid, SIGTERM);
2508 
2509     /*
2510      * We have arranged things so that printing this now either will
2511      * be legal, or the "E fatal error" line will get glommed onto the
2512      * end of an existing "E" or "M" response.
2513      */
2514 
2515     /* If this gives an error, not much we could do.  syslog() it?  */
2516     write (STDOUT_FILENO, msg, sizeof (msg) - 1);
2517 #ifdef HAVE_SYSLOG_H
2518     syslog (LOG_DAEMON | LOG_ERR, "virtual memory exhausted");
2519 #endif
2520     error_exit ();
2521 }
2522 
2523 static void
2524 input_memory_error (buf)
2525      struct buffer *buf;
2526 {
2527     outbuf_memory_error (buf);
2528 }
2529 
2530 
2531 
2532 /* If command is legal, return 1.
2533  * Else if command is illegal and croak_on_illegal is set, then die.
2534  * Else just return 0 to indicate that command is illegal.
2535  */
2536 static int
2537 check_command_legal_p (cmd_name)
2538     char *cmd_name;
2539 {
2540     /* Right now, only pserver notices illegal commands -- namely,
2541      * write attempts by a read-only user.  Therefore, if CVS_Username
2542      * is not set, this just returns 1, because CVS_Username unset
2543      * means pserver is not active.
2544      */
2545 #ifdef AUTH_SERVER_SUPPORT
2546     if (CVS_Username == NULL)
2547         return 1;
2548 
2549     if (lookup_command_attribute (cmd_name) & CVS_CMD_MODIFIES_REPOSITORY)
2550     {
2551         /* This command has the potential to modify the repository, so
2552          * we check if the user have permission to do that.
2553          *
2554          * (Only relevant for remote users -- local users can do
2555          * whatever normal Unix file permissions allow them to do.)
2556          *
2557          * The decision method:
2558          *
2559          *    If $CVSROOT/CVSADMROOT_READERS exists and user is listed
2560          *    in it, then read-only access for user.
2561          *
2562          *    Or if $CVSROOT/CVSADMROOT_WRITERS exists and user NOT
2563          *    listed in it, then also read-only access for user.
2564          *
2565          *    Else read-write access for user.
2566          */
2567 
2568          char *linebuf = NULL;
2569          int num_red = 0;
2570          size_t linebuf_len = 0;
2571          char *fname;
2572          size_t flen;
2573          FILE *fp;
2574          int found_it = 0;
2575 
2576          /* else */
2577          flen = strlen (current_parsed_root->directory)
2578                 + strlen (CVSROOTADM)
2579                 + strlen (CVSROOTADM_READERS)
2580                 + 3;
2581 
2582          fname = xmalloc (flen);
2583          (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
2584 			CVSROOTADM, CVSROOTADM_READERS);
2585 
2586          fp = fopen (fname, "r");
2587 
2588          if (fp == NULL)
2589 	 {
2590 	     if (!existence_error (errno))
2591 	     {
2592 		 /* Need to deny access, so that attackers can't fool
2593 		    us with some sort of denial of service attack.  */
2594 		 error (0, errno, "cannot open %s", fname);
2595 		 free (fname);
2596 		 return 0;
2597 	     }
2598 	 }
2599          else  /* successfully opened readers file */
2600          {
2601              while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
2602              {
2603                  /* Hmmm, is it worth importing my own readline
2604                     library into CVS?  It takes care of chopping
2605                     leading and trailing whitespace, "#" comments, and
2606                     newlines automatically when so requested.  Would
2607                     save some code here...  -kff */
2608 
2609                  /* Chop newline by hand, for strcmp()'s sake. */
2610                  if (num_red > 0 && linebuf[num_red - 1] == '\n')
2611                      linebuf[num_red - 1] = '\0';
2612 
2613                  if (strcmp (linebuf, CVS_Username) == 0)
2614                      goto handle_illegal;
2615              }
2616 	     if (num_red < 0 && !feof (fp))
2617 		 error (0, errno, "cannot read %s", fname);
2618 
2619              /* If not listed specifically as a reader, then this user
2620                 has write access by default unless writers are also
2621                 specified in a file . */
2622 	     if (fclose (fp) < 0)
2623 		 error (0, errno, "cannot close %s", fname);
2624          }
2625 	 free (fname);
2626 
2627 	 /* Now check the writers file.  */
2628 
2629          flen = strlen (current_parsed_root->directory)
2630                 + strlen (CVSROOTADM)
2631                 + strlen (CVSROOTADM_WRITERS)
2632                 + 3;
2633 
2634          fname = xmalloc (flen);
2635          (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
2636 			CVSROOTADM, CVSROOTADM_WRITERS);
2637 
2638          fp = fopen (fname, "r");
2639 
2640          if (fp == NULL)
2641          {
2642 	     if (linebuf)
2643 	         free (linebuf);
2644 	     if (existence_error (errno))
2645 	     {
2646 		 /* Writers file does not exist, so everyone is a writer,
2647 		    by default.  */
2648 		 free (fname);
2649 		 return 1;
2650 	     }
2651 	     else
2652 	     {
2653 		 /* Need to deny access, so that attackers can't fool
2654 		    us with some sort of denial of service attack.  */
2655 		 error (0, errno, "cannot read %s", fname);
2656 		 free (fname);
2657 		 return 0;
2658 	     }
2659          }
2660 
2661          found_it = 0;
2662          while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
2663          {
2664              /* Chop newline by hand, for strcmp()'s sake. */
2665              if (num_red > 0 && linebuf[num_red - 1] == '\n')
2666                  linebuf[num_red - 1] = '\0';
2667 
2668              if (strcmp (linebuf, CVS_Username) == 0)
2669              {
2670                  found_it = 1;
2671                  break;
2672              }
2673          }
2674 	 if (num_red < 0 && !feof (fp))
2675 	     error (0, errno, "cannot read %s", fname);
2676 
2677          if (found_it)
2678          {
2679              if (fclose (fp) < 0)
2680 		 error (0, errno, "cannot close %s", fname);
2681              if (linebuf)
2682                  free (linebuf);
2683 	     free (fname);
2684              return 1;
2685          }
2686          else   /* writers file exists, but this user not listed in it */
2687          {
2688          handle_illegal:
2689              if (fclose (fp) < 0)
2690 		 error (0, errno, "cannot close %s", fname);
2691              if (linebuf)
2692                  free (linebuf);
2693 	     free (fname);
2694 	     return 0;
2695          }
2696     }
2697 #endif /* AUTH_SERVER_SUPPORT */
2698 
2699     /* If ever reach end of this function, command must be legal. */
2700     return 1;
2701 }
2702 
2703 
2704 
2705 /* Execute COMMAND in a subprocess with the approriate funky things done.  */
2706 
2707 static struct fd_set_wrapper { fd_set fds; } command_fds_to_drain;
2708 static int max_command_fd;
2709 
2710 #ifdef SERVER_FLOWCONTROL
2711 static int flowcontrol_pipe[2];
2712 #endif /* SERVER_FLOWCONTROL */
2713 
2714 static void
2715 do_cvs_command (cmd_name, command)
2716     char *cmd_name;
2717     int (*command) PROTO((int argc, char **argv));
2718 {
2719     /*
2720      * The following file descriptors are set to -1 if that file is not
2721      * currently open.
2722      */
2723 
2724     /* Data on these pipes is a series of '\n'-terminated lines.  */
2725     int stdout_pipe[2];
2726     int stderr_pipe[2];
2727 
2728     /*
2729      * Data on this pipe is a series of counted (see buf_send_counted)
2730      * packets.  Each packet must be processed atomically (i.e. not
2731      * interleaved with data from stdout_pipe or stderr_pipe).
2732      */
2733     int protocol_pipe[2];
2734 
2735     int dev_null_fd = -1;
2736 
2737     int errs;
2738 
2739     command_pid = -1;
2740     stdout_pipe[0] = -1;
2741     stdout_pipe[1] = -1;
2742     stderr_pipe[0] = -1;
2743     stderr_pipe[1] = -1;
2744     protocol_pipe[0] = -1;
2745     protocol_pipe[1] = -1;
2746 
2747     server_write_entries ();
2748 
2749     if (print_pending_error ())
2750 	goto free_args_and_return;
2751 
2752     /* Global `command_name' is probably "server" right now -- only
2753        serve_export() sets it to anything else.  So we will use local
2754        parameter `cmd_name' to determine if this command is legal for
2755        this user.  */
2756     if (!check_command_legal_p (cmd_name))
2757     {
2758 	buf_output0 (buf_to_net, "E ");
2759 	buf_output0 (buf_to_net, program_name);
2760 	buf_output0 (buf_to_net, " [server aborted]: \"");
2761 	buf_output0 (buf_to_net, cmd_name);
2762 	buf_output0 (buf_to_net, "\" requires write access to the repository\n\
2763 error  \n");
2764 	goto free_args_and_return;
2765     }
2766 
2767     (void) server_notify ();
2768 
2769     /*
2770      * We use a child process which actually does the operation.  This
2771      * is so we can intercept its standard output.  Even if all of CVS
2772      * were written to go to some special routine instead of writing
2773      * to stdout or stderr, we would still need to do the same thing
2774      * for the RCS commands.
2775      */
2776 
2777     if (pipe (stdout_pipe) < 0)
2778     {
2779 	buf_output0 (buf_to_net, "E pipe failed\n");
2780 	print_error (errno);
2781 	goto error_exit;
2782     }
2783     if (pipe (stderr_pipe) < 0)
2784     {
2785 	buf_output0 (buf_to_net, "E pipe failed\n");
2786 	print_error (errno);
2787 	goto error_exit;
2788     }
2789     if (pipe (protocol_pipe) < 0)
2790     {
2791 	buf_output0 (buf_to_net, "E pipe failed\n");
2792 	print_error (errno);
2793 	goto error_exit;
2794     }
2795 #ifdef SERVER_FLOWCONTROL
2796     if (pipe (flowcontrol_pipe) < 0)
2797     {
2798 	buf_output0 (buf_to_net, "E pipe failed\n");
2799 	print_error (errno);
2800 	goto error_exit;
2801     }
2802     set_nonblock_fd (flowcontrol_pipe[0]);
2803     set_nonblock_fd (flowcontrol_pipe[1]);
2804 #endif /* SERVER_FLOWCONTROL */
2805 
2806     dev_null_fd = CVS_OPEN (DEVNULL, O_RDONLY);
2807     if (dev_null_fd < 0)
2808     {
2809 	buf_output0 (buf_to_net, "E open /dev/null failed\n");
2810 	print_error (errno);
2811 	goto error_exit;
2812     }
2813 
2814     /* We shouldn't have any partial lines from cvs_output and
2815        cvs_outerr, but we handle them here in case there is a bug.  */
2816     /* FIXME: appending a newline, rather than using "MT" as we
2817        do in the child process, is probably not really a very good
2818        way to "handle" them.  */
2819     if (! buf_empty_p (saved_output))
2820     {
2821 	buf_append_char (saved_output, '\n');
2822 	buf_copy_lines (buf_to_net, saved_output, 'M');
2823     }
2824     if (! buf_empty_p (saved_outerr))
2825     {
2826 	buf_append_char (saved_outerr, '\n');
2827 	buf_copy_lines (buf_to_net, saved_outerr, 'E');
2828     }
2829 
2830     /* Flush out any pending data.  */
2831     buf_flush (buf_to_net, 1);
2832 
2833     /* Don't use vfork; we're not going to exec().  */
2834     command_pid = fork ();
2835     if (command_pid < 0)
2836     {
2837 	buf_output0 (buf_to_net, "E fork failed\n");
2838 	print_error (errno);
2839 	goto error_exit;
2840     }
2841     if (command_pid == 0)
2842     {
2843 	int exitstatus;
2844 
2845 	/* Since we're in the child, and the parent is going to take
2846 	   care of packaging up our error messages, we can clear this
2847 	   flag.  */
2848 	error_use_protocol = 0;
2849 
2850 	protocol = fd_buffer_initialize (protocol_pipe[1], 0,
2851 					 protocol_memory_error);
2852 
2853 	/* At this point we should no longer be using buf_to_net and
2854            buf_from_net.  Instead, everything should go through
2855            protocol.  */
2856 	buf_to_net = NULL;
2857 	buf_from_net = NULL;
2858 
2859 	/* These were originally set up to use outbuf_memory_error.
2860            Since we're now in the child, we should use the simpler
2861            protocol_memory_error function.  */
2862 	saved_output->memory_error = protocol_memory_error;
2863 	saved_outerr->memory_error = protocol_memory_error;
2864 
2865 	if (dup2 (dev_null_fd, STDIN_FILENO) < 0)
2866 	    error (1, errno, "can't set up pipes");
2867 	if (dup2 (stdout_pipe[1], STDOUT_FILENO) < 0)
2868 	    error (1, errno, "can't set up pipes");
2869 	if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
2870 	    error (1, errno, "can't set up pipes");
2871 	close (dev_null_fd);
2872 	close (stdout_pipe[0]);
2873 	close (stdout_pipe[1]);
2874 	close (stderr_pipe[0]);
2875 	close (stderr_pipe[1]);
2876 	close (protocol_pipe[0]);
2877 	close_on_exec (protocol_pipe[1]);
2878 #ifdef SERVER_FLOWCONTROL
2879 	close_on_exec (flowcontrol_pipe[0]);
2880 	close (flowcontrol_pipe[1]);
2881 #endif /* SERVER_FLOWCONTROL */
2882 
2883 	/*
2884 	 * Set this in .bashrc if you want to give yourself time to attach
2885 	 * to the subprocess with a debugger.
2886 	 */
2887 	if (getenv ("CVS_SERVER_SLEEP"))
2888 	{
2889 	    int secs = atoi (getenv ("CVS_SERVER_SLEEP"));
2890 	    sleep (secs);
2891 	}
2892 
2893 	exitstatus = (*command) (argument_count, argument_vector);
2894 
2895 	/* Output any partial lines.  If the client doesn't support
2896 	   "MT", we go ahead and just tack on a newline since the
2897 	   protocol doesn't support anything better.  */
2898 	if (! buf_empty_p (saved_output))
2899 	{
2900 	    buf_output0 (protocol, supported_response ("MT") ? "MT text " : "M ");
2901 	    buf_append_buffer (protocol, saved_output);
2902 	    buf_output (protocol, "\n", 1);
2903 	    buf_send_counted (protocol);
2904 	}
2905 	/* For now we just discard partial lines on stderr.  I suspect
2906 	   that CVS can't write such lines unless there is a bug.  */
2907 
2908 	/*
2909 	 * When we exit, that will close the pipes, giving an EOF to
2910 	 * the parent.
2911 	 */
2912 	buf_free (protocol);
2913 	exit (exitstatus);
2914     }
2915 
2916     /* OK, sit around getting all the input from the child.  */
2917     {
2918 	struct buffer *stdoutbuf;
2919 	struct buffer *stderrbuf;
2920 	struct buffer *protocol_inbuf;
2921 	/* Number of file descriptors to check in select ().  */
2922 	int num_to_check;
2923 	int count_needed = 1;
2924 #ifdef SERVER_FLOWCONTROL
2925 	int have_flowcontrolled = 0;
2926 #endif /* SERVER_FLOWCONTROL */
2927 
2928 	FD_ZERO (&command_fds_to_drain.fds);
2929 	num_to_check = stdout_pipe[0];
2930 	FD_SET (stdout_pipe[0], &command_fds_to_drain.fds);
2931 	if (stderr_pipe[0] > num_to_check)
2932 	  num_to_check = stderr_pipe[0];
2933 	FD_SET (stderr_pipe[0], &command_fds_to_drain.fds);
2934 	if (protocol_pipe[0] > num_to_check)
2935 	  num_to_check = protocol_pipe[0];
2936 	FD_SET (protocol_pipe[0], &command_fds_to_drain.fds);
2937 	if (STDOUT_FILENO > num_to_check)
2938 	  num_to_check = STDOUT_FILENO;
2939 	max_command_fd = num_to_check;
2940 	/*
2941 	 * File descriptors are numbered from 0, so num_to_check needs to
2942 	 * be one larger than the largest descriptor.
2943 	 */
2944 	++num_to_check;
2945 	if (num_to_check > FD_SETSIZE)
2946 	{
2947 	    buf_output0 (buf_to_net,
2948 			 "E internal error: FD_SETSIZE not big enough.\n\
2949 error  \n");
2950 	    goto error_exit;
2951 	}
2952 
2953 	stdoutbuf = fd_buffer_initialize (stdout_pipe[0], 1,
2954 					  input_memory_error);
2955 
2956 	stderrbuf = fd_buffer_initialize (stderr_pipe[0], 1,
2957 					  input_memory_error);
2958 
2959 	protocol_inbuf = fd_buffer_initialize (protocol_pipe[0], 1,
2960 					       input_memory_error);
2961 
2962 	set_nonblock (buf_to_net);
2963 	set_nonblock (stdoutbuf);
2964 	set_nonblock (stderrbuf);
2965 	set_nonblock (protocol_inbuf);
2966 
2967 	if (close (stdout_pipe[1]) < 0)
2968 	{
2969 	    buf_output0 (buf_to_net, "E close failed\n");
2970 	    print_error (errno);
2971 	    goto error_exit;
2972 	}
2973 	stdout_pipe[1] = -1;
2974 
2975 	if (close (stderr_pipe[1]) < 0)
2976 	{
2977 	    buf_output0 (buf_to_net, "E close failed\n");
2978 	    print_error (errno);
2979 	    goto error_exit;
2980 	}
2981 	stderr_pipe[1] = -1;
2982 
2983 	if (close (protocol_pipe[1]) < 0)
2984 	{
2985 	    buf_output0 (buf_to_net, "E close failed\n");
2986 	    print_error (errno);
2987 	    goto error_exit;
2988 	}
2989 	protocol_pipe[1] = -1;
2990 
2991 #ifdef SERVER_FLOWCONTROL
2992 	if (close (flowcontrol_pipe[0]) < 0)
2993 	{
2994 	    buf_output0 (buf_to_net, "E close failed\n");
2995 	    print_error (errno);
2996 	    goto error_exit;
2997 	}
2998 	flowcontrol_pipe[0] = -1;
2999 #endif /* SERVER_FLOWCONTROL */
3000 
3001 	if (close (dev_null_fd) < 0)
3002 	{
3003 	    buf_output0 (buf_to_net, "E close failed\n");
3004 	    print_error (errno);
3005 	    goto error_exit;
3006 	}
3007 	dev_null_fd = -1;
3008 
3009 	while (stdout_pipe[0] >= 0
3010 	       || stderr_pipe[0] >= 0
3011 	       || protocol_pipe[0] >= 0
3012 	       || count_needed <= 0)
3013 	{
3014 	    fd_set readfds;
3015 	    fd_set writefds;
3016 	    int numfds;
3017 #ifdef SERVER_FLOWCONTROL
3018 	    int bufmemsize;
3019 	    struct timeval *timeout_ptr;
3020 	    struct timeval timeout;
3021 
3022 	    /*
3023 	     * See if we are swamping the remote client and filling our VM.
3024 	     * Tell child to hold off if we do.
3025 	     */
3026 	    bufmemsize = buf_count_mem (buf_to_net);
3027 	    if (!have_flowcontrolled && (bufmemsize > SERVER_HI_WATER))
3028 	    {
3029 		if (write(flowcontrol_pipe[1], "S", 1) == 1)
3030 		    have_flowcontrolled = 1;
3031 	    }
3032 	    else if (have_flowcontrolled && (bufmemsize < SERVER_LO_WATER))
3033 	    {
3034 		if (write(flowcontrol_pipe[1], "G", 1) == 1)
3035 		    have_flowcontrolled = 0;
3036 	    }
3037 #endif /* SERVER_FLOWCONTROL */
3038 
3039 	    FD_ZERO (&readfds);
3040 	    FD_ZERO (&writefds);
3041 
3042 	    if (count_needed <= 0)
3043 	    {
3044 		/* there is data pending which was read from the protocol pipe
3045 		 * so don't block if we don't find any data
3046 		 */
3047 		timeout.tv_sec = 0;
3048 		timeout.tv_usec = 0;
3049 		timeout_ptr = &timeout;
3050 	    }
3051 	    else
3052 	    {
3053 		/* block indefinately */
3054 		timeout_ptr = NULL;
3055 	    }
3056 
3057 	    if (! buf_empty_p (buf_to_net))
3058 		FD_SET (STDOUT_FILENO, &writefds);
3059 
3060 	    if (stdout_pipe[0] >= 0)
3061 	    {
3062 		FD_SET (stdout_pipe[0], &readfds);
3063 	    }
3064 	    if (stderr_pipe[0] >= 0)
3065 	    {
3066 		FD_SET (stderr_pipe[0], &readfds);
3067 	    }
3068 	    if (protocol_pipe[0] >= 0)
3069 	    {
3070 		FD_SET (protocol_pipe[0], &readfds);
3071 	    }
3072 
3073 	    /* This process of selecting on the three pipes means that
3074 	     we might not get output in the same order in which it
3075 	     was written, thus producing the well-known
3076 	     "out-of-order" bug.  If the child process uses
3077 	     cvs_output and cvs_outerr, it will send everything on
3078 	     the protocol_pipe and avoid this problem, so the
3079 	     solution is to use cvs_output and cvs_outerr in the
3080 	     child process.  */
3081 	    do {
3082 		/* This used to select on exceptions too, but as far
3083                    as I know there was never any reason to do that and
3084                    SCO doesn't let you select on exceptions on pipes.  */
3085 		numfds = select (num_to_check, &readfds, &writefds,
3086 				 (fd_set *)0, timeout_ptr);
3087 		if (numfds < 0
3088 			&& errno != EINTR)
3089 		{
3090 		    buf_output0 (buf_to_net, "E select failed\n");
3091 		    print_error (errno);
3092 		    goto error_exit;
3093 		}
3094 	    } while (numfds < 0);
3095 
3096 	    if (numfds == 0)
3097 	    {
3098 		FD_ZERO (&readfds);
3099 		FD_ZERO (&writefds);
3100 	    }
3101 
3102 	    if (FD_ISSET (STDOUT_FILENO, &writefds))
3103 	    {
3104 		/* What should we do with errors?  syslog() them?  */
3105 		buf_send_output (buf_to_net);
3106 	    }
3107 
3108 	    if (protocol_pipe[0] >= 0
3109 		&& (FD_ISSET (protocol_pipe[0], &readfds)))
3110 	    {
3111 		int status;
3112 		int count_read;
3113 
3114 		status = buf_input_data (protocol_inbuf, &count_read);
3115 
3116 		if (status == -1)
3117 		{
3118 		    close (protocol_pipe[0]);
3119 		    protocol_pipe[0] = -1;
3120 		}
3121 		else if (status > 0)
3122 		{
3123 		    buf_output0 (buf_to_net, "E buf_input_data failed\n");
3124 		    print_error (status);
3125 		    goto error_exit;
3126 		}
3127 
3128 		/*
3129 		 * We only call buf_copy_counted if we have read
3130 		 * enough bytes to make it worthwhile.  This saves us
3131 		 * from continually recounting the amount of data we
3132 		 * have.
3133 		 */
3134 		count_needed -= count_read;
3135 	    }
3136 	    /* this is still part of the protocol pipe procedure, but it is
3137 	     * outside the above conditional so that unprocessed data can be
3138 	     * left in the buffer and stderr/stdout can be read when a flush
3139 	     * signal is received and control can return here without passing
3140 	     * through the select code and maybe blocking
3141 	     */
3142 	    while (count_needed <= 0)
3143 	    {
3144 		int special = 0;
3145 
3146 		count_needed = buf_copy_counted (buf_to_net,
3147 						     protocol_inbuf,
3148 						     &special);
3149 
3150 		/* What should we do with errors?  syslog() them?  */
3151 		buf_send_output (buf_to_net);
3152 
3153 		/* If SPECIAL got set to <0, it means that the child
3154 		 * wants us to flush the pipe & maybe stderr or stdout.
3155 		 *
3156 		 * After that we break to read stderr & stdout again before
3157 		 * going back to the protocol pipe
3158 		 *
3159 		 * Upon breaking, count_needed = 0, so the next pass will only
3160 		 * perform a non-blocking select before returning here to finish
3161 		 * processing data we already read from the protocol buffer
3162 		 */
3163 		 if (special == -1)
3164 		 {
3165 		     cvs_flushout();
3166 		     break;
3167 		 }
3168 		if (special == -2)
3169 		{
3170 		    /* If the client supports the 'F' command, we send it. */
3171 		    if (supported_response ("F"))
3172 		    {
3173 			buf_append_char (buf_to_net, 'F');
3174 			buf_append_char (buf_to_net, '\n');
3175 		    }
3176 		    cvs_flusherr ();
3177 		    break;
3178 		}
3179 	    }
3180 
3181 	    if (stdout_pipe[0] >= 0
3182 		&& (FD_ISSET (stdout_pipe[0], &readfds)))
3183 	    {
3184 	        int status;
3185 
3186 	        status = buf_input_data (stdoutbuf, (int *) NULL);
3187 
3188 		buf_copy_lines (buf_to_net, stdoutbuf, 'M');
3189 
3190 		if (status == -1)
3191 		{
3192 		    close (stdout_pipe[0]);
3193 		    stdout_pipe[0] = -1;
3194 		}
3195 		else if (status > 0)
3196 		{
3197 		    buf_output0 (buf_to_net, "E buf_input_data failed\n");
3198 		    print_error (status);
3199 		    goto error_exit;
3200 		}
3201 
3202 		/* What should we do with errors?  syslog() them?  */
3203 		buf_send_output (buf_to_net);
3204 	    }
3205 
3206 	    if (stderr_pipe[0] >= 0
3207 		&& (FD_ISSET (stderr_pipe[0], &readfds)))
3208 	    {
3209 	        int status;
3210 
3211 	        status = buf_input_data (stderrbuf, (int *) NULL);
3212 
3213 		buf_copy_lines (buf_to_net, stderrbuf, 'E');
3214 
3215 		if (status == -1)
3216 		{
3217 		    close (stderr_pipe[0]);
3218 		    stderr_pipe[0] = -1;
3219 		}
3220 		else if (status > 0)
3221 		{
3222 		    buf_output0 (buf_to_net, "E buf_input_data failed\n");
3223 		    print_error (status);
3224 		    goto error_exit;
3225 		}
3226 
3227 		/* What should we do with errors?  syslog() them?  */
3228 		buf_send_output (buf_to_net);
3229 	    }
3230 	}
3231 
3232 	/*
3233 	 * OK, we've gotten EOF on all the pipes.  If there is
3234 	 * anything left on stdoutbuf or stderrbuf (this could only
3235 	 * happen if there was no trailing newline), send it over.
3236 	 */
3237 	if (! buf_empty_p (stdoutbuf))
3238 	{
3239 	    buf_append_char (stdoutbuf, '\n');
3240 	    buf_copy_lines (buf_to_net, stdoutbuf, 'M');
3241 	}
3242 	if (! buf_empty_p (stderrbuf))
3243 	{
3244 	    buf_append_char (stderrbuf, '\n');
3245 	    buf_copy_lines (buf_to_net, stderrbuf, 'E');
3246 	}
3247 	if (! buf_empty_p (protocol_inbuf))
3248 	    buf_output0 (buf_to_net,
3249 			 "E Protocol error: uncounted data discarded\n");
3250 
3251 #ifdef SERVER_FLOWCONTROL
3252 	close (flowcontrol_pipe[1]);
3253 	flowcontrol_pipe[1] = -1;
3254 #endif /* SERVER_FLOWCONTROL */
3255 
3256 	errs = 0;
3257 
3258 	while (command_pid > 0)
3259 	{
3260 	    int status;
3261 	    pid_t waited_pid;
3262 	    waited_pid = waitpid (command_pid, &status, 0);
3263 	    if (waited_pid < 0)
3264 	    {
3265 		/*
3266 		 * Intentionally ignoring EINTR.  Other errors
3267 		 * "can't happen".
3268 		 */
3269 		continue;
3270 	    }
3271 
3272 	    if (WIFEXITED (status))
3273 		errs += WEXITSTATUS (status);
3274 	    else
3275 	    {
3276 	        int sig = WTERMSIG (status);
3277 	        char buf[50];
3278 		/*
3279 		 * This is really evil, because signals might be numbered
3280 		 * differently on the two systems.  We should be using
3281 		 * signal names (either of the "Terminated" or the "SIGTERM"
3282 		 * variety).  But cvs doesn't currently use libiberty...we
3283 		 * could roll our own....  FIXME.
3284 		 */
3285 		buf_output0 (buf_to_net, "E Terminated with fatal signal ");
3286 		sprintf (buf, "%d\n", sig);
3287 		buf_output0 (buf_to_net, buf);
3288 
3289 		/* Test for a core dump.  Is this portable?  */
3290 		if (status & 0x80)
3291 		{
3292 		    buf_output0 (buf_to_net, "E Core dumped; preserving ");
3293 		    buf_output0 (buf_to_net, orig_server_temp_dir);
3294 		    buf_output0 (buf_to_net, " on server.\n\
3295 E CVS locks may need cleaning up.\n");
3296 		    dont_delete_temp = 1;
3297 		}
3298 		++errs;
3299 	    }
3300 	    if (waited_pid == command_pid)
3301 		command_pid = -1;
3302 	}
3303 
3304 	/*
3305 	 * OK, we've waited for the child.  By now all CVS locks are free
3306 	 * and it's OK to block on the network.
3307 	 */
3308 	set_block (buf_to_net);
3309 	buf_flush (buf_to_net, 1);
3310 	buf_shutdown (protocol_inbuf);
3311 	buf_free (protocol_inbuf);
3312 	buf_shutdown (stderrbuf);
3313 	buf_free (stderrbuf);
3314 	buf_shutdown (stdoutbuf);
3315 	buf_free (stdoutbuf);
3316     }
3317 
3318     if (errs)
3319 	/* We will have printed an error message already.  */
3320 	buf_output0 (buf_to_net, "error  \n");
3321     else
3322 	buf_output0 (buf_to_net, "ok\n");
3323     goto free_args_and_return;
3324 
3325  error_exit:
3326     if (command_pid > 0)
3327 	kill (command_pid, SIGTERM);
3328 
3329     while (command_pid > 0)
3330     {
3331 	pid_t waited_pid;
3332 	waited_pid = waitpid (command_pid, (int *) 0, 0);
3333 	if (waited_pid < 0 && errno == EINTR)
3334 	    continue;
3335 	if (waited_pid == command_pid)
3336 	    command_pid = -1;
3337     }
3338 
3339     close (dev_null_fd);
3340     close (protocol_pipe[0]);
3341     close (protocol_pipe[1]);
3342     close (stderr_pipe[0]);
3343     close (stderr_pipe[1]);
3344     close (stdout_pipe[0]);
3345     close (stdout_pipe[1]);
3346 #ifdef SERVER_FLOWCONTROL
3347     close (flowcontrol_pipe[0]);
3348     close (flowcontrol_pipe[1]);
3349 #endif /* SERVER_FLOWCONTROL */
3350 
3351  free_args_and_return:
3352     /* Now free the arguments.  */
3353     {
3354 	/* argument_vector[0] is a dummy argument, we don't mess with it.  */
3355 	char **cp;
3356 	for (cp = argument_vector + 1;
3357 	     cp < argument_vector + argument_count;
3358 	     ++cp)
3359 	    free (*cp);
3360 
3361 	argument_count = 1;
3362     }
3363 
3364     /* Flush out any data not yet sent.  */
3365     set_block (buf_to_net);
3366     buf_flush (buf_to_net, 1);
3367 
3368     return;
3369 }
3370 
3371 #ifdef SERVER_FLOWCONTROL
3372 /*
3373  * Called by the child at convenient points in the server's execution for
3374  * the server child to block.. ie: when it has no locks active.
3375  */
3376 void
3377 server_pause_check()
3378 {
3379     int paused = 0;
3380     char buf[1];
3381 
3382     while (read (flowcontrol_pipe[0], buf, 1) == 1)
3383     {
3384 	if (*buf == 'S')	/* Stop */
3385 	    paused = 1;
3386 	else if (*buf == 'G')	/* Go */
3387 	    paused = 0;
3388 	else
3389 	    return;		/* ??? */
3390     }
3391     while (paused) {
3392 	int numfds, numtocheck;
3393 	fd_set fds;
3394 
3395 	FD_ZERO (&fds);
3396 	FD_SET (flowcontrol_pipe[0], &fds);
3397 	numtocheck = flowcontrol_pipe[0] + 1;
3398 
3399 	do {
3400 	    numfds = select (numtocheck, &fds, (fd_set *)0,
3401 			     (fd_set *)0, (struct timeval *)NULL);
3402 	    if (numfds < 0
3403 		&& errno != EINTR)
3404 	    {
3405 		buf_output0 (buf_to_net, "E select failed\n");
3406 		print_error (errno);
3407 		return;
3408 	    }
3409 	} while (numfds < 0);
3410 
3411 	if (FD_ISSET (flowcontrol_pipe[0], &fds))
3412 	{
3413 	    int got;
3414 
3415 	    while ((got = read (flowcontrol_pipe[0], buf, 1)) == 1)
3416 	    {
3417 		if (*buf == 'S')	/* Stop */
3418 		    paused = 1;
3419 		else if (*buf == 'G')	/* Go */
3420 		    paused = 0;
3421 		else
3422 		    return;		/* ??? */
3423 	    }
3424 
3425 	    /* This assumes that we are using BSD or POSIX nonblocking
3426                I/O.  System V nonblocking I/O returns zero if there is
3427                nothing to read.  */
3428 	    if (got == 0)
3429 	        error (1, 0, "flow control EOF");
3430 	    if (got < 0 && ! blocking_error (errno))
3431 	    {
3432 	        error (1, errno, "flow control read failed");
3433 	    }
3434 	}
3435     }
3436 }
3437 #endif /* SERVER_FLOWCONTROL */
3438 
3439 /* This variable commented in server.h.  */
3440 char *server_dir = NULL;
3441 
3442 static void output_dir PROTO((char *, char *));
3443 
3444 static void
3445 output_dir (update_dir, repository)
3446     char *update_dir;
3447     char *repository;
3448 {
3449     if (server_dir != NULL)
3450     {
3451 	buf_output0 (protocol, server_dir);
3452 	buf_output0 (protocol, "/");
3453     }
3454     if (update_dir[0] == '\0')
3455 	buf_output0 (protocol, ".");
3456     else
3457 	buf_output0 (protocol, update_dir);
3458     buf_output0 (protocol, "/\n");
3459     buf_output0 (protocol, repository);
3460     buf_output0 (protocol, "/");
3461 }
3462 
3463 /*
3464  * Entries line that we are squirreling away to send to the client when
3465  * we are ready.
3466  */
3467 static char *entries_line;
3468 
3469 /*
3470  * File which has been Scratch_File'd, we are squirreling away that fact
3471  * to inform the client when we are ready.
3472  */
3473 static char *scratched_file;
3474 
3475 /*
3476  * The scratched_file will need to be removed as well as having its entry
3477  * removed.
3478  */
3479 static int kill_scratched_file;
3480 
3481 void
3482 server_register (name, version, timestamp, options, tag, date, conflict)
3483     char *name;
3484     char *version;
3485     char *timestamp;
3486     char *options;
3487     char *tag;
3488     char *date;
3489     char *conflict;
3490 {
3491     int len;
3492 
3493     if (options == NULL)
3494 	options = "";
3495 
3496     if (trace)
3497     {
3498 	(void) fprintf (stderr,
3499 			"%s-> server_register(%s, %s, %s, %s, %s, %s, %s)\n",
3500 			CLIENT_SERVER_STR,
3501 			name, version, timestamp ? timestamp : "", options,
3502 			tag ? tag : "", date ? date : "",
3503 			conflict ? conflict : "");
3504     }
3505 
3506     if (entries_line != NULL)
3507     {
3508 	/*
3509 	 * If CVS decides to Register it more than once (which happens
3510 	 * on "cvs update foo/foo.c" where foo and foo.c are already
3511 	 * checked out), use the last of the entries lines Register'd.
3512 	 */
3513 	free (entries_line);
3514     }
3515 
3516     /*
3517      * I have reports of Scratch_Entry and Register both happening, in
3518      * two different cases.  Using the last one which happens is almost
3519      * surely correct; I haven't tracked down why they both happen (or
3520      * even verified that they are for the same file).
3521      */
3522     if (scratched_file != NULL)
3523     {
3524 	free (scratched_file);
3525 	scratched_file = NULL;
3526     }
3527 
3528     len = (strlen (name) + strlen (version) + strlen (options) + 80);
3529     if (tag)
3530 	len += strlen (tag);
3531     if (date)
3532 	len += strlen (date);
3533 
3534     entries_line = xmalloc (len);
3535     sprintf (entries_line, "/%s/%s/", name, version);
3536     if (conflict != NULL)
3537     {
3538 	strcat (entries_line, "+=");
3539     }
3540     strcat (entries_line, "/");
3541     strcat (entries_line, options);
3542     strcat (entries_line, "/");
3543     if (tag != NULL)
3544     {
3545 	strcat (entries_line, "T");
3546 	strcat (entries_line, tag);
3547     }
3548     else if (date != NULL)
3549     {
3550 	strcat (entries_line, "D");
3551 	strcat (entries_line, date);
3552     }
3553 }
3554 
3555 void
3556 server_scratch (fname)
3557     char *fname;
3558 {
3559     /*
3560      * I have reports of Scratch_Entry and Register both happening, in
3561      * two different cases.  Using the last one which happens is almost
3562      * surely correct; I haven't tracked down why they both happen (or
3563      * even verified that they are for the same file).
3564      *
3565      * Don't know if this is what whoever wrote the above comment was
3566      * talking about, but this can happen in the case where a join
3567      * removes a file - the call to Register puts the '-vers' into the
3568      * Entries file after the file is removed
3569      */
3570     if (entries_line != NULL)
3571     {
3572 	free (entries_line);
3573 	entries_line = NULL;
3574     }
3575 
3576     if (scratched_file != NULL)
3577     {
3578 	buf_output0 (protocol,
3579 		     "E CVS server internal error: duplicate Scratch_Entry\n");
3580 	buf_send_counted (protocol);
3581 	return;
3582     }
3583     scratched_file = xstrdup (fname);
3584     kill_scratched_file = 1;
3585 }
3586 
3587 void
3588 server_scratch_entry_only ()
3589 {
3590     kill_scratched_file = 0;
3591 }
3592 
3593 /* Print a new entries line, from a previous server_register.  */
3594 static void
3595 new_entries_line ()
3596 {
3597     if (entries_line)
3598     {
3599 	buf_output0 (protocol, entries_line);
3600 	buf_output (protocol, "\n", 1);
3601     }
3602     else
3603 	/* Return the error message as the Entries line.  */
3604 	buf_output0 (protocol,
3605 		     "CVS server internal error: Register missing\n");
3606     free (entries_line);
3607     entries_line = NULL;
3608 }
3609 
3610 
3611 static void
3612 serve_ci (arg)
3613     char *arg;
3614 {
3615     do_cvs_command ("commit", commit);
3616 }
3617 
3618 static void
3619 checked_in_response (file, update_dir, repository)
3620     char *file;
3621     char *update_dir;
3622     char *repository;
3623 {
3624     if (supported_response ("Mode"))
3625     {
3626 	struct stat sb;
3627 	char *mode_string;
3628 
3629 	if ( CVS_STAT (file, &sb) < 0)
3630 	{
3631 	    /* Not clear to me why the file would fail to exist, but it
3632 	       was happening somewhere in the testsuite.  */
3633 	    if (!existence_error (errno))
3634 		error (0, errno, "cannot stat %s", file);
3635 	}
3636 	else
3637 	{
3638 	    buf_output0 (protocol, "Mode ");
3639 	    mode_string = mode_to_string (sb.st_mode);
3640 	    buf_output0 (protocol, mode_string);
3641 	    buf_output0 (protocol, "\n");
3642 	    free (mode_string);
3643 	}
3644     }
3645 
3646     buf_output0 (protocol, "Checked-in ");
3647     output_dir (update_dir, repository);
3648     buf_output0 (protocol, file);
3649     buf_output (protocol, "\n", 1);
3650     new_entries_line ();
3651 }
3652 
3653 void
3654 server_checked_in (file, update_dir, repository)
3655     char *file;
3656     char *update_dir;
3657     char *repository;
3658 {
3659     if (noexec)
3660 	return;
3661     if (scratched_file != NULL && entries_line == NULL)
3662     {
3663 	/*
3664 	 * This happens if we are now doing a "cvs remove" after a previous
3665 	 * "cvs add" (without a "cvs ci" in between).
3666 	 */
3667 	buf_output0 (protocol, "Remove-entry ");
3668 	output_dir (update_dir, repository);
3669 	buf_output0 (protocol, file);
3670 	buf_output (protocol, "\n", 1);
3671 	free (scratched_file);
3672 	scratched_file = NULL;
3673     }
3674     else
3675     {
3676 	checked_in_response (file, update_dir, repository);
3677     }
3678     buf_send_counted (protocol);
3679 }
3680 
3681 void
3682 server_update_entries (file, update_dir, repository, updated)
3683     char *file;
3684     char *update_dir;
3685     char *repository;
3686     enum server_updated_arg4 updated;
3687 {
3688     if (noexec)
3689 	return;
3690     if (updated == SERVER_UPDATED)
3691 	checked_in_response (file, update_dir, repository);
3692     else
3693     {
3694 	if (!supported_response ("New-entry"))
3695 	    return;
3696 	buf_output0 (protocol, "New-entry ");
3697 	output_dir (update_dir, repository);
3698 	buf_output0 (protocol, file);
3699 	buf_output (protocol, "\n", 1);
3700 	new_entries_line ();
3701     }
3702 
3703     buf_send_counted (protocol);
3704 }
3705 
3706 static void
3707 serve_update (arg)
3708     char *arg;
3709 {
3710     do_cvs_command ("update", update);
3711 }
3712 
3713 static void
3714 serve_diff (arg)
3715     char *arg;
3716 {
3717     do_cvs_command ("diff", diff);
3718 }
3719 
3720 static void
3721 serve_log (arg)
3722     char *arg;
3723 {
3724     do_cvs_command ("log", cvslog);
3725 }
3726 
3727 static void
3728 serve_rlog (arg)
3729     char *arg;
3730 {
3731     /* Tell cvslog() to behave like rlog not log.  */
3732     command_name = "rlog";
3733     do_cvs_command ("rlog", cvslog);
3734 }
3735 
3736 static void
3737 serve_add (arg)
3738     char *arg;
3739 {
3740     do_cvs_command ("add", add);
3741 }
3742 
3743 static void
3744 serve_remove (arg)
3745     char *arg;
3746 {
3747     do_cvs_command ("remove", cvsremove);
3748 }
3749 
3750 static void
3751 serve_status (arg)
3752     char *arg;
3753 {
3754     do_cvs_command ("status", cvsstatus);
3755 }
3756 
3757 static void
3758 serve_rdiff (arg)
3759     char *arg;
3760 {
3761     do_cvs_command ("rdiff", patch);
3762 }
3763 
3764 static void
3765 serve_tag (arg)
3766     char *arg;
3767 {
3768     do_cvs_command ("cvstag", cvstag);
3769 }
3770 
3771 static void
3772 serve_rtag (arg)
3773     char *arg;
3774 {
3775     /* Tell cvstag() to behave like rtag not tag.  */
3776     command_name = "rtag";
3777     do_cvs_command ("rtag", cvstag);
3778 }
3779 
3780 static void
3781 serve_import (arg)
3782     char *arg;
3783 {
3784     do_cvs_command ("import", import);
3785 }
3786 
3787 static void
3788 serve_admin (arg)
3789     char *arg;
3790 {
3791     do_cvs_command ("admin", admin);
3792 }
3793 
3794 static void
3795 serve_history (arg)
3796     char *arg;
3797 {
3798     do_cvs_command ("history", history);
3799 }
3800 
3801 static void
3802 serve_release (arg)
3803     char *arg;
3804 {
3805     do_cvs_command ("release", release);
3806 }
3807 
3808 static void serve_watch_on PROTO ((char *));
3809 
3810 static void
3811 serve_watch_on (arg)
3812     char *arg;
3813 {
3814     do_cvs_command ("watch_on", watch_on);
3815 }
3816 
3817 static void serve_watch_off PROTO ((char *));
3818 
3819 static void
3820 serve_watch_off (arg)
3821     char *arg;
3822 {
3823     do_cvs_command ("watch_off", watch_off);
3824 }
3825 
3826 static void serve_watch_add PROTO ((char *));
3827 
3828 static void
3829 serve_watch_add (arg)
3830     char *arg;
3831 {
3832     do_cvs_command ("watch_add", watch_add);
3833 }
3834 
3835 static void serve_watch_remove PROTO ((char *));
3836 
3837 static void
3838 serve_watch_remove (arg)
3839     char *arg;
3840 {
3841     do_cvs_command ("watch_remove", watch_remove);
3842 }
3843 
3844 static void serve_watchers PROTO ((char *));
3845 
3846 static void
3847 serve_watchers (arg)
3848     char *arg;
3849 {
3850     do_cvs_command ("watchers", watchers);
3851 }
3852 
3853 static void serve_editors PROTO ((char *));
3854 
3855 static void
3856 serve_editors (arg)
3857     char *arg;
3858 {
3859     do_cvs_command ("editors", editors);
3860 }
3861 
3862 static void serve_noop PROTO ((char *));
3863 
3864 static void
3865 serve_noop (arg)
3866     char *arg;
3867 {
3868 
3869     server_write_entries ();
3870     if (!print_pending_error ())
3871     {
3872 	(void) server_notify ();
3873 	buf_output0 (buf_to_net, "ok\n");
3874     }
3875     buf_flush (buf_to_net, 1);
3876 }
3877 
3878 static void serve_version PROTO ((char *));
3879 
3880 static void
3881 serve_version (arg)
3882     char *arg;
3883 {
3884     do_cvs_command ("version", version);
3885 }
3886 
3887 static void serve_init PROTO ((char *));
3888 
3889 static void
3890 serve_init (arg)
3891     char *arg;
3892 {
3893     if (!isabsolute (arg))
3894     {
3895 	if (alloc_pending (80 + strlen (arg)))
3896 	    sprintf (pending_error_text,
3897 		     "E Root %s must be an absolute pathname", arg);
3898 	/* Fall through to do_cvs_command which will return the
3899 	   actual error.  */
3900     }
3901 
3902     if (current_parsed_root != NULL)
3903 	free_cvsroot_t (current_parsed_root);
3904     current_parsed_root = local_cvsroot (arg);
3905 
3906     do_cvs_command ("init", init);
3907 }
3908 
3909 static void serve_annotate PROTO ((char *));
3910 
3911 static void
3912 serve_annotate (arg)
3913     char *arg;
3914 {
3915     do_cvs_command ("annotate", annotate);
3916 }
3917 
3918 static void serve_rannotate PROTO ((char *));
3919 
3920 static void
3921 serve_rannotate (arg)
3922     char *arg;
3923 {
3924     /* Tell annotate() to behave like rannotate not annotate.  */
3925     command_name = "rannotate";
3926     do_cvs_command ("rannotate", annotate);
3927 }
3928 
3929 static void
3930 serve_co (arg)
3931     char *arg;
3932 {
3933     char *tempdir;
3934     int status;
3935 
3936     if (print_pending_error ())
3937 	return;
3938 
3939     if (!isdir (CVSADM))
3940     {
3941 	/*
3942 	 * The client has not sent a "Repository" line.  Check out
3943 	 * into a pristine directory.
3944 	 */
3945 	tempdir = malloc (strlen (server_temp_dir) + 80);
3946 	if (tempdir == NULL)
3947 	{
3948 	    buf_output0 (buf_to_net, "E Out of memory\n");
3949 	    return;
3950 	}
3951 	strcpy (tempdir, server_temp_dir);
3952 	strcat (tempdir, "/checkout-dir");
3953 	status = mkdir_p (tempdir);
3954 	if (status != 0 && status != EEXIST)
3955 	{
3956 	    buf_output0 (buf_to_net, "E Cannot create ");
3957 	    buf_output0 (buf_to_net, tempdir);
3958 	    buf_append_char (buf_to_net, '\n');
3959 	    print_error (errno);
3960 	    free (tempdir);
3961 	    return;
3962 	}
3963 
3964 	if ( CVS_CHDIR (tempdir) < 0)
3965 	{
3966 	    buf_output0 (buf_to_net, "E Cannot change to directory ");
3967 	    buf_output0 (buf_to_net, tempdir);
3968 	    buf_append_char (buf_to_net, '\n');
3969 	    print_error (errno);
3970 	    free (tempdir);
3971 	    return;
3972 	}
3973 	free (tempdir);
3974     }
3975 
3976     /* Compensate for server_export()'s setting of command_name.
3977      *
3978      * [It probably doesn't matter if do_cvs_command() gets "export"
3979      *  or "checkout", but we ought to be accurate where possible.]
3980      */
3981     do_cvs_command ((strcmp (command_name, "export") == 0) ?
3982                     "export" : "checkout",
3983                     checkout);
3984 }
3985 
3986 static void
3987 serve_export (arg)
3988     char *arg;
3989 {
3990     /* Tell checkout() to behave like export not checkout.  */
3991     command_name = "export";
3992     serve_co (arg);
3993 }
3994 
3995 void
3996 server_copy_file (file, update_dir, repository, newfile)
3997     char *file;
3998     char *update_dir;
3999     char *repository;
4000     char *newfile;
4001 {
4002     /* At least for now, our practice is to have the server enforce
4003        noexec for the repository and the client enforce it for the
4004        working directory.  This might want more thought, and/or
4005        documentation in cvsclient.texi (other responses do it
4006        differently).  */
4007 
4008     if (!supported_response ("Copy-file"))
4009 	return;
4010     buf_output0 (protocol, "Copy-file ");
4011     output_dir (update_dir, repository);
4012     buf_output0 (protocol, file);
4013     buf_output0 (protocol, "\n");
4014     buf_output0 (protocol, newfile);
4015     buf_output0 (protocol, "\n");
4016 }
4017 
4018 /* See server.h for description.  */
4019 
4020 void
4021 server_modtime (finfo, vers_ts)
4022     struct file_info *finfo;
4023     Vers_TS *vers_ts;
4024 {
4025     char date[MAXDATELEN];
4026     char outdate[MAXDATELEN];
4027 
4028     assert (vers_ts->vn_rcs != NULL);
4029 
4030     if (!supported_response ("Mod-time"))
4031 	return;
4032 
4033     if (RCS_getrevtime (finfo->rcs, vers_ts->vn_rcs, date, 0) == (time_t) -1)
4034 	/* FIXME? should we be printing some kind of warning?  For one
4035 	   thing I'm not 100% sure whether this happens in non-error
4036 	   circumstances.  */
4037 	return;
4038     date_to_internet (outdate, date);
4039     buf_output0 (protocol, "Mod-time ");
4040     buf_output0 (protocol, outdate);
4041     buf_output0 (protocol, "\n");
4042 }
4043 
4044 /* See server.h for description.  */
4045 
4046 #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
4047 /* Need to prototype because mode_t might be smaller than int.  */
4048 void
4049 server_updated (
4050     struct file_info *finfo,
4051     Vers_TS *vers,
4052     enum server_updated_arg4 updated,
4053     mode_t mode,
4054     unsigned char *checksum,
4055     struct buffer *filebuf)
4056 #else
4057 void
4058 server_updated (finfo, vers, updated, mode, checksum, filebuf)
4059     struct file_info *finfo;
4060     Vers_TS *vers;
4061     enum server_updated_arg4 updated;
4062     mode_t mode;
4063     unsigned char *checksum;
4064     struct buffer *filebuf;
4065 #endif
4066 {
4067     if (noexec)
4068     {
4069 	/* Hmm, maybe if we did the same thing for entries_file, we
4070 	   could get rid of the kludges in server_register and
4071 	   server_scratch which refrain from warning if both
4072 	   Scratch_Entry and Register get called.  Maybe.  */
4073 	if (scratched_file)
4074 	{
4075 	    free (scratched_file);
4076 	    scratched_file = NULL;
4077 	}
4078 	return;
4079     }
4080 
4081     if (entries_line != NULL && scratched_file == NULL)
4082     {
4083 	FILE *f;
4084 	struct buffer_data *list, *last;
4085 	unsigned long size;
4086 	char size_text[80];
4087 
4088 	/* The contents of the file will be in one of filebuf,
4089 	   list/last, or here.  */
4090 	unsigned char *file;
4091 	size_t file_allocated;
4092 	size_t file_used;
4093 
4094 	if (filebuf != NULL)
4095 	{
4096 	    size = buf_length (filebuf);
4097 	    if (mode == (mode_t) -1)
4098 		error (1, 0, "\
4099 CVS server internal error: no mode in server_updated");
4100 	}
4101 	else
4102 	{
4103 	    struct stat sb;
4104 
4105 	    if ( CVS_STAT (finfo->file, &sb) < 0)
4106 	    {
4107 		if (existence_error (errno))
4108 		{
4109 		    /* If we have a sticky tag for a branch on which
4110 		       the file is dead, and cvs update the directory,
4111 		       it gets a T_CHECKOUT but no file.  So in this
4112 		       case just forget the whole thing.  */
4113 		    free (entries_line);
4114 		    entries_line = NULL;
4115 		    goto done;
4116 		}
4117 		error (1, errno, "reading %s", finfo->fullname);
4118 	    }
4119 	    size = sb.st_size;
4120 	    if (mode == (mode_t) -1)
4121 	    {
4122 		/* FIXME: When we check out files the umask of the
4123 		   server (set in .bashrc if rsh is in use) affects
4124 		   what mode we send, and it shouldn't.  */
4125 		mode = sb.st_mode;
4126 	    }
4127 	}
4128 
4129 	if (checksum != NULL)
4130 	{
4131 	    static int checksum_supported = -1;
4132 
4133 	    if (checksum_supported == -1)
4134 	    {
4135 		checksum_supported = supported_response ("Checksum");
4136 	    }
4137 
4138 	    if (checksum_supported)
4139 	    {
4140 	        int i;
4141 		char buf[3];
4142 
4143 	        buf_output0 (protocol, "Checksum ");
4144 		for (i = 0; i < 16; i++)
4145 		{
4146 		    sprintf (buf, "%02x", (unsigned int) checksum[i]);
4147 		    buf_output0 (protocol, buf);
4148 		}
4149 		buf_append_char (protocol, '\n');
4150 	    }
4151 	}
4152 
4153 	if (updated == SERVER_UPDATED)
4154 	{
4155 	    Node *node;
4156 	    Entnode *entnode;
4157 
4158 	    if (!(supported_response ("Created")
4159 		  && supported_response ("Update-existing")))
4160 		buf_output0 (protocol, "Updated ");
4161 	    else
4162 	    {
4163 		assert (vers != NULL);
4164 		if (vers->ts_user == NULL)
4165 		    buf_output0 (protocol, "Created ");
4166 		else
4167 		    buf_output0 (protocol, "Update-existing ");
4168 	    }
4169 
4170 	    /* Now munge the entries to say that the file is unmodified,
4171 	       in case we end up processing it again (e.g. modules3-6
4172 	       in the testsuite).  */
4173 	    node = findnode_fn (finfo->entries, finfo->file);
4174 	    entnode = (Entnode *)node->data;
4175 	    free (entnode->timestamp);
4176 	    entnode->timestamp = xstrdup ("=");
4177 	}
4178 	else if (updated == SERVER_MERGED)
4179 	    buf_output0 (protocol, "Merged ");
4180 	else if (updated == SERVER_PATCHED)
4181 	    buf_output0 (protocol, "Patched ");
4182 	else if (updated == SERVER_RCS_DIFF)
4183 	    buf_output0 (protocol, "Rcs-diff ");
4184 	else
4185 	    abort ();
4186 	output_dir (finfo->update_dir, finfo->repository);
4187 	buf_output0 (protocol, finfo->file);
4188 	buf_output (protocol, "\n", 1);
4189 
4190 	new_entries_line ();
4191 
4192         {
4193 	    char *mode_string;
4194 
4195 	    mode_string = mode_to_string (mode);
4196 	    buf_output0 (protocol, mode_string);
4197 	    buf_output0 (protocol, "\n");
4198 	    free (mode_string);
4199 	}
4200 
4201 	list = last = NULL;
4202 
4203 	file = NULL;
4204 	file_allocated = 0;
4205 	file_used = 0;
4206 
4207 	if (size > 0)
4208 	{
4209 	    /* Throughout this section we use binary mode to read the
4210 	       file we are sending.  The client handles any line ending
4211 	       translation if necessary.  */
4212 
4213 	    if (file_gzip_level
4214 		/*
4215 		 * For really tiny files, the gzip process startup
4216 		 * time will outweigh the compression savings.  This
4217 		 * might be computable somehow; using 100 here is just
4218 		 * a first approximation.
4219 		 */
4220 		&& size > 100)
4221 	    {
4222 		/* Basing this routine on read_and_gzip is not a
4223 		   high-performance approach.  But it seems easier
4224 		   to code than the alternative (and less
4225 		   vulnerable to subtle bugs).  Given that this feature
4226 		   is mainly for compatibility, that is the better
4227 		   tradeoff.  */
4228 
4229 		int fd;
4230 
4231 		/* Callers must avoid passing us a buffer if
4232                    file_gzip_level is set.  We could handle this case,
4233                    but it's not worth it since this case never arises
4234                    with a current client and server.  */
4235 		if (filebuf != NULL)
4236 		    error (1, 0, "\
4237 CVS server internal error: unhandled case in server_updated");
4238 
4239 		fd = CVS_OPEN (finfo->file, O_RDONLY | OPEN_BINARY, 0);
4240 		if (fd < 0)
4241 		    error (1, errno, "reading %s", finfo->fullname);
4242 		if (read_and_gzip (fd, finfo->fullname, &file,
4243 				   &file_allocated, &file_used,
4244 				   file_gzip_level))
4245 		    error (1, 0, "aborting due to compression error");
4246 		size = file_used;
4247 		if (close (fd) < 0)
4248 		    error (1, errno, "reading %s", finfo->fullname);
4249 		/* Prepending length with "z" is flag for using gzip here.  */
4250 		buf_output0 (protocol, "z");
4251 	    }
4252 	    else if (filebuf == NULL)
4253 	    {
4254 		long status;
4255 
4256 		f = CVS_FOPEN (finfo->file, "rb");
4257 		if (f == NULL)
4258 		    error (1, errno, "reading %s", finfo->fullname);
4259 		status = buf_read_file (f, size, &list, &last);
4260 		if (status == -2)
4261 		    (*protocol->memory_error) (protocol);
4262 		else if (status != 0)
4263 		    error (1, ferror (f) ? errno : 0, "reading %s",
4264 			   finfo->fullname);
4265 		if (fclose (f) == EOF)
4266 		    error (1, errno, "reading %s", finfo->fullname);
4267 	    }
4268 	}
4269 
4270 	sprintf (size_text, "%lu\n", size);
4271 	buf_output0 (protocol, size_text);
4272 
4273 	if (file != NULL)
4274 	{
4275 	    buf_output (protocol, (char *) file, file_used);
4276 	    free (file);
4277 	    file = NULL;
4278 	}
4279 	else if (filebuf == NULL)
4280 	    buf_append_data (protocol, list, last);
4281 	else
4282 	{
4283 	    buf_append_buffer (protocol, filebuf);
4284 	    buf_free (filebuf);
4285 	}
4286 	/* Note we only send a newline here if the file ended with one.  */
4287 
4288 	/*
4289 	 * Avoid using up too much disk space for temporary files.
4290 	 * A file which does not exist indicates that the file is up-to-date,
4291 	 * which is now the case.  If this is SERVER_MERGED, the file is
4292 	 * not up-to-date, and we indicate that by leaving the file there.
4293 	 * I'm thinking of cases like "cvs update foo/foo.c foo".
4294 	 */
4295 	if ((updated == SERVER_UPDATED
4296 	     || updated == SERVER_PATCHED
4297 	     || updated == SERVER_RCS_DIFF)
4298 	    && filebuf == NULL
4299 	    /* But if we are joining, we'll need the file when we call
4300 	       join_file.  */
4301 	    && !joining ())
4302 	{
4303 	    if (CVS_UNLINK (finfo->file) < 0)
4304 		error (0, errno, "cannot remove temp file for %s",
4305 		       finfo->fullname);
4306 	}
4307     }
4308     else if (scratched_file != NULL && entries_line == NULL)
4309     {
4310 	if (strcmp (scratched_file, finfo->file) != 0)
4311 	    error (1, 0,
4312 		   "CVS server internal error: `%s' vs. `%s' scratched",
4313 		   scratched_file,
4314 		   finfo->file);
4315 	free (scratched_file);
4316 	scratched_file = NULL;
4317 
4318 	if (kill_scratched_file)
4319 	    buf_output0 (protocol, "Removed ");
4320 	else
4321 	    buf_output0 (protocol, "Remove-entry ");
4322 	output_dir (finfo->update_dir, finfo->repository);
4323 	buf_output0 (protocol, finfo->file);
4324 	buf_output (protocol, "\n", 1);
4325 	/* keep the vers structure up to date in case we do a join
4326 	 * - if there isn't a file, it can't very well have a version number, can it?
4327 	 *
4328 	 * we do it here on the assumption that since we just told the client
4329 	 * to remove the file/entry, it will, and we want to remember that.
4330 	 * If it fails, that's the client's problem, not ours
4331 	 */
4332 	if (vers && vers->vn_user != NULL)
4333 	{
4334 	    free (vers->vn_user);
4335 	    vers->vn_user = NULL;
4336 	}
4337 	if (vers && vers->ts_user != NULL)
4338 	{
4339 	    free (vers->ts_user);
4340 	    vers->ts_user = NULL;
4341 	}
4342     }
4343     else if (scratched_file == NULL && entries_line == NULL)
4344     {
4345 	/*
4346 	 * This can happen with death support if we were processing
4347 	 * a dead file in a checkout.
4348 	 */
4349     }
4350     else
4351 	error (1, 0,
4352 	       "CVS server internal error: Register *and* Scratch_Entry.\n");
4353     buf_send_counted (protocol);
4354   done:;
4355 }
4356 
4357 /* Return whether we should send patches in RCS format.  */
4358 
4359 int
4360 server_use_rcs_diff ()
4361 {
4362     return supported_response ("Rcs-diff");
4363 }
4364 
4365 void
4366 server_set_entstat (update_dir, repository)
4367     char *update_dir;
4368     char *repository;
4369 {
4370     static int set_static_supported = -1;
4371     if (set_static_supported == -1)
4372 	set_static_supported = supported_response ("Set-static-directory");
4373     if (!set_static_supported) return;
4374 
4375     buf_output0 (protocol, "Set-static-directory ");
4376     output_dir (update_dir, repository);
4377     buf_output0 (protocol, "\n");
4378     buf_send_counted (protocol);
4379 }
4380 
4381 void
4382 server_clear_entstat (update_dir, repository)
4383      char *update_dir;
4384      char *repository;
4385 {
4386     static int clear_static_supported = -1;
4387     if (clear_static_supported == -1)
4388 	clear_static_supported = supported_response ("Clear-static-directory");
4389     if (!clear_static_supported) return;
4390 
4391     if (noexec)
4392 	return;
4393 
4394     buf_output0 (protocol, "Clear-static-directory ");
4395     output_dir (update_dir, repository);
4396     buf_output0 (protocol, "\n");
4397     buf_send_counted (protocol);
4398 }
4399 
4400 void
4401 server_set_sticky (update_dir, repository, tag, date, nonbranch)
4402     char *update_dir;
4403     char *repository;
4404     char *tag;
4405     char *date;
4406     int nonbranch;
4407 {
4408     static int set_sticky_supported = -1;
4409 
4410     assert (update_dir != NULL);
4411 
4412     if (set_sticky_supported == -1)
4413 	set_sticky_supported = supported_response ("Set-sticky");
4414     if (!set_sticky_supported) return;
4415 
4416     if (noexec)
4417 	return;
4418 
4419     if (tag == NULL && date == NULL)
4420     {
4421 	buf_output0 (protocol, "Clear-sticky ");
4422 	output_dir (update_dir, repository);
4423 	buf_output0 (protocol, "\n");
4424     }
4425     else
4426     {
4427 	buf_output0 (protocol, "Set-sticky ");
4428 	output_dir (update_dir, repository);
4429 	buf_output0 (protocol, "\n");
4430 	if (tag != NULL)
4431 	{
4432 	    if (nonbranch)
4433 		buf_output0 (protocol, "N");
4434 	    else
4435 		buf_output0 (protocol, "T");
4436 	    buf_output0 (protocol, tag);
4437 	}
4438 	else
4439 	{
4440 	    buf_output0 (protocol, "D");
4441 	    buf_output0 (protocol, date);
4442 	}
4443 	buf_output0 (protocol, "\n");
4444     }
4445     buf_send_counted (protocol);
4446 }
4447 
4448 struct template_proc_data
4449 {
4450     char *update_dir;
4451     char *repository;
4452 };
4453 
4454 /* Here as a static until we get around to fixing Parse_Info to pass along
4455    a void * for it.  */
4456 static struct template_proc_data *tpd;
4457 
4458 static int
4459 template_proc (repository, template)
4460     char *repository;
4461     char *template;
4462 {
4463     FILE *fp;
4464     char buf[1024];
4465     size_t n;
4466     struct stat sb;
4467     struct template_proc_data *data = tpd;
4468 
4469     if (!supported_response ("Template"))
4470 	/* Might want to warn the user that the rcsinfo feature won't work.  */
4471 	return 0;
4472     buf_output0 (protocol, "Template ");
4473     output_dir (data->update_dir, data->repository);
4474     buf_output0 (protocol, "\n");
4475 
4476     fp = CVS_FOPEN (template, "rb");
4477     if (fp == NULL)
4478     {
4479 	error (0, errno, "Couldn't open rcsinfo template file %s", template);
4480 	return 1;
4481     }
4482     if (fstat (fileno (fp), &sb) < 0)
4483     {
4484 	error (0, errno, "cannot stat rcsinfo template file %s", template);
4485 	return 1;
4486     }
4487     sprintf (buf, "%ld\n", (long) sb.st_size);
4488     buf_output0 (protocol, buf);
4489     while (!feof (fp))
4490     {
4491 	n = fread (buf, 1, sizeof buf, fp);
4492 	buf_output (protocol, buf, n);
4493 	if (ferror (fp))
4494 	{
4495 	    error (0, errno, "cannot read rcsinfo template file %s", template);
4496 	    (void) fclose (fp);
4497 	    return 1;
4498 	}
4499     }
4500     if (fclose (fp) < 0)
4501 	error (0, errno, "cannot close rcsinfo template file %s", template);
4502     return 0;
4503 }
4504 
4505 void
4506 server_template (update_dir, repository)
4507     char *update_dir;
4508     char *repository;
4509 {
4510     struct template_proc_data data;
4511     data.update_dir = update_dir;
4512     data.repository = repository;
4513     tpd = &data;
4514     (void) Parse_Info (CVSROOTADM_RCSINFO, repository, template_proc, 1);
4515 }
4516 
4517 static void
4518 serve_gzip_contents (arg)
4519      char *arg;
4520 {
4521     int level;
4522     level = atoi (arg);
4523     if (level == 0)
4524 	level = 6;
4525     file_gzip_level = level;
4526 }
4527 
4528 static void
4529 serve_gzip_stream (arg)
4530      char *arg;
4531 {
4532     int level;
4533     level = atoi (arg);
4534     if (level == 0)
4535 	level = 6;
4536 
4537     /* All further communication with the client will be compressed.  */
4538 
4539     buf_to_net = compress_buffer_initialize (buf_to_net, 0, level,
4540 					     buf_to_net->memory_error);
4541     buf_from_net = compress_buffer_initialize (buf_from_net, 1, level,
4542 					       buf_from_net->memory_error);
4543 }
4544 
4545 /* Tell the client about RCS options set in CVSROOT/cvswrappers. */
4546 static void
4547 serve_wrapper_sendme_rcs_options (arg)
4548      char *arg;
4549 {
4550     /* Actually, this is kind of sdrawkcab-ssa: the client wants
4551      * verbatim lines from a cvswrappers file, but the server has
4552      * already parsed the cvswrappers file into the wrap_list struct.
4553      * Therefore, the server loops over wrap_list, unparsing each
4554      * entry before sending it.
4555      */
4556     char *wrapper_line = NULL;
4557 
4558     wrap_setup ();
4559 
4560     for (wrap_unparse_rcs_options (&wrapper_line, 1);
4561          wrapper_line;
4562          wrap_unparse_rcs_options (&wrapper_line, 0))
4563     {
4564 	buf_output0 (buf_to_net, "Wrapper-rcsOption ");
4565 	buf_output0 (buf_to_net, wrapper_line);
4566 	buf_output0 (buf_to_net, "\012");;
4567 	free (wrapper_line);
4568     }
4569 
4570     buf_output0 (buf_to_net, "ok\012");
4571 
4572     /* The client is waiting for us, so we better send the data now.  */
4573     buf_flush (buf_to_net, 1);
4574 }
4575 
4576 
4577 static void
4578 serve_ignore (arg)
4579     char *arg;
4580 {
4581     /*
4582      * Just ignore this command.  This is used to support the
4583      * update-patches command, which is not a real command, but a signal
4584      * to the client that update will accept the -u argument.
4585      */
4586 }
4587 
4588 static int
4589 expand_proc (argc, argv, where, mwhere, mfile, shorten,
4590 	     local_specified, omodule, msg)
4591     int argc;
4592     char **argv;
4593     char *where;
4594     char *mwhere;
4595     char *mfile;
4596     int shorten;
4597     int local_specified;
4598     char *omodule;
4599     char *msg;
4600 {
4601     int i;
4602     char *dir = argv[0];
4603 
4604     /* If mwhere has been specified, the thing we're expanding is a
4605        module -- just return its name so the client will ask for the
4606        right thing later.  If it is an alias or a real directory,
4607        mwhere will not be set, so send out the appropriate
4608        expansion. */
4609 
4610     if (mwhere != NULL)
4611     {
4612 	buf_output0 (buf_to_net, "Module-expansion ");
4613 	if (server_dir != NULL)
4614 	{
4615 	    buf_output0 (buf_to_net, server_dir);
4616 	    buf_output0 (buf_to_net, "/");
4617 	}
4618 	buf_output0 (buf_to_net, mwhere);
4619 	if (mfile != NULL)
4620 	{
4621 	    buf_append_char (buf_to_net, '/');
4622 	    buf_output0 (buf_to_net, mfile);
4623 	}
4624 	buf_append_char (buf_to_net, '\n');
4625     }
4626     else
4627     {
4628 	/* We may not need to do this anymore -- check the definition
4629            of aliases before removing */
4630 	if (argc == 1)
4631 	{
4632 	    buf_output0 (buf_to_net, "Module-expansion ");
4633 	    if (server_dir != NULL)
4634 	    {
4635 		buf_output0 (buf_to_net, server_dir);
4636 		buf_output0 (buf_to_net, "/");
4637 	    }
4638 	    buf_output0 (buf_to_net, dir);
4639 	    buf_append_char (buf_to_net, '\n');
4640 	}
4641 	else
4642 	{
4643 	    for (i = 1; i < argc; ++i)
4644 	    {
4645 	        buf_output0 (buf_to_net, "Module-expansion ");
4646 		if (server_dir != NULL)
4647 		{
4648 		    buf_output0 (buf_to_net, server_dir);
4649 		    buf_output0 (buf_to_net, "/");
4650 		}
4651 		buf_output0 (buf_to_net, dir);
4652 		buf_append_char (buf_to_net, '/');
4653 		buf_output0 (buf_to_net, argv[i]);
4654 		buf_append_char (buf_to_net, '\n');
4655 	    }
4656 	}
4657     }
4658     return 0;
4659 }
4660 
4661 static void
4662 serve_expand_modules (arg)
4663     char *arg;
4664 {
4665     int i;
4666     int err;
4667     DBM *db;
4668     err = 0;
4669 
4670     server_expanding = 1;
4671     db = open_module ();
4672     for (i = 1; i < argument_count; i++)
4673 	err += do_module (db, argument_vector[i],
4674 			  CHECKOUT, "Updating", expand_proc,
4675 			  NULL, 0, 0, 0, 0,
4676 			  (char *) NULL);
4677     close_module (db);
4678     server_expanding = 0;
4679     {
4680 	/* argument_vector[0] is a dummy argument, we don't mess with it.  */
4681 	char **cp;
4682 	for (cp = argument_vector + 1;
4683 	     cp < argument_vector + argument_count;
4684 	     ++cp)
4685 	    free (*cp);
4686 
4687 	argument_count = 1;
4688     }
4689     if (err)
4690 	/* We will have printed an error message already.  */
4691 	buf_output0 (buf_to_net, "error  \n");
4692     else
4693 	buf_output0 (buf_to_net, "ok\n");
4694 
4695     /* The client is waiting for the module expansions, so we must
4696        send the output now.  */
4697     buf_flush (buf_to_net, 1);
4698 }
4699 
4700 void
4701 server_prog (dir, name, which)
4702     char *dir;
4703     char *name;
4704     enum progs which;
4705 {
4706     if (!supported_response ("Set-checkin-prog"))
4707     {
4708 	buf_output0 (buf_to_net, "E \
4709 warning: this client does not support -i or -u flags in the modules file.\n");
4710 	return;
4711     }
4712     switch (which)
4713     {
4714 	case PROG_CHECKIN:
4715 	    buf_output0 (buf_to_net, "Set-checkin-prog ");
4716 	    break;
4717 	case PROG_UPDATE:
4718 	    buf_output0 (buf_to_net, "Set-update-prog ");
4719 	    break;
4720     }
4721     buf_output0 (buf_to_net, dir);
4722     buf_append_char (buf_to_net, '\n');
4723     buf_output0 (buf_to_net, name);
4724     buf_append_char (buf_to_net, '\n');
4725 }
4726 
4727 static void
4728 serve_checkin_prog (arg)
4729     char *arg;
4730 {
4731     FILE *f;
4732 
4733     /* Before we do anything we first check if this command is not
4734        disabled. */
4735     if (disable_x_prog)
4736     {
4737 	if (alloc_pending (80))
4738 	    sprintf (pending_error_text, "\
4739 E Checkin-prog disabled by configuration");
4740 	return;
4741     }
4742 
4743     f = CVS_FOPEN (CVSADM_CIPROG, "w+");
4744     if (f == NULL)
4745     {
4746 	int save_errno = errno;
4747 	if (alloc_pending (80 + strlen (CVSADM_CIPROG)))
4748 	    sprintf (pending_error_text, "E cannot open %s", CVSADM_CIPROG);
4749 	pending_error = save_errno;
4750 	return;
4751     }
4752     if (fprintf (f, "%s\n", arg) < 0)
4753     {
4754 	int save_errno = errno;
4755 	if (alloc_pending (80 + strlen (CVSADM_CIPROG)))
4756 	    sprintf (pending_error_text,
4757 		     "E cannot write to %s", CVSADM_CIPROG);
4758 	pending_error = save_errno;
4759 	return;
4760     }
4761     if (fclose (f) == EOF)
4762     {
4763 	int save_errno = errno;
4764 	if (alloc_pending (80 + strlen (CVSADM_CIPROG)))
4765 	    sprintf (pending_error_text, "E cannot close %s", CVSADM_CIPROG);
4766 	pending_error = save_errno;
4767 	return;
4768     }
4769 }
4770 
4771 static void
4772 serve_update_prog (arg)
4773     char *arg;
4774 {
4775     FILE *f;
4776 
4777     /* Before we do anything we first check if this command is not
4778        disabled. */
4779     if (disable_x_prog)
4780     {
4781 	if (alloc_pending (80))
4782 	    sprintf (pending_error_text, "\
4783 E Update-prog disabled by configuration");
4784 	return;
4785     }
4786 
4787     /* Before we do anything we need to make sure we are not in readonly
4788        mode.  */
4789     if (!check_command_legal_p ("commit"))
4790     {
4791 	/* I might be willing to make this a warning, except we lack the
4792 	   machinery to do so.  */
4793 	if (alloc_pending (80))
4794 	    sprintf (pending_error_text, "\
4795 E Flag -u in modules not allowed in readonly mode");
4796 	return;
4797     }
4798 
4799     f = CVS_FOPEN (CVSADM_UPROG, "w+");
4800     if (f == NULL)
4801     {
4802 	int save_errno = errno;
4803 	if (alloc_pending (80 + strlen (CVSADM_UPROG)))
4804 	    sprintf (pending_error_text, "E cannot open %s", CVSADM_UPROG);
4805 	pending_error = save_errno;
4806 	return;
4807     }
4808     if (fprintf (f, "%s\n", arg) < 0)
4809     {
4810 	int save_errno = errno;
4811 	if (alloc_pending (80 + strlen (CVSADM_UPROG)))
4812 	    sprintf (pending_error_text, "E cannot write to %s", CVSADM_UPROG);
4813 	pending_error = save_errno;
4814 	return;
4815     }
4816     if (fclose (f) == EOF)
4817     {
4818 	int save_errno = errno;
4819 	if (alloc_pending (80 + strlen (CVSADM_UPROG)))
4820 	    sprintf (pending_error_text, "E cannot close %s", CVSADM_UPROG);
4821 	pending_error = save_errno;
4822 	return;
4823     }
4824 }
4825 
4826 static void serve_valid_requests PROTO((char *arg));
4827 
4828 #endif /* SERVER_SUPPORT */
4829 #if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
4830 
4831 /*
4832  * Parts of this table are shared with the client code,
4833  * but the client doesn't need to know about the handler
4834  * functions.
4835  */
4836 
4837 struct request requests[] =
4838 {
4839 #ifdef SERVER_SUPPORT
4840 #define REQ_LINE(n, f, s) {n, f, s}
4841 #else
4842 #define REQ_LINE(n, f, s) {n, s}
4843 #endif
4844 
4845   REQ_LINE("Root", serve_root, RQ_ESSENTIAL | RQ_ROOTLESS),
4846   REQ_LINE("Valid-responses", serve_valid_responses,
4847 	   RQ_ESSENTIAL | RQ_ROOTLESS),
4848   REQ_LINE("valid-requests", serve_valid_requests,
4849 	   RQ_ESSENTIAL | RQ_ROOTLESS),
4850   REQ_LINE("Repository", serve_repository, 0),
4851   REQ_LINE("Directory", serve_directory, RQ_ESSENTIAL),
4852   REQ_LINE("Max-dotdot", serve_max_dotdot, 0),
4853   REQ_LINE("Static-directory", serve_static_directory, 0),
4854   REQ_LINE("Sticky", serve_sticky, 0),
4855   REQ_LINE("Checkin-prog", serve_checkin_prog, 0),
4856   REQ_LINE("Update-prog", serve_update_prog, 0),
4857   REQ_LINE("Entry", serve_entry, RQ_ESSENTIAL),
4858   REQ_LINE("Kopt", serve_kopt, 0),
4859   REQ_LINE("Checkin-time", serve_checkin_time, 0),
4860   REQ_LINE("Modified", serve_modified, RQ_ESSENTIAL),
4861   REQ_LINE("Is-modified", serve_is_modified, 0),
4862 
4863   /* The client must send this request to interoperate with CVS 1.5
4864      through 1.9 servers.  The server must support it (although it can
4865      be and is a noop) to interoperate with CVS 1.5 to 1.9 clients.  */
4866   REQ_LINE("UseUnchanged", serve_enable_unchanged, RQ_ENABLEME | RQ_ROOTLESS),
4867 
4868   REQ_LINE("Unchanged", serve_unchanged, RQ_ESSENTIAL),
4869   REQ_LINE("Notify", serve_notify, 0),
4870   REQ_LINE("Questionable", serve_questionable, 0),
4871   REQ_LINE("Case", serve_case, 0),
4872   REQ_LINE("Argument", serve_argument, RQ_ESSENTIAL),
4873   REQ_LINE("Argumentx", serve_argumentx, RQ_ESSENTIAL),
4874   REQ_LINE("Global_option", serve_global_option, RQ_ROOTLESS),
4875   REQ_LINE("Gzip-stream", serve_gzip_stream, 0),
4876   REQ_LINE("wrapper-sendme-rcsOptions",
4877            serve_wrapper_sendme_rcs_options,
4878            0),
4879   REQ_LINE("Set", serve_set, RQ_ROOTLESS),
4880 #ifdef ENCRYPTION
4881 #  ifdef HAVE_KERBEROS
4882   REQ_LINE("Kerberos-encrypt", serve_kerberos_encrypt, 0),
4883 #  endif
4884 #  ifdef HAVE_GSSAPI
4885   REQ_LINE("Gssapi-encrypt", serve_gssapi_encrypt, 0),
4886 #  endif
4887 #endif
4888 #ifdef HAVE_GSSAPI
4889   REQ_LINE("Gssapi-authenticate", serve_gssapi_authenticate, 0),
4890 #endif
4891   REQ_LINE("expand-modules", serve_expand_modules, 0),
4892   REQ_LINE("ci", serve_ci, RQ_ESSENTIAL),
4893   REQ_LINE("co", serve_co, RQ_ESSENTIAL),
4894   REQ_LINE("update", serve_update, RQ_ESSENTIAL),
4895   REQ_LINE("diff", serve_diff, 0),
4896   REQ_LINE("log", serve_log, 0),
4897   REQ_LINE("rlog", serve_rlog, 0),
4898   REQ_LINE("add", serve_add, 0),
4899   REQ_LINE("remove", serve_remove, 0),
4900   REQ_LINE("update-patches", serve_ignore, 0),
4901   REQ_LINE("gzip-file-contents", serve_gzip_contents, 0),
4902   REQ_LINE("status", serve_status, 0),
4903   REQ_LINE("rdiff", serve_rdiff, 0),
4904   REQ_LINE("tag", serve_tag, 0),
4905   REQ_LINE("rtag", serve_rtag, 0),
4906   REQ_LINE("import", serve_import, 0),
4907   REQ_LINE("admin", serve_admin, 0),
4908   REQ_LINE("export", serve_export, 0),
4909   REQ_LINE("history", serve_history, 0),
4910   REQ_LINE("release", serve_release, 0),
4911   REQ_LINE("watch-on", serve_watch_on, 0),
4912   REQ_LINE("watch-off", serve_watch_off, 0),
4913   REQ_LINE("watch-add", serve_watch_add, 0),
4914   REQ_LINE("watch-remove", serve_watch_remove, 0),
4915   REQ_LINE("watchers", serve_watchers, 0),
4916   REQ_LINE("editors", serve_editors, 0),
4917   REQ_LINE("init", serve_init, RQ_ROOTLESS),
4918   REQ_LINE("annotate", serve_annotate, 0),
4919   REQ_LINE("rannotate", serve_rannotate, 0),
4920   REQ_LINE("noop", serve_noop, RQ_ROOTLESS),
4921   REQ_LINE("version", serve_version, RQ_ROOTLESS),
4922   REQ_LINE(NULL, NULL, 0)
4923 
4924 #undef REQ_LINE
4925 };
4926 
4927 #endif /* SERVER_SUPPORT or CLIENT_SUPPORT */
4928 #ifdef SERVER_SUPPORT
4929 
4930 static void
4931 serve_valid_requests (arg)
4932      char *arg;
4933 {
4934     struct request *rq;
4935     if (print_pending_error ())
4936 	return;
4937     buf_output0 (buf_to_net, "Valid-requests");
4938     for (rq = requests; rq->name != NULL; rq++)
4939     {
4940 	if (rq->func != NULL)
4941 	{
4942 	    buf_append_char (buf_to_net, ' ');
4943 	    buf_output0 (buf_to_net, rq->name);
4944 	}
4945     }
4946     buf_output0 (buf_to_net, "\nok\n");
4947 
4948     /* The client is waiting for the list of valid requests, so we
4949        must send the output now.  */
4950     buf_flush (buf_to_net, 1);
4951 }
4952 
4953 #ifdef SUNOS_KLUDGE
4954 /*
4955  * Delete temporary files.  SIG is the signal making this happen, or
4956  * 0 if not called as a result of a signal.
4957  */
4958 static int command_pid_is_dead;
4959 static void wait_sig (sig)
4960      int sig;
4961 {
4962     int status;
4963     int save_errno = errno;
4964 
4965     pid_t r = wait (&status);
4966     if (r == command_pid)
4967 	command_pid_is_dead++;
4968     errno = save_errno;
4969 }
4970 #endif /* SUNOS_KLUDGE */
4971 
4972 void
4973 server_cleanup (sig)
4974     int sig;
4975 {
4976     /* Do "rm -rf" on the temp directory.  */
4977     static int called = 0;
4978     int status;
4979     int save_noexec;
4980 
4981     if (called++)
4982 	return;
4983 
4984     /* already processing cleanup, do not want recursion */
4985 #ifdef SIGABRT
4986     (void) SIG_deregister (SIGABRT, server_cleanup);
4987 #endif
4988 #ifdef SIGHUP
4989     (void) SIG_deregister (SIGHUP, server_cleanup);
4990 #endif
4991 #ifdef SIGINT
4992     (void) SIG_deregister (SIGINT, server_cleanup);
4993 #endif
4994 #ifdef SIGQUIT
4995     (void) SIG_deregister (SIGQUIT, server_cleanup);
4996 #endif
4997 #ifdef SIGPIPE
4998     (void) SIG_deregister (SIGPIPE, server_cleanup);
4999 #endif
5000 #ifdef SIGTERM
5001     (void) SIG_deregister (SIGTERM, server_cleanup);
5002 #endif
5003 
5004     if (buf_to_net != NULL)
5005     {
5006 	/* FIXME: If this is not the final call from server, this
5007 	   could deadlock, because the client might be blocked writing
5008 	   to us.  This should not be a problem in practice, because
5009 	   we do not generate much output when the client is not
5010 	   waiting for it.  */
5011 	set_block (buf_to_net);
5012 	buf_flush (buf_to_net, 1);
5013 
5014 	/* The calls to buf_shutdown are currently only meaningful
5015 	   when we are using compression.  First we shut down
5016 	   BUF_FROM_NET.  That will pick up the checksum generated
5017 	   when the client shuts down its buffer.  Then, after we have
5018 	   generated any final output, we shut down BUF_TO_NET.  */
5019 
5020 	status = buf_shutdown (buf_from_net);
5021 	if (status != 0)
5022 	{
5023 	    error (0, status, "shutting down buffer from client");
5024 	    buf_flush (buf_to_net, 1);
5025 	}
5026     }
5027 
5028     if (dont_delete_temp)
5029     {
5030 	if (buf_to_net != NULL)
5031 	    (void) buf_shutdown (buf_to_net);
5032 	return;
5033     }
5034 
5035     /* What a bogus kludge.  This disgusting code makes all kinds of
5036        assumptions about SunOS, and is only for a bug in that system.
5037        So only enable it on Suns.  */
5038 #ifdef SUNOS_KLUDGE
5039     if (command_pid > 0)
5040     {
5041 	/* To avoid crashes on SunOS due to bugs in SunOS tmpfs
5042 	   triggered by the use of rename() in RCS, wait for the
5043 	   subprocess to die.  Unfortunately, this means draining output
5044 	   while waiting for it to unblock the signal we sent it.  Yuck!  */
5045 	int status;
5046 	pid_t r;
5047 
5048 	signal (SIGCHLD, wait_sig);
5049 	if (sig)
5050 	    /* Perhaps SIGTERM would be more correct.  But the child
5051 	       process will delay the SIGINT delivery until its own
5052 	       children have exited.  */
5053 	    kill (command_pid, SIGINT);
5054 	/* The caller may also have sent a signal to command_pid, so
5055 	   always try waiting.  First, though, check and see if it's still
5056 	   there....  */
5057     do_waitpid:
5058 	r = waitpid (command_pid, &status, WNOHANG);
5059 	if (r == 0)
5060 	    ;
5061 	else if (r == command_pid)
5062 	    command_pid_is_dead++;
5063 	else if (r == -1)
5064 	    switch (errno)
5065 	    {
5066 		case ECHILD:
5067 		    command_pid_is_dead++;
5068 		    break;
5069 		case EINTR:
5070 		    goto do_waitpid;
5071 	    }
5072 	else
5073 	    /* waitpid should always return one of the above values */
5074 	    abort ();
5075 	while (!command_pid_is_dead)
5076 	{
5077 	    struct timeval timeout;
5078 	    struct fd_set_wrapper readfds;
5079 	    char buf[100];
5080 	    int i;
5081 
5082 	    /* Use a non-zero timeout to avoid eating up CPU cycles.  */
5083 	    timeout.tv_sec = 2;
5084 	    timeout.tv_usec = 0;
5085 	    readfds = command_fds_to_drain;
5086 	    switch (select (max_command_fd + 1, &readfds.fds,
5087 			    (fd_set *)0, (fd_set *)0,
5088 			    &timeout))
5089 	    {
5090 		case -1:
5091 		    if (errno != EINTR)
5092 			abort ();
5093 		case 0:
5094 		    /* timeout */
5095 		    break;
5096 		case 1:
5097 		    for (i = 0; i <= max_command_fd; i++)
5098 		    {
5099 			if (!FD_ISSET (i, &readfds.fds))
5100 			    continue;
5101 			/* this fd is non-blocking */
5102 			while (read (i, buf, sizeof (buf)) >= 1)
5103 			    ;
5104 		    }
5105 		    break;
5106 		default:
5107 		    abort ();
5108 	    }
5109 	}
5110     }
5111 #endif /* SUNOS_KLUDGE */
5112 
5113     CVS_CHDIR (Tmpdir);
5114     /* Temporarily clear noexec, so that we clean up our temp directory
5115        regardless of it (this could more cleanly be handled by moving
5116        the noexec check to all the unlink_file_dir callers from
5117        unlink_file_dir itself).  */
5118     save_noexec = noexec;
5119     noexec = 0;
5120     /* FIXME?  Would be nice to not ignore errors.  But what should we do?
5121        We could try to do this before we shut down the network connection,
5122        and try to notify the client (but the client might not be waiting
5123        for responses).  We could try something like syslog() or our own
5124        log file.  */
5125     unlink_file_dir (orig_server_temp_dir);
5126     noexec = save_noexec;
5127 
5128     if (buf_to_net != NULL)
5129 	(void) buf_shutdown (buf_to_net);
5130 }
5131 
5132 int server_active = 0;
5133 int server_expanding = 0;
5134 
5135 int
5136 server (argc, argv)
5137      int argc;
5138      char **argv;
5139 {
5140     if (argc == -1)
5141     {
5142 	static const char *const msg[] =
5143 	{
5144 	    "Usage: %s %s\n",
5145 	    "  Normally invoked by a cvs client on a remote machine.\n",
5146 	    NULL
5147 	};
5148 	usage (msg);
5149     }
5150     /* Ignore argc and argv.  They might be from .cvsrc.  */
5151 
5152     buf_to_net = fd_buffer_initialize (STDOUT_FILENO, 0,
5153 				       outbuf_memory_error);
5154     buf_from_net = stdio_buffer_initialize (stdin, 1, outbuf_memory_error);
5155 
5156     saved_output = buf_nonio_initialize (outbuf_memory_error);
5157     saved_outerr = buf_nonio_initialize (outbuf_memory_error);
5158 
5159     /* Since we're in the server parent process, error should use the
5160        protocol to report error messages.  */
5161     error_use_protocol = 1;
5162 
5163     /* OK, now figure out where we stash our temporary files.  */
5164     {
5165 	char *p;
5166 
5167 	/* The code which wants to chdir into server_temp_dir is not set
5168 	   up to deal with it being a relative path.  So give an error
5169 	   for that case.  */
5170 	if (!isabsolute (Tmpdir))
5171 	{
5172 	    if (alloc_pending (80 + strlen (Tmpdir)))
5173 		sprintf (pending_error_text,
5174 			 "E Value of %s for TMPDIR is not absolute", Tmpdir);
5175 
5176 	    /* FIXME: we would like this error to be persistent, that
5177 	       is, not cleared by print_pending_error.  The current client
5178 	       will exit as soon as it gets an error, but the protocol spec
5179 	       does not require a client to do so.  */
5180 	}
5181 	else
5182 	{
5183 	    int status;
5184 	    int i = 0;
5185 
5186 	    server_temp_dir = malloc (strlen (Tmpdir) + 80);
5187 	    if (server_temp_dir == NULL)
5188 	    {
5189 		/*
5190 		 * Strictly speaking, we're not supposed to output anything
5191 		 * now.  But we're about to exit(), give it a try.
5192 		 */
5193 		printf ("E Fatal server error, aborting.\n\
5194 error ENOMEM Virtual memory exhausted.\n");
5195 
5196 		/* I'm doing this manually rather than via error_exit ()
5197 		   because I'm not sure whether we want to call server_cleanup.
5198 		   Needs more investigation....  */
5199 
5200 #ifdef SYSTEM_CLEANUP
5201 		/* Hook for OS-specific behavior, for example socket
5202 		   subsystems on NT and OS2 or dealing with windows
5203 		   and arguments on Mac.  */
5204 		SYSTEM_CLEANUP ();
5205 #endif
5206 
5207 		exit (EXIT_FAILURE);
5208 	    }
5209 	    strcpy (server_temp_dir, Tmpdir);
5210 
5211 	    /* Remove a trailing slash from TMPDIR if present.  */
5212 	    p = server_temp_dir + strlen (server_temp_dir) - 1;
5213 	    if (*p == '/')
5214 		*p = '\0';
5215 
5216 	    /*
5217 	     * I wanted to use cvs-serv/PID, but then you have to worry about
5218 	     * the permissions on the cvs-serv directory being right.  So
5219 	     * use cvs-servPID.
5220 	     */
5221 	    strcat (server_temp_dir, "/cvs-serv");
5222 
5223 	    p = server_temp_dir + strlen (server_temp_dir);
5224 	    sprintf (p, "%ld", (long) getpid ());
5225 
5226 	    orig_server_temp_dir = server_temp_dir;
5227 
5228 	    /* Create the temporary directory, and set the mode to
5229                700, to discourage random people from tampering with
5230                it.  */
5231 	    while ((status = mkdir_p (server_temp_dir)) == EEXIST)
5232 	    {
5233 	        static const char suffix[] = "abcdefghijklmnopqrstuvwxyz";
5234 
5235 	        if (i >= sizeof suffix - 1) break;
5236 		if (i == 0) p = server_temp_dir + strlen (server_temp_dir);
5237 		p[0] = suffix[i++];
5238 		p[1] = '\0';
5239 	    }
5240 	    if (status != 0)
5241 	    {
5242 		if (alloc_pending (80 + strlen (server_temp_dir)))
5243 		    sprintf (pending_error_text,
5244 			    "E can't create temporary directory %s",
5245 			    server_temp_dir);
5246 		pending_error = status;
5247 	    }
5248 #ifndef CHMOD_BROKEN
5249 	    else if (chmod (server_temp_dir, S_IRWXU) < 0)
5250 	    {
5251 		int save_errno = errno;
5252 		if (alloc_pending (80 + strlen (server_temp_dir)))
5253 		    sprintf (pending_error_text,
5254 "E cannot change permissions on temporary directory %s",
5255 			     server_temp_dir);
5256 		pending_error = save_errno;
5257 	    }
5258 #endif
5259 	    else if (CVS_CHDIR (server_temp_dir) < 0)
5260 	    {
5261 		int save_errno = errno;
5262 		if (alloc_pending (80 + strlen (server_temp_dir)))
5263 		    sprintf (pending_error_text,
5264 "E cannot change to temporary directory %s",
5265 			     server_temp_dir);
5266 		pending_error = save_errno;
5267 	    }
5268 	}
5269     }
5270 
5271 #ifdef SIGABRT
5272     (void) SIG_register (SIGABRT, server_cleanup);
5273 #endif
5274 #ifdef SIGHUP
5275     (void) SIG_register (SIGHUP, server_cleanup);
5276 #endif
5277 #ifdef SIGINT
5278     (void) SIG_register (SIGINT, server_cleanup);
5279 #endif
5280 #ifdef SIGQUIT
5281     (void) SIG_register (SIGQUIT, server_cleanup);
5282 #endif
5283 #ifdef SIGPIPE
5284     (void) SIG_register (SIGPIPE, server_cleanup);
5285 #endif
5286 #ifdef SIGTERM
5287     (void) SIG_register (SIGTERM, server_cleanup);
5288 #endif
5289 
5290     /* Now initialize our argument vector (for arguments from the client).  */
5291 
5292     /* Small for testing.  */
5293     argument_vector_size = 1;
5294     argument_vector =
5295 	(char **) malloc (argument_vector_size * sizeof (char *));
5296     if (argument_vector == NULL)
5297     {
5298 	/*
5299 	 * Strictly speaking, we're not supposed to output anything
5300 	 * now.  But we're about to exit(), give it a try.
5301 	 */
5302 	printf ("E Fatal server error, aborting.\n\
5303 error ENOMEM Virtual memory exhausted.\n");
5304 
5305 	/* I'm doing this manually rather than via error_exit ()
5306 	   because I'm not sure whether we want to call server_cleanup.
5307 	   Needs more investigation....  */
5308 
5309 #ifdef SYSTEM_CLEANUP
5310 	/* Hook for OS-specific behavior, for example socket subsystems on
5311 	   NT and OS2 or dealing with windows and arguments on Mac.  */
5312 	SYSTEM_CLEANUP ();
5313 #endif
5314 
5315 	exit (EXIT_FAILURE);
5316     }
5317 
5318     argument_count = 1;
5319     /* This gets printed if the client supports an option which the
5320        server doesn't, causing the server to print a usage message.
5321        FIXME: probably should be using program_name here.
5322        FIXME: just a nit, I suppose, but the usage message the server
5323        prints isn't literally true--it suggests "cvs server" followed
5324        by options which are for a particular command.  Might be nice to
5325        say something like "client apparently supports an option not supported
5326        by this server" or something like that instead of usage message.  */
5327     argument_vector[0] = "cvs server";
5328 
5329     while (1)
5330     {
5331 	char *cmd, *orig_cmd;
5332 	struct request *rq;
5333 	int status;
5334 
5335 	status = buf_read_line (buf_from_net, &cmd, (int *) NULL);
5336 	if (status == -2)
5337 	{
5338 	    buf_output0 (buf_to_net, "E Fatal server error, aborting.\n\
5339 error ENOMEM Virtual memory exhausted.\n");
5340 	    break;
5341 	}
5342 	if (status != 0)
5343 	    break;
5344 
5345 	orig_cmd = cmd;
5346 	for (rq = requests; rq->name != NULL; ++rq)
5347 	    if (strncmp (cmd, rq->name, strlen (rq->name)) == 0)
5348 	    {
5349 		int len = strlen (rq->name);
5350 		if (cmd[len] == '\0')
5351 		    cmd += len;
5352 		else if (cmd[len] == ' ')
5353 		    cmd += len + 1;
5354 		else
5355 		    /*
5356 		     * The first len characters match, but it's a different
5357 		     * command.  e.g. the command is "cooperate" but we matched
5358 		     * "co".
5359 		     */
5360 		    continue;
5361 
5362 		if (!(rq->flags & RQ_ROOTLESS)
5363 		    && current_parsed_root == NULL)
5364 		{
5365 		    /* For commands which change the way in which data
5366 		       is sent and received, for example Gzip-stream,
5367 		       this does the wrong thing.  Since the client
5368 		       assumes that everything is being compressed,
5369 		       unconditionally, there is no way to give this
5370 		       error to the client without turning on
5371 		       compression.  The obvious fix would be to make
5372 		       Gzip-stream RQ_ROOTLESS (with the corresponding
5373 		       change to the spec), and that might be a good
5374 		       idea but then again I can see some settings in
5375 		       CVSROOT about what compression level to allow.
5376 		       I suppose a more baroque answer would be to
5377 		       turn on compression (say, at level 1), just
5378 		       enough to give the "Root request missing"
5379 		       error.  For now we just lose.  */
5380 		    if (alloc_pending (80))
5381 			sprintf (pending_error_text,
5382 				 "E Protocol error: Root request missing");
5383 		}
5384 		else
5385 		    (*rq->func) (cmd);
5386 		break;
5387 	    }
5388 	if (rq->name == NULL)
5389 	{
5390 	    if (!print_pending_error ())
5391 	    {
5392 	        buf_output0 (buf_to_net, "error  unrecognized request `");
5393 		buf_output0 (buf_to_net, cmd);
5394 		buf_append_char (buf_to_net, '\'');
5395 		buf_append_char (buf_to_net, '\n');
5396 	    }
5397 	}
5398 	free (orig_cmd);
5399     }
5400     server_cleanup (0);
5401     return 0;
5402 }
5403 
5404 
5405 #if defined (HAVE_KERBEROS) || defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
5406 static void switch_to_user PROTO((const char *));
5407 
5408 static void
5409 switch_to_user (username)
5410     const char *username;
5411 {
5412     struct passwd *pw;
5413 
5414     pw = getpwnam (username);
5415     if (pw == NULL)
5416     {
5417 	/* Normally this won't be reached; check_password contains
5418 	   a similar check.  */
5419 
5420 	printf ("E Fatal error, aborting.\n\
5421 error 0 %s: no such user\n", username);
5422 	/* Don't worry about server_cleanup; server_active isn't set yet.  */
5423 	error_exit ();
5424     }
5425 
5426 #if HAVE_INITGROUPS
5427     if (initgroups (pw->pw_name, pw->pw_gid) < 0
5428 #  ifdef EPERM
5429 	/* At least on the system I tried, initgroups() only works as root.
5430 	   But we do still want to report ENOMEM and whatever other
5431 	   errors initgroups() might dish up.  */
5432 	&& errno != EPERM
5433 #  endif
5434 	)
5435     {
5436 	/* This could be a warning, but I'm not sure I see the point
5437 	   in doing that instead of an error given that it would happen
5438 	   on every connection.  We could log it somewhere and not tell
5439 	   the user.  But at least for now make it an error.  */
5440 	printf ("error 0 initgroups failed: %s\n", strerror (errno));
5441 	/* Don't worry about server_cleanup; server_active isn't set yet.  */
5442 	error_exit ();
5443     }
5444 #endif /* HAVE_INITGROUPS */
5445 
5446 #ifdef SETXID_SUPPORT
5447     /* honor the setgid bit iff set*/
5448     if (getgid() != getegid())
5449     {
5450 	if (setgid (getegid ()) < 0)
5451 	{
5452 	    /* See comments at setuid call below for more discussion.  */
5453 	    printf ("error 0 setgid failed: %s\n", strerror (errno));
5454 	    /* Don't worry about server_cleanup;
5455 	       server_active isn't set yet.  */
5456 	    error_exit ();
5457 	}
5458     }
5459     else
5460 #endif
5461     {
5462 	if (setgid (pw->pw_gid) < 0)
5463 	{
5464 	    /* See comments at setuid call below for more discussion.  */
5465 	    printf ("error 0 setgid failed: %s\n", strerror (errno));
5466 	    /* Don't worry about server_cleanup;
5467 	       server_active isn't set yet.  */
5468 	    error_exit ();
5469 	}
5470     }
5471 
5472     if (setuid (pw->pw_uid) < 0)
5473     {
5474 	/* Note that this means that if run as a non-root user,
5475 	   CVSROOT/passwd must contain the user we are running as
5476 	   (e.g. "joe:FsEfVcu:cvs" if run as "cvs" user).  This seems
5477 	   cleaner than ignoring the error like CVS 1.10 and older but
5478 	   it does mean that some people might need to update their
5479 	   CVSROOT/passwd file.  */
5480 	printf ("error 0 setuid failed: %s\n", strerror (errno));
5481 	/* Don't worry about server_cleanup; server_active isn't set yet.  */
5482 	error_exit ();
5483     }
5484 
5485     /* We don't want our umask to change file modes.  The modes should
5486        be set by the modes used in the repository, and by the umask of
5487        the client.  */
5488     umask (0);
5489 
5490 #ifdef AUTH_SERVER_SUPPORT
5491     /* Make sure our CVS_Username has been set. */
5492     if (CVS_Username == NULL)
5493 	CVS_Username = xstrdup (username);
5494 #endif
5495 
5496 #if HAVE_PUTENV
5497     /* Set LOGNAME, USER and CVS_USER in the environment, in case they
5498        are already set to something else.  */
5499     {
5500 	char *env;
5501 #ifdef AUTH_SERVER_SUPPORT
5502 	char *cvs_user;
5503 #endif
5504 
5505 	env = xmalloc (sizeof "LOGNAME=" + strlen (username));
5506 	(void) sprintf (env, "LOGNAME=%s", username);
5507 	(void) putenv (env);
5508 
5509 	env = xmalloc (sizeof "USER=" + strlen (username));
5510 	(void) sprintf (env, "USER=%s", username);
5511 	(void) putenv (env);
5512 
5513 #ifdef AUTH_SERVER_SUPPORT
5514         cvs_user = NULL != CVS_Username ? CVS_Username : "";
5515         env = xmalloc (sizeof "CVS_USER=" + strlen (cvs_user));
5516         (void) sprintf (env, "CVS_USER=%s", cvs_user);
5517         (void) putenv (env);
5518 #endif
5519     }
5520 #endif /* HAVE_PUTENV */
5521 }
5522 #endif
5523 
5524 #ifdef AUTH_SERVER_SUPPORT
5525 
5526 extern char *crypt PROTO((const char *, const char *));
5527 
5528 
5529 /*
5530  * 0 means no entry found for this user.
5531  * 1 means entry found and password matches (or found password is empty)
5532  * 2 means entry found, but password does not match.
5533  *
5534  * If 1, host_user_ptr will be set to point at the system
5535  * username (i.e., the "real" identity, which may or may not be the
5536  * CVS username) of this user; caller may free this.  Global
5537  * CVS_Username will point at an allocated copy of cvs username (i.e.,
5538  * the username argument below).
5539  * kff todo: FIXME: last sentence is not true, it applies to caller.
5540  */
5541 static int
5542 check_repository_password (username, password, repository, host_user_ptr)
5543      char *username, *password, *repository, **host_user_ptr;
5544 {
5545     int retval = 0;
5546     FILE *fp;
5547     char *filename;
5548     char *linebuf = NULL;
5549     size_t linebuf_len;
5550     int found_it = 0;
5551     int namelen;
5552 
5553     /* We don't use current_parsed_root->directory because it hasn't been set yet
5554      * -- our `repository' argument came from the authentication
5555      * protocol, not the regular CVS protocol.
5556      */
5557 
5558     filename = xmalloc (strlen (repository)
5559 			+ 1
5560 			+ strlen (CVSROOTADM)
5561 			+ 1
5562 			+ strlen (CVSROOTADM_PASSWD)
5563 			+ 1);
5564 
5565     (void) sprintf (filename, "%s/%s/%s", repository,
5566                     CVSROOTADM, CVSROOTADM_PASSWD);
5567 
5568     fp = CVS_FOPEN (filename, "r");
5569     if (fp == NULL)
5570     {
5571 	if (!existence_error (errno))
5572 	    error (0, errno, "cannot open %s", filename);
5573 	return 0;
5574     }
5575 
5576     /* Look for a relevant line -- one with this user's name. */
5577     namelen = strlen (username);
5578     while (getline (&linebuf, &linebuf_len, fp) >= 0)
5579     {
5580 	if ((strncmp (linebuf, username, namelen) == 0)
5581 	    && (linebuf[namelen] == ':'))
5582         {
5583 	    found_it = 1;
5584 	    break;
5585         }
5586     }
5587     if (ferror (fp))
5588 	error (0, errno, "cannot read %s", filename);
5589     if (fclose (fp) < 0)
5590 	error (0, errno, "cannot close %s", filename);
5591 
5592     /* If found_it, then linebuf contains the information we need. */
5593     if (found_it)
5594     {
5595 	char *found_password, *host_user_tmp;
5596         char *non_cvsuser_portion;
5597 
5598         /* We need to make sure lines such as
5599          *
5600          *    "username::sysuser\n"
5601          *    "username:\n"
5602          *    "username:  \n"
5603          *
5604          * all result in a found_password of NULL, but we also need to
5605          * make sure that
5606          *
5607          *    "username:   :sysuser\n"
5608          *    "username: <whatever>:sysuser\n"
5609          *
5610          * continues to result in an impossible password.  That way,
5611          * an admin would be on safe ground by going in and tacking a
5612          * space onto the front of a password to disable the account
5613          * (a technique some people use to close accounts
5614          * temporarily).
5615          */
5616 
5617         /* Make `non_cvsuser_portion' contain everything after the CVS
5618            username, but null out any final newline. */
5619 	non_cvsuser_portion = linebuf + namelen;
5620         strtok (non_cvsuser_portion, "\n");
5621 
5622         /* If there's a colon now, we just want to inch past it. */
5623         if (strchr (non_cvsuser_portion, ':') == non_cvsuser_portion)
5624             non_cvsuser_portion++;
5625 
5626         /* Okay, after this conditional chain, found_password and
5627            host_user_tmp will have useful values: */
5628 
5629         if ((non_cvsuser_portion == NULL)
5630             || (strlen (non_cvsuser_portion) == 0)
5631             || ((strspn (non_cvsuser_portion, " \t"))
5632                 == strlen (non_cvsuser_portion)))
5633         {
5634             found_password = NULL;
5635             host_user_tmp = NULL;
5636         }
5637         else if (strncmp (non_cvsuser_portion, ":", 1) == 0)
5638         {
5639             found_password = NULL;
5640             host_user_tmp = non_cvsuser_portion + 1;
5641             if (strlen (host_user_tmp) == 0)
5642                 host_user_tmp = NULL;
5643         }
5644         else
5645         {
5646             found_password = strtok (non_cvsuser_portion, ":");
5647             host_user_tmp = strtok (NULL, ":");
5648         }
5649 
5650         /* Of course, maybe there was no system user portion... */
5651 	if (host_user_tmp == NULL)
5652             host_user_tmp = username;
5653 
5654         /* Verify blank passwords directly, otherwise use crypt(). */
5655         if ((found_password == NULL)
5656             || ((strcmp (found_password, crypt (password, found_password))
5657                  == 0)))
5658         {
5659             /* Give host_user_ptr permanent storage. */
5660             *host_user_ptr = xstrdup (host_user_tmp);
5661 	    retval = 1;
5662         }
5663 	else
5664         {
5665             *host_user_ptr = NULL;
5666 	    retval         = 2;
5667         }
5668     }
5669     else     /* Didn't find this user, so deny access. */
5670     {
5671 	*host_user_ptr = NULL;
5672 	retval = 0;
5673     }
5674 
5675     free (filename);
5676     if (linebuf)
5677         free (linebuf);
5678 
5679     return retval;
5680 }
5681 
5682 
5683 /* Return a hosting username if password matches, else NULL. */
5684 static char *
5685 check_password (username, password, repository)
5686     char *username, *password, *repository;
5687 {
5688     int rc;
5689     char *host_user = NULL;
5690 
5691     /* First we see if this user has a password in the CVS-specific
5692        password file.  If so, that's enough to authenticate with.  If
5693        not, we'll check /etc/passwd. */
5694 
5695     rc = check_repository_password (username, password, repository,
5696 				    &host_user);
5697 
5698     if (rc == 2)
5699 	return NULL;
5700 
5701     /* else */
5702 
5703     if (rc == 1)
5704     {
5705         /* host_user already set by reference, so just return. */
5706         goto handle_return;
5707     }
5708     else if (rc == 0 && system_auth)
5709     {
5710 	/* No cvs password found, so try /etc/passwd. */
5711 
5712 	const char *found_passwd = NULL;
5713 	struct passwd *pw;
5714 #ifdef HAVE_GETSPNAM
5715 	struct spwd *spw;
5716 
5717 	spw = getspnam (username);
5718 	if (spw != NULL)
5719 	{
5720 	    found_passwd = spw->sp_pwdp;
5721 	}
5722 #endif
5723 
5724 	if (found_passwd == NULL && (pw = getpwnam (username)) != NULL)
5725 	{
5726 	    found_passwd = pw->pw_passwd;
5727 	}
5728 
5729 	if (found_passwd == NULL)
5730 	{
5731 	    printf ("E Fatal error, aborting.\n\
5732 error 0 %s: no such user\n", username);
5733 
5734 	    /* I'm doing this manually rather than via error_exit ()
5735 	       because I'm not sure whether we want to call server_cleanup.
5736 	       Needs more investigation....  */
5737 
5738 #ifdef SYSTEM_CLEANUP
5739 	    /* Hook for OS-specific behavior, for example socket subsystems on
5740 	       NT and OS2 or dealing with windows and arguments on Mac.  */
5741 	    SYSTEM_CLEANUP ();
5742 #endif
5743 
5744 	    exit (EXIT_FAILURE);
5745 	}
5746 
5747 	if (*found_passwd)
5748         {
5749 	    /* user exists and has a password */
5750 	    host_user = ((! strcmp (found_passwd,
5751                                     crypt (password, found_passwd)))
5752                          ? xstrdup (username) : NULL);
5753             goto handle_return;
5754         }
5755 	else if (password && *password)
5756         {
5757 	    /* user exists and has no system password, but we got
5758 	       one as parameter */
5759 	    host_user = xstrdup (username);
5760             goto handle_return;
5761         }
5762 	else
5763         {
5764 	    /* user exists but has no password at all */
5765 	    host_user = NULL;
5766             goto handle_return;
5767         }
5768     }
5769     else if (rc == 0)
5770     {
5771 	/* Note that the message _does_ distinguish between the case in
5772 	   which we check for a system password and the case in which
5773 	   we do not.  It is a real pain to track down why it isn't
5774 	   letting you in if it won't say why, and I am not convinced
5775 	   that the potential information disclosure to an attacker
5776 	   outweighs this.  */
5777 	printf ("error 0 no such user %s in CVSROOT/passwd\n", username);
5778 
5779 	/* I'm doing this manually rather than via error_exit ()
5780 	   because I'm not sure whether we want to call server_cleanup.
5781 	   Needs more investigation....  */
5782 
5783 #ifdef SYSTEM_CLEANUP
5784 	/* Hook for OS-specific behavior, for example socket subsystems on
5785 	   NT and OS2 or dealing with windows and arguments on Mac.  */
5786 	SYSTEM_CLEANUP ();
5787 #endif
5788 	exit (EXIT_FAILURE);
5789     }
5790     else
5791     {
5792 	/* Something strange happened.  We don't know what it was, but
5793 	   we certainly won't grant authorization. */
5794 	host_user = NULL;
5795         goto handle_return;
5796     }
5797 
5798 handle_return:
5799     if (host_user)
5800     {
5801         /* Set CVS_Username here, in allocated space.
5802            It might or might not be the same as host_user. */
5803         CVS_Username = xmalloc (strlen (username) + 1);
5804         strcpy (CVS_Username, username);
5805     }
5806 
5807     return host_user;
5808 }
5809 
5810 #endif /* AUTH_SERVER_SUPPORT */
5811 
5812 #if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
5813 
5814 /* Read username and password from client (i.e., stdin).
5815    If correct, then switch to run as that user and send an ACK to the
5816    client via stdout, else send NACK and die. */
5817 void
5818 pserver_authenticate_connection ()
5819 {
5820     char *tmp = NULL;
5821     size_t tmp_allocated = 0;
5822 #ifdef AUTH_SERVER_SUPPORT
5823     char *repository = NULL;
5824     size_t repository_allocated = 0;
5825     char *username = NULL;
5826     size_t username_allocated = 0;
5827     char *password = NULL;
5828     size_t password_allocated = 0;
5829 
5830     char *host_user;
5831     char *descrambled_password;
5832 #endif /* AUTH_SERVER_SUPPORT */
5833     int verify_and_exit = 0;
5834 
5835     /* The Authentication Protocol.  Client sends:
5836      *
5837      *   BEGIN AUTH REQUEST\n
5838      *   <REPOSITORY>\n
5839      *   <USERNAME>\n
5840      *   <PASSWORD>\n
5841      *   END AUTH REQUEST\n
5842      *
5843      * Server uses above information to authenticate, then sends
5844      *
5845      *   I LOVE YOU\n
5846      *
5847      * if it grants access, else
5848      *
5849      *   I HATE YOU\n
5850      *
5851      * if it denies access (and it exits if denying).
5852      *
5853      * When the client is "cvs login", the user does not desire actual
5854      * repository access, but would like to confirm the password with
5855      * the server.  In this case, the start and stop strings are
5856      *
5857      *   BEGIN VERIFICATION REQUEST\n
5858      *
5859      *            and
5860      *
5861      *   END VERIFICATION REQUEST\n
5862      *
5863      * On a verification request, the server's responses are the same
5864      * (with the obvious semantics), but it exits immediately after
5865      * sending the response in both cases.
5866      *
5867      * Why is the repository sent?  Well, note that the actual
5868      * client/server protocol can't start up until authentication is
5869      * successful.  But in order to perform authentication, the server
5870      * needs to look up the password in the special CVS passwd file,
5871      * before trying /etc/passwd.  So the client transmits the
5872      * repository as part of the "authentication protocol".  The
5873      * repository will be redundantly retransmitted later, but that's no
5874      * big deal.
5875      */
5876 
5877 #ifdef SO_KEEPALIVE
5878     /* Set SO_KEEPALIVE on the socket, so that we don't hang forever
5879        if the client dies while we are waiting for input.  */
5880     {
5881 	int on = 1;
5882 
5883 	if (setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
5884 			   (char *) &on, sizeof on) < 0)
5885 	{
5886 #ifdef HAVE_SYSLOG_H
5887 	    syslog (LOG_DAEMON | LOG_ERR, "error setting KEEPALIVE: %m");
5888 #endif
5889 	}
5890     }
5891 #endif
5892 
5893     /* Make sure the protocol starts off on the right foot... */
5894     if (getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX) < 0)
5895 	/* FIXME: what?  We could try writing error/eof, but chances
5896 	   are the network connection is dead bidirectionally.  log it
5897 	   somewhere?  */
5898 	;
5899 
5900     if (strcmp (tmp, "BEGIN VERIFICATION REQUEST\n") == 0)
5901 	verify_and_exit = 1;
5902     else if (strcmp (tmp, "BEGIN AUTH REQUEST\n") == 0)
5903 	;
5904     else if (strcmp (tmp, "BEGIN GSSAPI REQUEST\n") == 0)
5905     {
5906 #ifdef HAVE_GSSAPI
5907 	free (tmp);
5908 	gserver_authenticate_connection ();
5909 	return;
5910 #else
5911 	error (1, 0, "GSSAPI authentication not supported by this server");
5912 #endif
5913     }
5914     else
5915 	error (1, 0, "bad auth protocol start: %s", tmp);
5916 
5917 #ifndef AUTH_SERVER_SUPPORT
5918 
5919     error (1, 0, "Password authentication not supported by this server");
5920 
5921 #else /* AUTH_SERVER_SUPPORT */
5922 
5923     /* Get the three important pieces of information in order. */
5924     /* See above comment about error handling.  */
5925     getline_safe (&repository, &repository_allocated, stdin, PATH_MAX);
5926     getline_safe (&username, &username_allocated, stdin, PATH_MAX);
5927     getline_safe (&password, &password_allocated, stdin, PATH_MAX);
5928 
5929     /* Make them pure. */
5930     strip_trailing_newlines (repository);
5931     strip_trailing_newlines (username);
5932     strip_trailing_newlines (password);
5933 
5934     /* ... and make sure the protocol ends on the right foot. */
5935     /* See above comment about error handling.  */
5936     getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX);
5937     if (strcmp (tmp,
5938 		verify_and_exit ?
5939 		"END VERIFICATION REQUEST\n" : "END AUTH REQUEST\n")
5940 	!= 0)
5941     {
5942 	error (1, 0, "bad auth protocol end: %s", tmp);
5943     }
5944     if (!root_allow_ok (repository))
5945     {
5946 	printf ("error 0 %s: no such repository\n", repository);
5947 #ifdef HAVE_SYSLOG_H
5948 	syslog (LOG_DAEMON | LOG_NOTICE, "login refused for %s", repository);
5949 #endif
5950 	goto i_hate_you;
5951     }
5952 
5953     /* OK, now parse the config file, so we can use it to control how
5954        to check passwords.  If there was an error parsing the config
5955        file, parse_config already printed an error.  We keep going.
5956        Why?  Because if we didn't, then there would be no way to check
5957        in a new CVSROOT/config file to fix the broken one!  */
5958     parse_config (repository);
5959 
5960     /* We need the real cleartext before we hash it. */
5961     descrambled_password = descramble (password);
5962     host_user = check_password (username, descrambled_password, repository);
5963     memset (descrambled_password, 0, strlen (descrambled_password));
5964     free (descrambled_password);
5965     if (host_user == NULL)
5966     {
5967 #ifdef HAVE_SYSLOG_H
5968 	syslog (LOG_DAEMON | LOG_NOTICE, "login failure (for %s)", repository);
5969 #ifdef LOG_AUTHPRIV
5970         syslog (LOG_AUTHPRIV | LOG_NOTICE, "login failure by %s / %s (for %s)",
5971         	username, descrambled_password, repository);
5972 #endif
5973 #endif
5974     i_hate_you:
5975 	printf ("I HATE YOU\n");
5976 	fflush (stdout);
5977 
5978 	/* Don't worry about server_cleanup, server_active isn't set
5979 	   yet.  */
5980 	error_exit ();
5981     }
5982 
5983     /* Don't go any farther if we're just responding to "cvs login". */
5984     if (verify_and_exit)
5985     {
5986 	printf ("I LOVE YOU\n");
5987 	fflush (stdout);
5988 
5989 #ifdef SYSTEM_CLEANUP
5990 	/* Hook for OS-specific behavior, for example socket subsystems on
5991 	   NT and OS2 or dealing with windows and arguments on Mac.  */
5992 	SYSTEM_CLEANUP ();
5993 #endif
5994 
5995 	exit (0);
5996     }
5997 
5998     /* Set Pserver_Repos so that we can check later that the same
5999        repository is sent in later client/server protocol. */
6000     Pserver_Repos = xmalloc (strlen (repository) + 1);
6001     strcpy (Pserver_Repos, repository);
6002 
6003     /* Switch to run as this user. */
6004     switch_to_user (host_user);
6005     free (host_user);
6006     free (tmp);
6007     free (repository);
6008     free (username);
6009     free (password);
6010 
6011     printf ("I LOVE YOU\n");
6012     fflush (stdout);
6013 #endif /* AUTH_SERVER_SUPPORT */
6014 }
6015 
6016 #endif /* AUTH_SERVER_SUPPORT || HAVE_GSSAPI */
6017 
6018 
6019 #ifdef HAVE_KERBEROS
6020 void
6021 kserver_authenticate_connection ()
6022 {
6023     int status;
6024     char instance[INST_SZ];
6025     struct sockaddr_in peer;
6026     struct sockaddr_in laddr;
6027     int len;
6028     KTEXT_ST ticket;
6029     AUTH_DAT auth;
6030     char version[KRB_SENDAUTH_VLEN];
6031     char user[ANAME_SZ];
6032 
6033     strcpy (instance, "*");
6034     len = sizeof peer;
6035     if (getpeername (STDIN_FILENO, (struct sockaddr *) &peer, &len) < 0
6036 	|| getsockname (STDIN_FILENO, (struct sockaddr *) &laddr,
6037 			&len) < 0)
6038     {
6039 	printf ("E Fatal error, aborting.\n\
6040 error %s getpeername or getsockname failed\n", strerror (errno));
6041 #ifdef SYSTEM_CLEANUP
6042 	/* Hook for OS-specific behavior, for example socket subsystems on
6043 	   NT and OS2 or dealing with windows and arguments on Mac.  */
6044 	SYSTEM_CLEANUP ();
6045 #endif
6046 	exit (EXIT_FAILURE);
6047     }
6048 
6049 #ifdef SO_KEEPALIVE
6050     /* Set SO_KEEPALIVE on the socket, so that we don't hang forever
6051        if the client dies while we are waiting for input.  */
6052     {
6053 	int on = 1;
6054 
6055 	if (setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
6056 			   (char *) &on, sizeof on) < 0)
6057 	{
6058 #ifdef HAVE_SYSLOG_H
6059 	    syslog (LOG_DAEMON | LOG_ERR, "error setting KEEPALIVE: %m");
6060 #endif
6061 	}
6062     }
6063 #endif
6064 
6065     status = krb_recvauth (KOPT_DO_MUTUAL, STDIN_FILENO, &ticket, "rcmd",
6066 			   instance, &peer, &laddr, &auth, "", sched,
6067 			   version);
6068     if (status != KSUCCESS)
6069     {
6070 	printf ("E Fatal error, aborting.\n\
6071 error 0 kerberos: %s\n", krb_get_err_text(status));
6072 #ifdef SYSTEM_CLEANUP
6073 	/* Hook for OS-specific behavior, for example socket subsystems on
6074 	   NT and OS2 or dealing with windows and arguments on Mac.  */
6075 	SYSTEM_CLEANUP ();
6076 #endif
6077 	exit (EXIT_FAILURE);
6078     }
6079 
6080     memcpy (kblock, auth.session, sizeof (C_Block));
6081 
6082     /* Get the local name.  */
6083     status = krb_kntoln (&auth, user);
6084     if (status != KSUCCESS)
6085     {
6086 	printf ("E Fatal error, aborting.\n\
6087 error 0 kerberos: can't get local name: %s\n", krb_get_err_text(status));
6088 #ifdef SYSTEM_CLEANUP
6089 	/* Hook for OS-specific behavior, for example socket subsystems on
6090 	   NT and OS2 or dealing with windows and arguments on Mac.  */
6091 	SYSTEM_CLEANUP ();
6092 #endif
6093 	exit (EXIT_FAILURE);
6094     }
6095 
6096     /* Switch to run as this user. */
6097     switch_to_user (user);
6098 }
6099 #endif /* HAVE_KERBEROS */
6100 
6101 #ifdef HAVE_GSSAPI
6102 
6103 #ifndef MAXHOSTNAMELEN
6104 #define MAXHOSTNAMELEN (256)
6105 #endif
6106 
6107 /* Authenticate a GSSAPI connection.  This is called from
6108    pserver_authenticate_connection, and it handles success and failure
6109    the same way.  */
6110 
6111 static void
6112 gserver_authenticate_connection ()
6113 {
6114     char hostname[MAXHOSTNAMELEN];
6115     struct hostent *hp;
6116     gss_buffer_desc tok_in, tok_out;
6117     char buf[1024];
6118     OM_uint32 stat_min, ret;
6119     gss_name_t server_name, client_name;
6120     gss_cred_id_t server_creds;
6121     int nbytes;
6122     gss_OID mechid;
6123 
6124     gethostname (hostname, sizeof hostname);
6125     hp = gethostbyname (hostname);
6126     if (hp == NULL)
6127 	error (1, 0, "can't get canonical hostname");
6128 
6129     sprintf (buf, "cvs@%s", hp->h_name);
6130     tok_in.value = buf;
6131     tok_in.length = strlen (buf);
6132 
6133     if (gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE,
6134 			 &server_name) != GSS_S_COMPLETE)
6135 	error (1, 0, "could not import GSSAPI service name %s", buf);
6136 
6137     /* Acquire the server credential to verify the client's
6138        authentication.  */
6139     if (gss_acquire_cred (&stat_min, server_name, 0, GSS_C_NULL_OID_SET,
6140 			  GSS_C_ACCEPT, &server_creds,
6141 			  NULL, NULL) != GSS_S_COMPLETE)
6142 	error (1, 0, "could not acquire GSSAPI server credentials");
6143 
6144     gss_release_name (&stat_min, &server_name);
6145 
6146     /* The client will send us a two byte length followed by that many
6147        bytes.  */
6148     if (fread (buf, 1, 2, stdin) != 2)
6149 	error (1, errno, "read of length failed");
6150 
6151     nbytes = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
6152     assert (nbytes <= sizeof buf);
6153 
6154     if (fread (buf, 1, nbytes, stdin) != nbytes)
6155 	error (1, errno, "read of data failed");
6156 
6157     gcontext = GSS_C_NO_CONTEXT;
6158     tok_in.length = nbytes;
6159     tok_in.value = buf;
6160 
6161     if (gss_accept_sec_context (&stat_min,
6162                                 &gcontext,	/* context_handle */
6163                                 server_creds,	/* verifier_cred_handle */
6164                                 &tok_in,	/* input_token */
6165                                 NULL,		/* channel bindings */
6166                                 &client_name,	/* src_name */
6167                                 &mechid,	/* mech_type */
6168                                 &tok_out,	/* output_token */
6169                                 &ret,
6170                                 NULL,	 	/* ignore time_rec */
6171                                 NULL)		/* ignore del_cred_handle */
6172 	!= GSS_S_COMPLETE)
6173     {
6174 	error (1, 0, "could not verify credentials");
6175     }
6176 
6177     /* FIXME: Use Kerberos v5 specific code to authenticate to a user.
6178        We could instead use an authentication to access mapping.  */
6179     {
6180 	krb5_context kc;
6181 	krb5_principal p;
6182 	gss_buffer_desc desc;
6183 
6184 	krb5_init_context (&kc);
6185 	if (gss_display_name (&stat_min, client_name, &desc,
6186 			      &mechid) != GSS_S_COMPLETE
6187 	    || krb5_parse_name (kc, ((gss_buffer_t) &desc)->value, &p) != 0
6188 	    || krb5_aname_to_localname (kc, p, sizeof buf, buf) != 0
6189 	    || krb5_kuserok (kc, p, buf) != TRUE)
6190 	{
6191 	    error (1, 0, "access denied");
6192 	}
6193 	krb5_free_principal (kc, p);
6194 	krb5_free_context (kc);
6195     }
6196 
6197     if (tok_out.length != 0)
6198     {
6199 	char cbuf[2];
6200 
6201 	cbuf[0] = (tok_out.length >> 8) & 0xff;
6202 	cbuf[1] = tok_out.length & 0xff;
6203 	if (fwrite (cbuf, 1, 2, stdout) != 2
6204 	    || (fwrite (tok_out.value, 1, tok_out.length, stdout)
6205 		!= tok_out.length))
6206 	    error (1, errno, "fwrite failed");
6207     }
6208 
6209     switch_to_user (buf);
6210 
6211     printf ("I LOVE YOU\n");
6212     fflush (stdout);
6213 }
6214 
6215 #endif /* HAVE_GSSAPI */
6216 
6217 #endif /* SERVER_SUPPORT */
6218 
6219 #if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
6220 
6221 /* This global variable is non-zero if the user requests encryption on
6222    the command line.  */
6223 int cvsencrypt;
6224 
6225 /* This global variable is non-zero if the users requests stream
6226    authentication on the command line.  */
6227 int cvsauthenticate;
6228 
6229 #ifdef HAVE_GSSAPI
6230 
6231 /* An buffer interface using GSSAPI.  This is built on top of a
6232    packetizing buffer.  */
6233 
6234 /* This structure is the closure field of the GSSAPI translation
6235    routines.  */
6236 
6237 struct cvs_gssapi_wrap_data
6238 {
6239     /* The GSSAPI context.  */
6240     gss_ctx_id_t gcontext;
6241 };
6242 
6243 static int cvs_gssapi_wrap_input PROTO((void *, const char *, char *, int));
6244 static int cvs_gssapi_wrap_output PROTO((void *, const char *, char *, int,
6245 					 int *));
6246 
6247 /* Create a GSSAPI wrapping buffer.  We use a packetizing buffer with
6248    GSSAPI wrapping routines.  */
6249 
6250 struct buffer *
6251 cvs_gssapi_wrap_buffer_initialize (buf, input, gcontext, memory)
6252      struct buffer *buf;
6253      int input;
6254      gss_ctx_id_t gcontext;
6255      void (*memory) PROTO((struct buffer *));
6256 {
6257     struct cvs_gssapi_wrap_data *gd;
6258 
6259     gd = (struct cvs_gssapi_wrap_data *) xmalloc (sizeof *gd);
6260     gd->gcontext = gcontext;
6261 
6262     return (packetizing_buffer_initialize
6263 	    (buf,
6264 	     input ? cvs_gssapi_wrap_input : NULL,
6265 	     input ? NULL : cvs_gssapi_wrap_output,
6266 	     gd,
6267 	     memory));
6268 }
6269 
6270 /* Unwrap data using GSSAPI.  */
6271 
6272 static int
6273 cvs_gssapi_wrap_input (fnclosure, input, output, size)
6274      void *fnclosure;
6275      const char *input;
6276      char *output;
6277      int size;
6278 {
6279     struct cvs_gssapi_wrap_data *gd =
6280 	(struct cvs_gssapi_wrap_data *) fnclosure;
6281     gss_buffer_desc inbuf, outbuf;
6282     OM_uint32 stat_min;
6283     int conf;
6284 
6285     inbuf.value = (void *) input;
6286     inbuf.length = size;
6287 
6288     if (gss_unwrap (&stat_min, gd->gcontext, &inbuf, &outbuf, &conf, NULL)
6289 	!= GSS_S_COMPLETE)
6290     {
6291 	error (1, 0, "gss_unwrap failed");
6292     }
6293 
6294     if (outbuf.length > size)
6295 	abort ();
6296 
6297     memcpy (output, outbuf.value, outbuf.length);
6298 
6299     /* The real packet size is stored in the data, so we don't need to
6300        remember outbuf.length.  */
6301 
6302     gss_release_buffer (&stat_min, &outbuf);
6303 
6304     return 0;
6305 }
6306 
6307 /* Wrap data using GSSAPI.  */
6308 
6309 static int
6310 cvs_gssapi_wrap_output (fnclosure, input, output, size, translated)
6311      void *fnclosure;
6312      const char *input;
6313      char *output;
6314      int size;
6315      int *translated;
6316 {
6317     struct cvs_gssapi_wrap_data *gd =
6318 	(struct cvs_gssapi_wrap_data *) fnclosure;
6319     gss_buffer_desc inbuf, outbuf;
6320     OM_uint32 stat_min;
6321     int conf_req, conf;
6322 
6323     inbuf.value = (void *) input;
6324     inbuf.length = size;
6325 
6326 #ifdef ENCRYPTION
6327     conf_req = cvs_gssapi_encrypt;
6328 #else
6329     conf_req = 0;
6330 #endif
6331 
6332     if (gss_wrap (&stat_min, gd->gcontext, conf_req, GSS_C_QOP_DEFAULT,
6333 		  &inbuf, &conf, &outbuf) != GSS_S_COMPLETE)
6334 	error (1, 0, "gss_wrap failed");
6335 
6336     /* The packetizing buffer only permits us to add 100 bytes.
6337        FIXME: I don't know what, if anything, is guaranteed by GSSAPI.
6338        This may need to be increased for a different GSSAPI
6339        implementation, or we may need a different algorithm.  */
6340     if (outbuf.length > size + 100)
6341 	abort ();
6342 
6343     memcpy (output, outbuf.value, outbuf.length);
6344 
6345     *translated = outbuf.length;
6346 
6347     gss_release_buffer (&stat_min, &outbuf);
6348 
6349     return 0;
6350 }
6351 
6352 #endif /* HAVE_GSSAPI */
6353 
6354 #ifdef ENCRYPTION
6355 
6356 #ifdef HAVE_KERBEROS
6357 
6358 /* An encryption interface using Kerberos.  This is built on top of a
6359    packetizing buffer.  */
6360 
6361 /* This structure is the closure field of the Kerberos translation
6362    routines.  */
6363 
6364 struct krb_encrypt_data
6365 {
6366     /* The Kerberos key schedule.  */
6367     Key_schedule sched;
6368     /* The Kerberos DES block.  */
6369     C_Block block;
6370 };
6371 
6372 static int krb_encrypt_input PROTO((void *, const char *, char *, int));
6373 static int krb_encrypt_output PROTO((void *, const char *, char *, int,
6374 				     int *));
6375 
6376 /* Create a Kerberos encryption buffer.  We use a packetizing buffer
6377    with Kerberos encryption translation routines.  */
6378 
6379 struct buffer *
6380 krb_encrypt_buffer_initialize (buf, input, sched, block, memory)
6381      struct buffer *buf;
6382      int input;
6383      Key_schedule sched;
6384      C_Block block;
6385      void (*memory) PROTO((struct buffer *));
6386 {
6387     struct krb_encrypt_data *kd;
6388 
6389     kd = (struct krb_encrypt_data *) xmalloc (sizeof *kd);
6390     memcpy (kd->sched, sched, sizeof (Key_schedule));
6391     memcpy (kd->block, block, sizeof (C_Block));
6392 
6393     return packetizing_buffer_initialize (buf,
6394 					  input ? krb_encrypt_input : NULL,
6395 					  input ? NULL : krb_encrypt_output,
6396 					  kd,
6397 					  memory);
6398 }
6399 
6400 /* Decrypt Kerberos data.  */
6401 
6402 static int
6403 krb_encrypt_input (fnclosure, input, output, size)
6404      void *fnclosure;
6405      const char *input;
6406      char *output;
6407      int size;
6408 {
6409     struct krb_encrypt_data *kd = (struct krb_encrypt_data *) fnclosure;
6410     int tcount;
6411 
6412     des_cbc_encrypt ((C_Block *) input, (C_Block *) output,
6413 		     size, kd->sched, &kd->block, 0);
6414 
6415     /* SIZE is the size of the buffer, which is set by the encryption
6416        routine.  The packetizing buffer will arrange for the first two
6417        bytes in the decrypted buffer to be the real (unaligned)
6418        length.  As a safety check, make sure that the length in the
6419        buffer corresponds to SIZE.  Note that the length in the buffer
6420        is just the length of the data.  We must add 2 to account for
6421        the buffer count itself.  */
6422     tcount = ((output[0] & 0xff) << 8) + (output[1] & 0xff);
6423     if (((tcount + 2 + 7) & ~7) != size)
6424       error (1, 0, "Decryption failure");
6425 
6426     return 0;
6427 }
6428 
6429 /* Encrypt Kerberos data.  */
6430 
6431 static int
6432 krb_encrypt_output (fnclosure, input, output, size, translated)
6433      void *fnclosure;
6434      const char *input;
6435      char *output;
6436      int size;
6437      int *translated;
6438 {
6439     struct krb_encrypt_data *kd = (struct krb_encrypt_data *) fnclosure;
6440     int aligned;
6441 
6442     /* For security against a known plaintext attack, we should
6443        initialize any padding bytes to random values.  Instead, we
6444        just pick up whatever is on the stack, which is at least better
6445        than using zero.  */
6446 
6447     /* Align SIZE to an 8 byte boundary.  Note that SIZE includes the
6448        two byte buffer count at the start of INPUT which was added by
6449        the packetizing buffer.  */
6450     aligned = (size + 7) & ~7;
6451 
6452     /* We use des_cbc_encrypt rather than krb_mk_priv because the
6453        latter sticks a timestamp in the block, and krb_rd_priv expects
6454        that timestamp to be within five minutes of the current time.
6455        Given the way the CVS server buffers up data, that can easily
6456        fail over a long network connection.  We trust krb_recvauth to
6457        guard against a replay attack.  */
6458 
6459     des_cbc_encrypt ((C_Block *) input, (C_Block *) output, aligned,
6460 		     kd->sched, &kd->block, 1);
6461 
6462     *translated = aligned;
6463 
6464     return 0;
6465 }
6466 
6467 #endif /* HAVE_KERBEROS */
6468 #endif /* ENCRYPTION */
6469 #endif /* defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT) */
6470 
6471 /* Output LEN bytes at STR.  If LEN is zero, then output up to (not including)
6472    the first '\0' byte.  */
6473 
6474 void
6475 cvs_output (str, len)
6476     const char *str;
6477     size_t len;
6478 {
6479     if (len == 0)
6480 	len = strlen (str);
6481 #ifdef SERVER_SUPPORT
6482     if (error_use_protocol)
6483     {
6484 	buf_output (saved_output, str, len);
6485 	buf_copy_lines (buf_to_net, saved_output, 'M');
6486     }
6487     else if (server_active)
6488     {
6489 	buf_output (saved_output, str, len);
6490 	buf_copy_lines (protocol, saved_output, 'M');
6491 	buf_send_counted (protocol);
6492     }
6493     else
6494 #endif
6495     {
6496 	size_t written;
6497 	size_t to_write = len;
6498 	const char *p = str;
6499 
6500 	/* For symmetry with cvs_outerr we would call fflush (stderr)
6501 	   here.  I guess the assumption is that stderr will be
6502 	   unbuffered, so we don't need to.  That sounds like a sound
6503 	   assumption from the manpage I looked at, but if there was
6504 	   something fishy about it, my guess is that calling fflush
6505 	   would not produce a significant performance problem.  */
6506 
6507 	while (to_write > 0)
6508 	{
6509 	    written = fwrite (p, 1, to_write, stdout);
6510 	    if (written == 0)
6511 		break;
6512 	    p += written;
6513 	    to_write -= written;
6514 	}
6515     }
6516 }
6517 
6518 /* Output LEN bytes at STR in binary mode.  If LEN is zero, then
6519    output zero bytes.  */
6520 
6521 void
6522 cvs_output_binary (str, len)
6523     char *str;
6524     size_t len;
6525 {
6526 #ifdef SERVER_SUPPORT
6527     if (error_use_protocol || server_active)
6528     {
6529 	struct buffer *buf;
6530 	char size_text[40];
6531 
6532 	if (error_use_protocol)
6533 	    buf = buf_to_net;
6534 	else
6535 	    buf = protocol;
6536 
6537 	if (!supported_response ("Mbinary"))
6538 	{
6539 	    error (0, 0, "\
6540 this client does not support writing binary files to stdout");
6541 	    return;
6542 	}
6543 
6544 	buf_output0 (buf, "Mbinary\012");
6545 	sprintf (size_text, "%lu\012", (unsigned long) len);
6546 	buf_output0 (buf, size_text);
6547 
6548 	/* Not sure what would be involved in using buf_append_data here
6549 	   without stepping on the toes of our caller (which is responsible
6550 	   for the memory allocation of STR).  */
6551 	buf_output (buf, str, len);
6552 
6553 	if (!error_use_protocol)
6554 	    buf_send_counted (protocol);
6555     }
6556     else
6557 #endif
6558     {
6559 	size_t written;
6560 	size_t to_write = len;
6561 	const char *p = str;
6562 
6563 	/* For symmetry with cvs_outerr we would call fflush (stderr)
6564 	   here.  I guess the assumption is that stderr will be
6565 	   unbuffered, so we don't need to.  That sounds like a sound
6566 	   assumption from the manpage I looked at, but if there was
6567 	   something fishy about it, my guess is that calling fflush
6568 	   would not produce a significant performance problem.  */
6569 #ifdef USE_SETMODE_STDOUT
6570 	int oldmode;
6571 
6572 	/* It is possible that this should be the same ifdef as
6573 	   USE_SETMODE_BINARY but at least for the moment we keep them
6574 	   separate.  Mostly this is just laziness and/or a question
6575 	   of what has been tested where.  Also there might be an
6576 	   issue of setmode vs. _setmode.  */
6577 	/* The Windows doc says to call setmode only right after startup.
6578 	   I assume that what they are talking about can also be helped
6579 	   by flushing the stream before changing the mode.  */
6580 	fflush (stdout);
6581 	oldmode = _setmode (_fileno (stdout), OPEN_BINARY);
6582 	if (oldmode < 0)
6583 	    error (0, errno, "failed to setmode on stdout");
6584 #endif
6585 
6586 	while (to_write > 0)
6587 	{
6588 	    written = fwrite (p, 1, to_write, stdout);
6589 	    if (written == 0)
6590 		break;
6591 	    p += written;
6592 	    to_write -= written;
6593 	}
6594 #ifdef USE_SETMODE_STDOUT
6595 	fflush (stdout);
6596 	if (_setmode (_fileno (stdout), oldmode) != OPEN_BINARY)
6597 	    error (0, errno, "failed to setmode on stdout");
6598 #endif
6599     }
6600 }
6601 
6602 /* Like CVS_OUTPUT but output is for stderr not stdout.  */
6603 
6604 void
6605 cvs_outerr (str, len)
6606     const char *str;
6607     size_t len;
6608 {
6609     if (len == 0)
6610 	len = strlen (str);
6611 #ifdef SERVER_SUPPORT
6612     if (error_use_protocol)
6613     {
6614 	buf_output (saved_outerr, str, len);
6615 	buf_copy_lines (buf_to_net, saved_outerr, 'E');
6616     }
6617     else if (server_active)
6618     {
6619 	buf_output (saved_outerr, str, len);
6620 	buf_copy_lines (protocol, saved_outerr, 'E');
6621 	buf_send_counted (protocol);
6622     }
6623     else
6624 #endif
6625     {
6626 	size_t written;
6627 	size_t to_write = len;
6628 	const char *p = str;
6629 
6630 	/* Make sure that output appears in order if stdout and stderr
6631 	   point to the same place.  For the server case this is taken
6632 	   care of by the fact that saved_outerr always holds less
6633 	   than a line.  */
6634 	fflush (stdout);
6635 
6636 	while (to_write > 0)
6637 	{
6638 	    written = fwrite (p, 1, to_write, stderr);
6639 	    if (written == 0)
6640 		break;
6641 	    p += written;
6642 	    to_write -= written;
6643 	}
6644     }
6645 }
6646 
6647 /* Flush stderr.  stderr is normally flushed automatically, of course,
6648    but this function is used to flush information from the server back
6649    to the client.  */
6650 
6651 void
6652 cvs_flusherr ()
6653 {
6654 #ifdef SERVER_SUPPORT
6655     if (error_use_protocol)
6656     {
6657 	/* skip the actual stderr flush in this case since the parent process
6658 	 * on the server should only be writing to stdout anyhow
6659 	 */
6660 	/* Flush what we can to the network, but don't block.  */
6661 	buf_flush (buf_to_net, 0);
6662     }
6663     else if (server_active)
6664     {
6665 	/* make sure stderr is flushed before we send the flush count on the
6666 	 * protocol pipe
6667 	 */
6668 	fflush (stderr);
6669 	/* Send a special count to tell the parent to flush.  */
6670 	buf_send_special_count (protocol, -2);
6671     }
6672     else
6673 #endif
6674 	fflush (stderr);
6675 }
6676 
6677 /* Make it possible for the user to see what has been written to
6678    stdout (it is up to the implementation to decide exactly how far it
6679    should go to ensure this).  */
6680 
6681 void
6682 cvs_flushout ()
6683 {
6684 #ifdef SERVER_SUPPORT
6685     if (error_use_protocol)
6686     {
6687 	/* Flush what we can to the network, but don't block.  */
6688 	buf_flush (buf_to_net, 0);
6689     }
6690     else if (server_active)
6691     {
6692 	/* Just do nothing.  This is because the code which
6693 	   cvs_flushout replaces, setting stdout to line buffering in
6694 	   main.c, didn't get called in the server child process.  But
6695 	   in the future it is quite plausible that we'll want to make
6696 	   this case work analogously to cvs_flusherr.
6697 
6698 	   FIXME - DRP - I tried to implement this and triggered the following
6699 	   error: "Protocol error: uncounted data discarded".  I don't need
6700 	   this feature right now, so I'm not going to bother with it yet.
6701 	 */
6702 	buf_send_special_count (protocol, -1);
6703     }
6704     else
6705 #endif
6706 	fflush (stdout);
6707 }
6708 
6709 /* Output TEXT, tagging it according to TAG.  There are lots more
6710    details about what TAG means in cvsclient.texi but for the simple
6711    case (e.g. non-client/server), TAG is just "newline" to output a
6712    newline (in which case TEXT must be NULL), and any other tag to
6713    output normal text.
6714 
6715    Note that there is no way to output either \0 or \n as part of TEXT.  */
6716 
6717 void
6718 cvs_output_tagged (tag, text)
6719     char *tag;
6720     char *text;
6721 {
6722     if (text != NULL && strchr (text, '\n') != NULL)
6723 	/* Uh oh.  The protocol has no way to cope with this.  For now
6724 	   we dump core, although that really isn't such a nice
6725 	   response given that this probably can be caused by newlines
6726 	   in filenames and other causes other than bugs in CVS.  Note
6727 	   that we don't want to turn this into "MT newline" because
6728 	   this case is a newline within a tagged item, not a newline
6729 	   as extraneous sugar for the user.  */
6730 	assert (0);
6731 
6732     /* Start and end tags don't take any text, per cvsclient.texi.  */
6733     if (tag[0] == '+' || tag[0] == '-')
6734 	assert (text == NULL);
6735 
6736 #ifdef SERVER_SUPPORT
6737     if (server_active && supported_response ("MT"))
6738     {
6739 	struct buffer *buf;
6740 
6741 	if (error_use_protocol)
6742 	    buf = buf_to_net;
6743 	else
6744 	    buf = protocol;
6745 
6746 	buf_output0 (buf, "MT ");
6747 	buf_output0 (buf, tag);
6748 	if (text != NULL)
6749 	{
6750 	    buf_output (buf, " ", 1);
6751 	    buf_output0 (buf, text);
6752 	}
6753 	buf_output (buf, "\n", 1);
6754 
6755 	if (!error_use_protocol)
6756 	    buf_send_counted (protocol);
6757     }
6758     else
6759 #endif
6760     {
6761 	if (strcmp (tag, "newline") == 0)
6762 	    cvs_output ("\n", 1);
6763 	else if (text != NULL)
6764 	    cvs_output (text, 0);
6765     }
6766 }
6767