/* -*-c-*-
*
- * $Id: pixie.c,v 1.4 2000/06/17 11:50:53 mdw Exp $
+ * $Id: pixie.c,v 1.10 2001/02/21 20:03:54 mdw Exp $
*
* Passphrase pixie for Catacomb
*
/*----- Revision history --------------------------------------------------*
*
* $Log: pixie.c,v $
+ * Revision 1.10 2001/02/21 20:03:54 mdw
+ * Handle select errors (by bombing out). Cosmetic tweak.
+ *
+ * Revision 1.9 2001/02/03 16:06:44 mdw
+ * Don't set a handler for @SIGINT@ if it's ignored at startup. Add some
+ * error handling for the @select@ loop.
+ *
+ * Revision 1.8 2001/01/25 22:19:31 mdw
+ * Make flags be unsigned.
+ *
+ * Revision 1.7 2000/12/06 20:33:27 mdw
+ * Make flags be macros rather than enumerations, to ensure that they're
+ * unsigned.
+ *
+ * Revision 1.6 2000/10/08 12:06:46 mdw
+ * Change size passed to socket function to be a @size_t@. Insert missing
+ * type name for flag declaration.
+ *
+ * Revision 1.5 2000/07/29 22:05:22 mdw
+ * Miscellaneous tidyings:
+ *
+ * * Change the timeout to something more appropriate for real use.
+ *
+ * * Check assumptions about object types when binding the socket. In
+ * particular, don't zap the socket if it's really something else.
+ *
+ * * In @p_request@, return a failure if the shell command returned
+ * nonzero. Fix a bug in @p_get@ which incorrectly passes on a success
+ * code when this happens.
+ *
+ * * Dispose of the locked memory in client mode to avoid being
+ * antisocial.
+ *
+ * * Also in client mode, don't report closure from the server if we're
+ * running noninteractively.
+ *
+ * * Insert a missing option letter into the usage string.
+ *
+ * * Change to the root directory after forking in daemon mode.
+ *
* Revision 1.4 2000/06/17 11:50:53 mdw
* New pixie protocol allowing application to request passphrases and send
* them to the pixie. Use the secure arena interface for the input
/*----- Static variables --------------------------------------------------*/
-static unsigned long timeout = 300;
+static unsigned long timeout = 900;
static sel_state sel;
static unsigned verbose = 1;
static const char *command = 0;
static lmem lm;
static unsigned flags = 0;
-enum {
- F_SYSLOG = 1,
- F_FETCH = 2
-};
+#define F_SYSLOG 1u
+#define F_FETCH 2u
/*----- Event logging -----------------------------------------------------*/
int fd[2];
pid_t kid;
int r;
+ int rc;
/* --- Substitute the prompt string into the command --- */
*q = 0;
}
close(fd[0]);
- waitpid(kid, 0, 0);
+ waitpid(kid, &rc, 0);
dstr_destroy(&d);
- if (r < 0)
+ if (r < 0 || rc != 0)
goto fail_0;
goto ok;
memset(pp, 0, LBUFSZ);
l_free(&lm, pp);
}
- return (0);
+ return (-1);
#undef LBUFSZ
}
unsigned f;
} pixserv;
-enum { px_stdin = 1 };
+#define px_stdin 1u
#define PIXSERV_TIMEOUT 30
{
int nfd;
struct sockaddr_un sun;
- int sunsz = sizeof(sun);
+ size_t sunsz = sizeof(sun);
if (mode != SEL_READ)
return;
/* --- Set up the parent directory --- */
{
- dstr d = DSTR_INIT;
char *p = sun->sun_path;
char *q = strrchr(p, '/');
if (q) {
+ dstr d = DSTR_INIT;
struct stat st;
DPUTM(&d, p, q - p);
mkdir(d.buf, 0700);
if (stat(d.buf, &st))
die(1, "couldn't stat `%s': %s", d.buf, strerror(errno));
+ if (!S_ISDIR(st.st_mode))
+ die(1, "object `%s' isn't a directory", d.buf);
if (st.st_mode & 0077)
die(1, "parent directory `%s' has group or world access", d.buf);
+ dstr_destroy(&d);
}
}
die(1, "too many retries; giving up");
n--;
if (connect(fd, (struct sockaddr *)sun, sz)) {
+ struct stat st;
if (errno != ECONNREFUSED)
die(1, "couldn't bind to address: %s", strerror(e));
+ if (stat(sun->sun_path, &st))
+ die(1, "couldn't stat `%s': %s", sun->sun_path, strerror(errno));
+ if (!S_ISSOCK(st.st_mode))
+ die(1, "object `%s' isn't a socket", sun->sun_path);
if (verbose)
log("stale socket found; removing it");
unlink(sun->sun_path);
/* --- Variables --- */
static selbuf c_server, c_client;
-static c_flags = 0;
-enum { cf_uclose = 1, cf_sclose = 2 };
+static unsigned c_flags = 0;
+
+#define cf_uclose 1u
+#define cf_sclose 2u
/* --- Line handler functions --- */
selbuf_destroy(&c_client);
}
exit(0);
- } else
- puts(s);
+ }
+ puts(s);
}
/* --- @pix_client@ --- *
{
int fd;
+ /* --- Dispose of locked memory --- */
+
+ l_destroy(&lm);
+
/* --- Open the socket --- */
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
DPUTC(&d, '\n');
write(fd, d.buf, d.len);
shutdown(fd, 1);
+ c_flags |= cf_uclose;
dstr_destroy(&d);
}
/* --- And repeat --- */
- for (;;)
- sel_select(&sel);
+ for (;;) {
+ if (sel_select(&sel))
+ die(EXIT_FAILURE, "select error: %s", strerror(errno));
+ }
}
/*----- Main code ---------------------------------------------------------*/
{
pquis(fp, "\
Usage:\n\
- $ [-qvidl] [-c command] [-t timeout] [-s socket]\n\
+ $ [-qvfidl] [-c command] [-t timeout] [-s socket]\n\
$ [-s socket] -C [command args...]\n\
");
}
size_t sz;
unsigned f = 0;
- enum {
- f_bogus = 1,
- f_client = 2,
- f_stdin = 4,
- f_daemon = 8,
- f_syslog = 16
- };
+#define f_bogus 1u
+#define f_client 2u
+#define f_stdin 4u
+#define f_daemon 8u
+#define f_syslog 16u
/* --- Initialize libraries --- */
{
static sig sigint, sigterm, sigquit, sighup;
+ struct sigaction sa;
sig_init(&sel);
- sig_add(&sigint, SIGINT, pix_sigdie, 0);
+ sigaction(SIGINT, 0, &sa);
+ if (sa.sa_handler != SIG_IGN)
+ sig_add(&sigint, SIGINT, pix_sigdie, 0);
sig_add(&sigterm, SIGTERM, pix_sigdie, 0);
sig_add(&sigquit, SIGQUIT, pix_sigflush, 0);
sig_add(&sighup, SIGHUP, pix_sigflush, 0);
}
}
#endif
+ chdir("/");
setsid();
- if (fork() > 0)
+ if (fork() >= 0)
_exit(0);
}
if (verbose)
log("initialized ok");
- for (;;)
- sel_select(&sel);
+
+ {
+ int selerr = 0;
+ for (;;) {
+ if (!sel_select(&sel))
+ selerr = 0;
+ else if (errno != EINTR && errno != EAGAIN) {
+ log("error from select: %s", strerror(errno));
+ selerr++;
+ if (selerr > 8) {
+ log("too many consecutive select errors: bailing out");
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ }
return (0);
}