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