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