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