version 1.97, 2006/04/14 02:45:35 |
version 1.98, 2006/05/27 03:30:30 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* |
/* |
|
* Copyright (c) 2006 Joris Vink <joris@openbsd.org> |
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> |
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> |
* All rights reserved. |
* All rights reserved. |
* |
* |
|
|
#include "log.h" |
#include "log.h" |
#include "file.h" |
#include "file.h" |
|
|
|
|
extern char *__progname; |
extern char *__progname; |
|
|
|
|
/* verbosity level: 0 = really quiet, 1 = quiet, 2 = verbose */ |
/* verbosity level: 0 = really quiet, 1 = quiet, 2 = verbose */ |
int verbosity = 2; |
int verbosity = 2; |
|
|
/* compression level used with zlib, 0 meaning no compression taking place */ |
/* compression level used with zlib, 0 meaning no compression taking place */ |
int cvs_compress = 0; |
int cvs_compress = 0; |
int cvs_readrc = 1; /* read .cvsrc on startup */ |
int cvs_readrc = 1; /* read .cvsrc on startup */ |
int cvs_trace = 0; |
int cvs_trace = 0; |
int cvs_nolog = 0; |
int cvs_nolog = 0; |
int cvs_readonly = 0; |
int cvs_readonly = 0; |
int cvs_nocase = 0; /* set to 1 to disable filename case sensitivity */ |
int cvs_nocase = 0; /* set to 1 to disable filename case sensitivity */ |
int cvs_noexec = 0; /* set to 1 to disable disk operations (-n option) */ |
int cvs_noexec = 0; /* set to 1 to disable disk operations (-n option) */ |
int cvs_error = -1; /* set to the correct error code on failure */ |
int cvs_error = -1; /* set to the correct error code on failure */ |
char *cvs_defargs; /* default global arguments from .cvsrc */ |
int cvs_cmdop; |
char *cvs_command; /* name of the command we are running */ |
|
int cvs_cmdop; |
|
char *cvs_rootstr; |
|
char *cvs_rsh = CVS_RSH_DEFAULT; |
|
char *cvs_editor = CVS_EDITOR_DEFAULT; |
|
char *cvs_homedir = NULL; |
|
char *cvs_msg = NULL; |
|
char *cvs_repo_base = NULL; |
|
char *cvs_tmpdir = CVS_TMPDIR_DEFAULT; |
|
|
|
/* hierarchy of all the files affected by the command */ |
char *cvs_defargs; /* default global arguments from .cvsrc */ |
CVSFILE *cvs_files; |
char *cvs_command; /* name of the command we are running */ |
|
char *cvs_rootstr; |
|
char *cvs_rsh = CVS_RSH_DEFAULT; |
|
char *cvs_editor = CVS_EDITOR_DEFAULT; |
|
char *cvs_homedir = NULL; |
|
char *cvs_msg = NULL; |
|
char *cvs_repo_base = NULL; |
|
char *cvs_tmpdir = CVS_TMPDIR_DEFAULT; |
|
|
|
struct cvsroot *current_cvsroot = NULL; |
|
|
static TAILQ_HEAD(, cvs_var) cvs_variables; |
static TAILQ_HEAD(, cvs_var) cvs_variables; |
|
|
|
int cvs_getopt(int, char **); |
void usage(void); |
void usage(void); |
static void cvs_read_rcfile(void); |
static void cvs_read_rcfile(void); |
int cvs_getopt(int, char **); |
|
|
|
/* |
struct cvs_wklhead temp_files; |
* usage() |
|
* |
void sighandler(int); |
* Display usage information. |
volatile sig_atomic_t cvs_quit = 0; |
*/ |
volatile sig_atomic_t sig_received = 0; |
|
|
void |
void |
|
sighandler(int sig) |
|
{ |
|
sig_received = sig; |
|
|
|
switch (sig) { |
|
case SIGINT: |
|
case SIGTERM: |
|
cvs_quit = 1; |
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
|
|
void |
|
cvs_cleanup(void) |
|
{ |
|
cvs_log(LP_TRACE, "cvs_cleanup: removing locks"); |
|
cvs_worklist_run(&repo_locks, cvs_worklist_unlink); |
|
|
|
cvs_log(LP_TRACE, "cvs_cleanup: removing temp files"); |
|
cvs_worklist_run(&temp_files, cvs_worklist_unlink); |
|
} |
|
|
|
void |
usage(void) |
usage(void) |
{ |
{ |
fprintf(stderr, |
fprintf(stderr, |
|
|
"[-T tmpdir] [-z level] command [...]\n", __progname); |
"[-T tmpdir] [-z level] command [...]\n", __progname); |
} |
} |
|
|
|
|
int |
int |
main(int argc, char **argv) |
main(int argc, char **argv) |
{ |
{ |
|
|
tzset(); |
tzset(); |
|
|
TAILQ_INIT(&cvs_variables); |
TAILQ_INIT(&cvs_variables); |
|
SLIST_INIT(&repo_locks); |
|
SLIST_INIT(&temp_files); |
|
|
cvs_log_init(LD_STD, 0); |
|
|
|
/* by default, be very verbose */ |
|
(void)cvs_log_filter(LP_FILTER_UNSET, LP_INFO); |
|
|
|
#ifdef DEBUG |
|
(void)cvs_log_filter(LP_FILTER_UNSET, LP_DEBUG); |
|
#endif |
|
|
|
/* check environment so command-line options override it */ |
/* check environment so command-line options override it */ |
if ((envstr = getenv("CVS_RSH")) != NULL) |
if ((envstr = getenv("CVS_RSH")) != NULL) |
cvs_rsh = envstr; |
cvs_rsh = envstr; |
|
|
argv += ret; |
argv += ret; |
if (argc == 0) { |
if (argc == 0) { |
usage(); |
usage(); |
exit(CVS_EX_USAGE); |
exit(1); |
} |
} |
|
|
cvs_command = argv[0]; |
cvs_command = argv[0]; |
|
|
} |
} |
|
|
/* setup signal handlers */ |
/* setup signal handlers */ |
signal(SIGPIPE, SIG_IGN); |
signal(SIGTERM, sighandler); |
|
signal(SIGINT, sighandler); |
|
signal(SIGHUP, sighandler); |
|
signal(SIGABRT, sighandler); |
|
signal(SIGALRM, sighandler); |
|
signal(SIGPIPE, sighandler); |
|
|
if (cvs_file_init() < 0) |
|
fatal("failed to initialize file support"); |
|
|
|
ret = -1; |
|
|
|
cmdp = cvs_findcmd(cvs_command); |
cmdp = cvs_findcmd(cvs_command); |
if (cmdp == NULL) { |
if (cmdp == NULL) { |
fprintf(stderr, "Unknown command: `%s'\n\n", cvs_command); |
fprintf(stderr, "Unknown command: `%s'\n\n", cvs_command); |
|
|
for (i = 0; cvs_cdt[i] != NULL; i++) |
for (i = 0; cvs_cdt[i] != NULL; i++) |
fprintf(stderr, "\t%-16s%s\n", |
fprintf(stderr, "\t%-16s%s\n", |
cvs_cdt[i]->cmd_name, cvs_cdt[i]->cmd_descr); |
cvs_cdt[i]->cmd_name, cvs_cdt[i]->cmd_descr); |
exit(CVS_EX_USAGE); |
exit(1); |
} |
} |
|
|
cvs_cmdop = cmdp->cmd_op; |
cvs_cmdop = cmdp->cmd_op; |
|
|
|
|
cmd_argc += ret; |
cmd_argc += ret; |
} |
} |
|
|
for (ret = 1; ret < argc; ret++) |
for (ret = 1; ret < argc; ret++) |
cmd_argv[cmd_argc++] = argv[ret]; |
cmd_argv[cmd_argc++] = argv[ret]; |
|
|
ret = cvs_startcmd(cmdp, cmd_argc, cmd_argv); |
cvs_file_init(); |
switch (ret) { |
|
case CVS_EX_USAGE: |
if ((current_cvsroot = cvsroot_get(".")) == NULL) { |
fprintf(stderr, "Usage: %s %s %s\n", __progname, |
|
cmdp->cmd_name, cmdp->cmd_synopsis); |
|
break; |
|
case CVS_EX_DATA: |
|
cvs_log(LP_ABORT, "internal data error"); |
|
break; |
|
case CVS_EX_PROTO: |
|
cvs_log(LP_ABORT, "protocol error"); |
|
break; |
|
case CVS_EX_FILE: |
|
cvs_log(LP_ABORT, "an operation on a file or directory failed"); |
|
break; |
|
case CVS_EX_BADROOT: |
|
/* match GNU CVS output, thus the LP_ERR and LP_ABORT codes. */ |
|
cvs_log(LP_ERR, |
cvs_log(LP_ERR, |
"No CVSROOT specified! Please use the `-d' option"); |
"No CVSROOT specified! Please use the '-d' option"); |
cvs_log(LP_ABORT, |
fatal("or set the CVSROOT enviroment variable."); |
"or set the CVSROOT enviroment variable."); |
|
break; |
|
case CVS_EX_ERR: |
|
cvs_log(LP_ABORT, "yeah, we failed, and we don't know why"); |
|
break; |
|
default: |
|
break; |
|
} |
} |
|
|
if (cvs_files != NULL) |
if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) |
cvs_file_free(cvs_files); |
fatal("remote setups are not supported yet"); |
if (cvs_msg != NULL) |
|
xfree(cvs_msg); |
|
|
|
return (ret); |
cmdp->cmd(cmd_argc, cmd_argv); |
|
cvs_cleanup(); |
|
|
|
return (0); |
} |
} |
|
|
|
|
int |
int |
cvs_getopt(int argc, char **argv) |
cvs_getopt(int argc, char **argv) |
{ |
{ |
|
|
ep = strchr(optarg, '='); |
ep = strchr(optarg, '='); |
if (ep == NULL) { |
if (ep == NULL) { |
cvs_log(LP_ERR, "no = in variable assignment"); |
cvs_log(LP_ERR, "no = in variable assignment"); |
exit(CVS_EX_USAGE); |
exit(1); |
} |
} |
*(ep++) = '\0'; |
*(ep++) = '\0'; |
if (cvs_var_set(optarg, ep) < 0) |
if (cvs_var_set(optarg, ep) < 0) |
exit(CVS_EX_USAGE); |
exit(1); |
break; |
break; |
case 'T': |
case 'T': |
cvs_tmpdir = optarg; |
cvs_tmpdir = optarg; |
break; |
break; |
case 't': |
case 't': |
(void)cvs_log_filter(LP_FILTER_UNSET, LP_TRACE); |
|
cvs_trace = 1; |
cvs_trace = 1; |
break; |
break; |
case 'v': |
case 'v': |
|
|
break; |
break; |
default: |
default: |
usage(); |
usage(); |
exit(CVS_EX_USAGE); |
exit(1); |
} |
} |
} |
} |
|
|
|
|
return (ret); |
return (ret); |
} |
} |
|
|
|
|
/* |
/* |
* cvs_read_rcfile() |
* cvs_read_rcfile() |
* |
* |
|
|
strlcat(rcpath, "/", sizeof(rcpath)) >= sizeof(rcpath) || |
strlcat(rcpath, "/", sizeof(rcpath)) >= sizeof(rcpath) || |
strlcat(rcpath, CVS_PATH_RC, sizeof(rcpath)) >= sizeof(rcpath)) { |
strlcat(rcpath, CVS_PATH_RC, sizeof(rcpath)) >= sizeof(rcpath)) { |
errno = ENAMETOOLONG; |
errno = ENAMETOOLONG; |
cvs_log(LP_ERRNO, "%s", rcpath); |
cvs_log(LP_ERR, "%s", rcpath); |
return; |
return; |
} |
} |
|
|
|
|
if ((len = strlen(linebuf)) == 0) |
if ((len = strlen(linebuf)) == 0) |
continue; |
continue; |
if (linebuf[len - 1] != '\n') { |
if (linebuf[len - 1] != '\n') { |
cvs_log(LP_WARN, "line too long in `%s:%d'", rcpath, |
cvs_log(LP_ERR, "line too long in `%s:%d'", rcpath, |
linenum); |
linenum); |
break; |
break; |
} |
} |
|
|
cmdp->cmd_defargs = xstrdup(lp); |
cmdp->cmd_defargs = xstrdup(lp); |
} |
} |
} |
} |
|
|
if (ferror(fp)) { |
if (ferror(fp)) { |
cvs_log(LP_NOTICE, "failed to read line from `%s'", rcpath); |
cvs_log(LP_NOTICE, "failed to read line from `%s'", rcpath); |
} |
} |
|
|
(void)fclose(fp); |
(void)fclose(fp); |
} |
} |
|
|
|
|
/* |
/* |
* cvs_var_set() |
* cvs_var_set() |
* |
* |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
|
/* |
/* |
* cvs_var_set() |
* cvs_var_set() |
* |
* |
|
|
} |
} |
|
|
return (-1); |
return (-1); |
|
|
} |
} |
|
|
|
|
/* |
/* |
* cvs_var_get() |
* cvs_var_get() |