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