Release 1.2.4.
[checkpath] / tmpdir.c
index 8e704e6..0bf51d3 100644 (file)
--- a/tmpdir.c
+++ b/tmpdir.c
@@ -5,7 +5,7 @@
  * (c) 1999 Mark Wooding
  */
 
-/*----- Licensing notice --------------------------------------------------* 
+/*----- Licensing notice --------------------------------------------------*
  *
  * This file is part of chkpath.
  *
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * chkpath is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with chkpath; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 /*----- Header files ------------------------------------------------------*/
 
+#include "config.h"
+
 #include <errno.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -35,6 +38,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <pwd.h>
+#include <grp.h>
 
 #include <mLib/alloc.h>
 #include <mLib/dstr.h>
@@ -44,6 +48,7 @@
 #include <mLib/report.h>
 
 #include "checkpath.h"
+#include "utils.h"
 
 /*----- Static variables --------------------------------------------------*/
 
@@ -64,6 +69,17 @@ static struct passwd *pw;
  *             and @*f@ is set, then try to create the directory.
  */
 
+static void complain(const char *p, const char *msg, int err)
+{
+  dstr d = DSTR_INIT;
+
+  if (!cp.cp_verbose) return;
+  dstr_putf(&d, "Path: %s: %s", p, msg);
+  if (err) dstr_putf(&d, ": %s", strerror(err));
+  moan(d.buf);
+  dstr_destroy(&d);
+}
+
 static int ok(const char *p, int *f)
 {
   struct stat st;
@@ -74,9 +90,12 @@ static int ok(const char *p, int *f)
 
     /* --- Maybe create it if it doesn't exist --- */
 
-    if (errno != ENOENT || !f || !*f)
+    if (errno != ENOENT || !f || !*f) {
+      complain(p, "can't stat", errno);
       return (0);
+    }
     if (mkdir(p, 0700)) {
+      complain(p, "can't create", errno);
       *f = 0;
       return (0);
     }
@@ -87,8 +106,10 @@ static int ok(const char *p, int *f)
      * the @mkdir@.
      */
 
-    if (lstat(p, &st))
+    if (lstat(p, &st)) {
+      complain(p, "can't stat after creating", errno);
       return (0);
+    }
   }
 
   /* --- Make sure the directory is good --- *
@@ -97,7 +118,13 @@ static int ok(const char *p, int *f)
    * and writable only by its owner, and that owner must be me.
    */
 
-  if (S_ISDIR(st.st_mode) && (st.st_mode & 0777) == 0700 && st.st_uid == me)
+  if (!S_ISDIR(st.st_mode))
+    complain(p, "not a directory", 0);
+  else if (st.st_uid != me)
+    complain(p, "not owner", 0);
+  else if ((st.st_mode & 0777) != 0700)
+    complain(p, "non-owner access permitted", 0);
+  else
     return (1);
   return (0);
 }
@@ -179,9 +206,7 @@ good:
  */
 
 static int fullcheck(const char *p)
-{
-  return (checkpath(p, &cp) == 0 && ok(p, 0));
-}
+  { return (checkpath(p, &cp) == 0 && ok(p, 0)); }
 
 /* --- @goodtmp@ --- *
  *
@@ -204,16 +229,12 @@ static char *goodtmp(void)
 
   /* --- Try making a directory in `/tmp' --- */
 
-  if (!(q = getenv("USER")) && !(q = getenv("LOGNAME")))
-    q = pw->pw_name;
-  if ((q = trytmp("/tmp", q)) != 0)
+  if ((q = trytmp("/tmp", pw->pw_name)) != 0)
     return (q);
 
   /* --- That failed: try a directory in the user's home --- */
 
-  if (!(q = getenv("HOME")))
-    q = pw->pw_dir;
-  if ((q = trytmp(q, "tmp")) != 0)
+  if ((q = trytmp(pw->pw_dir, "tmp")) != 0)
     return (q);
 
   /* --- Still no joy: give up --- *
@@ -235,7 +256,7 @@ static void report(unsigned what, int verbose,
 /* --- @usage@ --- */
 
 static void usage(FILE *fp)
-  { fprintf(fp, "Usage: %s [-bc] [-v PATH]\n", QUIS); }
+  { fprintf(fp, "Usage: %s [-bcv] [-g NAME] [-C PATH]\n", QUIS); }
 
 /* --- @version@ --- */
 
@@ -265,6 +286,7 @@ Options supported:\n\
 -b, --bourne           Output a `TMPDIR' setting for Bourne shell users.\n\
 -c, --cshell           Output a `TMPDIR' setting for C shell users.\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\
@@ -298,11 +320,12 @@ int main(int argc, char *argv[])
   /* --- Initialize variables --- */
 
   ego(argv[0]);
-  me = getuid();
-  cp.cp_what = CP_WRWORLD | CP_WRGRP | CP_WROTHUSR | CP_STICKYOK | CP_REPORT;
+  me = cp.cp_uid = geteuid();
+  cp.cp_what = (CP_WRWORLD | CP_WROTHGRP | CP_WROTHUSR |
+               CP_STICKYOK | CP_REPORT | CP_ERROR);
   cp.cp_verbose = 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");
@@ -312,16 +335,18 @@ int main(int argc, char *argv[])
   for (;;) {
     static struct option opts[] = {
       { "help",                0,              0,      'h' },
-      { "version",     0,              0,      'V' },
+      { "version",     0,              0,      'V' },
       { "usage",       0,              0,      'u' },
       { "bourne",      0,              0,      'b' },
       { "cshell",      0,              0,      'c' },
       { "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 bcvc:", opts, 0, 0, 0);
+    int i = mdwopt(argc, argv, "hVu" "bcvtg:C:", opts, 0, 0, 0);
 
     if (i < 0)
       break;
@@ -344,6 +369,9 @@ int main(int argc, char *argv[])
       case 'C':
        return (!fullcheck(optarg));
        break;
+      case 'g':
+       allowgroup(&cp, optarg);
+       break;
       case 'v':
        cp.cp_verbose++;
        break;
@@ -380,7 +408,7 @@ int main(int argc, char *argv[])
     case sh_csh:
       printf("setenv TMPDIR \"%s\"\n", p);
        break;
-  }    
+  }
 
   return (0);
 }