bin/120730: [patch] man(1): support for running on local files, also for bzip2(1) compressed manpages

Ighighi ighighi at gmail.com
Sat Feb 16 11:50:02 UTC 2008


>Number:         120730
>Category:       bin
>Synopsis:       [patch] man(1): support for running on local files, also for bzip2(1) compressed manpages
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sat Feb 16 11:50:01 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Ighighi
>Release:        6.3-STABLE
>Organization:
>Environment:
FreeBSD orion.nebula.mil 6.3-STABLE FreeBSD 6.3-STABLE #0: Fri Feb 15 12:35:41 VET 2008     root at orion:/usr/obj/usr/src/sys/CUSTOM  i386

>Description:
This is a merge from 2 previous PR's:

http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/116702
http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/103007

I combined them both so to have an unique diff in case one of them is merged,
to keep the same line numbers.  Also, they're now easier to implement since
FreeBSD 6.2 / 7 because BSD gunzip(1) supports bzip2(1) archives as well.

About running man(1) on local files: it has long been in the TODO file and
I think it's a feature that comes in handy to both developers and users alike
when creating and browsing manpages...  The semantics are simple: if the
argument contains a directory separator ('/'), then open that file and forget
about $MANPATH. To open a manpage in the current directory, all the user has
to do is use "./".  If this patch is eventually merged, I could add the 
relevant notes to man(1) myself.

This patch to man(1) adds support support for bzip2-compressed manpages.
Useful in multi-boot/custom environments, letting you read those Linux
manpages compressed with bzip2.
>How-To-Repeat:

>Fix:


Patch attached with submission follows:

--- src/gnu/usr.bin/man/lib/util.c.orig	1999-05-13 11:59:27.000000000 -0400
+++ src/gnu/usr.bin/man/lib/util.c	2008-02-14 05:58:49.944858771 -0430
@@ -120,6 +120,24 @@ is_directory (path)
 }
 
 /*
+ * Is path a regular file?
+ */
+int
+is_file (path)
+     char *path;
+{
+  struct stat sb;
+  register int status;
+
+  status = stat (path, &sb);
+
+  if (status != 0)
+    return -1;
+
+  return ((sb.st_mode & S_IFREG) == S_IFREG);
+}
+
+/*
  * Attempt a system () call.  Return 1 for success and 0 for failure
  * (handy for counting successes :-).
  */
--- src/gnu/usr.bin/man/man/man.c.orig	2007-09-27 23:53:06.000000000 -0400
+++ src/gnu/usr.bin/man/man/man.c	2008-02-14 05:59:18.027587722 -0430
@@ -29,6 +29,7 @@ static const char rcsid[] =
 #ifdef __FreeBSD__
 #include <locale.h>
 #include <langinfo.h>
+#include <libgen.h>
 #endif
 #include <stdio.h>
 #include <string.h>
@@ -69,6 +70,7 @@ extern char *sprintf ();
 extern char **glob_filename ();
 extern int is_newer ();
 extern int is_directory ();
+extern int is_file ();
 extern int do_system_command ();
 
 char *prognam;
@@ -85,6 +87,7 @@ static int apropos;
 static int whatis;
 static int findall;
 static int print_where;
+static char *ultimate_source ();
 
 #ifdef __FreeBSD__
 static char *locale, *locale_opts, *locale_nroff, *locale_codeset;
@@ -201,10 +204,17 @@ main (argc, argv)
       }
       else
 	{
-	  status = man (nextarg);
+	  if (strchr(nextarg, '/') != NULL && is_file(nextarg) == 1) {
+	    char *dir = dirname(nextarg);
+	    char *srcfile = ultimate_source(nextarg, dir);
+	    format_and_display(dirname(srcfile), srcfile, NULL);
+	  }
+	  else {
+	    status = man (nextarg);
 
-	  if (status == 0)
-	    gripe_not_found (nextarg, longsec);
+	    if (status == 0)
+	      gripe_not_found (nextarg, longsec);
+	  }
 	}
     }
   return (status==0);         /* status==1 --> exit(0),
@@ -807,7 +817,7 @@ get_expander (file)
     return YCAT;
 #endif	/* YCAT */
 #ifdef ZCAT
-  if (*end == 'Z' || !strcmp(end, "gz"))
+  if (*end == 'Z' || !strcmp(end, "gz") || !strcmp(end, "bz2"))
     return ZCAT;
 #endif	/* ZCAT */
   return NULL;
@@ -1391,14 +1401,21 @@ format_and_display (path, man_file, cat_
   if (access (man_file, R_OK) != 0)
     return 0;
 
-  if (troff)
+  if (troff || cat_file == NULL)
     {
       roff_command = make_roff_command (man_file);
       if (roff_command == NULL)
 	return 0;
-      else
+      else if (cat_file != NULL)
 	snprintf (command, sizeof(command), "(cd %s ; %s)", path, roff_command);
-
+      else
+	{
+	   if (strchr(man_file, '/') != NULL)
+    	     snprintf (command, sizeof(command), "%s | %s", roff_command, pager);
+	   else
+    	     snprintf (command, sizeof(command), "(cd %s ; %s | %s)", path,
+		      roff_command, pager);
+	}
       found = do_system_command (command);
     }
   else
--- src/gnu/usr.bin/man/TODO.orig	1993-07-07 19:06:59.000000000 -0400
+++ src/gnu/usr.bin/man/TODO	2008-02-14 05:58:49.950858975 -0430
@@ -105,8 +105,6 @@ XX  I've been using your man(1) package 
     file names used by Motif.  Maybe there's a better way to handle
     this?
 
-15. Add ability to run man on a local file
-
 16. Handle per-tree tmac macros
     
 XX  Allow user-definable section search order via -S or $MANSECT.


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list