* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
static char sccsid
[] = "@(#)man.c 5.12 (Berkeley) 3/20/86";
* link also to apropos and whatis
* This version uses more for underlining and paging.
#define NROFFCAT "nroff -h -man" /* for nroffing to cat file */
#define NROFF "nroff -man" /* for nroffing to tty */
#define MORE "more -s" /* paging filter */
#define CAT_ "/bin/cat" /* for when output is not a tty */
#define CAT_S "/bin/cat -s" /* for '-' opt (no more) */
#define TROFFCMD "vtroff -man %s"
#define ALLSECT "1nl6823457po" /* order to look through sections */
#define SECT1 "1nlo" /* sections to look at if 1 is specified */
#define SUBSEC1 "cg" /* subsections to try in section 1 */
char *manpath
= "/usr/man";
#define eq(a,b) (strcmp(a,b) == 0)
if ((mp
= getenv("MANPATH")) != NULL
)
if (strcmp(argv
[0], "apropos") == 0) {
runpath(argc
-1, argv
+1, apropos
);
if (strcmp(argv
[0], "whatis") == 0) {
runpath(argc
-1, argv
+1, whatis
);
fprintf(stderr
, "Usage: man [ section ] name ...\n");
while (argc
> 0 && argv
[0][0] == '-') {
case 'P': /* backwards compatibility */
fprintf(stderr
, "%s: missing path\n", *argv
);
if (troffit
== 0 && nomore
== 0 && !isatty(1))
if (eq(argv
[0], "local")) {
} else if (eq(argv
[0], "new")) {
} else if (eq(argv
[0], "old")) {
} else if (eq(argv
[0], "public")) {
} else if (isdigit(argv
[0][0]) &&
(argv
[0][1] == 0 || argv
[0][2] == 0)) {
"But what do you want from section %s?\n",
manual(section
, argv
[0]);
if (ac
> 0 && strcmp(av
[0], "-M") == 0 || strcmp(av
[0], "-P") == 0) {
fprintf(stderr
, "%s: missing path\n", av
[0]);
char work
[100], work2
[100];
char path
[MAXPATHLEN
+1], realname
[MAXPATHLEN
+1];
struct stat stbuf
, stbuf2
;
if (section
== 0) { /* no section or section 1 given */
for (section
= *sp
++; section
; section
= *sp
++) {
if (pathstat(work
, path
, &stbuf
))
if (work
[last
] >= '1' && work
[last
] <= '8') {
case '1': cp
= SUBSEC1
; break;
case '3': cp
= SUBSEC3
; break;
case '4': cp
= SUBSEC4
; break;
case '8': cp
= SUBSEC8
; break;
if (pathstat(work
, path
, &stbuf
)) {
printf("No manual entry for %s.\n", name
);
printf("No entry for %s in section %c%s.\n",
name
, sec
, " of the manual");
} else { /* section given */
if (!pathstat(work
, path
, &stbuf
)) {
if ((section
>= '1' && section
<= '8') && subsec
== 0) {
else if (section
== 'o') { /* XXX */
for (sec
= '0'; sec
<= '8'; sec
++) {
if (pathstat(work
, path
, &stbuf
))
case '1': cp
= SUBSEC1
; break;
case '3': cp
= SUBSEC3
; break;
case '4': cp
= SUBSEC4
; break;
case '8': cp
= SUBSEC8
; break;
if (pathstat(work
, path
, &stbuf
)) {
printf("No entry for %s in section %c", name
, section
);
printf(" of the manual.\n");
sprintf(realname
, "%s/%s", path
, work
);
if ((it
= fopen(realname
, "r")) == NULL
) {
if (fgets(abuf
, BUFSIZ
-1, it
) &&
strncmp(abuf
, ".so ", 4) == 0) {
register char *cp
= abuf
+4;
while (*cp
&& *cp
!= '\n')
while (cp
> abuf
&& *--cp
!= '/')
if (cp
!= abuf
+strlen(dp
)+1) {
for (cp
= abuf
; *cp
== *dp
&& *cp
; cp
++, dp
++)
sprintf(realname
, "%s/%s", path
, work2
);
if (stat(realname
, &stbuf2
) < 0)
sprintf(realname
, "%s/%s", path
, work2
);
if (stat(realname
, &stbuf2
) < 0 || stbuf2
.st_mtime
< stbuf
.st_mtime
) {
printf("Reformatting page. Wait...");
if (signal(SIGINT
, SIG_IGN
) == SIG_DFL
) {
(void) signal(SIGINT
, remove
);
(void) signal(SIGQUIT
, remove
);
(void) signal(SIGTERM
, remove
);
sprintf(cmdbuf
, "%s %s/%s > /tmp/man%d; trap '' 1 15",
NROFFCAT
, path
, work
, mypid
);
printf(" aborted (sorry)\n");
sprintf(cmdbuf
, "/bin/mv -f /tmp/man%d %s/%s 2>/dev/null",
sprintf(work2
, "tmp/man%d", mypid
);
* Use the manpath to look for
* the file name. The result of
* stat is returned in stbuf, the
* successful path in path.
pathstat(name
, path
, stbuf
)
static char *manpaths
[] = {"man", "cat", 0};
static char *nopaths
[] = {"", 0};
if (strncmp(name
, "man", 3) == 0)
for (cp
= manpath
; cp
&& *cp
; cp
= tp
) {
sprintf(path
, "%s%s", *cpp
,
sprintf(path
, "%.*s/%s%s", tp
-cp
, cp
,
*cpp
, name
+strlen(*cpp
));
sprintf(path
, "%s/%s%s", cp
, *cpp
,
if (stat(path
, stbuf
) >= 0) {
if (wp
[0] == 'c' || wp
[0] == 't')
sprintf(cmd
, "%s %s", nomore
? CAT
: MORE
, wp
);
sprintf(cmd
, nomore
? "%s %s" : "%s %s|%s", NROFF
, wp
, MORE
);
sprintf(cmdbuf
, TROFFCMD
, wp
);
sprintf(name
, "/tmp/man%d", mypid
);
register unsigned int i
= 0;
char buf
[BUFSIZ
], file
[MAXPATHLEN
+1];
fprintf(stderr
, "apropos what?\n");
gotit
= calloc(1, blklen(argv
));
for (cp
= manpath
; cp
; cp
= tp
) {
sprintf(file
, "%.*s/%s", tp
-cp
, cp
, WHATIS
);
sprintf(file
, "%s/%s", cp
, WHATIS
);
if (freopen(file
, "r", stdin
) == NULL
)
while (fgets(buf
, sizeof buf
, stdin
) != NULL
)
for (vp
= argv
; *vp
; vp
++)
for (vp
= argv
; *vp
; vp
++)
if (gotit
[vp
- argv
] == 0)
printf("%s: nothing appropriate\n", *vp
);
while (*cp
&& *dp
&& lmatch(*cp
, *dp
))
if (!isalpha(c
) || !isalpha(d
))
register char *gotit
, **vp
;
char buf
[BUFSIZ
], file
[MAXPATHLEN
+1], *cp
, *tp
;
fprintf(stderr
, "whatis what?\n");
for (vp
= argv
; *vp
; vp
++)
gotit
= calloc(1, blklen(argv
));
for (cp
= manpath
; cp
; cp
= tp
) {
sprintf(file
, "%.*s/%s", tp
-cp
, cp
, WHATIS
);
sprintf(file
, "%s/%s", cp
, WHATIS
);
if (freopen(file
, "r", stdin
) == NULL
)
while (fgets(buf
, sizeof buf
, stdin
) != NULL
)
for (vp
= argv
; *vp
; vp
++)
for (vp
= argv
; *vp
; vp
++)
if (gotit
[vp
- argv
] == 0)
printf("%s: not found\n", *vp
);
while (*bp
&& *cp
&& lmatch(*bp
, *cp
))
if (*cp
== 0 && (*bp
== '(' || *bp
== ',' || *bp
== '\t' || *bp
== ' '))
while (isalpha(*bp
) || isdigit(*bp
))
if (cp
+ 3 <= dp
&& dp
[-2] == '.' &&
any(dp
[-1], "cosa12345678npP"))
if (cp
+ 4 <= dp
&& dp
[-3] == '.' &&
any(dp
[-2], "13") && isalpha(dp
[-1]))