=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/cvs/cvs.c,v retrieving revision 1.16 retrieving revision 1.17 diff -c -r1.16 -r1.17 *** src/usr.bin/cvs/cvs.c 2004/12/06 21:58:31 1.16 --- src/usr.bin/cvs/cvs.c 2004/12/07 06:33:10 1.17 *************** *** 1,4 **** ! /* $OpenBSD: cvs.c,v 1.16 2004/12/06 21:58:31 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau * All rights reserved. --- 1,4 ---- ! /* $OpenBSD: cvs.c,v 1.17 2004/12/07 06:33:10 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau * All rights reserved. *************** *** 52,64 **** /* compression level used with zlib, 0 meaning no compression taking place */ int cvs_compress = 0; int cvs_trace = 0; int cvs_nolog = 0; int cvs_readonly = 0; ! int cvs_nocase = 0; /* set to 1 to disable case sensitivity on filenames */ ! /* name of the command we are running */ ! char *cvs_command; int cvs_cmdop; char *cvs_rootstr; char *cvs_rsh = CVS_RSH_DEFAULT; --- 52,65 ---- /* compression level used with zlib, 0 meaning no compression taking place */ int cvs_compress = 0; + int cvs_readrc = 1; /* read .cvsrc on startup */ int cvs_trace = 0; int cvs_nolog = 0; int cvs_readonly = 0; ! int cvs_nocase = 0; /* set to 1 to disable filename case sensitivity */ ! char *cvs_defargs; /* default global arguments from .cvsrc */ ! char *cvs_command; /* name of the command we are running */ int cvs_cmdop; char *cvs_rootstr; char *cvs_rsh = CVS_RSH_DEFAULT; *************** *** 93,158 **** --- 94,170 ---- char *cmd_synopsis; char *cmd_opts; char cmd_descr[CVS_CMD_MAXDESCRLEN]; + char *cmd_defargs; } cvs_cdt[] = { { CVS_OP_ADD, "add", { "ad", "new" }, cvs_add, "[-m msg] file ...", "", "Add a new file/directory to the repository", + NULL, }, { -1, "admin", { "adm", "rcs" }, NULL, "", "", "Administration front end for rcs", + NULL, }, { CVS_OP_ANNOTATE, "annotate", { "ann" }, NULL, "", "", "Show last revision where each line was modified", + NULL, }, { CVS_OP_CHECKOUT, "checkout", { "co", "get" }, cvs_checkout, "", "", "Checkout sources for editing", + NULL, }, { CVS_OP_COMMIT, "commit", { "ci", "com" }, cvs_commit, "[-flR] [-F logfile | -m msg] [-r rev] ...", "F:flm:Rr:", "Check files into the repository", + NULL, }, { CVS_OP_DIFF, "diff", { "di", "dif" }, cvs_diff, "[-cilu] [-D date] [-r rev] ...", "cD:ilur:", "Show differences between revisions", + NULL, }, { -1, "edit", { }, NULL, "", "", "Get ready to edit a watched file", + NULL, }, { -1, "editors", { }, NULL, "", "", "See who is editing a watched file", + NULL, }, { -1, "export", { "ex", "exp" }, NULL, "", "", "Export sources from CVS, similar to checkout", + NULL, }, { CVS_OP_HISTORY, "history", { "hi", "his" }, cvs_history, "", "", "Show repository access history", + NULL, }, { CVS_OP_IMPORT, "import", { "im", "imp" }, NULL, *************** *** 160,171 **** --- 172,185 ---- "repository vendor-tag release-tags ...", "b:dI:k:m:", "Import sources into CVS, using vendor branches", + NULL, }, { CVS_OP_INIT, "init", { }, cvs_init, "", "", "Create a CVS repository if it doesn't exist", + NULL, }, #if defined(HAVE_KERBEROS) { *************** *** 173,178 **** --- 187,193 ---- "", "", "Start a Kerberos authentication CVS server", + NULL, }, #endif { *************** *** 180,274 **** --- 195,305 ---- "", "", "Print out history information for files", + NULL, }, { -1, "login", {}, NULL, "", "", "Prompt for password for authenticating server", + NULL, }, { -1, "logout", {}, NULL, "", "", "Removes entry in .cvspass for remote repository", + NULL, }, { -1, "rdiff", {}, NULL, "", "", "Create 'patch' format diffs between releases", + NULL, }, { -1, "release", {}, NULL, "", "", "Indicate that a Module is no longer in use", + NULL, }, { CVS_OP_REMOVE, "remove", {}, NULL, "", "", "Remove an entry from the repository", + NULL, }, { -1, "rlog", {}, NULL, "", "", "Print out history information for a module", + NULL, }, { -1, "rtag", {}, NULL, "", "", "Add a symbolic tag to a module", + NULL, }, { CVS_OP_SERVER, "server", {}, cvs_server, "", "", "Server mode", + NULL, }, { CVS_OP_STATUS, "status", { "st", "stat" }, cvs_status, "", "", "Display status information on checked out files", + NULL, }, { CVS_OP_TAG, "tag", { "ta", "freeze" }, NULL, "", "", "Add a symbolic tag to checked out version of files", + NULL, }, { -1, "unedit", {}, NULL, "", "", "Undo an edit command", + NULL, }, { CVS_OP_UPDATE, "update", { "up", "upd" }, cvs_update, "", "", "Bring work tree in sync with repository", + NULL, }, { CVS_OP_VERSION, "version", { "ve", "ver" }, cvs_version, "", "", "Show current CVS version(s)", + NULL, }, { -1, "watch", {}, NULL, "", "", "Set watches", + NULL, }, { -1, "watchers", {}, NULL, "", "", "See who is watching a file", + NULL, }, }; *************** *** 278,285 **** void usage (void); void sigchld_hdlr (int); ! void cvs_readrc (void); struct cvs_cmd* cvs_findcmd (const char *); /* --- 309,317 ---- void usage (void); void sigchld_hdlr (int); ! void cvs_read_rcfile (void); struct cvs_cmd* cvs_findcmd (const char *); + int cvs_getopt (int, char **); /* *************** *** 301,313 **** int main(int argc, char **argv) { ! char *envstr, *ep; ! int ret; ! u_int i, readrc; struct cvs_cmd *cmdp; - readrc = 1; - if (cvs_log_init(LD_STD, 0) < 0) err(1, "failed to initialize logging"); --- 333,342 ---- int main(int argc, char **argv) { ! char *envstr, *cmd_argv[CVS_CMD_MAXARG], **targv; ! int i, ret, cmd_argc; struct cvs_cmd *cmdp; if (cvs_log_init(LD_STD, 0) < 0) err(1, "failed to initialize logging"); *************** *** 327,332 **** --- 356,450 ---- ((envstr = getenv("EDITOR")) != NULL)) cvs_editor = envstr; + ret = cvs_getopt(argc, argv); + + argc -= ret; + argv += ret; + if (argc == 0) { + usage(); + exit(EX_USAGE); + } + cvs_command = argv[0]; + + if (cvs_readrc) { + cvs_read_rcfile(); + + if (cvs_defargs != NULL) { + targv = cvs_makeargv(cvs_defargs, &i); + if (targv == NULL) { + cvs_log(LP_ERR, + "failed to load default arguments to %s", + __progname); + exit(EX_OSERR); + } + + cvs_getopt(i, targv); + cvs_freeargv(targv, i); + free(targv); + } + } + + /* setup signal handlers */ + signal(SIGPIPE, SIG_IGN); + + cvs_file_init(); + + ret = -1; + + cmdp = cvs_findcmd(cvs_command); + if (cmdp == NULL) { + fprintf(stderr, "Unknown command: `%s'\n\n", cvs_command); + fprintf(stderr, "CVS commands are:\n"); + for (i = 0; i < (int)CVS_NBCMD; i++) + fprintf(stderr, "\t%-16s%s\n", + cvs_cdt[i].cmd_name, cvs_cdt[i].cmd_descr); + exit(EX_USAGE); + } + + if (cmdp->cmd_hdlr == NULL) { + cvs_log(LP_ERR, "command `%s' not implemented", cvs_command); + exit(1); + } + + cvs_cmdop = cmdp->cmd_op; + + cmd_argc = 0; + memset(cmd_argv, 0, sizeof(cmd_argv)); + + cmd_argv[cmd_argc++] = argv[0]; + if (cmdp->cmd_defargs != NULL) { + /* transform into a new argument vector */ + ret = cvs_getargv(cmdp->cmd_defargs, cmd_argv + 1, + CVS_CMD_MAXARG - 1); + if (ret < 0) { + cvs_log(LP_ERRNO, "failed to generate argument vector " + "from default arguments"); + exit(EX_DATAERR); + } + cmd_argc += ret; + } + for (ret = 1; ret < argc; ret++) + cmd_argv[cmd_argc++] = argv[ret]; + + ret = (*cmdp->cmd_hdlr)(cmd_argc, cmd_argv); + if (ret == EX_USAGE) { + fprintf(stderr, "Usage: %s %s %s\n", __progname, cvs_command, + cmdp->cmd_synopsis); + } + + if (cvs_files != NULL) + cvs_file_free(cvs_files); + + return (ret); + } + + + int + cvs_getopt(int argc, char **argv) + { + int ret; + char *ep; + while ((ret = getopt(argc, argv, "b:d:e:fHlnQqrtvz:")) != -1) { switch (ret) { case 'b': *************** *** 344,350 **** cvs_editor = optarg; break; case 'f': ! readrc = 0; break; case 'l': cvs_nolog = 1; --- 462,468 ---- cvs_editor = optarg; break; case 'f': ! cvs_readrc = 0; break; case 'l': cvs_nolog = 1; *************** *** 389,443 **** } } ! argc -= optind; ! argv += optind; ! ! /* reset getopt() for use by commands */ optind = 1; ! optreset = 1; - if (argc == 0) { - usage(); - exit(EX_USAGE); - } - - /* setup signal handlers */ - signal(SIGPIPE, SIG_IGN); - - cvs_file_init(); - - if (readrc) - cvs_readrc(); - - cvs_command = argv[0]; - ret = -1; - - cmdp = cvs_findcmd(cvs_command); - if (cmdp == NULL) { - fprintf(stderr, "Unknown command: `%s'\n\n", cvs_command); - fprintf(stderr, "CVS commands are:\n"); - for (i = 0; i < CVS_NBCMD; i++) - fprintf(stderr, "\t%-16s%s\n", - cvs_cdt[i].cmd_name, cvs_cdt[i].cmd_descr); - exit(EX_USAGE); - } - - if (cmdp->cmd_hdlr == NULL) { - cvs_log(LP_ERR, "command `%s' not implemented", cvs_command); - exit(1); - } - - cvs_cmdop = cmdp->cmd_op; - - ret = (*cmdp->cmd_hdlr)(argc, argv); - if (ret == EX_USAGE) { - fprintf(stderr, "Usage: %s %s %s\n", __progname, cvs_command, - cmdp->cmd_synopsis); - } - - if (cvs_files != NULL) - cvs_file_free(cvs_files); - return (ret); } --- 507,516 ---- } } ! ret = optind; optind = 1; ! optreset = 1; /* for next call */ return (ret); } *************** *** 476,482 **** /* ! * cvs_readrc() * * Read the CVS `.cvsrc' file in the user's home directory. If the file * exists, it should contain a list of arguments that should always be given --- 549,555 ---- /* ! * cvs_read_rcfile() * * Read the CVS `.cvsrc' file in the user's home directory. If the file * exists, it should contain a list of arguments that should always be given *************** *** 484,492 **** */ void ! cvs_readrc(void) { char rcpath[MAXPATHLEN], linebuf[128], *lp; struct cvs_cmd *cmdp; struct passwd *pw; FILE *fp; --- 557,566 ---- */ void ! cvs_read_rcfile(void) { char rcpath[MAXPATHLEN], linebuf[128], *lp; + size_t len; struct cvs_cmd *cmdp; struct passwd *pw; FILE *fp; *************** *** 508,523 **** } while (fgets(linebuf, sizeof(linebuf), fp) != NULL) { ! lp = strchr(linebuf, ' '); ! ! /* ignore lines with no arguments */ ! if (lp == NULL) continue; ! *(lp++) = '\0'; if (strcmp(linebuf, "cvs") == 0) { ! /* global options */ } else { cmdp = cvs_findcmd(linebuf); if (cmdp == NULL) { cvs_log(LP_NOTICE, --- 582,613 ---- } while (fgets(linebuf, sizeof(linebuf), fp) != NULL) { ! if ((len = strlen(linebuf)) == 0) continue; + if (linebuf[len - 1] != '\n') { + cvs_log(LP_WARN, ".cvsrc line too long"); + break; + } + linebuf[--len] = '\0'; ! lp = strchr(linebuf, ' '); ! if (lp == NULL) ! continue; /* ignore lines with no arguments */ ! *lp = '\0'; if (strcmp(linebuf, "cvs") == 0) { ! /* ! * Global default options. In the case of cvs only, ! * we keep the 'cvs' string as first argument because ! * getopt() does not like starting at index 0 for ! * argument processing. ! */ ! *lp = ' '; ! cvs_defargs = strdup(linebuf); ! if (cvs_defargs == NULL) ! cvs_log(LP_ERRNO, ! "failed to copy global arguments"); } else { + lp++; cmdp = cvs_findcmd(linebuf); if (cmdp == NULL) { cvs_log(LP_NOTICE, *************** *** 525,530 **** --- 615,626 ---- linebuf); continue; } + + cmdp->cmd_defargs = strdup(lp); + if (cmdp->cmd_defargs == NULL) + cvs_log(LP_ERRNO, + "failed to copy default arguments for %s", + cmdp->cmd_name); } } if (ferror(fp)) {