]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/cvs/src/main.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / cvs / src / main.c
1 /*
2  * Copyright (C) 1986-2008 The Free Software Foundation, Inc.
3  *
4  * Portions Copyright (C) 1998-2006 Derek Price, Ximbiot <http://ximbiot.com>,
5  *                                  and others.
6  *
7  * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8  * Portions Copyright (C) 1989-1992, Brian Berliner
9  *
10  * You may distribute under the terms of the GNU General Public License
11  * as specified in the README file that comes with the CVS source distribution.
12  *
13  * This is the main C driver for the CVS system.
14  *
15  * Credit to Dick Grune, Vrije Universiteit, Amsterdam, for writing
16  * the shell-script CVS system that this is based on.
17  *
18  * $FreeBSD$
19  */
20
21 #include <assert.h>
22 #include "cvs.h"
23 #include "prepend_args.h"
24
25 #ifdef HAVE_WINSOCK_H
26 #include <winsock.h>
27 #else
28 extern int gethostname ();
29 #endif
30
31 const char *program_name;
32 const char *program_path;
33 const char *cvs_cmd_name;
34
35 /* I'd dynamically allocate this, but it seems like gethostname
36    requires a fixed size array.  If I'm remembering the RFCs right,
37    256 should be enough.  */
38 #ifndef MAXHOSTNAMELEN
39 #define MAXHOSTNAMELEN  256
40 #endif
41
42 char hostname[MAXHOSTNAMELEN];
43
44 int use_editor = 1;
45 int use_cvsrc = 1;
46 int cvswrite = !CVSREAD_DFLT;
47 int really_quiet = 0;
48 int quiet = 0;
49 int trace = 0;
50 int noexec = 0;
51 int readonlyfs = 0;
52 int require_real_user = 0;
53 int logoff = 0;
54
55 /*
56  * Zero if compression isn't supported or requested; non-zero to indicate
57  * a compression level to request from gzip.
58  */
59 int gzip_level;
60
61 /* Set if we should be writing CVSADM directories at top level.  At
62    least for now we'll make the default be off (the CVS 1.9, not CVS
63    1.9.2, behavior). */
64 int top_level_admin = 0;
65
66 mode_t cvsumask = UMASK_DFLT;
67
68 char *CurDir;
69
70 /*
71  * Defaults, for the environment variables that are not set
72  */
73 char *Tmpdir = TMPDIR_DFLT;
74 char *Editor = EDITOR_DFLT;
75
76
77 /* When our working directory contains subdirectories with different
78    values in CVS/Root files, we maintain a list of them.  */
79 List *root_directories = NULL;
80
81 static const struct cmd
82 {
83     char *fullname;             /* Full name of the function (e.g. "commit") */
84
85     /* Synonyms for the command, nick1 and nick2.  We supply them
86        mostly for two reasons: (1) CVS has always supported them, and
87        we need to maintain compatibility, (2) if there is a need for a
88        version which is shorter than the fullname, for ease in typing.
89        Synonyms have the disadvantage that people will see "new" and
90        then have to think about it, or look it up, to realize that is
91        the operation they know as "add".  Also, this means that one
92        cannot create a command "cvs new" with a different meaning.  So
93        new synonyms are probably best used sparingly, and where used
94        should be abbreviations of the fullname (preferably consisting
95        of the first 2 or 3 or so letters).
96
97        One thing that some systems do is to recognize any unique
98        abbreviation, for example "annotat" "annota", etc., for
99        "annotate".  The problem with this is that scripts and user
100        habits will expect a certain abbreviation to be unique, and in
101        a future release of CVS it may not be.  So it is better to
102        accept only an explicit list of abbreviations and plan on
103        supporting them in the future as well as now.  */
104
105     char *nick1;
106     char *nick2;
107     
108     int (*func) ();             /* Function takes (argc, argv) arguments. */
109     unsigned long attr;         /* Attributes. */
110 } cmds[] =
111
112 {
113     { "add",      "ad",       "new",       add,       CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
114     { "admin",    "adm",      "rcs",       admin,     CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
115     { "annotate", "ann",      "blame",     annotate,  CVS_CMD_USES_WORK_DIR },
116     { "checkout", "co",       "get",       checkout,  0 },
117     { "commit",   "ci",       "com",       commit,    CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
118     { "diff",     "di",       "dif",       diff,      CVS_CMD_USES_WORK_DIR },
119     { "edit",     NULL,       NULL,        edit,      CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
120     { "editors",  NULL,       NULL,        editors,   CVS_CMD_USES_WORK_DIR },
121     { "export",   "exp",      "ex",        checkout,  CVS_CMD_USES_WORK_DIR },
122     { "history",  "hi",       "his",       history,   CVS_CMD_USES_WORK_DIR },
123     { "import",   "im",       "imp",       import,    CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR | CVS_CMD_IGNORE_ADMROOT},
124     { "init",     NULL,       NULL,        init,      CVS_CMD_MODIFIES_REPOSITORY },
125 #if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
126     { "kserver",  NULL,       NULL,        server,    CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
127 #endif
128     { "log",      "lo",       NULL,        cvslog,    CVS_CMD_USES_WORK_DIR },
129 #ifdef AUTH_CLIENT_SUPPORT
130     { "login",    "logon",    "lgn",       login,     0 },
131     { "logout",   NULL,       NULL,        logout,    0 },
132 #endif /* AUTH_CLIENT_SUPPORT */
133 #if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
134     { "pserver",  NULL,       NULL,        server,    CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
135 #endif
136     { "rannotate","rann",     "ra",        annotate,  0 },
137     { "rdiff",    "patch",    "pa",        patch,     0 },
138     { "release",  "re",       "rel",       release,   0 },
139     { "remove",   "rm",       "delete",    cvsremove, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
140     { "rlog",     "rl",       NULL,        cvslog,    0 },
141     { "rtag",     "rt",       "rfreeze",   cvstag,    CVS_CMD_MODIFIES_REPOSITORY },
142 #ifdef SERVER_SUPPORT
143     { "server",   NULL,       NULL,        server,    CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
144 #endif
145     { "status",   "st",       "stat",      cvsstatus, CVS_CMD_USES_WORK_DIR },
146     { "tag",      "ta",       "freeze",    cvstag,    CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
147     { "unedit",   NULL,       NULL,        unedit,    CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
148     { "update",   "up",       "upd",       update,    CVS_CMD_USES_WORK_DIR },
149     { "version",  "ve",       "ver",       version,   0 },
150     { "watch",    NULL,       NULL,        watch,     CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
151     { "watchers", NULL,       NULL,        watchers,  CVS_CMD_USES_WORK_DIR },
152     { NULL, NULL, NULL, NULL, 0 },
153 };
154
155 static const char *const usg[] =
156 {
157     /* CVS usage messages never have followed the GNU convention of
158        putting metavariables in uppercase.  I don't know whether that
159        is a good convention or not, but if it changes it would have to
160        change in all the usage messages.  For now, they consistently
161        use lowercase, as far as I know.  Punctuation is pretty funky,
162        though.  Sometimes they use none, as here.  Sometimes they use
163        single quotes (not the TeX-ish `' stuff), as in --help-options.
164        Sometimes they use double quotes, as in cvs -H add.
165
166        Most (not all) of the usage messages seem to have periods at
167        the end of each line.  I haven't tried to duplicate this style
168        in --help as it is a rather different format from the rest.  */
169
170     "Usage: %s [cvs-options] command [command-options-and-arguments]\n",
171     "  where cvs-options are -q, -n, etc.\n",
172     "    (specify --help-options for a list of options)\n",
173     "  where command is add, admin, etc.\n",
174     "    (specify --help-commands for a list of commands\n",
175     "     or --help-synonyms for a list of command synonyms)\n",
176     "  where command-options-and-arguments depend on the specific command\n",
177     "    (specify -H followed by a command name for command-specific help)\n",
178     "  Specify --help to receive this message\n",
179     "\n",
180
181     /* Some people think that a bug-reporting address should go here.  IMHO,
182        the web sites are better because anything else is very likely to go
183        obsolete in the years between a release and when someone might be
184        reading this help.  Besides, we could never adequately discuss
185        bug reporting in a concise enough way to put in a help message.  */
186
187     /* I was going to put this at the top, but usage() wants the %s to
188        be in the first line.  */
189     "The Concurrent Versions System (CVS) is a tool for version control.\n",
190     /* I really don't think I want to try to define "version control"
191        in one line.  I'm not sure one can get more concise than the
192        paragraph in ../cvs.spec without assuming the reader knows what
193        version control means.  */
194
195     "For CVS updates and additional information, see\n",
196     "    the CVS home page at http://cvs.nongnu.org/\n",
197     NULL,
198 };
199
200 static const char *const cmd_usage[] =
201 {
202     "CVS commands are:\n",
203     "        add          Add a new file/directory to the repository\n",
204     "        admin        Administration front end for rcs\n",
205     "        annotate     Show last revision where each line was modified\n",
206     "        checkout     Checkout sources for editing\n",
207     "        commit       Check files into the repository\n",
208     "        diff         Show differences between revisions\n",
209     "        edit         Get ready to edit a watched file\n",
210     "        editors      See who is editing a watched file\n",
211     "        export       Export sources from CVS, similar to checkout\n",
212     "        history      Show repository access history\n",
213     "        import       Import sources into CVS, using vendor branches\n",
214     "        init         Create a CVS repository if it doesn't exist\n",
215 #if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
216     "        kserver      Kerberos server mode\n",
217 #endif
218     "        log          Print out history information for files\n",
219 #ifdef AUTH_CLIENT_SUPPORT
220     "        login        Prompt for password for authenticating server\n",
221     "        logout       Removes entry in .cvspass for remote repository\n",
222 #endif /* AUTH_CLIENT_SUPPORT */
223 #if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
224     "        pserver      Password server mode\n",
225 #endif
226     "        rannotate    Show last revision where each line of module was modified\n",
227     "        rdiff        Create 'patch' format diffs between releases\n",
228     "        release      Indicate that a Module is no longer in use\n",
229     "        remove       Remove an entry from the repository\n",
230     "        rlog         Print out history information for a module\n",
231     "        rtag         Add a symbolic tag to a module\n",
232 #ifdef SERVER_SUPPORT
233     "        server       Server mode\n",
234 #endif
235     "        status       Display status information on checked out files\n",
236     "        tag          Add a symbolic tag to checked out version of files\n",
237     "        unedit       Undo an edit command\n",
238     "        update       Bring work tree in sync with repository\n",
239     "        version      Show current CVS version(s)\n",
240     "        watch        Set watches\n",
241     "        watchers     See who is watching a file\n",
242     "(Specify the --help option for a list of other help options)\n",
243     NULL,
244 };
245
246 static const char *const opt_usage[] =
247 {
248     /* Omit -b because it is just for compatibility.  */
249     "CVS global options (specified before the command name) are:\n",
250     "    -H           Displays usage information for command.\n",
251     "    -Q           Cause CVS to be really quiet.\n",
252     "    -q           Cause CVS to be somewhat quiet.\n",
253     "    -r           Make checked-out files read-only.\n",
254     "    -w           Make checked-out files read-write (default).\n",
255     "    -g           Force group-write perms on checked-out files.\n",
256     "    -n           Do not execute anything that will change the disk.\n",
257     "    -t           Show trace of program execution -- try with -n.\n",
258     "    -R           Assume repository is read-only, such as CDROM\n",
259     "    -v           CVS version and copyright.\n",
260     "    -T tmpdir    Use 'tmpdir' for temporary files.\n",
261     "    -e editor    Use 'editor' for editing log information.\n",
262     "    -d CVS_root  Overrides $CVSROOT as the root of the CVS tree.\n",
263     "    -f           Do not use the ~/.cvsrc file.\n",
264 #ifdef CLIENT_SUPPORT
265     "    -z #         Use compression level '#' for net traffic.\n",
266 #ifdef ENCRYPTION
267     "    -x           Encrypt all net traffic.\n",
268 #endif
269     "    -a           Authenticate all net traffic.\n",
270 #endif
271     "    -s VAR=VAL   Set CVS user variable.\n",
272     "(Specify the --help option for a list of other help options)\n",
273     NULL
274 };
275
276
277 static int
278 set_root_directory (p, ignored)
279     Node *p;
280     void *ignored;
281 {
282     if (current_parsed_root == NULL && p->data != NULL)
283     {
284         current_parsed_root = p->data;
285         return 1;
286     }
287     return 0;
288 }
289
290
291 static const char * const*
292 cmd_synonyms ()
293 {
294     char ** synonyms;
295     char ** line;
296     const struct cmd *c = &cmds[0];
297     /* Three more for title, "specify --help" line, and NULL.  */
298     int numcmds = 3;
299
300     while (c->fullname != NULL)
301     {
302         numcmds++;
303         c++;
304     }
305     
306     synonyms = (char **) xmalloc(numcmds * sizeof(char *));
307     line = synonyms;
308     *line++ = "CVS command synonyms are:\n";
309     for (c = &cmds[0]; c->fullname != NULL; c++)
310     {
311         if (c->nick1 || c->nick2)
312         {
313             *line = xmalloc (strlen (c->fullname)
314                              + (c->nick1 != NULL ? strlen (c->nick1) : 0)
315                              + (c->nick2 != NULL ? strlen (c->nick2) : 0)
316                              + 40);
317             sprintf(*line, "        %-12s %s %s\n", c->fullname,
318                     c->nick1 ? c->nick1 : "",
319                     c->nick2 ? c->nick2 : "");
320             line++;
321         }
322     }
323     *line++ = "(Specify the --help option for a list of other help options)\n";
324     *line = NULL;
325     
326     return (const char * const*) synonyms; /* will never be freed */
327 }
328
329
330 unsigned long int
331 lookup_command_attribute (cmd_name)
332      char *cmd_name;
333 {
334     const struct cmd *cm;
335
336     for (cm = cmds; cm->fullname; cm++)
337     {
338         if (strcmp (cmd_name, cm->fullname) == 0)
339             break;
340     }
341     if (!cm->fullname)
342         error (1, 0, "unknown command: %s", cmd_name);
343     return cm->attr;
344 }
345
346
347 static RETSIGTYPE
348 main_cleanup (sig)
349     int sig;
350 {
351 #ifndef DONT_USE_SIGNALS
352     const char *name;
353     char temp[10];
354
355     switch (sig)
356     {
357 #ifdef SIGABRT
358     case SIGABRT:
359         name = "abort";
360         break;
361 #endif
362 #ifdef SIGHUP
363     case SIGHUP:
364         name = "hangup";
365         break;
366 #endif
367 #ifdef SIGINT
368     case SIGINT:
369         name = "interrupt";
370         break;
371 #endif
372 #ifdef SIGQUIT
373     case SIGQUIT:
374         name = "quit";
375         break;
376 #endif
377 #ifdef SIGPIPE
378     case SIGPIPE:
379         name = "broken pipe";
380         break;
381 #endif
382 #ifdef SIGTERM
383     case SIGTERM:
384         name = "termination";
385         break;
386 #endif
387     default:
388         /* This case should never be reached, because we list above all
389            the signals for which we actually establish a signal handler.  */
390         sprintf (temp, "%d", sig);
391         name = temp;
392         break;
393     }
394
395     error (1, 0, "received %s signal", name);
396 #endif /* !DONT_USE_SIGNALS */
397 }
398
399 int
400 main (argc, argv)
401     int argc;
402     char **argv;
403 {
404     cvsroot_t *CVSroot_parsed = NULL;
405     int cvsroot_update_env = 1;
406     char *cp, *end;
407     const struct cmd *cm;
408     int c, err = 0;
409     int tmpdir_update_env;
410     int free_Editor = 0;
411     int free_Tmpdir = 0;
412
413     int help = 0;               /* Has the user asked for help?  This
414                                    lets us support the `cvs -H cmd'
415                                    convention to give help for cmd. */
416     static const char short_options[] = "+QqgrwtnRvb:T:e:d:Hfz:s:xaU";
417     static struct option long_options[] =
418     {
419         {"help", 0, NULL, 'H'},
420         {"version", 0, NULL, 'v'},
421         {"help-commands", 0, NULL, 1},
422         {"help-synonyms", 0, NULL, 2},
423         {"help-options", 0, NULL, 4},
424         {"allow-root", required_argument, NULL, 3},
425         {0, 0, 0, 0}
426     };
427     /* `getopt_long' stores the option index here, but right now we
428         don't use it. */
429     int option_index = 0;
430
431 #ifdef SYSTEM_INITIALIZE
432     /* Hook for OS-specific behavior, for example socket subsystems on
433        NT and OS2 or dealing with windows and arguments on Mac.  */
434     SYSTEM_INITIALIZE (&argc, &argv);
435 #endif
436
437 #ifdef HAVE_TZSET
438     /* On systems that have tzset (which is almost all the ones I know
439        of), it's a good idea to call it.  */
440     tzset ();
441 #endif
442
443     /*
444      * Just save the last component of the path for error messages
445      */
446     program_path = xstrdup (argv[0]);
447 #ifdef ARGV0_NOT_PROGRAM_NAME
448     /* On some systems, e.g. VMS, argv[0] is not the name of the command
449        which the user types to invoke the program.  */
450     program_name = "cvs";
451 #else
452     program_name = last_component (argv[0]);
453 #endif
454
455     /*
456      * Query the environment variables up-front, so that
457      * they can be overridden by command line arguments
458      */
459     tmpdir_update_env = *Tmpdir;        /* TMPDIR_DFLT must be set */
460     if ((cp = getenv (TMPDIR_ENV)) != NULL)
461     {
462         Tmpdir = cp;
463         tmpdir_update_env = 0;          /* it's already there */
464     }
465     if ((cp = getenv (EDITOR1_ENV)) != NULL)
466         Editor = cp;
467     else if ((cp = getenv (EDITOR2_ENV)) != NULL)
468         Editor = cp;
469     else if ((cp = getenv (EDITOR3_ENV)) != NULL)
470         Editor = cp;
471     if (getenv (CVSREAD_ENV) != NULL)
472         cvswrite = 0;
473     if (getenv (CVSREADONLYFS_ENV) != NULL) {
474         readonlyfs = 1;
475         logoff = 1;
476     }
477
478     prepend_default_options (getenv ("CVS_OPTIONS"), &argc, &argv);
479
480     /* Set this to 0 to force getopt initialization.  getopt() sets
481        this to 1 internally.  */
482     optind = 0;
483
484     /* We have to parse the options twice because else there is no
485        chance to avoid reading the global options from ".cvsrc".  Set
486        opterr to 0 for avoiding error messages about invalid options.
487        */
488     opterr = 0;
489
490     while ((c = getopt_long
491             (argc, argv, short_options, long_options, &option_index))
492            != EOF)
493     {
494         if (c == 'f')
495             use_cvsrc = 0;
496     }
497
498     /*
499      * Scan cvsrc file for global options.
500      */
501     if (use_cvsrc)
502         read_cvsrc (&argc, &argv, "cvs");
503
504     optind = 0;
505     opterr = 1;
506
507     while ((c = getopt_long
508             (argc, argv, short_options, long_options, &option_index))
509            != EOF)
510     {
511         switch (c)
512         {
513             case 1:
514                 /* --help-commands */
515                 usage (cmd_usage);
516                 break;
517             case 2:
518                 /* --help-synonyms */
519                 usage (cmd_synonyms());
520                 break;
521             case 4:
522                 /* --help-options */
523                 usage (opt_usage);
524                 break;
525             case 3:
526                 /* --allow-root */
527                 root_allow_add (optarg);
528                 break;
529             case 'Q':
530                 really_quiet = 1;
531                 /* FALL THROUGH */
532             case 'q':
533                 quiet = 1;
534                 break;
535             case 'r':
536                 cvswrite = 0;
537                 break;
538             case 'w':
539                 cvswrite = 1;
540                 break;
541             case 'g':
542                 /*
543                  * force full group write perms (used for shared checked-out
544                  * source trees, see manual page)
545                  */
546                 umask(umask(077) & 007);
547                 break;
548             case 't':
549                 trace = 1;
550                 break;
551             case 'R':
552                 readonlyfs = 1;
553                 logoff = 1;
554                 break;
555             case 'n':
556                 noexec = 1;
557                 logoff = 1;
558                 break;
559             case 'v':
560                 (void) fputs ("\n", stdout);
561                 version (0, (char **) NULL);    
562                 (void) fputs ("\n", stdout);
563                 (void) fputs ("\
564 Copyright (C) 2006 Free Software Foundation, Inc.\n\
565 \n\
566 Senior active maintainers include Larry Jones, Derek R. Price,\n\
567 and Mark D. Baushke.  Please see the AUTHORS and README files from the CVS\n\
568 distribution kit for a complete list of contributors and copyrights.\n",
569                               stdout);
570                 (void) fputs ("\n", stdout);
571                 (void) fputs ("CVS may be copied only under the terms of the GNU General Public License,\n", stdout);
572                 (void) fputs ("a copy of which can be found with the CVS distribution kit.\n", stdout);
573                 (void) fputs ("\n", stdout);
574
575                 (void) fputs ("Specify the --help option for further information about CVS\n", stdout);
576
577 #ifdef SYSTEM_CLEANUP
578                 /* Hook for OS-specific behavior, for example socket subsystems
579                  * on NT and OS2 or dealing with windows and arguments on Mac.
580                  */
581                 SYSTEM_CLEANUP ();
582 #endif
583                 exit (0);
584                 break;
585             case 'b':
586                 /* This option used to specify the directory for RCS
587                    executables.  But since we don't run them any more,
588                    this is a noop.  Silently ignore it so that .cvsrc
589                    and scripts and inetd.conf and such can work with
590                    either new or old CVS.  */
591                 break;
592             case 'T':
593                 if (free_Tmpdir) free (Tmpdir);
594                 Tmpdir = xstrdup (optarg);
595                 free_Tmpdir = 1;
596                 tmpdir_update_env = 1;  /* need to update environment */
597                 break;
598             case 'e':
599                 if (free_Editor) free (Editor);
600                 Editor = xstrdup (optarg);
601                 free_Editor = 1;
602                 break;
603             case 'd':
604                 if (CVSroot_cmdline != NULL)
605                     free (CVSroot_cmdline);
606                 CVSroot_cmdline = xstrdup (optarg);
607                 break;
608             case 'H':
609                 help = 1;
610                 break;
611             case 'f':
612                 use_cvsrc = 0; /* unnecessary, since we've done it above */
613                 break;
614             case 'z':
615                 gzip_level = strtol (optarg, &end, 10);
616                 if (*end != '\0' || gzip_level < 0 || gzip_level > 9)
617                   error (1, 0,
618                          "gzip compression level must be between 0 and 9");
619                 /* If no CLIENT_SUPPORT, we just silently ignore the gzip
620                  * level, so that users can have it in their .cvsrc and not
621                  * cause any trouble.
622                  *
623                  * We still parse the argument to -z for correctness since
624                  * one user complained of being bitten by a run of
625                  * `cvs -z -n up' which read -n as the argument to -z without
626                  * complaining.  */
627                 break;
628             case 's':
629                 variable_set (optarg);
630                 break;
631             case 'x':
632 #ifdef CLIENT_SUPPORT
633                 cvsencrypt = 1;
634 #endif /* CLIENT_SUPPORT */
635                 /* If no CLIENT_SUPPORT, ignore -x, so that users can
636                    have it in their .cvsrc and not cause any trouble.
637                    If no ENCRYPTION, we still accept -x, but issue an
638                    error if we are being run as a client.  */
639                 break;
640             case 'a':
641 #ifdef CLIENT_SUPPORT
642                 cvsauthenticate = 1;
643 #endif
644                 /* If no CLIENT_SUPPORT, ignore -a, so that users can
645                    have it in their .cvsrc and not cause any trouble.
646                    We will issue an error later if stream
647                    authentication is not supported.  */
648                 break;
649             case 'U':
650 #ifdef SERVER_SUPPORT
651                 require_real_user = 1;
652 #endif
653                 break;
654             case '?':
655             default:
656                 usage (usg);
657         }
658     }
659
660     argc -= optind;
661     argv += optind;
662     if (argc < 1)
663         usage (usg);
664
665
666     /* Look up the command name. */
667
668     cvs_cmd_name = argv[0];
669     for (cm = cmds; cm->fullname; cm++)
670     {
671         if (cm->nick1 && !strcmp (cvs_cmd_name, cm->nick1))
672             break;
673         if (cm->nick2 && !strcmp (cvs_cmd_name, cm->nick2))
674             break;
675         if (!strcmp (cvs_cmd_name, cm->fullname))
676             break;
677     }
678
679     if (!cm->fullname)
680     {
681         fprintf (stderr, "Unknown command: `%s'\n\n", cvs_cmd_name);
682         usage (cmd_usage);
683     }
684     else
685         cvs_cmd_name = cm->fullname;    /* Global pointer for later use */
686
687     if (help)
688     {
689         argc = -1;              /* some functions only check for this */
690         err = (*(cm->func)) (argc, argv);
691     }
692     else
693     {
694         /* The user didn't ask for help, so go ahead and authenticate,
695            set up CVSROOT, and the rest of it. */
696
697         /* The UMASK environment variable isn't handled with the
698            others above, since we don't want to signal errors if the
699            user has asked for help.  This won't work if somebody adds
700            a command-line flag to set the umask, since we'll have to
701            parse it before we get here. */
702
703         if ((cp = getenv (CVSUMASK_ENV)) != NULL)
704         {
705             /* FIXME: Should be accepting symbolic as well as numeric mask.  */
706             cvsumask = strtol (cp, &end, 8) & 0777;
707             if (*end != '\0')
708                 error (1, errno, "invalid umask value in %s (%s)",
709                        CVSUMASK_ENV, cp);
710         }
711
712 #ifdef SERVER_SUPPORT
713
714 # ifdef HAVE_KERBEROS
715         /* If we are invoked with a single argument "kserver", then we are
716            running as Kerberos server as root.  Do the authentication as
717            the very first thing, to minimize the amount of time we are
718            running as root.  */
719         if (strcmp (cvs_cmd_name, "kserver") == 0)
720         {
721             kserver_authenticate_connection ();
722
723             /* Pretend we were invoked as a plain server.  */
724             cvs_cmd_name = "server";
725         }
726 # endif /* HAVE_KERBEROS */
727
728
729 # if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
730         if (strcmp (cvs_cmd_name, "pserver") == 0)
731         {
732             /* The reason that --allow-root is not a command option
733                is mainly the comment in server() about how argc,argv
734                might be from .cvsrc.  I'm not sure about that, and
735                I'm not sure it is only true of command options, but
736                it seems easier to make it a global option.  */
737
738             /* Gets username and password from client, authenticates, then
739                switches to run as that user and sends an ACK back to the
740                client. */
741             pserver_authenticate_connection ();
742       
743             /* Pretend we were invoked as a plain server.  */
744             cvs_cmd_name = "server";
745         }
746 # endif /* AUTH_SERVER_SUPPORT || HAVE_GSSAPI */
747 #endif /* SERVER_SUPPORT */
748
749         server_active = strcmp (cvs_cmd_name, "server") == 0;
750
751         /* This is only used for writing into the history file.  For
752            remote connections, it might be nice to have hostname
753            and/or remote path, on the other hand I'm not sure whether
754            it is worth the trouble.  */
755
756         if (server_active)
757             CurDir = xstrdup ("<remote>");
758         else
759         {
760             CurDir = xgetwd ();
761             if (CurDir == NULL)
762                 error (1, errno, "cannot get working directory");
763         }
764
765         if (Tmpdir == NULL || Tmpdir[0] == '\0')
766         {
767             if (free_Tmpdir) free (Tmpdir);
768             Tmpdir = "/tmp";
769         }
770
771 #ifdef HAVE_PUTENV
772         if (tmpdir_update_env)
773         {
774             char *env;
775             env = xmalloc (strlen (TMPDIR_ENV) + strlen (Tmpdir) + 1 + 1);
776             (void) sprintf (env, "%s=%s", TMPDIR_ENV, Tmpdir);
777             (void) putenv (env);
778             /* do not free env, as putenv has control of it */
779         }
780         {
781             char *env;
782             env = xmalloc (sizeof "CVS_PID=" + 32); /* XXX pid < 10^32 */
783             (void) sprintf (env, "CVS_PID=%ld", (long) getpid ());
784             (void) putenv (env);
785         }
786 #endif
787
788 #ifndef DONT_USE_SIGNALS
789         /* make sure we clean up on error */
790 #ifdef SIGABRT
791         (void) SIG_register (SIGABRT, main_cleanup);
792 #endif
793 #ifdef SIGHUP
794         (void) SIG_register (SIGHUP, main_cleanup);
795 #endif
796 #ifdef SIGINT
797         (void) SIG_register (SIGINT, main_cleanup);
798 #endif
799 #ifdef SIGQUIT
800         (void) SIG_register (SIGQUIT, main_cleanup);
801 #endif
802 #ifdef SIGPIPE
803         (void) SIG_register (SIGPIPE, main_cleanup);
804 #endif
805 #ifdef SIGTERM
806         (void) SIG_register (SIGTERM, main_cleanup);
807 #endif
808 #endif /* !DONT_USE_SIGNALS */
809
810         gethostname(hostname, sizeof (hostname));
811
812 #ifdef KLUDGE_FOR_WNT_TESTSUITE
813         /* Probably the need for this will go away at some point once
814            we call fflush enough places (e.g. fflush (stdout) in
815            cvs_outerr).  */
816         (void) setvbuf (stdout, (char *) NULL, _IONBF, 0);
817         (void) setvbuf (stderr, (char *) NULL, _IONBF, 0);
818 #endif /* KLUDGE_FOR_WNT_TESTSUITE */
819
820         if (use_cvsrc)
821             read_cvsrc (&argc, &argv, cvs_cmd_name);
822
823         /* Fiddling with CVSROOT doesn't make sense if we're running
824          * in server mode, since the client will send the repository
825          * directory after the connection is made.
826          */
827         if (!server_active)
828         {
829             /* First check if a root was set via the command line.  */
830             if (CVSroot_cmdline)
831             {
832                  if (!(CVSroot_parsed = parse_cvsroot (CVSroot_cmdline)))
833                      error (1, 0, "Bad CVSROOT: `%s'.", CVSroot_cmdline);
834             }
835
836             /* See if we are able to find a 'better' value for CVSroot
837              * in the CVSADM_ROOT directory.
838              *
839              * "cvs import" shouldn't check CVS/Root; in general it
840              * ignores CVS directories and CVS/Root is likely to
841              * specify a different repository than the one we are
842              * importing to, but if this is not import and no root was
843              * specified on the command line, set the root from the
844              * CVS/Root file.
845              */
846             if (!CVSroot_parsed
847                 && !(cm->attr & CVS_CMD_IGNORE_ADMROOT)
848                )
849                 CVSroot_parsed = Name_Root (NULL, NULL);
850
851             /* Now, if there is no root on the command line and we didn't find
852              * one in a file, set it via the $CVSROOT env var.
853              */
854             if (!CVSroot_parsed)
855             {
856                 char *tmp = getenv (CVSROOT_ENV);
857                 if (tmp)
858                 {
859                     if (!(CVSroot_parsed = parse_cvsroot (tmp)))
860                         error (1, 0, "Bad CVSROOT: `%s'.", tmp);
861                     cvsroot_update_env = 0;
862                 }
863             }
864
865 #ifdef CVSROOT_DFLT
866             if (!CVSroot_parsed)
867             {
868                 if (!(CVSroot_parsed = parse_cvsroot (CVSROOT_DFLT)))
869                     error (1, 0, "Bad CVSROOT: `%s'.", CVSROOT_DFLT);
870             }
871 #endif /* CVSROOT_DFLT */
872
873             /* Now we've reconciled CVSROOT from the command line, the
874                CVS/Root file, and the environment variable.  Do the
875                last sanity checks on the variable. */
876             if (!CVSroot_parsed)
877             {
878                 error (0, 0,
879                        "No CVSROOT specified!  Please use the `-d' option");
880                 error (1, 0,
881                        "or set the %s environment variable.", CVSROOT_ENV);
882             }
883         }
884
885         /* Here begins the big loop over unique cvsroot values.  We
886            need to call do_recursion once for each unique value found
887            in CVS/Root.  Prime the list with the current value. */
888
889         /* Create the list. */
890         assert (root_directories == NULL);
891         root_directories = getlist ();
892
893         /* Prime it. */
894         if (CVSroot_parsed)
895         {
896             Node *n;
897             n = getnode ();
898             n->type = NT_UNKNOWN;
899             n->key = xstrdup (CVSroot_parsed->original);
900             n->data = CVSroot_parsed;
901
902             if (addnode (root_directories, n))
903                 error (1, 0, "cannot add initial CVSROOT %s", n->key);
904         }
905
906         assert (current_parsed_root == NULL);
907
908         /* If we're running the server, we want to execute this main
909            loop once and only once (we won't be serving multiple roots
910            from this connection, so there's no need to do it more than
911            once).  To get out of the loop, we perform a "break" at the
912            end of things.  */
913
914         while (server_active ||
915                walklist (root_directories, set_root_directory, NULL))
916         {
917             /* Fiddling with CVSROOT doesn't make sense if we're running
918                in server mode, since the client will send the repository
919                directory after the connection is made. */
920
921             if (!server_active)
922             {
923                 /* Now we're 100% sure that we have a valid CVSROOT
924                    variable.  Parse it to see if we're supposed to do
925                    remote accesses or use a special access method. */
926
927                 if (trace)
928                     fprintf (stderr, "%s-> main loop with CVSROOT=%s\n",
929                            CLIENT_SERVER_STR, current_parsed_root->original);
930
931                 /*
932                  * Check to see if the repository exists.
933                  */
934                 if (!current_parsed_root->isremote)
935                 {
936                     char *path;
937                     int save_errno;
938
939                     path = xmalloc (strlen (current_parsed_root->directory)
940                                     + strlen (CVSROOTADM) + 2);
941                     sprintf (path, "%s/%s", current_parsed_root->directory,
942                              CVSROOTADM);
943                     if (!isaccessible (path, R_OK | X_OK))
944                     {
945                         save_errno = errno;
946                         /* If this is "cvs init", the root need not exist yet.
947                          */
948                         if (strcmp (cvs_cmd_name, "init"))
949                             error (1, save_errno, "%s", path);
950                         }
951                     free (path);
952                 }
953
954 #ifdef HAVE_PUTENV
955                 /* Update the CVSROOT environment variable.  */
956                 if (cvsroot_update_env)
957                 {
958                     static char *prev;
959                     char *env;
960
961                     env = xmalloc (strlen (CVSROOT_ENV)
962                                    + strlen (current_parsed_root->original)
963                                    + 2);
964                     sprintf (env, "%s=%s", CVSROOT_ENV,
965                              current_parsed_root->original);
966                     (void) putenv (env);
967                     /* do not free env yet, as putenv has control of it */
968                     /* but do free the previous value, if any */
969                     if (prev != NULL)
970                         free (prev);
971                     prev = env;
972                 }
973 #endif
974             }
975         
976             /* Parse the CVSROOT/config file, but only for local.  For the
977                server, we parse it after we know $CVSROOT.  For the
978                client, it doesn't get parsed at all, obviously.  The
979                presence of the parse_config call here is not mean to
980                predetermine whether CVSROOT/config overrides things from
981                read_cvsrc and other such places or vice versa.  That sort
982                of thing probably needs more thought.  */
983             if (!server_active && !current_parsed_root->isremote)
984             {
985                 /* If there was an error parsing the config file, parse_config
986                    already printed an error.  We keep going.  Why?  Because
987                    if we didn't, then there would be no way to check in a new
988                    CVSROOT/config file to fix the broken one!  */
989                 parse_config (current_parsed_root->directory);
990
991                 /* Now is a convenient time to read CVSROOT/options */
992                 parseopts(current_parsed_root->directory);
993             }
994
995 #ifdef CLIENT_SUPPORT
996             /* Need to check for current_parsed_root != NULL here since
997              * we could still be in server mode before the server function
998              * gets called below and sets the root
999              */
1000             if (current_parsed_root != NULL && current_parsed_root->isremote)
1001             {
1002                 /* Create a new list for directory names that we've
1003                    sent to the server. */
1004                 if (dirs_sent_to_server != NULL)
1005                     dellist (&dirs_sent_to_server);
1006                 dirs_sent_to_server = getlist ();
1007             }
1008 #endif
1009
1010             err = (*(cm->func)) (argc, argv);
1011         
1012             /* Mark this root directory as done.  When the server is
1013                active, our list will be empty -- don't try and
1014                remove it from the list. */
1015
1016             if (!server_active)
1017             {
1018                 Node *n = findnode (root_directories,
1019                                     current_parsed_root->original);
1020                 assert (n != NULL);
1021                 assert (n->data != NULL);
1022                 free_cvsroot_t (n->data);
1023                 n->data = NULL;
1024                 current_parsed_root = NULL;
1025             }
1026
1027             if (server_active)
1028             {
1029                 server_active = 0;
1030                 break;
1031             }
1032         } /* end of loop for cvsroot values */
1033
1034         dellist (&root_directories);
1035     } /* end of stuff that gets done if the user DOESN'T ask for help */
1036
1037     Lock_Cleanup ();
1038
1039     /* It's okay to cast out the const below since we know we allocated this in
1040      * this function.  The const was to keep other functions from messing with
1041      * this.
1042      */
1043     free ((char *)program_path);
1044     if (CVSroot_cmdline != NULL)
1045         free (CVSroot_cmdline);
1046     if (free_Editor)
1047         free (Editor);
1048     if (free_Tmpdir)
1049         free (Tmpdir);
1050     root_allow_free ();
1051
1052 #ifdef SYSTEM_CLEANUP
1053     /* Hook for OS-specific behavior, for example socket subsystems on
1054        NT and OS2 or dealing with windows and arguments on Mac.  */
1055     SYSTEM_CLEANUP ();
1056 #endif
1057
1058     /* This is exit rather than return because apparently that keeps
1059        some tools which check for memory leaks happier.  */
1060     exit (err ? EXIT_FAILURE : 0);
1061         /* Keep picky/stupid compilers (e.g. Visual C++ 5.0) happy.  */
1062         return 0;
1063 }
1064
1065 char *
1066 Make_Date (rawdate)
1067     char *rawdate;
1068 {
1069     time_t unixtime;
1070
1071     unixtime = get_date (rawdate, (struct timeb *) NULL);
1072     if (unixtime == (time_t) - 1)
1073         error (1, 0, "Can't parse date/time: %s", rawdate);
1074     return date_from_time_t (unixtime);
1075 }
1076
1077 /* Convert a time_t to an RCS format date.  This is mainly for the
1078    use of "cvs history", because the CVSROOT/history file contains
1079    time_t format dates; most parts of CVS will want to avoid using
1080    time_t's directly, and instead use RCS_datecmp, Make_Date, &c.
1081    Assuming that the time_t is in GMT (as it generally should be),
1082    then the result will be in GMT too.
1083
1084    Returns a newly malloc'd string.  */
1085
1086 char *
1087 date_from_time_t (unixtime)
1088     time_t unixtime;
1089 {
1090     struct tm *ftm;
1091     char date[MAXDATELEN];
1092     char *ret;
1093
1094     ftm = gmtime (&unixtime);
1095     if (ftm == NULL)
1096         /* This is a system, like VMS, where the system clock is in local
1097            time.  Hopefully using localtime here matches the "zero timezone"
1098            hack I added to get_date (get_date of course being the relevant
1099            issue for Make_Date, and for history.c too I think).  */
1100         ftm = localtime (&unixtime);
1101
1102     (void) sprintf (date, DATEFORM,
1103                     ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
1104                     ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
1105                     ftm->tm_min, ftm->tm_sec);
1106     ret = xstrdup (date);
1107     return (ret);
1108 }
1109
1110 /* Convert a date to RFC822/1123 format.  This is used in contexts like
1111    dates to send in the protocol; it should not vary based on locale or
1112    other such conventions for users.  We should have another routine which
1113    does that kind of thing.
1114
1115    The SOURCE date is in our internal RCS format.  DEST should point to
1116    storage managed by the caller, at least MAXDATELEN characters.  */
1117 void
1118 date_to_internet (dest, source)
1119     char *dest;
1120     const char *source;
1121 {
1122     struct tm date;
1123
1124     date_to_tm (&date, source);
1125     tm_to_internet (dest, &date);
1126 }
1127
1128 void
1129 date_to_tm (dest, source)
1130     struct tm *dest;
1131     const char *source;
1132 {
1133     if (sscanf (source, SDATEFORM,
1134                 &dest->tm_year, &dest->tm_mon, &dest->tm_mday,
1135                 &dest->tm_hour, &dest->tm_min, &dest->tm_sec)
1136             != 6)
1137         /* Is there a better way to handle errors here?  I made this
1138            non-fatal in case we are called from the code which can't
1139            deal with fatal errors.  */
1140         error (0, 0, "internal error: bad date %s", source);
1141
1142     if (dest->tm_year > 100)
1143         dest->tm_year -= 1900;
1144
1145     dest->tm_mon -= 1;
1146 }
1147
1148 /* Convert a date to RFC822/1123 format.  This is used in contexts like
1149    dates to send in the protocol; it should not vary based on locale or
1150    other such conventions for users.  We should have another routine which
1151    does that kind of thing.
1152
1153    The SOURCE date is a pointer to a struct tm.  DEST should point to
1154    storage managed by the caller, at least MAXDATELEN characters.  */
1155 void
1156 tm_to_internet (dest, source)
1157     char *dest;
1158     const struct tm *source;
1159 {
1160     /* Just to reiterate, these strings are from RFC822 and do not vary
1161        according to locale.  */
1162     static const char *const month_names[] =
1163       {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
1164          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
1165     
1166     sprintf (dest, "%d %s %d %02d:%02d:%02d -0000", source->tm_mday,
1167              source->tm_mon < 0 || source->tm_mon > 11 ? "???" : month_names[source->tm_mon],
1168              source->tm_year + 1900, source->tm_hour, source->tm_min, source->tm_sec);
1169 }
1170
1171 void
1172 usage (cpp)
1173     register const char *const *cpp;
1174 {
1175     (void) fprintf (stderr, *cpp++, program_name, cvs_cmd_name);
1176     for (; *cpp; cpp++)
1177         (void) fprintf (stderr, *cpp);
1178     error_exit ();
1179 }
1180
1181 void
1182 parseopts(root)
1183     const char *root;
1184 {
1185     char path[PATH_MAX];
1186     int save_errno;
1187     char buf[1024];
1188     const char *p;
1189     char *q;
1190     FILE *fp;
1191
1192     if (root == NULL) {
1193         printf("no CVSROOT in parseopts\n");
1194         return;
1195     }
1196     p = strchr (root, ':');
1197     if (p)
1198         p++;
1199     else
1200         p = root;
1201     if (p == NULL) {
1202         printf("mangled CVSROOT in parseopts\n");
1203         return;
1204     }
1205     (void) sprintf (path, "%s/%s/%s", p, CVSROOTADM, CVSROOTADM_OPTIONS);
1206     if ((fp = fopen(path, "r")) != NULL) {
1207         while (fgets(buf, sizeof buf, fp) != NULL) {
1208             if (buf[0] == '#')
1209                 continue;
1210             q = strrchr(buf, '\n');
1211             if (q)
1212                 *q = '\0';
1213
1214             if (!strcmp(buf, "iso8601")) {
1215                 datesep = '-';
1216             }
1217             if (!strncmp(buf, "tag=", 4)) {
1218                 char *what;
1219                 char *rcs_localid;
1220
1221                 rcs_localid = buf + 4;
1222                 RCS_setlocalid(rcs_localid);
1223             }
1224             if (!strncmp(buf, "tagexpand=", 10)) {
1225                 char *what;
1226                 char *rcs_incexc;
1227
1228                 rcs_incexc = buf + 10;
1229                 RCS_setincexc(rcs_incexc);
1230             }
1231             /*
1232              * OpenBSD has a "umask=" and "dlimit=" command, we silently
1233              * ignore them here since they are not much use to us.  cvsumask
1234              * defaults to 002 already, and the dlimit (data size limit)
1235              * should really be handled elsewhere (eg: login.conf).
1236              */
1237         }
1238         fclose(fp);
1239     }
1240 }