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