summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/cvs/mkmodules/mkmodules.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cvs/mkmodules/mkmodules.c')
-rw-r--r--gnu/usr.bin/cvs/mkmodules/mkmodules.c395
1 files changed, 395 insertions, 0 deletions
diff --git a/gnu/usr.bin/cvs/mkmodules/mkmodules.c b/gnu/usr.bin/cvs/mkmodules/mkmodules.c
new file mode 100644
index 0000000..59ec13a
--- /dev/null
+++ b/gnu/usr.bin/cvs/mkmodules/mkmodules.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 1992, Brian Berliner and Jeff Polk
+ * 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 1.3 kit.
+ *
+ * mkmodules
+ *
+ * Re-build the modules database for the CVS system. Accepts one argument,
+ * which is the directory that the modules,v file lives in.
+ */
+
+#include "cvs.h"
+
+#undef PATH_MAX
+#define PATH_MAX 1024 /* max number of bytes in pathname */
+
+#ifndef lint
+static char rcsid[] = "@(#)mkmodules.c 1.39 92/03/31";
+#endif
+
+#ifndef DBLKSIZ
+#define DBLKSIZ 4096 /* since GNU ndbm doesn't define it */
+#endif
+
+char *program_name, *command_name;
+
+char *Rcsbin = RCSBIN_DFLT;
+int noexec = 0; /* Here only to satisfy use in subr.c */
+int trace = 0; /* Here only to satisfy use in subr.c */
+
+#if __STDC__
+static int checkout_file (char *file, char *temp);
+static void make_tempfile (char *temp);
+static void mkmodules_usage (void);
+static void rename_rcsfile (char *temp, char *real);
+
+#ifndef MY_NDBM
+static void rename_dbmfile (char *temp);
+static void write_dbmfile (char *temp);
+#endif /* !MY_NDBM */
+
+#else /* !__STDC__ */
+
+static void make_tempfile ();
+static int checkout_file ();
+static void rename_rcsfile ();
+static void mkmodules_usage ();
+
+#ifndef MY_NDBM
+static void write_dbmfile ();
+static void rename_dbmfile ();
+#endif /* !MY_NDBM */
+
+#endif /* __STDC__ */
+
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *getenv ();
+ char temp[PATH_MAX];
+ char *cp;
+#ifdef MY_NDBM
+ DBM *db;
+#endif
+
+ /*
+ * Just save the last component of the path for error messages
+ */
+ if ((program_name = rindex (argv[0], '/')) == NULL)
+ program_name = argv[0];
+ else
+ program_name++;
+
+ if (argc != 2)
+ mkmodules_usage ();
+
+ if ((cp = getenv (RCSBIN_ENV)) != NULL)
+ Rcsbin = cp;
+
+ /*
+ * If Rcsbin is set to something, make sure it is terminated with a slash
+ * character. If not, add one.
+ */
+ if (Rcsbin[0] != '\0')
+ {
+ int len = strlen (Rcsbin);
+ char *rcsbin;
+
+ if (Rcsbin[len - 1] != '/')
+ {
+ rcsbin = Rcsbin;
+ Rcsbin = xmalloc (len + 2); /* one for '/', one for NULL */
+ (void) strcpy (Rcsbin, rcsbin);
+ (void) strcat (Rcsbin, "/");
+ }
+ }
+
+ if (chdir (argv[1]) < 0)
+ error (1, errno, "cannot chdir to %s", argv[1]);
+
+ /*
+ * First, do the work necessary to update the "modules" database.
+ */
+ make_tempfile (temp);
+ switch (checkout_file (CVSROOTADM_MODULES, temp))
+ {
+
+ case 0: /* everything ok */
+#ifdef MY_NDBM
+ /* open it, to generate any duplicate errors */
+ if ((db = dbm_open (temp, O_RDONLY, 0666)) != NULL)
+ dbm_close (db);
+#else
+ write_dbmfile (temp);
+ rename_dbmfile (temp);
+#endif
+ rename_rcsfile (temp, CVSROOTADM_MODULES);
+ break;
+
+ case -1: /* fork failed */
+ (void) unlink_file (temp);
+ exit (1);
+ /* NOTREACHED */
+
+ default:
+ error (0, 0,
+ "'cvs checkout' is less functional without a %s file",
+ CVSROOTADM_MODULES);
+ break;
+ } /* switch on checkout_file() */
+
+ (void) unlink_file (temp);
+
+ /*
+ * Now, check out the "loginfo" file, so that it is always up-to-date in
+ * the CVSROOT directory.
+ */
+ make_tempfile (temp);
+ if (checkout_file (CVSROOTADM_LOGINFO, temp) == 0)
+ rename_rcsfile (temp, CVSROOTADM_LOGINFO);
+ else
+ error (0, 0,
+ "no logging of 'cvs commit' messages is done without a %s file",
+ CVSROOTADM_LOGINFO);
+ (void) unlink_file (temp);
+
+ /*
+ * Now, check out the "rcsinfo" file, so that it is always up-to-date in
+ * the CVSROOT directory.
+ */
+ make_tempfile (temp);
+ if (checkout_file (CVSROOTADM_RCSINFO, temp) == 0)
+ rename_rcsfile (temp, CVSROOTADM_RCSINFO);
+ else
+ error (0, 0,
+ "a %s file can be used to configure 'cvs commit' templates",
+ CVSROOTADM_RCSINFO);
+ (void) unlink_file (temp);
+
+ /*
+ * Now, check out the "editinfo" file, so that it is always up-to-date in
+ * the CVSROOT directory.
+ */
+ make_tempfile (temp);
+ if (checkout_file (CVSROOTADM_EDITINFO, temp) == 0)
+ rename_rcsfile (temp, CVSROOTADM_EDITINFO);
+ else
+ error (0, 0,
+ "a %s file can be used to validate log messages",
+ CVSROOTADM_EDITINFO);
+ (void) unlink_file (temp);
+
+ /*
+ * Now, check out the "commitinfo" file, so that it is always up-to-date
+ * in the CVSROOT directory.
+ */
+ make_tempfile (temp);
+ if (checkout_file (CVSROOTADM_COMMITINFO, temp) == 0)
+ rename_rcsfile (temp, CVSROOTADM_COMMITINFO);
+ else
+ error (0, 0,
+ "a %s file can be used to configure 'cvs commit' checking",
+ CVSROOTADM_COMMITINFO);
+ (void) unlink_file (temp);
+ return (0);
+}
+
+/*
+ * Yeah, I know, there are NFS race conditions here.
+ */
+static void
+make_tempfile (temp)
+ char *temp;
+{
+ static int seed = 0;
+ int fd;
+
+ if (seed == 0)
+ seed = getpid ();
+ while (1)
+ {
+ (void) sprintf (temp, "%s%d", BAKPREFIX, seed++);
+ if ((fd = open (temp, O_CREAT|O_EXCL|O_RDWR, 0666)) != -1)
+ break;
+ if (errno != EEXIST)
+ error (1, errno, "cannot create temporary file %s", temp);
+ }
+ if (close(fd) < 0)
+ error(1, errno, "cannot close temporary file %s", temp);
+}
+
+static int
+checkout_file (file, temp)
+ char *file;
+ char *temp;
+{
+ char rcs[PATH_MAX];
+ int retcode = 0;
+
+ (void) sprintf (rcs, "%s%s", file, RCSEXT);
+ if (!isfile (rcs))
+ return (1);
+ run_setup ("%s%s -q -p", Rcsbin, RCS_CO);
+ run_arg (rcs);
+ if ((retcode = run_exec (RUN_TTY, temp, RUN_TTY, RUN_NORMAL)) != 0)
+ {
+ error (0, retcode == -1 ? errno : 0, "failed to check out %s file", file);
+ }
+ return (retcode);
+}
+
+#ifndef MY_NDBM
+
+static void
+write_dbmfile (temp)
+ char *temp;
+{
+ char line[DBLKSIZ], value[DBLKSIZ];
+ FILE *fp;
+ DBM *db;
+ char *cp, *vp;
+ datum key, val;
+ int len, cont, err = 0;
+
+ fp = open_file (temp, "r");
+ if ((db = dbm_open (temp, O_RDWR | O_CREAT | O_TRUNC, 0666)) == NULL)
+ error (1, errno, "cannot open dbm file %s for creation", temp);
+ for (cont = 0; fgets (line, sizeof (line), fp) != NULL;)
+ {
+ if ((cp = rindex (line, '\n')) != NULL)
+ *cp = '\0'; /* strip the newline */
+
+ /*
+ * Add the line to the value, at the end if this is a continuation
+ * line; otherwise at the beginning, but only after any trailing
+ * backslash is removed.
+ */
+ vp = value;
+ if (cont)
+ vp += strlen (value);
+
+ /*
+ * See if the line we read is a continuation line, and strip the
+ * backslash if so.
+ */
+ len = strlen (line);
+ if (len > 0)
+ cp = &line[len - 1];
+ else
+ cp = line;
+ if (*cp == '\\')
+ {
+ cont = 1;
+ *cp = '\0';
+ }
+ else
+ {
+ cont = 0;
+ }
+ (void) strcpy (vp, line);
+ if (value[0] == '#')
+ continue; /* comment line */
+ vp = value;
+ while (*vp && isspace (*vp))
+ vp++;
+ if (*vp == '\0')
+ continue; /* empty line */
+
+ /*
+ * If this was not a continuation line, add the entry to the database
+ */
+ if (!cont)
+ {
+ key.dptr = vp;
+ while (*vp && !isspace (*vp))
+ vp++;
+ key.dsize = vp - key.dptr;
+ *vp++ = '\0'; /* NULL terminate the key */
+ while (*vp && isspace (*vp))
+ vp++; /* skip whitespace to value */
+ if (*vp == '\0')
+ {
+ error (0, 0, "warning: NULL value for key `%s'", key.dptr);
+ continue;
+ }
+ val.dptr = vp;
+ val.dsize = strlen (vp);
+ if (dbm_store (db, key, val, DBM_INSERT) == 1)
+ {
+ error (0, 0, "duplicate key found for `%s'", key.dptr);
+ err++;
+ }
+ }
+ }
+ dbm_close (db);
+ (void) fclose (fp);
+ if (err)
+ {
+ char dotdir[50], dotpag[50];
+
+ (void) sprintf (dotdir, "%s.dir", temp);
+ (void) sprintf (dotpag, "%s.pag", temp);
+ (void) unlink_file (dotdir);
+ (void) unlink_file (dotpag);
+ error (1, 0, "DBM creation failed; correct above errors");
+ }
+}
+
+static void
+rename_dbmfile (temp)
+ char *temp;
+{
+ char newdir[50], newpag[50];
+ char dotdir[50], dotpag[50];
+ char bakdir[50], bakpag[50];
+
+ (void) sprintf (dotdir, "%s.dir", CVSROOTADM_MODULES);
+ (void) sprintf (dotpag, "%s.pag", CVSROOTADM_MODULES);
+ (void) sprintf (bakdir, "%s%s.dir", BAKPREFIX, CVSROOTADM_MODULES);
+ (void) sprintf (bakpag, "%s%s.pag", BAKPREFIX, CVSROOTADM_MODULES);
+ (void) sprintf (newdir, "%s.dir", temp);
+ (void) sprintf (newpag, "%s.pag", temp);
+
+ (void) chmod (newdir, 0666);
+ (void) chmod (newpag, 0666);
+
+ /* don't mess with me */
+ SIG_beginCrSect ();
+
+ (void) unlink_file (bakdir); /* rm .#modules.dir .#modules.pag */
+ (void) unlink_file (bakpag);
+ (void) rename (dotdir, bakdir); /* mv modules.dir .#modules.dir */
+ (void) rename (dotpag, bakpag); /* mv modules.pag .#modules.pag */
+ (void) rename (newdir, dotdir); /* mv "temp".dir modules.dir */
+ (void) rename (newpag, dotpag); /* mv "temp".pag modules.pag */
+
+ /* OK -- make my day */
+ SIG_endCrSect ();
+}
+
+#endif /* !MY_NDBM */
+
+static void
+rename_rcsfile (temp, real)
+ char *temp;
+ char *real;
+{
+ char bak[50];
+
+ if (chmod (temp, 0444) < 0) /* chmod 444 "temp" */
+ error (0, errno, "warning: cannot chmod %s", temp);
+ (void) sprintf (bak, "%s%s", BAKPREFIX, real);
+ (void) unlink_file (bak); /* rm .#loginfo */
+ (void) rename (real, bak); /* mv loginfo .#loginfo */
+ (void) rename (temp, real); /* mv "temp" loginfo */
+}
+
+/*
+ * For error() only
+ */
+void
+Lock_Cleanup ()
+{
+}
+
+static void
+mkmodules_usage ()
+{
+ (void) fprintf (stderr, "Usage: %s modules-directory\n", program_name);
+ exit (1);
+}
OpenPOWER on IntegriCloud