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