source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Remove the hack of scrolling forward and backward with +G1G that
@ 2015-07-28 18:39 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2015-07-28 18:39 UTC (permalink / raw)
  To: source

Log Message:
-----------
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.

Modified Files:
--------------
    mdocml:
        main.c
        tag.c
        tag.h

Revision Data
-------------
Index: tag.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/tag.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -Ltag.h -Ltag.h -u -p -r1.4 -r1.5
--- tag.h
+++ tag.h
@@ -15,9 +15,16 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+struct	tag_files {
+	char	 ofn[20];
+	char	 tfn[20];
+	int	 ofd;
+	int	 tfd;
+};
+
 __BEGIN_DECLS
 
-char	*tag_init(void);
+struct tag_files *tag_init(void);
 void	 tag_put(const char *, int, size_t);
 void	 tag_write(void);
 void	 tag_unlink(void);
Index: main.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/main.c,v
retrieving revision 1.243
retrieving revision 1.244
diff -Lmain.c -Lmain.c -u -p -r1.243 -r1.244
--- main.c
+++ main.c
@@ -95,7 +95,6 @@ static	int		  fs_lookup(const struct man
 static	void		  fs_search(const struct mansearch *,
 				const struct manpaths *, int, char**,
 				struct manpage **, size_t *);
-static	void		  handle_sigpipe(int);
 static	int		  koptions(int *, char *);
 #if HAVE_SQLITE3
 int			  mandocdb(int, char**);
@@ -105,7 +104,7 @@ static	void		  mmsg(enum mandocerr, enum
 				const char *, int, int, const char *);
 static	void		  parse(struct curparse *, int, const char *);
 static	void		  passthrough(const char *, int, int);
-static	pid_t		  spawn_pager(void);
+static	pid_t		  spawn_pager(struct tag_files *);
 static	int		  toptions(struct curparse *, char *);
 static	void		  usage(enum argmode) __attribute__((noreturn));
 static	int		  woptions(struct curparse *, char *);
@@ -123,6 +122,7 @@ main(int argc, char *argv[])
 	struct manconf	 conf;
 	struct curparse	 curp;
 	struct mansearch search;
+	struct tag_files *tag_files;
 	char		*auxpaths;
 	char		*defos;
 	unsigned char	*uc;
@@ -136,8 +136,8 @@ main(int argc, char *argv[])
 	int		 fd;
 	int		 show_usage;
 	int		 options;
+	int		 use_pager;
 	int		 c;
-	pid_t		 pager_pid;  /* 0: don't use; 1: not yet spawned. */
 
 	if (argc < 1)
 		progname = "mandoc";
@@ -180,7 +180,8 @@ main(int argc, char *argv[])
 	options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1;
 	defos = NULL;
 
-	pager_pid = 1;
+	use_pager = 1;
+	tag_files = NULL;
 	show_usage = 0;
 	outmode = OUTMODE_DEF;
 
@@ -194,14 +195,14 @@ main(int argc, char *argv[])
 			conf_file = optarg;
 			break;
 		case 'c':
-			pager_pid = 0;
+			use_pager = 0;
 			break;
 		case 'f':
 			search.argmode = ARG_WORD;
 			break;
 		case 'h':
 			conf.output.synopsisonly = 1;
-			pager_pid = 0;
+			use_pager = 0;
 			outmode = OUTMODE_ALL;
 			break;
 		case 'I':
@@ -277,7 +278,7 @@ main(int argc, char *argv[])
 		switch (search.argmode) {
 		case ARG_FILE:
 			outmode = OUTMODE_ALL;
-			pager_pid = 0;
+			use_pager = 0;
 			break;
 		case ARG_NAME:
 			outmode = OUTMODE_ONE;
@@ -419,8 +420,8 @@ main(int argc, char *argv[])
 	if (search.argmode == ARG_FILE && ! moptions(&options, auxpaths))
 		return((int)MANDOCLEVEL_BADARG);
 
-	if (pager_pid == 1 && isatty(STDOUT_FILENO) == 0)
-		pager_pid = 0;
+	if (use_pager && ! isatty(STDOUT_FILENO))
+		use_pager = 0;
 
 	curp.mchars = mchars_alloc();
 	curp.mp = mparse_alloc(options, curp.wlevel, mmsg,
@@ -433,8 +434,8 @@ main(int argc, char *argv[])
 		mparse_keep(curp.mp);
 
 	if (argc < 1) {
-		if (pager_pid == 1)
-			pager_pid = spawn_pager();
+		if (use_pager)
+			tag_files = tag_init();
 		parse(&curp, STDIN_FILENO, "<stdin>");
 	}
 
@@ -445,8 +446,10 @@ main(int argc, char *argv[])
 			rc = rctmp;
 
 		if (fd != -1) {
-			if (pager_pid == 1)
-				pager_pid = spawn_pager();
+			if (use_pager) {
+				tag_files = tag_init();
+				use_pager = 0;
+			}
 
 			if (resp == NULL)
 				parse(&curp, fd, *argv);
@@ -490,15 +493,14 @@ out:
 	free(defos);
 
 	/*
-	 * If a pager is attached, flush the pipe leading to it
-	 * and signal end of file such that the user can browse
-	 * to the end.  Then wait for the user to close the pager.
+	 * When using a pager, finish writing both temporary files,
+	 * fork it, wait for the user to close it, and clean up.
 	 */
 
-	if (pager_pid != 0 && pager_pid != 1) {
+	if (tag_files != NULL) {
 		fclose(stdout);
 		tag_write();
-		waitpid(pager_pid, NULL, 0);
+		waitpid(spawn_pager(tag_files), NULL, 0);
 		tag_unlink();
 	}
 
@@ -947,22 +949,14 @@ mmsg(enum mandocerr t, enum mandoclevel 
 	fputc('\n', stderr);
 }
 
-static void
-handle_sigpipe(int signum)
-{
-
-	exit((int)rc);
-}
-
 static pid_t
-spawn_pager(void)
+spawn_pager(struct tag_files *tag_files)
 {
 #define MAX_PAGER_ARGS 16
 	char		*argv[MAX_PAGER_ARGS];
 	const char	*pager;
 	char		*cp;
 	size_t		 cmdlen;
-	int		 fildes[2];
 	int		 argc;
 	pid_t		 pager_pid;
 
@@ -991,29 +985,18 @@ spawn_pager(void)
 			break;
 	}
 
-	/* Read all text right away and use the tag file. */
+	/* For more(1) and less(1), use the tag file. */
 
-	for (;;) {
-		if ((cmdlen = strlen(argv[0])) < 4)
-			break;
+	if ((cmdlen = strlen(argv[0])) >= 4) {
 		cp = argv[0] + cmdlen - 4;
-		if (strcmp(cp, "less") && strcmp(cp, "more"))
-			break;
-		if ((cp = tag_init()) == NULL)
-			break;
-		argv[argc++] = mandoc_strdup("+G1G");
-		argv[argc++] = mandoc_strdup("-T");
-		argv[argc++] = cp;
-		break;
+		if (strcmp(cp, "less") == 0 || strcmp(cp, "more") == 0) {
+			argv[argc++] = mandoc_strdup("-T");
+			argv[argc++] = tag_files->tfn;
+		}
 	}
+	argv[argc++] = tag_files->ofn;
 	argv[argc] = NULL;
 
-	if (pipe(fildes) == -1) {
-		fprintf(stderr, "%s: pipe: %s\n",
-		    progname, strerror(errno));
-		return(0);
-	}
-
 	switch (pager_pid = fork()) {
 	case -1:
 		fprintf(stderr, "%s: fork: %s\n",
@@ -1022,29 +1005,17 @@ spawn_pager(void)
 	case 0:
 		break;
 	default:
-		close(fildes[0]);
-		if (dup2(fildes[1], STDOUT_FILENO) == -1) {
-			fprintf(stderr, "%s: dup output: %s\n",
-			    progname, strerror(errno));
-			exit((int)MANDOCLEVEL_SYSERR);
-		}
-		close(fildes[1]);
-		signal(SIGPIPE, handle_sigpipe);
 		return(pager_pid);
 	}
 
 	/* The child process becomes the pager. */
 
-	close(fildes[1]);
-	if (dup2(fildes[0], STDIN_FILENO) == -1) {
-		fprintf(stderr, "%s: dup input: %s\n",
-		    progname, strerror(errno));
+	if (dup2(tag_files->ofd, STDOUT_FILENO) == -1) {
+		fprintf(stderr, "pager: stdout: %s\n", strerror(errno));
 		exit((int)MANDOCLEVEL_SYSERR);
 	}
-	close(fildes[0]);
-
-	/* Hand over to the pager. */
-
+	close(tag_files->ofd);
+	close(tag_files->tfd);
 	execvp(argv[0], argv);
 	fprintf(stderr, "%s: exec %s: %s\n",
 	    progname, argv[0], strerror(errno));
Index: tag.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/tag.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -Ltag.c -Ltag.c -u -p -r1.5 -r1.6
--- tag.c
+++ tag.c
@@ -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 
 	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
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-07-28 18:39 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-28 18:39 mdocml: Remove the hack of scrolling forward and backward with +G1G that schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).