From 12f4fdd4872dac294b89bcf984492bc88dca0b5e Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Tue, 28 Jul 2015 18:38:55 +0000 Subject: Remove the hack of scrolling forward and backward with +G1G that many (jmc@, millert@, espie@, deraadt@) considered revolting. Instead, when using a pager, since we are using a temporary file for tags anyway, use another temporary file for the formatted page(s), as suggested by millert@ and similar to what the traditional BSD man(1) did, except that we use only one single temporary output file rather than one for each formatted manual page, such that searching (both with / and :t) works across all the displayed files. --- tag.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 20 deletions(-) (limited to 'tag.c') diff --git a/tag.c b/tag.c index 02020663..3b3de023 100644 --- a/tag.c +++ b/tag.c @@ -1,4 +1,4 @@ -/* $Id: tag.c,v 1.5 2015/07/25 14:28:59 schwarze Exp $ */ +/* $Id: tag.c,v 1.6 2015/07/28 18:38:55 schwarze Exp $ */ /* * Copyright (c) 2015 Ingo Schwarze * @@ -44,29 +44,49 @@ static void tag_free(void *, void *); static void *tag_calloc(size_t, size_t, void *); static struct ohash tag_data; -static char *tag_fn = NULL; -static int tag_fd = -1; +static struct tag_files tag_files; /* - * Set up the ohash table to collect output line numbers - * where various marked-up terms are documented and create - * the temporary tags file, saving the name for the pager. + * Prepare for using a pager. + * Not all pagers are capable of using a tag file, + * but for simplicity, create it anyway. */ -char * +struct tag_files * tag_init(void) { struct ohash_info tag_info; + int ofd; - tag_fn = mandoc_strdup("/tmp/man.XXXXXXXXXX"); + ofd = -1; + tag_files.tfd = -1; + + /* Save the original standard output for use by the pager. */ + + if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1) + goto fail; + + /* Create both temporary output files. */ + + (void)strlcpy(tag_files.ofn, "/tmp/man.XXXXXXXXXX", + 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 ((tag_fd = mkstemp(tag_fn)) == -1) { - free(tag_fn); - tag_fn = NULL; - return(NULL); - } + if ((ofd = mkstemp(tag_files.ofn)) == -1) + goto fail; + if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1) + goto fail; + if (dup2(ofd, STDOUT_FILENO) == -1) + goto fail; + close(ofd); + + /* + * Set up the ohash table to collect output line numbers + * where various marked-up terms are documented. + */ tag_info.alloc = tag_alloc; tag_info.calloc = tag_calloc; @@ -74,7 +94,21 @@ tag_init(void) tag_info.key_offset = offsetof(struct tag_entry, s); tag_info.data = NULL; ohash_init(&tag_data, 4, &tag_info); - return(tag_fn); + return(&tag_files); + +fail: + tag_unlink(); + if (ofd != -1) + close(ofd); + if (tag_files.ofd != -1) + close(tag_files.ofd); + if (tag_files.tfd != -1) + close(tag_files.tfd); + *tag_files.ofn = '\0'; + *tag_files.tfn = '\0'; + tag_files.ofd = -1; + tag_files.tfd = -1; + return(NULL); } /* @@ -88,7 +122,7 @@ tag_put(const char *s, int prio, size_t line) size_t len; unsigned int slot; - if (tag_fd == -1) + if (tag_files.tfd <= 0) return; slot = ohash_qlookup(&tag_data, s); entry = ohash_find(&tag_data, slot); @@ -114,13 +148,14 @@ tag_write(void) struct tag_entry *entry; unsigned int slot; - if (tag_fd == -1) + if (tag_files.tfd <= 0) return; - stream = fdopen(tag_fd, "w"); + stream = fdopen(tag_files.tfd, "w"); entry = ohash_first(&tag_data, &slot); while (entry != NULL) { if (stream != NULL) - fprintf(stream, "%s - %zu\n", entry->s, entry->line); + fprintf(stream, "%s %s %zu\n", + entry->s, tag_files.ofn, entry->line); free(entry); entry = ohash_next(&tag_data, &slot); } @@ -133,8 +168,10 @@ void tag_unlink(void) { - if (tag_fn != NULL) - unlink(tag_fn); + if (*tag_files.ofn != '\0') + unlink(tag_files.ofn); + if (*tag_files.tfn != '\0') + unlink(tag_files.tfn); } static void -- cgit v1.2.3-56-ge451