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