diff options
Diffstat (limited to 'contrib/texinfo/info/man.c')
-rw-r--r-- | contrib/texinfo/info/man.c | 139 |
1 files changed, 114 insertions, 25 deletions
diff --git a/contrib/texinfo/info/man.c b/contrib/texinfo/info/man.c index a6695950b30a..ee68cbb6320f 100644 --- a/contrib/texinfo/info/man.c +++ b/contrib/texinfo/info/man.c @@ -1,7 +1,7 @@ /* man.c: How to read and format man files. - $Id: man.c,v 1.6 1997/07/31 23:49:59 karl Exp $ + $Id: man.c,v 1.13 1999/07/05 20:43:23 karl Exp $ - Copyright (C) 1995, 97 Free Software Foundation, Inc. + Copyright (C) 1995, 97, 98, 99 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,6 +44,14 @@ # endif /* !hpux */ #endif /* FD_SET */ +#if STRIP_DOT_EXE +static char const * const exec_extensions[] = { + ".exe", ".com", ".bat", ".btm", ".sh", ".ksh", ".pl", ".sed", "", NULL +}; +#else +static char const * const exec_extensions[] = { "", NULL }; +#endif + static char *read_from_fd (); static void clean_manpage (); static NODE *manpage_node_of_file_buffer (); @@ -76,6 +84,7 @@ get_manpage_node (file_buffer, pagename) char header[1024]; long oldsize, newsize; int hlen, plen; + char *old_contents = file_buffer->contents; sprintf (header, "\n\n%c\n%s %s, %s %s, %s (dir)\n\n", INFO_COOKIE, @@ -89,13 +98,49 @@ get_manpage_node (file_buffer, pagename) file_buffer->contents = (char *)xrealloc (file_buffer->contents, 1 + newsize); memcpy (file_buffer->contents + oldsize, header, hlen); - oldsize += hlen; - memcpy (file_buffer->contents + oldsize, page, plen); + memcpy (file_buffer->contents + oldsize + hlen, page, plen); file_buffer->contents[newsize] = '\0'; file_buffer->filesize = newsize; file_buffer->finfo.st_size = newsize; build_tags_and_nodes (file_buffer); free (page); + /* We have just relocated file_buffer->contents from under + the feet of info_windows[] array. Therefore, all the + nodes on that list which are showing man pages have their + contents member pointing into the blue. Undo that harm. */ + if (old_contents && oldsize && old_contents != file_buffer->contents) + { + int iw; + INFO_WINDOW *info_win; + char *old_contents_end = old_contents + oldsize; + + for (iw = 0; (info_win = info_windows[iw]); iw++) + { + int in; + + for (in = 0; in < info_win->nodes_index; in++) + { + NODE *node = info_win->nodes[in]; + + /* It really only suffices to see that node->filename + is "*manpages*". But after several hours of + debugging this, would you blame me for being a bit + paranoid? */ + if (node && node->filename && node->contents && + strcmp (node->filename, + MANPAGE_FILE_BUFFER_NAME) == 0 && + node->contents >= old_contents && + node->contents + node->nodelen <= old_contents_end) + { + info_win->nodes[in] = + manpage_node_of_file_buffer (file_buffer, + node->nodename); + free (node->nodename); + free (node); + } + } + } + } } node = manpage_node_of_file_buffer (file_buffer, pagename); @@ -134,6 +179,8 @@ executable_file_in_path (filename, path) while ((temp_dirname = extract_colon_unit (path, &dirname_index))) { char *temp; + char *temp_end; + int i; /* Expand a leading tilde if one is present. */ if (*temp_dirname == '~') @@ -145,22 +192,30 @@ executable_file_in_path (filename, path) temp_dirname = expanded_dirname; } - temp = (char *)xmalloc (30 + strlen (temp_dirname) + strlen (filename)); + temp = (char *)xmalloc (34 + strlen (temp_dirname) + strlen (filename)); strcpy (temp, temp_dirname); - if (temp[(strlen (temp)) - 1] != '/') + if (!IS_SLASH (temp[(strlen (temp)) - 1])) strcat (temp, "/"); strcat (temp, filename); + temp_end = temp + strlen (temp); free (temp_dirname); - statable = (stat (temp, &finfo) == 0); - - /* If we have found a regular executable file, then use it. */ - if ((statable) && (S_ISREG (finfo.st_mode)) && - (access (temp, X_OK) == 0)) - return (temp); - else - free (temp); + /* Look for FILENAME, possibly with any of the extensions + in EXEC_EXTENSIONS[]. */ + for (i = 0; exec_extensions[i]; i++) + { + if (exec_extensions[i][0]) + strcpy (temp_end, exec_extensions[i]); + statable = (stat (temp, &finfo) == 0); + + /* If we have found a regular executable file, then use it. */ + if ((statable) && (S_ISREG (finfo.st_mode)) && + (access (temp, X_OK) == 0)) + return (temp); + } + + free (temp); } return ((char *)NULL); } @@ -210,13 +265,14 @@ get_page_and_section (pagename) } } +#if PIPE_USE_FORK static void reap_children (sig) int sig; { - int status; - wait (&status); + wait (NULL); } +#endif static char * get_manpage_contents (pagename) @@ -225,7 +281,8 @@ get_manpage_contents (pagename) static char *formatter_args[4] = { (char *)NULL }; int pipes[2]; pid_t child; - char *formatted_page = (char *)NULL; + RETSIGTYPE (*sigsave) (); + char *formatted_page = NULL; int arg_index = 1; if (formatter_args[0] == (char *)NULL) @@ -245,12 +302,12 @@ get_manpage_contents (pagename) /* Open a pipe to this program, read the output, and save it away in FORMATTED_PAGE. The reader end of the pipe is pipes[0]; the writer end is pipes[1]. */ +#if PIPE_USE_FORK pipe (pipes); - signal (SIGCHLD, reap_children); + sigsave = signal (SIGCHLD, reap_children); child = fork (); - if (child == -1) return ((char *)NULL); @@ -261,14 +318,14 @@ get_manpage_contents (pagename) close (pipes[1]); formatted_page = read_from_fd (pipes[0]); close (pipes[0]); + signal (SIGCHLD, sigsave); } else - { - /* In the child, close the read end of the pipe, make the write end + { /* In the child, close the read end of the pipe, make the write end of the pipe be stdout, and execute the man page formatter. */ close (pipes[0]); - close (fileno (stderr)); - close (fileno (stdin)); /* Don't print errors. */ + freopen (NULL_DEVICE, "w", stderr); + freopen (NULL_DEVICE, "r", stdin); dup2 (pipes[1], fileno (stdout)); execv (formatter_args[0], formatter_args); @@ -276,8 +333,39 @@ get_manpage_contents (pagename) /* If we get here, we couldn't exec, so close out the pipe and exit. */ close (pipes[1]); - exit (0); + xexit (0); } +#else /* !PIPE_USE_FORK */ + /* Cannot fork/exec, but can popen/pclose. */ + { + FILE *fpipe; + char *cmdline = xmalloc (strlen (formatter_args[0]) + + strlen (manpage_pagename) + + (arg_index > 2 ? strlen (manpage_section) : 0) + + 3); + int save_stderr = dup (fileno (stderr)); + int fd_err = open (NULL_DEVICE, O_WRONLY, 0666); + + if (fd_err > 2) + dup2 (fd_err, fileno (stderr)); /* Don't print errors. */ + sprintf (cmdline, "%s %s %s", formatter_args[0], manpage_pagename, + arg_index > 2 ? manpage_section : ""); + fpipe = popen (cmdline, "r"); + free (cmdline); + if (fd_err > 2) + close (fd_err); + dup2 (save_stderr, fileno (stderr)); + if (fpipe == 0) + return ((char *)NULL); + formatted_page = read_from_fd (fileno (fpipe)); + if (pclose (fpipe) == -1) + { + if (formatted_page) + free (formatted_page); + return ((char *)NULL); + } + } +#endif /* !PIPE_USE_FORK */ /* If we have the page, then clean it up. */ if (formatted_page) @@ -342,10 +430,11 @@ manpage_node_of_file_buffer (file_buffer, pagename) { node = (NODE *)xmalloc (sizeof (NODE)); node->filename = file_buffer->filename; - node->nodename = tag->nodename; + node->nodename = xstrdup (tag->nodename); node->contents = file_buffer->contents + tag->nodestart; node->nodelen = tag->nodelen; node->flags = 0; + node->display_pos = 0; node->parent = (char *)NULL; node->flags = (N_HasTagsTable | N_IsManPage); node->contents += skip_node_separator (node->contents); |