summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/cvs/lib/subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cvs/lib/subr.c')
-rw-r--r--gnu/usr.bin/cvs/lib/subr.c817
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