Merge branch 'master' of chiark:src/checkpath
[checkpath] / tmpdir.c
index f7e611b..f0fcb5f 100644 (file)
--- a/tmpdir.c
+++ b/tmpdir.c
@@ -1,7 +1,5 @@
 /* -*-c-*-
  *
- * $Id: tmpdir.c,v 1.5 2004/04/08 01:36:22 mdw Exp $
- *
  * Choose and check temporary directories
  *
  * (c) 1999 Mark Wooding
@@ -31,6 +29,7 @@
 #include "config.h"
 
 #include <errno.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <pwd.h>
+#include <grp.h>
 
 #include <mLib/alloc.h>
 #include <mLib/dstr.h>
+#include <mLib/macros.h>
 #include <mLib/mdwopt.h>
 #include <mLib/quis.h>
 #include <mLib/report.h>
@@ -222,6 +223,13 @@ static char *goodtmp(void)
   return (0);
 }
 
+/* --- @report@ --- */
+
+static void report(unsigned what, int verbose,
+                  const char *p, const char *msg,
+                  void *arg)
+  { moan("%s", msg); }
+
 /* --- @usage@ --- */
 
 static void usage(FILE *fp)
@@ -254,7 +262,9 @@ Options supported:\n\
 \n\
 -b, --bourne           Output a `TMPDIR' setting for Bourne shell users.\n\
 -c, --cshell           Output a `TMPDIR' setting for C shell users.\n\
--v, --verify PATH      Check whether PATH is good, setting exit status.\n\
+-v, --verbose          Report problems to standard error.\n\
+-g, --group NAME       Trust group NAME to be honest and true.\n\
+-C, --check PATH       Check whether PATH is good, setting exit status.\n\
 \n\
 The default action is to examine the caller's shell and output a suitable\n\
 setting for that shell type.\n\
@@ -262,6 +272,46 @@ setting for that shell type.\n\
        fp);
 }
 
+/* --- @allowgroup@ --- *
+ *
+ * Arguments:  @const char *gname@ = trust group @gname@
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds the gid corresponding to @gname@ (which may be a number)
+ *             to the list of things we trust.
+ */
+
+static void allowgroup(const char *gname)
+{
+  struct group *gr;
+  const char *p;
+  gid_t g;
+
+  /* --- Check for numeric group spec --- */
+
+  for (p = gname; *p; p++) {
+    if (!isdigit((unsigned char)*p))
+      goto lookup;
+  }
+  g = atoi(gname);
+  goto insert;
+
+  /* --- Look up a group by name --- */
+
+lookup:
+  if ((gr = getgrnam(gname)) == 0)
+    die(1, "group %s not found", gname);
+  g = gr->gr_gid;
+
+  /* --- Insert the group into the table --- */
+
+insert:
+  if (cp.cp_gids >= N(cp.cp_gid))
+    die(1, "too many groups");
+  cp.cp_gid[cp.cp_gids++] = g;
+}
+
 /* --- @main@ --- *
  *
  * Arguments:  @int argc@ = number of command line arguments
@@ -276,6 +326,7 @@ int main(int argc, char *argv[])
 {
   int shell = 0;
   int duff = 0;
+  char *p;
 
   enum {
     sh_unknown,
@@ -287,10 +338,12 @@ int main(int argc, char *argv[])
 
   ego(argv[0]);
   me = geteuid();
-  cp.cp_what = CP_WRWORLD | CP_WRGRP | CP_WROTHUSR | CP_STICKYOK;
+  cp.cp_what = (CP_WRWORLD | CP_WROTHGRP | CP_WROTHUSR |
+               CP_STICKYOK | CP_REPORT);
   cp.cp_verbose = 0;
-  cp.cp_report = 0;
+  cp.cp_report = report;
   checkpath_setids(&cp);
+  cp.cp_gids = 0;                      /* ignore group membership */
   pw = getpwuid(me);
   if (!pw)
     die(1, "you don't exist");
@@ -304,10 +357,14 @@ int main(int argc, char *argv[])
       { "usage",       0,              0,      'u' },
       { "bourne",      0,              0,      'b' },
       { "cshell",      0,              0,      'c' },
-      { "verify",      OPTF_ARGREQ,    0,      'v' },
+      { "check",       OPTF_ARGREQ,    0,      'C' },
+      { "verify",      OPTF_ARGREQ,    0,      'C' },
+      { "verbose",     0,              0,      'v' },
+      { "trust-groups",        0,              0,      't' },
+      { "group",       OPTF_ARGREQ,    0,      'g' },
       { 0,             0,              0,      0 }
     };
-    int i = mdwopt(argc, argv, "hVu" "bcv:", opts, 0, 0, 0);
+    int i = mdwopt(argc, argv, "hVu" "bcvtg:c:", opts, 0, 0, 0);
 
     if (i < 0)
       break;
@@ -327,9 +384,15 @@ int main(int argc, char *argv[])
       case 'c':
        shell = sh_csh;
        break;
-      case 'v':
+      case 'C':
        return (!fullcheck(optarg));
        break;
+      case 'g':
+       allowgroup(optarg);
+       break;
+      case 'v':
+       cp.cp_verbose++;
+       break;
       default:
        duff = 1;
        break;
@@ -344,7 +407,6 @@ int main(int argc, char *argv[])
   /* --- Choose a shell --- */
 
   if (!shell) {
-    char *p;
     if (!(p = getenv("SHELL")))
       p = pw->pw_shell;
     if (strstr(p, "csh"))
@@ -355,19 +417,16 @@ int main(int argc, char *argv[])
 
   /* --- Start the checking --- */
 
-  {
-    char *p = goodtmp();
-    if (!p)
-      die(1, "no good tmp directory");
-    switch (shell) {
-      case sh_bourne:
-       printf("TMPDIR=\"%s\"; export TMPDIR\n", p);
-       break;
-      case sh_csh:
-       printf("setenv TMPDIR \"%s\"\n", p);
+  if ((p = goodtmp()) == 0)
+    die(1, "no good tmp directory");
+  switch (shell) {
+    case sh_bourne:
+      printf("TMPDIR=\"%s\"; export TMPDIR\n", p);
+      break;
+    case sh_csh:
+      printf("setenv TMPDIR \"%s\"\n", p);
        break;
-    }
-  }
+  }    
 
   return (0);
 }