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