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