-/* $Id: tag.c,v 1.8 2015/10/06 18:32:20 schwarze Exp $ */
+/* $Id: tag.c,v 1.13 2016/07/20 13:03:24 schwarze Exp $ */
/*
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
*
#include <string.h>
#include <unistd.h>
-#if HAVE_OHASH
-#include <ohash.h>
-#else
-#include "compat_ohash.h"
-#endif
-
#include "mandoc_aux.h"
+#include "mandoc_ohash.h"
#include "tag.h"
struct tag_entry {
char s[];
};
-static void tag_signal(int);
-static void *tag_alloc(size_t, void *);
-static void tag_free(void *, void *);
-static void *tag_calloc(size_t, size_t, void *);
+static void tag_signal(int) __attribute__((noreturn));
static struct ohash tag_data;
static struct tag_files tag_files;
struct tag_files *
tag_init(void)
{
- struct ohash_info tag_info;
+ struct sigaction sa;
int ofd;
ofd = -1;
tag_files.tfd = -1;
+ tag_files.tcpgid = -1;
+
+ /* Clean up when dying from a signal. */
+
+ memset(&sa, 0, sizeof(sa));
+ sigfillset(&sa.sa_mask);
+ sa.sa_handler = tag_signal;
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+ /*
+ * POSIX requires that a process calling tcsetpgrp(3)
+ * from the background gets a SIGTTOU signal.
+ * In that case, do not stop.
+ */
+
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGTTOU, &sa, NULL);
/* Save the original standard output for use by the pager. */
sizeof(tag_files.ofn));
(void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX",
sizeof(tag_files.tfn));
- signal(SIGHUP, tag_signal);
- signal(SIGINT, tag_signal);
- signal(SIGTERM, tag_signal);
if ((ofd = mkstemp(tag_files.ofn)) == -1)
goto fail;
if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1)
* where various marked-up terms are documented.
*/
- tag_info.alloc = tag_alloc;
- tag_info.calloc = tag_calloc;
- tag_info.free = tag_free;
- tag_info.key_offset = offsetof(struct tag_entry, s);
- tag_info.data = NULL;
- ohash_init(&tag_data, 4, &tag_info);
+ mandoc_ohash_init(&tag_data, 4, offsetof(struct tag_entry, s));
return &tag_files;
fail:
size_t len;
unsigned int slot;
- if (tag_files.tfd <= 0)
+ if (tag_files.tfd <= 0 || strchr(s, ' ') != NULL)
return;
slot = ohash_qlookup(&tag_data, s);
entry = ohash_find(&tag_data, slot);
void
tag_unlink(void)
{
-
+ pid_t tc_pgid;
+
+ if (tag_files.tcpgid != -1) {
+ tc_pgid = tcgetpgrp(STDIN_FILENO);
+ if (tc_pgid == tag_files.pager_pid ||
+ tc_pgid == getpgid(0) ||
+ getpgid(tc_pgid) == -1)
+ (void)tcsetpgrp(STDIN_FILENO, tag_files.tcpgid);
+ }
if (*tag_files.ofn != '\0')
unlink(tag_files.ofn);
if (*tag_files.tfn != '\0')
static void
tag_signal(int signum)
{
+ struct sigaction sa;
tag_unlink();
- signal(signum, SIG_DFL);
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = SIG_DFL;
+ sigaction(signum, &sa, NULL);
kill(getpid(), signum);
/* NOTREACHED */
_exit(1);
}
-
-/*
- * Memory management callback functions for ohash.
- */
-static void *
-tag_alloc(size_t sz, void *arg)
-{
-
- return mandoc_malloc(sz);
-}
-
-static void *
-tag_calloc(size_t nmemb, size_t sz, void *arg)
-{
-
- return mandoc_calloc(nmemb, sz);
-}
-
-static void
-tag_free(void *p, void *arg)
-{
-
- free(p);
-}