diff options
Diffstat (limited to 'contrib/cvs/src/main.c')
-rw-r--r-- | contrib/cvs/src/main.c | 268 |
1 files changed, 166 insertions, 102 deletions
diff --git a/contrib/cvs/src/main.c b/contrib/cvs/src/main.c index 3352f60..2397d7e 100644 --- a/contrib/cvs/src/main.c +++ b/contrib/cvs/src/main.c @@ -3,7 +3,7 @@ * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License - * as specified in the README file that comes with the CVS 1.4 kit. + * as specified in the README file that comes with the CVS source distribution. * * This is the main C driver for the CVS system. * @@ -33,14 +33,14 @@ char *command_name; char hostname[MAXHOSTNAMELEN]; -int use_editor = TRUE; -int use_cvsrc = TRUE; +int use_editor = 1; +int use_cvsrc = 1; int cvswrite = !CVSREAD_DFLT; -int really_quiet = FALSE; -int quiet = FALSE; -int trace = FALSE; -int noexec = FALSE; -int logoff = FALSE; +int really_quiet = 0; +int quiet = 0; +int trace = 0; +int noexec = 0; +int logoff = 0; mode_t cvsumask = UMASK_DFLT; char *CurDir; @@ -48,7 +48,6 @@ char *CurDir; /* * Defaults, for the environment variables that are not set */ -char *Rcsbin = RCSBIN_DFLT; char *Tmpdir = TMPDIR_DFLT; char *Editor = EDITOR_DFLT; @@ -124,32 +123,47 @@ static const struct cmd static const char *const usg[] = { - "Usage: %s [cvs-options] command [command-options] [files...]\n", - " Where 'cvs-options' are:\n", - " -H Displays Usage information for command\n", - " -Q Cause CVS to be really quiet.\n", - " -q Cause CVS to be somewhat quiet.\n", - " -r Make checked-out files read-only\n", - " -w Make checked-out files read-write (default)\n", - " -l Turn History logging off\n", - " -n Do not execute anything that will change the disk\n", - " -t Show trace of program execution -- Try with -n\n", - " -v CVS version and copyright\n", - " -b bindir Find RCS programs in 'bindir'\n", - " -T tmpdir Use 'tmpdir' for temporary files\n", - " -e editor Use 'editor' for editing log information\n", - " -d CVS_root Overrides $CVSROOT as the root of the CVS tree\n", - " -f Do not use the ~/.cvsrc file\n", -#ifdef CLIENT_SUPPORT - " -z # Use compression level '#' for net traffic.\n", -#ifdef ENCRYPTION - " -x Encrypt all net traffic.\n", -#endif -#endif - " -s VAR=VAL Set CVS user variable.\n", + /* CVS usage messages never have followed the GNU convention of + putting metavariables in uppercase. I don't know whether that + is a good convention or not, but if it changes it would have to + change in all the usage messages. For now, they consistently + use lowercase, as far as I know. Puncutation is pretty funky, + though. Sometimes they use none, as here. Sometimes they use + single quotes (not the TeX-ish `' stuff), as in --help-options. + Sometimes they use double quotes, as in cvs -H add. + + Most (not all) of the usage messages seem to have periods at + the end of each line. I haven't tried to duplicate this style + in --help as it is a rather different format from the rest. */ + + "Usage: %s [cvs-options] command [command-options-and-arguments]\n", + " where cvs-options are -q, -n, etc.\n", + " (specify --help-options for a list of options)\n", + " where command is add, admin, etc.\n", + " (specify --help-commands for a list of commands\n", + " or --help-synonyms for a list of command synonyms)\n", + " where command-options-and-arguments depend on the specific command\n", + " (specify -H followed by a command name for command-specific help)\n", + " Specify --help to receive this message\n", "\n", - " and where 'command' is: add, admin, etc. (use the --help-commands\n", - " option for a list of commands)\n", + + /* Some people think that a bug-reporting address should go here. IMHO, + the web sites are better because anything else is very likely to go + obsolete in the years between a release and when someone might be + reading this help. Besides, we could never adequately discuss + bug reporting in a concise enough way to put in a help message. */ + + /* I was going to put this at the top, but usage() wants the %s to + be in the first line. */ + "The Concurrent Versions System (CVS) is a tool for version control.\n", + /* I really don't think I want to try to define "version control" + in one line. I'm not sure one can get more concise than the + paragraph in ../cvs.spec without assuming the reader knows what + version control means. */ + + "For CVS updates and additional information, see\n", + " Cyclic Software at http://www.cyclic.com/ or\n", + " Pascal Molli's CVS site at http://www.loria.fr/~molli/cvs-index.html\n", NULL, }; @@ -183,17 +197,47 @@ static const char *const cmd_usage[] = " update Bring work tree in sync with repository\n", " watch Set watches\n", " watchers See who is watching a file\n", - "(Use the --help-synonyms option for a list of alternate command names)\n", + "(Specify the --help option for a list of other help options)\n", NULL, }; +static const char *const opt_usage[] = +{ + "CVS global options (specified before the command name) are:\n", + " -H Displays usage information for command.\n", + " -Q Cause CVS to be really quiet.\n", + " -q Cause CVS to be somewhat quiet.\n", + " -r Make checked-out files read-only.\n", + " -w Make checked-out files read-write (default).\n", + " -l Turn history logging off.\n", + " -n Do not execute anything that will change the disk.\n", + " -t Show trace of program execution -- try with -n.\n", + " -v CVS version and copyright.\n", + " -b bindir Find RCS programs in 'bindir'.\n", + " -T tmpdir Use 'tmpdir' for temporary files.\n", + " -e editor Use 'editor' for editing log information.\n", + " -d CVS_root Overrides $CVSROOT as the root of the CVS tree.\n", + " -f Do not use the ~/.cvsrc file.\n", +#ifdef CLIENT_SUPPORT + " -z # Use compression level '#' for net traffic.\n", +#ifdef ENCRYPTION + " -x Encrypt all net traffic.\n", +#endif + " -a Authenticate all net traffic.\n", +#endif + " -s VAR=VAL Set CVS user variable.\n", + "(Specify the --help option for a list of other help options)\n", + NULL +}; + static const char * const* cmd_synonyms () { char ** synonyms; char ** line; const struct cmd *c = &cmds[0]; - int numcmds = 2; /* two more for title and end */ + /* Three more for title, "specify --help" line, and NULL. */ + int numcmds = 3; while (c->fullname != NULL) { @@ -218,6 +262,7 @@ cmd_synonyms () line++; } } + *line++ = "(Specify the --help option for a list of other help options)\n"; *line = NULL; return (const char * const*) synonyms; /* will never be freed */ @@ -328,11 +373,10 @@ main (argc, argv) char *cp, *end; const struct cmd *cm; int c, err = 0; - int rcsbin_update_env, tmpdir_update_env, cvs_update_env; + int tmpdir_update_env, cvs_update_env; int free_CVSroot = 0; int free_Editor = 0; int free_Tmpdir = 0; - int free_Rcsbin = 0; int help = 0; /* Has the user asked for help? This lets us support the `cvs -H cmd' @@ -343,6 +387,7 @@ main (argc, argv) {"version", 0, NULL, 'v'}, {"help-commands", 0, NULL, 1}, {"help-synonyms", 0, NULL, 2}, + {"help-options", 0, NULL, 4}, {"allow-root", required_argument, NULL, 3}, {0, 0, 0, 0} }; @@ -380,12 +425,6 @@ main (argc, argv) * they can be overridden by command line arguments */ cvs_update_env = 0; - rcsbin_update_env = *Rcsbin; /* RCSBIN_DFLT must be set */ - if ((cp = getenv (RCSBIN_ENV)) != NULL) - { - Rcsbin = cp; - rcsbin_update_env = 0; /* it's already there */ - } tmpdir_update_env = *Tmpdir; /* TMPDIR_DFLT must be set */ if ((cp = getenv (TMPDIR_ENV)) != NULL) { @@ -404,7 +443,7 @@ main (argc, argv) cvs_update_env = 0; /* it's already there */ } if (getenv (CVSREAD_ENV) != NULL) - cvswrite = FALSE; + cvswrite = 0; /* Set this to 0 to force getopt initialization. getopt() sets this to 1 internally. */ @@ -421,7 +460,7 @@ main (argc, argv) != EOF) { if (c == 'f') - use_cvsrc = FALSE; + use_cvsrc = 0; } /* @@ -434,7 +473,7 @@ main (argc, argv) opterr = 1; while ((c = getopt_long - (argc, argv, "+Qqrwtnlvb:T:e:d:Hfz:s:x", long_options, &option_index)) + (argc, argv, "+Qqrwtnlvb:T:e:d:Hfz:s:xa", long_options, &option_index)) != EOF) { switch (c) @@ -447,47 +486,59 @@ main (argc, argv) /* --help-synonyms */ usage (cmd_synonyms()); break; + case 4: + /* --help-options */ + usage (opt_usage); + break; case 3: /* --allow-root */ root_allow_add (optarg); break; case 'Q': - really_quiet = TRUE; + really_quiet = 1; /* FALL THROUGH */ case 'q': - quiet = TRUE; + quiet = 1; break; case 'r': - cvswrite = FALSE; + cvswrite = 0; break; case 'w': - cvswrite = TRUE; + cvswrite = 1; break; case 't': - trace = TRUE; + trace = 1; break; case 'n': - noexec = TRUE; + noexec = 1; case 'l': /* Fall through */ - logoff = TRUE; + logoff = 1; break; case 'v': + /* Having the year here is a good idea, so people have + some idea of how long ago their version of CVS was + released. */ (void) fputs (version_string, stdout); (void) fputs (config_string, stdout); (void) fputs ("\n", stdout); - (void) fputs ("Copyright (c) 1993-1994 Brian Berliner\n", stdout); - (void) fputs ("Copyright (c) 1993-1994 david d `zoo' zuhn\n", stdout); - (void) fputs ("Copyright (c) 1992, Brian Berliner and Jeff Polk\n", stdout); - (void) fputs ("Copyright (c) 1989-1992, Brian Berliner\n", stdout); + (void) fputs ("\ +Copyright (c) 1989-1997 Brian Berliner, david d `zoo' zuhn, \n\ + Jeff Polk, and other authors\n", stdout); (void) fputs ("\n", stdout); (void) fputs ("CVS may be copied only under the terms of the GNU General Public License,\n", stdout); (void) fputs ("a copy of which can be found with the CVS distribution kit.\n", stdout); + (void) fputs ("\n", stdout); + + (void) fputs ("Specify the --help option for further information about CVS\n", stdout); + exit (0); break; case 'b': - Rcsbin = xstrdup (optarg); - free_Rcsbin = 1; - rcsbin_update_env = 1; /* need to update environment */ + /* This option used to specify the directory for RCS + executables. But since we don't run them any more, + this is a noop. Silently ignore it so that .cvsrc + and scripts and inetd.conf and such can work with + either new or old CVS. */ break; case 'T': Tmpdir = xstrdup (optarg); @@ -507,7 +558,7 @@ main (argc, argv) help = 1; break; case 'f': - use_cvsrc = FALSE; /* unnecessary, since we've done it above */ + use_cvsrc = 0; /* unnecessary, since we've done it above */ break; case 'z': #ifdef CLIENT_SUPPORT @@ -532,6 +583,15 @@ main (argc, argv) If no ENCRYPTION, we still accept -x, but issue an error if we are being run as a client. */ break; + case 'a': +#ifdef CLIENT_SUPPORT + cvsauthenticate = 1; +#endif + /* If no CLIENT_SUPPORT, ignore -a, so that users can + have it in their .cvsrc and not cause any trouble. + We will issue an error later if stream + authentication is not supported. */ + break; case '?': default: usage (usg); @@ -562,6 +622,9 @@ main (argc, argv) else command_name = cm->fullname; /* Global pointer for later use */ + /* This should probably remain a warning, rather than an error, + for quite a while. For one thing the version of VC distributed + with GNU emacs 19.34 invokes 'cvs rlog' instead of 'cvs log'. */ if (strcmp (argv[0], "rlog") == 0) { error (0, 0, "warning: the rlog command is deprecated"); @@ -605,7 +668,7 @@ main (argc, argv) #endif /* HAVE_KERBEROS */ -#if defined(AUTH_SERVER_SUPPORT) && defined(SERVER_SUPPORT) +#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT) if (strcmp (command_name, "pserver") == 0) { /* The reason that --allow-root is not a command option @@ -622,15 +685,16 @@ main (argc, argv) /* Pretend we were invoked as a plain server. */ command_name = "server"; } -#endif /* AUTH_SERVER_SUPPORT && SERVER_SUPPORT */ +#endif /* (AUTH_SERVER_SUPPORT || HAVE_GSSAPI) && SERVER_SUPPORT */ +#ifdef SERVER_SUPPORT + server_active = strcmp (command_name, "server") == 0; /* Fiddling with CVSROOT doesn't make sense if we're running in server mode, since the client will send the repository directory after the connection is made. */ -#ifdef SERVER_SUPPORT - if (strcmp (command_name, "server") != 0) + if (!server_active) #endif { char *CVSADM_Root; @@ -777,7 +841,7 @@ main (argc, argv) it is worth the trouble. */ #ifdef SERVER_SUPPORT - if (strcmp (command_name, "server") == 0) + if (server_active) CurDir = xstrdup ("<remote>"); else #endif @@ -791,16 +855,6 @@ main (argc, argv) Tmpdir = "/tmp"; #ifdef HAVE_PUTENV - /* Now, see if we should update the environment with the - Rcsbin value */ - if (rcsbin_update_env) - { - char *env; - env = xmalloc (strlen (RCSBIN_ENV) + strlen (Rcsbin) + 1 + 1); - (void) sprintf (env, "%s=%s", RCSBIN_ENV, Rcsbin); - (void) putenv (env); - /* do not free env, as putenv has control of it */ - } if (tmpdir_update_env) { char *env; @@ -811,24 +865,6 @@ main (argc, argv) } #endif - /* - * If Rcsbin is set to something, make sure it is terminated with - * a slash character. If not, add one. - */ - if (*Rcsbin) - { - int len = strlen (Rcsbin); - char *rcsbin; - - if (Rcsbin[len - 1] != '/') - { - rcsbin = Rcsbin; - Rcsbin = xmalloc (len + 2); /* one for '/', one for NULL */ - (void) strcpy (Rcsbin, rcsbin); - (void) strcat (Rcsbin, "/"); - } - } - #ifndef DONT_USE_SIGNALS /* make sure we clean up on error */ #ifdef SIGHUP @@ -866,6 +902,28 @@ main (argc, argv) if (use_cvsrc) read_cvsrc (&argc, &argv, command_name); + /* Parse the CVSROOT/config file, but only for local. For the + server, we parse it after we know $CVSROOT. For the + client, it doesn't get parsed at all, obviously. The + presence of the parse_config call here is not mean to + predetermine whether CVSROOT/config overrides things from + read_cvsrc and other such places or vice versa. That sort + of thing probably needs more thought. */ + if (1 +#ifdef SERVER_SUPPORT + && !server_active +#endif +#ifdef CLIENT_SUPPORT + && !client_active +#endif + ) + { + /* If there was an error parsing the config file, parse_config + already printed an error. We keep going. Why? Because + if we didn't, then there would be no way to check in a new + CVSROOT/config file to fix the broken one! */ + parse_config (CVSroot_directory); + } } /* end of stuff that gets done if the user DOESN'T ask for help */ err = (*(cm->func)) (argc, argv); @@ -874,7 +932,10 @@ main (argc, argv) { /* Update the CVS/Root file. We might want to do this in all directories that we recurse into, but currently we - don't. */ + don't. Note that if there is an error writing the file, + we give an error/warning. This is so if users try to rewrite + CVS/Root with the -d option (a documented feature), they will + either succeed, or be told why it didn't work. */ Create_Root (NULL, CVSroot); } @@ -887,8 +948,6 @@ main (argc, argv) free (Editor); if (free_Tmpdir) free (Tmpdir); - if (free_Rcsbin) - free (Rcsbin); root_allow_free (); #ifdef SYSTEM_CLEANUP @@ -900,6 +959,8 @@ main (argc, argv) /* This is exit rather than return because apparently that keeps some tools which check for memory leaks happier. */ exit (err ? EXIT_FAILURE : 0); + /* Keep picky/stupid compilers (e.g. Visual C++ 5.0) happy. */ + return 0; } char * @@ -914,11 +975,14 @@ Make_Date (rawdate) unixtime = get_date (rawdate, (struct timeb *) NULL); if (unixtime == (time_t) - 1) error (1, 0, "Can't parse date/time: %s", rawdate); -#ifdef HAVE_RCS5 + ftm = gmtime (&unixtime); -#else - ftm = localtime (&unixtime); -#endif + if (ftm == NULL) + /* This is a system, like VMS, where the system clock is in local + time. Hopefully using localtime here matches the "zero timezone" + hack I added to get_date. */ + ftm = localtime (&unixtime); + (void) sprintf (date, DATEFORM, ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900), ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour, |