diff options
| author | Peter Wemm <peter@FreeBSD.org> | 1995-12-10 22:31:58 +0000 | 
|---|---|---|
| committer | Peter Wemm <peter@FreeBSD.org> | 1995-12-10 22:31:58 +0000 | 
| commit | ac4bd338c8528cb5af4afdfa3b4e57438a25cc29 (patch) | |
| tree | a30333a66eed74477c5cb0ebe9623b52e9e9a385 /gnu/usr.bin/cvs/lib/subr.c | |
| parent | b05543098cea72287ad383f7d67da2cf8ae60b38 (diff) | |
Notes
Diffstat (limited to 'gnu/usr.bin/cvs/lib/subr.c')
| -rw-r--r-- | gnu/usr.bin/cvs/lib/subr.c | 817 | 
1 files changed, 45 insertions, 772 deletions
| diff --git a/gnu/usr.bin/cvs/lib/subr.c b/gnu/usr.bin/cvs/lib/subr.c index d3d40b1fd669..228581c5b1e0 100644 --- a/gnu/usr.bin/cvs/lib/subr.c +++ b/gnu/usr.bin/cvs/lib/subr.c @@ -11,248 +11,11 @@  #include "cvs.h"  #ifndef lint -static char rcsid[] = "$CVSid: @(#)subr.c 1.64 94/10/07 $"; -USE(rcsid) +static const char rcsid[] = "$CVSid: @(#)subr.c 1.64 94/10/07 $"; +USE(rcsid);  #endif -#ifdef _MINIX -#undef	POSIX		/* Minix 1.6 doesn't support POSIX.1 sigaction yet */ -#endif - -#ifdef HAVE_VPRINTF -#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) -#include <stdarg.h> -#define VA_START(args, lastarg) va_start(args, lastarg) -#else -#include <varargs.h> -#define VA_START(args, lastarg) va_start(args) -#endif -#else -#define va_alist a1, a2, a3, a4, a5, a6, a7, a8 -#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; -#endif - -/* - * I don't know of a convenient way to test this at configure time, or else - * I'd certainly do it there. - */ -#if defined(NeXT) -#define LOSING_TMPNAM_FUNCTION -#ifndef	_POSIX_SOURCE -/* - * NeXT doesn't define these without _POSIX_SOURCE, - * but that changes a lot of things. - */ -#define	WEXITSTATUS(x)	((x).w_retcode) -#define	WTERMSIG(x)	((x).w_termsig) -#endif -#endif - -static void run_add_arg PROTO((char *s)); -static void run_init_prog PROTO((void)); -  extern char *getlogin (); -extern char *strtok (); - -/* - * Copies "from" to "to". mallocs a buffer large enough to hold the entire - * file and does one read/one write to do the copy.  This is reasonable, - * since source files are typically not too large. - */ -void -copy_file (from, to) -    char *from; -    char *to; -{ -    struct stat sb; -    struct utimbuf t; -    int fdin, fdout; -    char *buf; - -    if (trace) -	(void) fprintf (stderr, "-> copy(%s,%s)\n", from, to); -    if (noexec) -	return; - -    if ((fdin = open (from, O_RDONLY)) < 0) -	error (1, errno, "cannot open %s for copying", from); -    if (fstat (fdin, &sb) < 0) -	error (1, errno, "cannot fstat %s", from); -    if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0) -	error (1, errno, "cannot create %s for copying", to); -    if (sb.st_size > 0) -    { -	buf = xmalloc ((int) sb.st_size); -	if (read (fdin, buf, (int) sb.st_size) != (int) sb.st_size) -	    error (1, errno, "cannot read file %s for copying", from); -	if (write (fdout, buf, (int) sb.st_size) != (int) sb.st_size -#ifdef HAVE_FSYNC -	    || fsync (fdout) == -1 -#endif -	    ) -	{ -	    error (1, errno, "cannot write file %s for copying", to); -	} -	free (buf); -    } -    (void) close (fdin); -    if (close (fdout) < 0) -	error (1, errno, "cannot close %s", to); - -    /* now, set the times for the copied file to match those of the original */ -    memset ((char *) &t, 0, sizeof (t)); -    t.actime = sb.st_atime; -    t.modtime = sb.st_mtime; -    (void) utime (to, &t); -} - -/* FIXME-krp: these functions would benefit from caching the char * & -   stat buf.  */ - -/* - * Returns non-zero if the argument file is a directory, or is a symbolic - * link which points to a directory. - */ -int -isdir (file) -    char *file; -{ -    struct stat sb; - -    if (stat (file, &sb) < 0) -	return (0); -    return (S_ISDIR (sb.st_mode)); -} - -/* - * Returns non-zero if the argument file is a symbolic link. - */ -int -islink (file) -    char *file; -{ -#ifdef S_ISLNK -    struct stat sb; - -    if (lstat (file, &sb) < 0) -	return (0); -    return (S_ISLNK (sb.st_mode)); -#else -    return (0); -#endif -} - -/* - * Returns non-zero if the argument file exists. - */ -int -isfile (file) -    char *file; -{ -    struct stat sb; - -    if (stat (file, &sb) < 0) -	return (0); -    return (1); -} - -/* - * Returns non-zero if the argument file is readable. - * XXX - must be careful if "cvs" is ever made setuid! - */ -int -isreadable (file) -    char *file; -{ -    return (access (file, R_OK) != -1); -} - -/* - * Returns non-zero if the argument file is writable - * XXX - muct be careful if "cvs" is ever made setuid! - */ -int -iswritable (file) -    char *file; -{ -    return (access (file, W_OK) != -1); -} - -/* - * Open a file and die if it fails - */ -FILE * -open_file (name, mode) -    char *name; -    char *mode; -{ -    FILE *fp; - -    if ((fp = fopen (name, mode)) == NULL) -	error (1, errno, "cannot open %s", name); -    return (fp); -} - -/* - * Open a file if allowed and return. - */ -FILE * -Fopen (name, mode) -    char *name; -    char *mode; -{ -    if (trace) -	(void) fprintf (stderr, "-> fopen(%s,%s)\n", name, mode); -    if (noexec) -	return (NULL); - -    return (fopen (name, mode)); -} - -/* - * Make a directory and die if it fails - */ -void -make_directory (name) -    char *name; -{ -    struct stat buf; - -    if (stat (name, &buf) == 0 && (!S_ISDIR (buf.st_mode))) -	    error (0, 0, "%s already exists but is not a directory", name); -    if (!noexec && mkdir (name, 0777) < 0) -	error (1, errno, "cannot make directory %s", name); -} - -/* - * Make a path to the argument directory, printing a message if something - * goes wrong. - */ -void -make_directories (name) -    char *name; -{ -    char *cp; - -    if (noexec) -	return; - -    if (mkdir (name, 0777) == 0 || errno == EEXIST) -	return; -    if (errno != ENOENT) -    { -	error (0, errno, "cannot make path to %s", name); -	return; -    } -    if ((cp = strrchr (name, '/')) == NULL) -	return; -    *cp = '\0'; -    make_directories (name); -    *cp++ = '/'; -    if (*cp == '\0') -	return; -    (void) mkdir (name, 0777); -}  /*   * malloc some data and die if it fails @@ -263,7 +26,14 @@ xmalloc (bytes)  {      char *cp; -    if ((cp = malloc (bytes)) == NULL) +    /* Parts of CVS try to xmalloc zero bytes and then free it.  Some +       systems have a malloc which returns NULL for zero byte +       allocations but a free which can't handle NULL, so compensate. */ +    if (bytes == 0) +	bytes = 1; + +    cp = malloc (bytes); +    if (cp == NULL)  	error (1, 0, "can not allocate %lu bytes", (unsigned long) bytes);      return (cp);  } @@ -295,7 +65,7 @@ xrealloc (ptr, bytes)   */  char *  xstrdup (str) -    char *str; +    const char *str;  {      char *s; @@ -306,143 +76,16 @@ xstrdup (str)      return (s);  } -/* - * Change the mode of a file, either adding write permissions, or removing - * all write permissions.  Adding write permissions honors the current umask - * setting. - */ +/* Remove trailing newlines from STRING, destructively. */  void -xchmod (fname, writable) -    char *fname; -    int writable; +strip_trailing_newlines (str) +     char *str;  { -    struct stat sb; -    mode_t mode, oumask; +  int len; +  len = strlen (str) - 1; -    if (stat (fname, &sb) < 0) -    { -	if (!noexec) -	    error (0, errno, "cannot stat %s", fname); -	return; -    } -    if (writable) -    { -	oumask = umask (0); -	(void) umask (oumask); -	mode = sb.st_mode | ((S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask); -    } -    else -    { -	mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH); -    } - -    if (trace) -	(void) fprintf (stderr, "-> chmod(%s,%o)\n", fname, mode); -    if (noexec) -	return; - -    if (chmod (fname, mode) < 0) -	error (0, errno, "cannot change mode of file %s", fname); -} - -/* - * Rename a file and die if it fails - */ -void -rename_file (from, to) -    char *from; -    char *to; -{ -    if (trace) -	(void) fprintf (stderr, "-> rename(%s,%s)\n", from, to); -    if (noexec) -	return; - -    if (rename (from, to) < 0) -	error (1, errno, "cannot rename file %s to %s", from, to); -} - -/* - * link a file, if possible. - */ -int -link_file (from, to) -    char *from, *to; -{ -    if (trace) -	(void) fprintf (stderr, "-> link(%s,%s)\n", from, to); -    if (noexec) -	return (0); - -    return (link (from, to)); -} - -/* - * unlink a file, if possible. - */ -int -unlink_file (f) -    char *f; -{ -    if (trace) -	(void) fprintf (stderr, "-> unlink(%s)\n", f); -    if (noexec) -	return (0); - -    return (unlink (f)); -} - -/* - * Compare "file1" to "file2". Return non-zero if they don't compare exactly. - *  - * mallocs a buffer large enough to hold the entire file and does two reads to - * load the buffer and calls memcmp to do the cmp. This is reasonable, since - * source files are typically not too large. - */ - -/* richfix: this *could* exploit mmap. */ - -int -xcmp (file1, file2) -    char *file1; -    char *file2; -{ -    register char *buf1, *buf2; -    struct stat sb; -    off_t size; -    int ret, fd1, fd2; - -    if ((fd1 = open (file1, O_RDONLY)) < 0) -	error (1, errno, "cannot open file %s for comparing", file1); -    if ((fd2 = open (file2, O_RDONLY)) < 0) -	error (1, errno, "cannot open file %s for comparing", file2); -    if (fstat (fd1, &sb) < 0) -	error (1, errno, "cannot fstat %s", file1); -    size = sb.st_size; -    if (fstat (fd2, &sb) < 0) -	error (1, errno, "cannot fstat %s", file2); -    if (size == sb.st_size) -    { -	if (size == 0) -	    ret = 0; -	else -	{ -	    buf1 = xmalloc ((int) size); -	    buf2 = xmalloc ((int) size); -	    if (read (fd1, buf1, (int) size) != (int) size) -		error (1, errno, "cannot read file %s for comparing", file1); -	    if (read (fd2, buf2, (int) size) != (int) size) -		error (1, errno, "cannot read file %s for comparing", file2); -	    ret = memcmp(buf1, buf2, (int) size); -	    free (buf1); -	    free (buf2); -	} -    } -    else -	ret = 1; -    (void) close (fd1); -    (void) close (fd2); -    return (ret); +  while (str[len] == '\n') +    str[len--] = '\0';  }  /* @@ -451,7 +94,7 @@ xcmp (file1, file2)  void  free_names (pargc, argv)      int *pargc; -    char *argv[]; +    char **argv;  {      register int i; @@ -470,7 +113,7 @@ free_names (pargc, argv)  void  line2argv (pargc, argv, line)      int *pargc; -    char *argv[]; +    char **argv;      char *line;  {      char *cp; @@ -488,14 +131,13 @@ line2argv (pargc, argv, line)   */  int  numdots (s) -    char *s; +    const char *s;  { -    char *cp;      int dots = 0; -    for (cp = s; *cp; cp++) +    for (; *s; s++)      { -	if (*cp == '.') +	if (*s == '.')  	    dots++;      }      return (dots); @@ -518,394 +160,18 @@ getcaller ()      if (uid == (uid_t) 0)      {  	/* super-user; try getlogin() to distinguish */ -	if (((name = getenv("LOGNAME")) || (name = getenv("USER")) || -	     (name = getlogin ())) && *name) +	if (((name = getlogin ()) || (name = getenv("LOGNAME")) || +	     (name = getenv("USER"))) && *name)  	    return (name);      }      if ((pw = (struct passwd *) getpwuid (uid)) == NULL)      { -	(void) sprintf (uidname, "uid%d", (unsigned long) uid); +	(void) sprintf (uidname, "uid%lu", (unsigned long) uid);  	return (uidname);      }      return (pw->pw_name);  } -/* - * To exec a program under CVS, first call run_setup() to setup any initial - * arguments.  The options to run_setup are essentially like printf(). The - * arguments will be parsed into whitespace separated words and added to the - * global run_argv list. - *  - * Then, optionally call run_arg() for each additional argument that you'd like - * to pass to the executed program. - *  - * Finally, call run_exec() to execute the program with the specified arguments. - * The execvp() syscall will be used, so that the PATH is searched correctly. - * File redirections can be performed in the call to run_exec(). - */ -static char *run_prog; -static char **run_argv; -static int run_argc; -static int run_argc_allocated; - -/* VARARGS */ -#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)) -void  -run_setup (char *fmt,...) -#else -void  -run_setup (fmt, va_alist) -    char *fmt; -    va_dcl - -#endif -{ -#ifdef HAVE_VPRINTF -    va_list args; - -#endif -    char *cp; -    int i; - -    run_init_prog (); - -    /* clean out any malloc'ed values from run_argv */ -    for (i = 0; i < run_argc; i++) -    { -	if (run_argv[i]) -	{ -	    free (run_argv[i]); -	    run_argv[i] = (char *) 0; -	} -    } -    run_argc = 0; - -    /* process the varargs into run_prog */ -#ifdef HAVE_VPRINTF -    VA_START (args, fmt); -    (void) vsprintf (run_prog, fmt, args); -    va_end (args); -#else -    (void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8); -#endif - -    /* put each word into run_argv, allocating it as we go */ -    for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t")) -	run_add_arg (cp); -} - -void -run_arg (s) -    char *s; -{ -    run_add_arg (s); -} - -/* VARARGS */ -#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)) -void  -run_args (char *fmt,...) -#else -void  -run_args (fmt, va_alist) -    char *fmt; -    va_dcl - -#endif -{ -#ifdef HAVE_VPRINTF -    va_list args; - -#endif - -    run_init_prog (); - -    /* process the varargs into run_prog */ -#ifdef HAVE_VPRINTF -    VA_START (args, fmt); -    (void) vsprintf (run_prog, fmt, args); -    va_end (args); -#else -    (void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8); -#endif - -    /* and add the (single) argument to the run_argv list */ -    run_add_arg (run_prog); -} - -static void -run_add_arg (s) -    char *s; -{ -    /* allocate more argv entries if we've run out */ -    if (run_argc >= run_argc_allocated) -    { -	run_argc_allocated += 50; -	run_argv = (char **) xrealloc ((char *) run_argv, -				     run_argc_allocated * sizeof (char **)); -    } - -    if (s) -	run_argv[run_argc++] = xstrdup (s); -    else -	run_argv[run_argc] = (char *) 0;/* not post-incremented on purpose! */ -} - -static void -run_init_prog () -{ -    /* make sure that run_prog is allocated once */ -    if (run_prog == (char *) 0) -	run_prog = xmalloc (10 * 1024);	/* 10K of args for _setup and _arg */ -} - -int -run_exec (stin, stout, sterr, flags) -    char *stin; -    char *stout; -    char *sterr; -    int flags; -{ -    int shin, shout, sherr; -    int mode_out, mode_err; -#if	defined(NeXT) && !defined(_POSIX_SOURCE) -    union wait status; -#else -    int status; -#endif -    int rc = -1; -    int rerrno = 0; -    int pid, w; - -#ifdef POSIX -    sigset_t sigset_mask, sigset_omask; -    struct sigaction act, iact, qact; - -#else -#ifdef BSD_SIGNALS -    int mask; -    struct sigvec vec, ivec, qvec; - -#else -    RETSIGTYPE (*istat) (), (*qstat) (); -#endif -#endif - -    if (trace) -    { -	(void) fprintf (stderr, "-> system("); -	run_print (stderr); -	(void) fprintf (stderr, ")\n"); -    } -    if (noexec && (flags & RUN_REALLY) == 0) -	return (0); - -    /* make sure that we are null terminated, since we didn't calloc */ -    run_add_arg ((char *) 0); - -    /* setup default file descriptor numbers */ -    shin = 0; -    shout = 1; -    sherr = 2; - -    /* set the file modes for stdout and stderr */ -    mode_out = mode_err = O_WRONLY | O_CREAT; -    mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC); -    mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC); - -    if (stin && (shin = open (stin, O_RDONLY)) == -1) -    { -	rerrno = errno; -	error (0, errno, "cannot open %s for reading (prog %s)", -	       stin, run_argv[0]); -	goto out0; -    } -    if (stout && (shout = open (stout, mode_out, 0666)) == -1) -    { -	rerrno = errno; -	error (0, errno, "cannot open %s for writing (prog %s)", -	       stout, run_argv[0]); -	goto out1; -    } -    if (sterr && (flags & RUN_COMBINED) == 0) -    { -	if ((sherr = open (sterr, mode_err, 0666)) == -1) -	{ -	    rerrno = errno; -	    error (0, errno, "cannot open %s for writing (prog %s)", -		   sterr, run_argv[0]); -	    goto out2; -	} -    } - -    /* Make sure we don't flush this twice, once in the subprocess.  */ -    fflush (stdout); -    fflush (stderr); - -    /* The output files, if any, are now created.  Do the fork and dups */ -#ifdef HAVE_VFORK -    pid = vfork (); -#else -    pid = fork (); -#endif -    if (pid == 0) -    { -	if (shin != 0) -	{ -	    (void) dup2 (shin, 0); -	    (void) close (shin); -	} -	if (shout != 1) -	{ -	    (void) dup2 (shout, 1); -	    (void) close (shout); -	} -	if (flags & RUN_COMBINED) -	    (void) dup2 (1, 2); -	else if (sherr != 2) -	{ -	    (void) dup2 (sherr, 2); -	    (void) close (sherr); -	} - -	/* dup'ing is done.  try to run it now */ -	(void) execvp (run_argv[0], run_argv); -	error (0, errno, "cannot exec %s", run_argv[0]); -	_exit (127); -    } -    else if (pid == -1) -    { -	rerrno = errno; -	goto out; -    } - -    /* the parent.  Ignore some signals for now */ -#ifdef POSIX -    if (flags & RUN_SIGIGNORE) -    { -	act.sa_handler = SIG_IGN; -	(void) sigemptyset (&act.sa_mask); -	act.sa_flags = 0; -	(void) sigaction (SIGINT, &act, &iact); -	(void) sigaction (SIGQUIT, &act, &qact); -    } -    else -    { -	(void) sigemptyset (&sigset_mask); -	(void) sigaddset (&sigset_mask, SIGINT); -	(void) sigaddset (&sigset_mask, SIGQUIT); -	(void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask); -    } -#else -#ifdef BSD_SIGNALS -    if (flags & RUN_SIGIGNORE) -    { -	memset ((char *) &vec, 0, sizeof (vec)); -	vec.sv_handler = SIG_IGN; -	(void) sigvec (SIGINT, &vec, &ivec); -	(void) sigvec (SIGQUIT, &vec, &qvec); -    } -    else -	mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT)); -#else -    istat = signal (SIGINT, SIG_IGN); -    qstat = signal (SIGQUIT, SIG_IGN); -#endif -#endif - -    /* wait for our process to die and munge return status */ -#ifdef POSIX -    while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR) -	; -#else -    while ((w = wait (&status)) != pid) -    { -	if (w == -1 && errno != EINTR) -	    break; -    } -#endif -    if (w == -1) -    { -	rc = -1; -	rerrno = errno; -    } -    else if (WIFEXITED (status)) -	rc = WEXITSTATUS (status); -    else if (WIFSIGNALED (status)) -    { -	if (WTERMSIG (status) == SIGPIPE) -	    error (1, 0, "broken pipe"); -	rc = 2; -    } -    else -	rc = 1; - -    /* restore the signals */ -#ifdef POSIX -    if (flags & RUN_SIGIGNORE) -    { -	(void) sigaction (SIGINT, &iact, (struct sigaction *) NULL); -	(void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL); -    } -    else -	(void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL); -#else -#ifdef BSD_SIGNALS -    if (flags & RUN_SIGIGNORE) -    { -	(void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL); -	(void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL); -    } -    else -	(void) sigsetmask (mask); -#else -    (void) signal (SIGINT, istat); -    (void) signal (SIGQUIT, qstat); -#endif -#endif - -    /* cleanup the open file descriptors */ -  out: -    if (sterr) -	(void) close (sherr); -  out2: -    if (stout) -	(void) close (shout); -  out1: -    if (stin) -	(void) close (shin); - -  out0: -    if (rerrno) -	errno = rerrno; -    return (rc); -} - -void -run_print (fp) -    FILE *fp; -{ -    int i; - -    for (i = 0; i < run_argc; i++) -    { -	(void) fprintf (fp, "%s", run_argv[i]); -	if (i != run_argc - 1) -	    (void) fprintf (fp, " "); -    } -} - -FILE * -Popen (cmd, mode) -    char *cmd, *mode; -{ -    if (trace) -	(void) fprintf (stderr, "-> Popen(%s,%s)\n", cmd, mode); -    if (noexec) -	return (NULL); -    return (popen (cmd, mode)); -} -  #ifdef lint  #ifndef __GNUC__  /* ARGSUSED */ @@ -1031,19 +297,26 @@ gca (rev1, rev2)      return (xstrdup (gca));  } -#ifdef LOSING_TMPNAM_FUNCTION -char *tmpnam(char *s) +/* + *  Sanity checks and any required fix-up on message passed to RCS via '-m'. + *  RCS 5.7 requires that a non-total-whitespace, non-null message be provided + *  with '-m'. + */ +char * +make_message_rcslegal (message) +     char *message;  { -    static char value[L_tmpnam+1]; +    if ((message == NULL) || (*message == '\0') || isspace (*message)) +    { +        char *t; + +	if (message) +	    for (t = message; *t; t++) +	        if (!isspace (*t)) +		    return message; -    if (s){ -       strcpy(s,"/tmp/cvsXXXXXX"); -       mktemp(s); -       return s; -    }else{ -       strcpy(value,"/tmp/cvsXXXXXX"); -       mktemp(s); -       return value; +	return "*** empty log message ***\n";      } + +    return message;  } -#endif | 
