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