int pixie_getpass(const char *prompt, char *buf, size_t sz)
{
const char *pfd = getenv("CATACOMB_PASSPHRASE_FD");
+ struct termios ta;
+ struct termios ota;
+ char nl = '\n';
int fd = 0;
/* --- See whether a terminal is what's wanted --- */
fd = atoi(pfd);
pixie_fdline(fd, buf, sz);
} else {
- struct termios ta;
- struct termios ota;
- char nl = '\n';
-
if ((fd = open("/dev/tty", O_RDWR)) < 0)
goto fail_0;
if (tcgetattr(fd, &ta) < 0)
goto fail_1;
ota = ta;
ta.c_lflag &= ~(ECHO | ISIG);
- if (tcsetattr(fd, TCSAFLUSH, &ta))
- goto fail_1;
- write(fd, prompt, strlen(prompt));
+ if (tcsetattr(fd, TCSAFLUSH, &ta)) goto fail_1;
+ if (write(fd, prompt, strlen(prompt)) < 0) goto fail_2;
pixie_fdline(fd, buf, sz);
tcsetattr(fd, TCSAFLUSH, &ota);
- write(fd, &nl, 1);
+ if (write(fd, &nl, 1) < 0) goto fail_1;
close(fd);
}
return (0);
/* --- Tidy up if things went wrong --- */
+fail_2:
+ tcsetattr(fd, TCSAFLUSH, &ota);
fail_1:
close(fd);
fail_0:
/* --- Send the request --- */
dstr_putf(&d, "%s %s\n", mode == PMODE_READ ? "PASS" : "VERIFY", tag);
- write(fd, d.buf, d.len);
+ if (write(fd, d.buf, d.len) < 0) return (-1);
dstr_destroy(&d);
/* --- Sort out the result --- */
*/
dstr_putf(&d, "SET %s -- ", tag);
- write(fd, d.buf, d.len);
- write(fd, phrase, sz);
- write(fd, &nl, 1);
+ if (write(fd, d.buf, d.len) < 0 ||
+ write(fd, phrase, sz) < 0 ||
+ write(fd, &nl, 1) < 0)
+ return;
dstr_destroy(&d);
/* --- Pick up the pieces --- */
/* --- Send the request --- */
dstr_putf(&d, "FLUSH %s\n", tag);
- write(fd, d.buf, d.len);
+ if (write(fd, d.buf, d.len) < 0) return;
dstr_destroy(&d);
/* --- Sort out the result --- */
}
/*----- That's all, folks -------------------------------------------------*/
-
* @const char *p@ = pointer to skeleton string
* @...@ = other arguments to fill in
*
- * Returns: ---
+ * Returns: Zero on success, @-1@ on error.
*
* Use: Formats a string and emits it to the output file.
*/
-static void PRINTF_LIKE(2, 3) pixserv_write(pixserv *px, const char *p, ...)
+static int PRINTF_LIKE(2, 3) pixserv_write(pixserv *px, const char *p, ...)
{
dstr d = DSTR_INIT;
va_list ap;
+ int rc;
va_start(ap, p);
dstr_vputf(&d, p, &ap);
- write(px->fd, d.buf, d.len);
+ rc = write(px->fd, d.buf, d.len);
va_end(ap);
dstr_destroy(&d);
+ if (rc < 0) {
+ pxlog("failed to write to client: %s (closing)", strerror(errno));
+ return (-1);
+ }
+ return (0);
}
/* --- @pixserv_timeout@ --- *
if (!(px->f & px_stdin))
sel_rmtimer(&px->timer);
- if (!s) {
- if (px->fd != px->b.reader.fd)
- close(px->fd);
- selbuf_destroy(&px->b);
- close(px->b.reader.fd);
- return;
- }
+ if (!s) goto close;
/* --- Fiddle the timeout --- */
/* --- Handle a help request --- */
if (strcmp(q, "help") == 0) {
- pixserv_write(px, "\
+ if (pixserv_write(px, "\
INFO Commands supported:\n\
INFO HELP\n\
INFO LIST\n\
INFO SET tag [expire] -- phrase\n\
INFO QUIT\n\
OK\n\
-");
+"))
+ goto close;
}
/* --- List the passphrases --- */
phrase *p;
for (p = p_head; p; p = p->next) {
- if (!p->t)
- pixserv_write(px, "ITEM %s no-expire\n", p->tag);
- else {
+ if (!p->t) {
+ if (pixserv_write(px, "ITEM %s no-expire\n", p->tag)) goto close;
+ } else {
struct timeval tv;
gettimeofday(&tv, 0);
TV_SUB(&tv, &p->timer.tv, &tv);
- pixserv_write(px, "ITEM %s %lu\n", p->tag, (unsigned long)tv.tv_sec);
+ if (pixserv_write(px, "ITEM %s %lu\n",
+ p->tag, (unsigned long)tv.tv_sec))
+ goto close;
}
}
- pixserv_write(px, "OK\n");
+ if (pixserv_write(px, "OK\n")) goto close;
}
/* --- Request a passphrase --- */
rc = p_get(&p, q, mode, t > timeout ? timeout : t);
switch (rc) {
case 0:
- pixserv_write(px, "OK %s\n", p);
+ if (pixserv_write(px, "OK %s\n", p)) goto close;
break;
case -1:
- pixserv_write(px, "FAIL error reading passphrase\n");
+ if (pixserv_write(px, "FAIL error reading passphrase\n"))
+ goto close;
break;
case +1:
- pixserv_write(px, "MISSING\n");
+ if (pixserv_write(px, "MISSING\n")) goto close;
break;
}
}
else if (strcmp(q, "flush") == 0) {
q = str_getword(&s);
p_flush(q);
- pixserv_write(px, "OK\n");
+ if (pixserv_write(px, "OK\n")) goto close;
}
/* --- Set a passphrase --- */
else if (strcmp(q, "set") == 0) {
char *tag;
unsigned long t;
- if ((tag = str_getword(&s)) == 0)
- pixserv_write(px, "FAIL missing tag\n");
- else if ((q = str_getword(&s)) == 0)
- pixserv_write(px, "FAIL no passphrase\n");
- else {
+ if ((tag = str_getword(&s)) == 0) {
+ if (pixserv_write(px, "FAIL missing tag\n")) goto close;
+ } else if ((q = str_getword(&s)) == 0) {
+ if (pixserv_write(px, "FAIL no passphrase\n")) goto close;
+ } else {
if (strcmp(q, "--") != 0) {
t = pixserv_timeout(q);
q = str_getword(&s);
} else
t = pixserv_timeout(0);
- if (!q)
- pixserv_write(px, "FAIL no passphrase\n");
- else if (strcmp(q, "--") != 0)
- pixserv_write(px, "FAIL rubbish found before passphrase\n");
- else {
+ if (!q) {
+ if (pixserv_write(px, "FAIL no passphrase\n")) goto close;
+ } else if (strcmp(q, "--") != 0) {
+ if (pixserv_write(px, "FAIL rubbish found before passphrase\n"))
+ goto close;
+ } else {
p_flush(tag);
p_add(tag, s, t);
- pixserv_write(px, "OK\n");
+ if (pixserv_write(px, "OK\n")) goto close;
}
}
}
/* --- Shut the server down --- */
else if (strcmp(q, "quit") == 0) {
- if (verbose)
+ if (verbose) {
pxlog("%s client requested shutdown",
px->f & px_stdin ? "local" : "remote");
- pixserv_write(px, "OK\n");
+ }
+ if (pixserv_write(px, "OK\n")) goto close;
exit(0);
}
/* --- Report an error for other commands --- */
- else
- pixserv_write(px, "FAIL unknown command `%s'\n", q);
+ else {
+ if (pixserv_write(px, "FAIL unknown command `%s'\n", q)) goto close;
+ }
+ return;
+
+close:
+ if (px->fd != px->b.reader.fd)
+ close(px->fd);
+ selbuf_destroy(&px->b);
+ close(px->b.reader.fd);
}
/* --- @pixserv_create@ --- *
} else {
if (verbose)
pxlog("server already running; shutting it down");
- write(fd, "QUIT\n", 5);
+ if (write(fd, "QUIT\n", 5) < 0) {
+ die(EXIT_FAILURE, "failed to shut down old server: %s",
+ strerror(errno));
+ }
sleep(1);
close(fd);
}
c_flags |= cf_uclose;
} else {
s[len++] = '\n';
- write(c_server.reader.fd, s, len);
+ if (write(c_server.reader.fd, s, len) < 0)
+ die(EXIT_FAILURE, "failed to read from stdin: %s", strerror(errno));
}
}
DPUTS(&d, *argv++);
}
DPUTC(&d, '\n');
- write(fd, d.buf, d.len);
- shutdown(fd, 1);
+ if (write(fd, d.buf, d.len) < 0 || shutdown(fd, 1))
+ die(EXIT_FAILURE, "failed to write command: %s", strerror(errno));
c_flags |= cf_uclose | cf_cooked;
dstr_destroy(&d);
}
}
}
#endif
- chdir("/");
+ DISCARD(chdir("/"));
setsid();
if (fork() != 0)