summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/main.c')
-rw-r--r--contrib/cvs/src/main.c1240
1 files changed, 0 insertions, 1240 deletions
diff --git a/contrib/cvs/src/main.c b/contrib/cvs/src/main.c
deleted file mode 100644
index 332946a..0000000
--- a/contrib/cvs/src/main.c
+++ /dev/null
@@ -1,1240 +0,0 @@
-/*
- * Copyright (C) 1986-2008 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2006 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions 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 source distribution.
- *
- * This is the main C driver for the CVS system.
- *
- * Credit to Dick Grune, Vrije Universiteit, Amsterdam, for writing
- * the shell-script CVS system that this is based on.
- *
- * $FreeBSD$
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "prepend_args.h"
-
-#ifdef HAVE_WINSOCK_H
-#include <winsock.h>
-#else
-extern int gethostname ();
-#endif
-
-const char *program_name;
-const char *program_path;
-const char *cvs_cmd_name;
-
-/* I'd dynamically allocate this, but it seems like gethostname
- requires a fixed size array. If I'm remembering the RFCs right,
- 256 should be enough. */
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 256
-#endif
-
-char hostname[MAXHOSTNAMELEN];
-
-int use_editor = 1;
-int use_cvsrc = 1;
-int cvswrite = !CVSREAD_DFLT;
-int really_quiet = 0;
-int quiet = 0;
-int trace = 0;
-int noexec = 0;
-int readonlyfs = 0;
-int require_real_user = 0;
-int logoff = 0;
-
-/*
- * Zero if compression isn't supported or requested; non-zero to indicate
- * a compression level to request from gzip.
- */
-int gzip_level;
-
-/* Set if we should be writing CVSADM directories at top level. At
- least for now we'll make the default be off (the CVS 1.9, not CVS
- 1.9.2, behavior). */
-int top_level_admin = 0;
-
-mode_t cvsumask = UMASK_DFLT;
-
-char *CurDir;
-
-/*
- * Defaults, for the environment variables that are not set
- */
-char *Tmpdir = TMPDIR_DFLT;
-char *Editor = EDITOR_DFLT;
-
-
-/* When our working directory contains subdirectories with different
- values in CVS/Root files, we maintain a list of them. */
-List *root_directories = NULL;
-
-static const struct cmd
-{
- char *fullname; /* Full name of the function (e.g. "commit") */
-
- /* Synonyms for the command, nick1 and nick2. We supply them
- mostly for two reasons: (1) CVS has always supported them, and
- we need to maintain compatibility, (2) if there is a need for a
- version which is shorter than the fullname, for ease in typing.
- Synonyms have the disadvantage that people will see "new" and
- then have to think about it, or look it up, to realize that is
- the operation they know as "add". Also, this means that one
- cannot create a command "cvs new" with a different meaning. So
- new synonyms are probably best used sparingly, and where used
- should be abbreviations of the fullname (preferably consisting
- of the first 2 or 3 or so letters).
-
- One thing that some systems do is to recognize any unique
- abbreviation, for example "annotat" "annota", etc., for
- "annotate". The problem with this is that scripts and user
- habits will expect a certain abbreviation to be unique, and in
- a future release of CVS it may not be. So it is better to
- accept only an explicit list of abbreviations and plan on
- supporting them in the future as well as now. */
-
- char *nick1;
- char *nick2;
-
- int (*func) (); /* Function takes (argc, argv) arguments. */
- unsigned long attr; /* Attributes. */
-} cmds[] =
-
-{
- { "add", "ad", "new", add, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "admin", "adm", "rcs", admin, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "annotate", "ann", "blame", annotate, CVS_CMD_USES_WORK_DIR },
- { "checkout", "co", "get", checkout, 0 },
- { "commit", "ci", "com", commit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "diff", "di", "dif", diff, CVS_CMD_USES_WORK_DIR },
- { "edit", NULL, NULL, edit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "editors", NULL, NULL, editors, CVS_CMD_USES_WORK_DIR },
- { "export", "exp", "ex", checkout, CVS_CMD_USES_WORK_DIR },
- { "history", "hi", "his", history, CVS_CMD_USES_WORK_DIR },
- { "import", "im", "imp", import, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR | CVS_CMD_IGNORE_ADMROOT},
- { "init", NULL, NULL, init, CVS_CMD_MODIFIES_REPOSITORY },
-#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
- { "kserver", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
-#endif
- { "log", "lo", NULL, cvslog, CVS_CMD_USES_WORK_DIR },
-#ifdef AUTH_CLIENT_SUPPORT
- { "login", "logon", "lgn", login, 0 },
- { "logout", NULL, NULL, logout, 0 },
-#endif /* AUTH_CLIENT_SUPPORT */
-#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
- { "pserver", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
-#endif
- { "rannotate","rann", "ra", annotate, 0 },
- { "rdiff", "patch", "pa", patch, 0 },
- { "release", "re", "rel", release, 0 },
- { "remove", "rm", "delete", cvsremove, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "rlog", "rl", NULL, cvslog, 0 },
- { "rtag", "rt", "rfreeze", cvstag, CVS_CMD_MODIFIES_REPOSITORY },
-#ifdef SERVER_SUPPORT
- { "server", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
-#endif
- { "status", "st", "stat", cvsstatus, CVS_CMD_USES_WORK_DIR },
- { "tag", "ta", "freeze", cvstag, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "unedit", NULL, NULL, unedit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "update", "up", "upd", update, CVS_CMD_USES_WORK_DIR },
- { "version", "ve", "ver", version, 0 },
- { "watch", NULL, NULL, watch, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "watchers", NULL, NULL, watchers, CVS_CMD_USES_WORK_DIR },
- { NULL, NULL, NULL, NULL, 0 },
-};
-
-static const char *const usg[] =
-{
- /* 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. Punctuation 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",
-
- /* 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",
- " the CVS home page at http://cvs.nongnu.org/\n",
- NULL,
-};
-
-static const char *const cmd_usage[] =
-{
- "CVS commands are:\n",
- " add Add a new file/directory to the repository\n",
- " admin Administration front end for rcs\n",
- " annotate Show last revision where each line was modified\n",
- " checkout Checkout sources for editing\n",
- " commit Check files into the repository\n",
- " diff Show differences between revisions\n",
- " edit Get ready to edit a watched file\n",
- " editors See who is editing a watched file\n",
- " export Export sources from CVS, similar to checkout\n",
- " history Show repository access history\n",
- " import Import sources into CVS, using vendor branches\n",
- " init Create a CVS repository if it doesn't exist\n",
-#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
- " kserver Kerberos server mode\n",
-#endif
- " log Print out history information for files\n",
-#ifdef AUTH_CLIENT_SUPPORT
- " login Prompt for password for authenticating server\n",
- " logout Removes entry in .cvspass for remote repository\n",
-#endif /* AUTH_CLIENT_SUPPORT */
-#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
- " pserver Password server mode\n",
-#endif
- " rannotate Show last revision where each line of module was modified\n",
- " rdiff Create 'patch' format diffs between releases\n",
- " release Indicate that a Module is no longer in use\n",
- " remove Remove an entry from the repository\n",
- " rlog Print out history information for a module\n",
- " rtag Add a symbolic tag to a module\n",
-#ifdef SERVER_SUPPORT
- " server Server mode\n",
-#endif
- " status Display status information on checked out files\n",
- " tag Add a symbolic tag to checked out version of files\n",
- " unedit Undo an edit command\n",
- " update Bring work tree in sync with repository\n",
- " version Show current CVS version(s)\n",
- " watch Set watches\n",
- " watchers See who is watching a file\n",
- "(Specify the --help option for a list of other help options)\n",
- NULL,
-};
-
-static const char *const opt_usage[] =
-{
- /* Omit -b because it is just for compatibility. */
- "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",
- " -g Force group-write perms on checked-out files.\n",
- " -n Do not execute anything that will change the disk.\n",
- " -t Show trace of program execution -- try with -n.\n",
- " -R Assume repository is read-only, such as CDROM\n",
- " -v CVS version and copyright.\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 int
-set_root_directory (p, ignored)
- Node *p;
- void *ignored;
-{
- if (current_parsed_root == NULL && p->data != NULL)
- {
- current_parsed_root = p->data;
- return 1;
- }
- return 0;
-}
-
-
-static const char * const*
-cmd_synonyms ()
-{
- char ** synonyms;
- char ** line;
- const struct cmd *c = &cmds[0];
- /* Three more for title, "specify --help" line, and NULL. */
- int numcmds = 3;
-
- while (c->fullname != NULL)
- {
- numcmds++;
- c++;
- }
-
- synonyms = (char **) xmalloc(numcmds * sizeof(char *));
- line = synonyms;
- *line++ = "CVS command synonyms are:\n";
- for (c = &cmds[0]; c->fullname != NULL; c++)
- {
- if (c->nick1 || c->nick2)
- {
- *line = xmalloc (strlen (c->fullname)
- + (c->nick1 != NULL ? strlen (c->nick1) : 0)
- + (c->nick2 != NULL ? strlen (c->nick2) : 0)
- + 40);
- sprintf(*line, " %-12s %s %s\n", c->fullname,
- c->nick1 ? c->nick1 : "",
- c->nick2 ? c->nick2 : "");
- 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 */
-}
-
-
-unsigned long int
-lookup_command_attribute (cmd_name)
- char *cmd_name;
-{
- const struct cmd *cm;
-
- for (cm = cmds; cm->fullname; cm++)
- {
- if (strcmp (cmd_name, cm->fullname) == 0)
- break;
- }
- if (!cm->fullname)
- error (1, 0, "unknown command: %s", cmd_name);
- return cm->attr;
-}
-
-
-static RETSIGTYPE
-main_cleanup (sig)
- int sig;
-{
-#ifndef DONT_USE_SIGNALS
- const char *name;
- char temp[10];
-
- switch (sig)
- {
-#ifdef SIGABRT
- case SIGABRT:
- name = "abort";
- break;
-#endif
-#ifdef SIGHUP
- case SIGHUP:
- name = "hangup";
- break;
-#endif
-#ifdef SIGINT
- case SIGINT:
- name = "interrupt";
- break;
-#endif
-#ifdef SIGQUIT
- case SIGQUIT:
- name = "quit";
- break;
-#endif
-#ifdef SIGPIPE
- case SIGPIPE:
- name = "broken pipe";
- break;
-#endif
-#ifdef SIGTERM
- case SIGTERM:
- name = "termination";
- break;
-#endif
- default:
- /* This case should never be reached, because we list above all
- the signals for which we actually establish a signal handler. */
- sprintf (temp, "%d", sig);
- name = temp;
- break;
- }
-
- error (1, 0, "received %s signal", name);
-#endif /* !DONT_USE_SIGNALS */
-}
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- cvsroot_t *CVSroot_parsed = NULL;
- int cvsroot_update_env = 1;
- char *cp, *end;
- const struct cmd *cm;
- int c, err = 0;
- int tmpdir_update_env;
- int free_Editor = 0;
- int free_Tmpdir = 0;
-
- int help = 0; /* Has the user asked for help? This
- lets us support the `cvs -H cmd'
- convention to give help for cmd. */
- static const char short_options[] = "+QqgrwtnRvb:T:e:d:Hfz:s:xaU";
- static struct option long_options[] =
- {
- {"help", 0, NULL, 'H'},
- {"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}
- };
- /* `getopt_long' stores the option index here, but right now we
- don't use it. */
- int option_index = 0;
-
-#ifdef SYSTEM_INITIALIZE
- /* Hook for OS-specific behavior, for example socket subsystems on
- NT and OS2 or dealing with windows and arguments on Mac. */
- SYSTEM_INITIALIZE (&argc, &argv);
-#endif
-
-#ifdef HAVE_TZSET
- /* On systems that have tzset (which is almost all the ones I know
- of), it's a good idea to call it. */
- tzset ();
-#endif
-
- /*
- * Just save the last component of the path for error messages
- */
- program_path = xstrdup (argv[0]);
-#ifdef ARGV0_NOT_PROGRAM_NAME
- /* On some systems, e.g. VMS, argv[0] is not the name of the command
- which the user types to invoke the program. */
- program_name = "cvs";
-#else
- program_name = last_component (argv[0]);
-#endif
-
- /*
- * Query the environment variables up-front, so that
- * they can be overridden by command line arguments
- */
- tmpdir_update_env = *Tmpdir; /* TMPDIR_DFLT must be set */
- if ((cp = getenv (TMPDIR_ENV)) != NULL)
- {
- Tmpdir = cp;
- tmpdir_update_env = 0; /* it's already there */
- }
- if ((cp = getenv (EDITOR1_ENV)) != NULL)
- Editor = cp;
- else if ((cp = getenv (EDITOR2_ENV)) != NULL)
- Editor = cp;
- else if ((cp = getenv (EDITOR3_ENV)) != NULL)
- Editor = cp;
- if (getenv (CVSREAD_ENV) != NULL)
- cvswrite = 0;
- if (getenv (CVSREADONLYFS_ENV) != NULL) {
- readonlyfs = 1;
- logoff = 1;
- }
-
- prepend_default_options (getenv ("CVS_OPTIONS"), &argc, &argv);
-
- /* Set this to 0 to force getopt initialization. getopt() sets
- this to 1 internally. */
- optind = 0;
-
- /* We have to parse the options twice because else there is no
- chance to avoid reading the global options from ".cvsrc". Set
- opterr to 0 for avoiding error messages about invalid options.
- */
- opterr = 0;
-
- while ((c = getopt_long
- (argc, argv, short_options, long_options, &option_index))
- != EOF)
- {
- if (c == 'f')
- use_cvsrc = 0;
- }
-
- /*
- * Scan cvsrc file for global options.
- */
- if (use_cvsrc)
- read_cvsrc (&argc, &argv, "cvs");
-
- optind = 0;
- opterr = 1;
-
- while ((c = getopt_long
- (argc, argv, short_options, long_options, &option_index))
- != EOF)
- {
- switch (c)
- {
- case 1:
- /* --help-commands */
- usage (cmd_usage);
- break;
- case 2:
- /* --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 = 1;
- /* FALL THROUGH */
- case 'q':
- quiet = 1;
- break;
- case 'r':
- cvswrite = 0;
- break;
- case 'w':
- cvswrite = 1;
- break;
- case 'g':
- /*
- * force full group write perms (used for shared checked-out
- * source trees, see manual page)
- */
- umask(umask(077) & 007);
- break;
- case 't':
- trace = 1;
- break;
- case 'R':
- readonlyfs = 1;
- logoff = 1;
- break;
- case 'n':
- noexec = 1;
- logoff = 1;
- break;
- case 'v':
- (void) fputs ("\n", stdout);
- version (0, (char **) NULL);
- (void) fputs ("\n", stdout);
- (void) fputs ("\
-Copyright (C) 2006 Free Software Foundation, Inc.\n\
-\n\
-Senior active maintainers include Larry Jones, Derek R. Price,\n\
-and Mark D. Baushke. Please see the AUTHORS and README files from the CVS\n\
-distribution kit for a complete list of contributors and copyrights.\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);
-
-#ifdef SYSTEM_CLEANUP
- /* Hook for OS-specific behavior, for example socket subsystems
- * on NT and OS2 or dealing with windows and arguments on Mac.
- */
- SYSTEM_CLEANUP ();
-#endif
- exit (0);
- break;
- case 'b':
- /* 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':
- if (free_Tmpdir) free (Tmpdir);
- Tmpdir = xstrdup (optarg);
- free_Tmpdir = 1;
- tmpdir_update_env = 1; /* need to update environment */
- break;
- case 'e':
- if (free_Editor) free (Editor);
- Editor = xstrdup (optarg);
- free_Editor = 1;
- break;
- case 'd':
- if (CVSroot_cmdline != NULL)
- free (CVSroot_cmdline);
- CVSroot_cmdline = xstrdup (optarg);
- break;
- case 'H':
- help = 1;
- break;
- case 'f':
- use_cvsrc = 0; /* unnecessary, since we've done it above */
- break;
- case 'z':
- gzip_level = strtol (optarg, &end, 10);
- if (*end != '\0' || gzip_level < 0 || gzip_level > 9)
- error (1, 0,
- "gzip compression level must be between 0 and 9");
- /* If no CLIENT_SUPPORT, we just silently ignore the gzip
- * level, so that users can have it in their .cvsrc and not
- * cause any trouble.
- *
- * We still parse the argument to -z for correctness since
- * one user complained of being bitten by a run of
- * `cvs -z -n up' which read -n as the argument to -z without
- * complaining. */
- break;
- case 's':
- variable_set (optarg);
- break;
- case 'x':
-#ifdef CLIENT_SUPPORT
- cvsencrypt = 1;
-#endif /* CLIENT_SUPPORT */
- /* If no CLIENT_SUPPORT, ignore -x, so that users can
- have it in their .cvsrc and not cause any trouble.
- 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 'U':
-#ifdef SERVER_SUPPORT
- require_real_user = 1;
-#endif
- break;
- case '?':
- default:
- usage (usg);
- }
- }
-
- argc -= optind;
- argv += optind;
- if (argc < 1)
- usage (usg);
-
-
- /* Look up the command name. */
-
- cvs_cmd_name = argv[0];
- for (cm = cmds; cm->fullname; cm++)
- {
- if (cm->nick1 && !strcmp (cvs_cmd_name, cm->nick1))
- break;
- if (cm->nick2 && !strcmp (cvs_cmd_name, cm->nick2))
- break;
- if (!strcmp (cvs_cmd_name, cm->fullname))
- break;
- }
-
- if (!cm->fullname)
- {
- fprintf (stderr, "Unknown command: `%s'\n\n", cvs_cmd_name);
- usage (cmd_usage);
- }
- else
- cvs_cmd_name = cm->fullname; /* Global pointer for later use */
-
- if (help)
- {
- argc = -1; /* some functions only check for this */
- err = (*(cm->func)) (argc, argv);
- }
- else
- {
- /* The user didn't ask for help, so go ahead and authenticate,
- set up CVSROOT, and the rest of it. */
-
- /* The UMASK environment variable isn't handled with the
- others above, since we don't want to signal errors if the
- user has asked for help. This won't work if somebody adds
- a command-line flag to set the umask, since we'll have to
- parse it before we get here. */
-
- if ((cp = getenv (CVSUMASK_ENV)) != NULL)
- {
- /* FIXME: Should be accepting symbolic as well as numeric mask. */
- cvsumask = strtol (cp, &end, 8) & 0777;
- if (*end != '\0')
- error (1, errno, "invalid umask value in %s (%s)",
- CVSUMASK_ENV, cp);
- }
-
-#ifdef SERVER_SUPPORT
-
-# ifdef HAVE_KERBEROS
- /* If we are invoked with a single argument "kserver", then we are
- running as Kerberos server as root. Do the authentication as
- the very first thing, to minimize the amount of time we are
- running as root. */
- if (strcmp (cvs_cmd_name, "kserver") == 0)
- {
- kserver_authenticate_connection ();
-
- /* Pretend we were invoked as a plain server. */
- cvs_cmd_name = "server";
- }
-# endif /* HAVE_KERBEROS */
-
-
-# if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
- if (strcmp (cvs_cmd_name, "pserver") == 0)
- {
- /* The reason that --allow-root is not a command option
- is mainly the comment in server() about how argc,argv
- might be from .cvsrc. I'm not sure about that, and
- I'm not sure it is only true of command options, but
- it seems easier to make it a global option. */
-
- /* Gets username and password from client, authenticates, then
- switches to run as that user and sends an ACK back to the
- client. */
- pserver_authenticate_connection ();
-
- /* Pretend we were invoked as a plain server. */
- cvs_cmd_name = "server";
- }
-# endif /* AUTH_SERVER_SUPPORT || HAVE_GSSAPI */
-#endif /* SERVER_SUPPORT */
-
- server_active = strcmp (cvs_cmd_name, "server") == 0;
-
- /* This is only used for writing into the history file. For
- remote connections, it might be nice to have hostname
- and/or remote path, on the other hand I'm not sure whether
- it is worth the trouble. */
-
- if (server_active)
- CurDir = xstrdup ("<remote>");
- else
- {
- CurDir = xgetwd ();
- if (CurDir == NULL)
- error (1, errno, "cannot get working directory");
- }
-
- if (Tmpdir == NULL || Tmpdir[0] == '\0')
- {
- if (free_Tmpdir) free (Tmpdir);
- Tmpdir = "/tmp";
- }
-
-#ifdef HAVE_PUTENV
- if (tmpdir_update_env)
- {
- char *env;
- env = xmalloc (strlen (TMPDIR_ENV) + strlen (Tmpdir) + 1 + 1);
- (void) sprintf (env, "%s=%s", TMPDIR_ENV, Tmpdir);
- (void) putenv (env);
- /* do not free env, as putenv has control of it */
- }
- {
- char *env;
- env = xmalloc (sizeof "CVS_PID=" + 32); /* XXX pid < 10^32 */
- (void) sprintf (env, "CVS_PID=%ld", (long) getpid ());
- (void) putenv (env);
- }
-#endif
-
-#ifndef DONT_USE_SIGNALS
- /* make sure we clean up on error */
-#ifdef SIGABRT
- (void) SIG_register (SIGABRT, main_cleanup);
-#endif
-#ifdef SIGHUP
- (void) SIG_register (SIGHUP, main_cleanup);
-#endif
-#ifdef SIGINT
- (void) SIG_register (SIGINT, main_cleanup);
-#endif
-#ifdef SIGQUIT
- (void) SIG_register (SIGQUIT, main_cleanup);
-#endif
-#ifdef SIGPIPE
- (void) SIG_register (SIGPIPE, main_cleanup);
-#endif
-#ifdef SIGTERM
- (void) SIG_register (SIGTERM, main_cleanup);
-#endif
-#endif /* !DONT_USE_SIGNALS */
-
- gethostname(hostname, sizeof (hostname));
-
-#ifdef KLUDGE_FOR_WNT_TESTSUITE
- /* Probably the need for this will go away at some point once
- we call fflush enough places (e.g. fflush (stdout) in
- cvs_outerr). */
- (void) setvbuf (stdout, (char *) NULL, _IONBF, 0);
- (void) setvbuf (stderr, (char *) NULL, _IONBF, 0);
-#endif /* KLUDGE_FOR_WNT_TESTSUITE */
-
- if (use_cvsrc)
- read_cvsrc (&argc, &argv, cvs_cmd_name);
-
- /* 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.
- */
- if (!server_active)
- {
- /* First check if a root was set via the command line. */
- if (CVSroot_cmdline)
- {
- if (!(CVSroot_parsed = parse_cvsroot (CVSroot_cmdline)))
- error (1, 0, "Bad CVSROOT: `%s'.", CVSroot_cmdline);
- }
-
- /* See if we are able to find a 'better' value for CVSroot
- * in the CVSADM_ROOT directory.
- *
- * "cvs import" shouldn't check CVS/Root; in general it
- * ignores CVS directories and CVS/Root is likely to
- * specify a different repository than the one we are
- * importing to, but if this is not import and no root was
- * specified on the command line, set the root from the
- * CVS/Root file.
- */
- if (!CVSroot_parsed
- && !(cm->attr & CVS_CMD_IGNORE_ADMROOT)
- )
- CVSroot_parsed = Name_Root (NULL, NULL);
-
- /* Now, if there is no root on the command line and we didn't find
- * one in a file, set it via the $CVSROOT env var.
- */
- if (!CVSroot_parsed)
- {
- char *tmp = getenv (CVSROOT_ENV);
- if (tmp)
- {
- if (!(CVSroot_parsed = parse_cvsroot (tmp)))
- error (1, 0, "Bad CVSROOT: `%s'.", tmp);
- cvsroot_update_env = 0;
- }
- }
-
-#ifdef CVSROOT_DFLT
- if (!CVSroot_parsed)
- {
- if (!(CVSroot_parsed = parse_cvsroot (CVSROOT_DFLT)))
- error (1, 0, "Bad CVSROOT: `%s'.", CVSROOT_DFLT);
- }
-#endif /* CVSROOT_DFLT */
-
- /* Now we've reconciled CVSROOT from the command line, the
- CVS/Root file, and the environment variable. Do the
- last sanity checks on the variable. */
- if (!CVSroot_parsed)
- {
- error (0, 0,
- "No CVSROOT specified! Please use the `-d' option");
- error (1, 0,
- "or set the %s environment variable.", CVSROOT_ENV);
- }
- }
-
- /* Here begins the big loop over unique cvsroot values. We
- need to call do_recursion once for each unique value found
- in CVS/Root. Prime the list with the current value. */
-
- /* Create the list. */
- assert (root_directories == NULL);
- root_directories = getlist ();
-
- /* Prime it. */
- if (CVSroot_parsed)
- {
- Node *n;
- n = getnode ();
- n->type = NT_UNKNOWN;
- n->key = xstrdup (CVSroot_parsed->original);
- n->data = CVSroot_parsed;
-
- if (addnode (root_directories, n))
- error (1, 0, "cannot add initial CVSROOT %s", n->key);
- }
-
- assert (current_parsed_root == NULL);
-
- /* If we're running the server, we want to execute this main
- loop once and only once (we won't be serving multiple roots
- from this connection, so there's no need to do it more than
- once). To get out of the loop, we perform a "break" at the
- end of things. */
-
- while (server_active ||
- walklist (root_directories, set_root_directory, NULL))
- {
- /* 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. */
-
- if (!server_active)
- {
- /* Now we're 100% sure that we have a valid CVSROOT
- variable. Parse it to see if we're supposed to do
- remote accesses or use a special access method. */
-
- if (trace)
- fprintf (stderr, "%s-> main loop with CVSROOT=%s\n",
- CLIENT_SERVER_STR, current_parsed_root->original);
-
- /*
- * Check to see if the repository exists.
- */
- if (!current_parsed_root->isremote)
- {
- char *path;
- int save_errno;
-
- path = xmalloc (strlen (current_parsed_root->directory)
- + strlen (CVSROOTADM) + 2);
- sprintf (path, "%s/%s", current_parsed_root->directory,
- CVSROOTADM);
- if (!isaccessible (path, R_OK | X_OK))
- {
- save_errno = errno;
- /* If this is "cvs init", the root need not exist yet.
- */
- if (strcmp (cvs_cmd_name, "init"))
- error (1, save_errno, "%s", path);
- }
- free (path);
- }
-
-#ifdef HAVE_PUTENV
- /* Update the CVSROOT environment variable. */
- if (cvsroot_update_env)
- {
- static char *prev;
- char *env;
-
- env = xmalloc (strlen (CVSROOT_ENV)
- + strlen (current_parsed_root->original)
- + 2);
- sprintf (env, "%s=%s", CVSROOT_ENV,
- current_parsed_root->original);
- (void) putenv (env);
- /* do not free env yet, as putenv has control of it */
- /* but do free the previous value, if any */
- if (prev != NULL)
- free (prev);
- prev = env;
- }
-#endif
- }
-
- /* 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 (!server_active && !current_parsed_root->isremote)
- {
- /* 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 (current_parsed_root->directory);
-
- /* Now is a convenient time to read CVSROOT/options */
- parseopts(current_parsed_root->directory);
- }
-
-#ifdef CLIENT_SUPPORT
- /* Need to check for current_parsed_root != NULL here since
- * we could still be in server mode before the server function
- * gets called below and sets the root
- */
- if (current_parsed_root != NULL && current_parsed_root->isremote)
- {
- /* Create a new list for directory names that we've
- sent to the server. */
- if (dirs_sent_to_server != NULL)
- dellist (&dirs_sent_to_server);
- dirs_sent_to_server = getlist ();
- }
-#endif
-
- err = (*(cm->func)) (argc, argv);
-
- /* Mark this root directory as done. When the server is
- active, our list will be empty -- don't try and
- remove it from the list. */
-
- if (!server_active)
- {
- Node *n = findnode (root_directories,
- current_parsed_root->original);
- assert (n != NULL);
- assert (n->data != NULL);
- free_cvsroot_t (n->data);
- n->data = NULL;
- current_parsed_root = NULL;
- }
-
- if (server_active)
- {
- server_active = 0;
- break;
- }
- } /* end of loop for cvsroot values */
-
- dellist (&root_directories);
- } /* end of stuff that gets done if the user DOESN'T ask for help */
-
- Lock_Cleanup ();
-
- /* It's okay to cast out the const below since we know we allocated this in
- * this function. The const was to keep other functions from messing with
- * this.
- */
- free ((char *)program_path);
- if (CVSroot_cmdline != NULL)
- free (CVSroot_cmdline);
- if (free_Editor)
- free (Editor);
- if (free_Tmpdir)
- free (Tmpdir);
- root_allow_free ();
-
-#ifdef SYSTEM_CLEANUP
- /* Hook for OS-specific behavior, for example socket subsystems on
- NT and OS2 or dealing with windows and arguments on Mac. */
- SYSTEM_CLEANUP ();
-#endif
-
- /* 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 *
-Make_Date (rawdate)
- char *rawdate;
-{
- time_t unixtime;
-
- unixtime = get_date (rawdate, (struct timeb *) NULL);
- if (unixtime == (time_t) - 1)
- error (1, 0, "Can't parse date/time: %s", rawdate);
- return date_from_time_t (unixtime);
-}
-
-/* Convert a time_t to an RCS format date. This is mainly for the
- use of "cvs history", because the CVSROOT/history file contains
- time_t format dates; most parts of CVS will want to avoid using
- time_t's directly, and instead use RCS_datecmp, Make_Date, &c.
- Assuming that the time_t is in GMT (as it generally should be),
- then the result will be in GMT too.
-
- Returns a newly malloc'd string. */
-
-char *
-date_from_time_t (unixtime)
- time_t unixtime;
-{
- struct tm *ftm;
- char date[MAXDATELEN];
- char *ret;
-
- ftm = gmtime (&unixtime);
- 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 (get_date of course being the relevant
- issue for Make_Date, and for history.c too I think). */
- 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,
- ftm->tm_min, ftm->tm_sec);
- ret = xstrdup (date);
- return (ret);
-}
-
-/* Convert a date to RFC822/1123 format. This is used in contexts like
- dates to send in the protocol; it should not vary based on locale or
- other such conventions for users. We should have another routine which
- does that kind of thing.
-
- The SOURCE date is in our internal RCS format. DEST should point to
- storage managed by the caller, at least MAXDATELEN characters. */
-void
-date_to_internet (dest, source)
- char *dest;
- const char *source;
-{
- struct tm date;
-
- date_to_tm (&date, source);
- tm_to_internet (dest, &date);
-}
-
-void
-date_to_tm (dest, source)
- struct tm *dest;
- const char *source;
-{
- if (sscanf (source, SDATEFORM,
- &dest->tm_year, &dest->tm_mon, &dest->tm_mday,
- &dest->tm_hour, &dest->tm_min, &dest->tm_sec)
- != 6)
- /* Is there a better way to handle errors here? I made this
- non-fatal in case we are called from the code which can't
- deal with fatal errors. */
- error (0, 0, "internal error: bad date %s", source);
-
- if (dest->tm_year > 100)
- dest->tm_year -= 1900;
-
- dest->tm_mon -= 1;
-}
-
-/* Convert a date to RFC822/1123 format. This is used in contexts like
- dates to send in the protocol; it should not vary based on locale or
- other such conventions for users. We should have another routine which
- does that kind of thing.
-
- The SOURCE date is a pointer to a struct tm. DEST should point to
- storage managed by the caller, at least MAXDATELEN characters. */
-void
-tm_to_internet (dest, source)
- char *dest;
- const struct tm *source;
-{
- /* Just to reiterate, these strings are from RFC822 and do not vary
- according to locale. */
- static const char *const month_names[] =
- {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
- sprintf (dest, "%d %s %d %02d:%02d:%02d -0000", source->tm_mday,
- source->tm_mon < 0 || source->tm_mon > 11 ? "???" : month_names[source->tm_mon],
- source->tm_year + 1900, source->tm_hour, source->tm_min, source->tm_sec);
-}
-
-void
-usage (cpp)
- register const char *const *cpp;
-{
- (void) fprintf (stderr, *cpp++, program_name, cvs_cmd_name);
- for (; *cpp; cpp++)
- (void) fprintf (stderr, *cpp);
- error_exit ();
-}
-
-void
-parseopts(root)
- const char *root;
-{
- char path[PATH_MAX];
- int save_errno;
- char buf[1024];
- const char *p;
- char *q;
- FILE *fp;
-
- if (root == NULL) {
- printf("no CVSROOT in parseopts\n");
- return;
- }
- p = strchr (root, ':');
- if (p)
- p++;
- else
- p = root;
- if (p == NULL) {
- printf("mangled CVSROOT in parseopts\n");
- return;
- }
- (void) sprintf (path, "%s/%s/%s", p, CVSROOTADM, CVSROOTADM_OPTIONS);
- if ((fp = fopen(path, "r")) != NULL) {
- while (fgets(buf, sizeof buf, fp) != NULL) {
- if (buf[0] == '#')
- continue;
- q = strrchr(buf, '\n');
- if (q)
- *q = '\0';
-
- if (!strcmp(buf, "iso8601")) {
- datesep = '-';
- }
- if (!strncmp(buf, "tag=", 4)) {
- char *what;
- char *rcs_localid;
-
- rcs_localid = buf + 4;
- RCS_setlocalid(rcs_localid);
- }
- if (!strncmp(buf, "tagexpand=", 10)) {
- char *what;
- char *rcs_incexc;
-
- rcs_incexc = buf + 10;
- RCS_setincexc(rcs_incexc);
- }
- /*
- * OpenBSD has a "umask=" and "dlimit=" command, we silently
- * ignore them here since they are not much use to us. cvsumask
- * defaults to 002 already, and the dlimit (data size limit)
- * should really be handled elsewhere (eg: login.conf).
- */
- }
- fclose(fp);
- }
-}
OpenPOWER on IntegriCloud