This commit was manufactured by cvs2svn to create tag 'v1_0'.

This commit is contained in:
cvs2git 1996-01-28 00:52:49 +00:00
commit 4ecc6ce806
56 changed files with 1020 additions and 9357 deletions

View File

@ -1,209 +1,14 @@
--------------------------------------------
Name: manpack
Version: 3.0
Author: Devin Reade <gdr@myrias.com>
Name: makewhatis
Version: 1.0
Author: Devin Reade <glyn@cs.ualberta.ca>
Computer: Apple IIgs
Requires: GNO v2.x
Requires: Gno v2.x
--------------------------------------------
===========
Description:
===========
Description: Generates the whatis database for apropos(1) and whatis(1)
See the man page for a detailed description.
Various programs for working with manual pages. This archive includes:
apropos v3.0 locate commands by keyword
catman v1.0 format cat pages from man pages
makewhatis v1.2 create the whatis database
man v3.0 display reference manual pages
whatis v3.0 locate commands by name
============
Installation:
============
Type at the command line `dmake install`. You may wish to first
verify the destination directories in "Makefile.mk". By default
these are:
BINDIR = /usr/bin (apropos, catman, man, and whatis)
SBINDIR = /usr/sbin (makewhatis)
MANDIR = /usr/man (all manual pages)
Ensure that all older versions of these programs are deleted.
They may or may not be in the above directories.
==========
Legalities:
==========
These utilities are copyright 1995 by Devin Reade <gdr@myrias.com>.
They are provided as freeware, and may be distributed by Internet
archive sites, online services such as GEnie, or BBSes provided that
the archive remains intact. Permission is granted for distribution
with GNO/ME and Orca provided credit for this work is given along
with any other attributions.
Inclusion of these utilities in collections on disk, CD-ROM, or
other portable media is permitted provided that only a nominal
fee (not much more than the media cost) is charged. Contact the
author regarding other commercial distributions.
Updates to these utilities may be distributed provided that the source
and this README file are included. Please follow the coding style
already in use and document your changes in this file.
=======
CHANGES:
=======
apropos, whatis
v3.0 (24 Jul 95)
Complete rewrite from scratch by Devin Reade.
This version makes use of MANPATH in the same way
as man(1) v3.0. Similarily, it will also search
the 17/syscmnd Orca database.
In the previous version, the behavior of apropos was
identical to that of whatis. This version has been
fixed so that whatis is case sensitive and searches
only the manual page names. The apropos search is
case insensitive and searches the entire database
entry.
v2.1 (1 Jul 92 ?)
This version is by Mike Horwath and shipped with GNO v1.1.
Although no version flags or resource forks where provided
with this release, this release is designated as v2.1
because it shipped with man(1) v2.1.
catman
v1.0 (24 Jul 95)
Initial release. Written from scratch by Devin Reade.
makewhatis
v1.2 (24 Jul 95)
Fixed bug where pages in "manl" ending in ".l" (that's
"ell" in both cases) would be ignored.
Added recognition of files compressed with gzip.
File compression suffixes are now case sensitive.
If none of MANPATH, USRMAN, or MANDIR are defined,
"/usr/man" will now be used.
Fixed a bug where the word SYNOPSIS appearing in the
description would mangle the database entry.
Added a verbose-level-three flag (-v3), which is basically
the old -v2 flag. The new -v2 is somewhat less verbose
than it was.
v1.1 (29 May 94)
Makewhatis will now ignore any man page starting with
".so", in order to eliminate multiple files. The resultant
blank lines in the whatis database have therefore been
eliminated.
Changed -v flag to {-v1|-v2} for differing stages of verbosity.
Only error output will be logged with the -l flag.
Manual page was updated, to include a correction to the -o
flag usage and the modification to the -v flag. Descriptions
of bugs unlikely to be fixed were added. Date and version
were changed.
Fixed bug where input buffer wasn't properly terminated, and
added checks for buffer overflows.
Makewhatis will now display all commands about which the
manual page is written. For example, if foo.1 described
both foo(1) and bar(1), and bar.1 was an .so (or .l) link
to foo.1, then the database entry will have changed from
foo (1) - extract and add thingys
foo, bar (1) - extract and add thingys
Makewhatis used to pick up the first NAME string in the file
as a reference point. Now, any NAME is ignored in any line
starting with .\" or .TH
Filename chapter numbers will now be correctly extracted
regardless of the existence of .Z, .z, .F, or .f suffixes,
or of the existence of '.' within the base file name.
Makewhatis is now linked with Soenke's gnulib for the
getopt() function, rather than using the libc version.
Stack usage was reduced to 1k. Be aware, though, that a
fair amount of global storage is used, including three 1k
buffers.
v1.0 (15 May 94)
Initial release. Written from scratch by Devin Reade.
man
v3.0 (24 Jul 95)
Complete rewrite from scratch by Devin Reade.
The -k, -t, -, -f, -M, and -T flags were added.
Man now supports the MANPATH environment variable which
can be a list of paths delimited by either colons or
spaces.
Added sections 3f, l, n, o, and p to searched subdirectories.
Added gzip(1) to compress(1) and freeze(1) as allowable
source compressors.
Fixed bug with the .so source command; .so references
should now (properly) appear as ".so man<section>/<filename>"
instead of using the full pathname.
Updates to apropos v3.0 apply to man when invoked with
the -k flag.
Preprocessing by eqn(1), refer(1), tbl(1), and vgrind(1)
is not yet supported.
v2.1 (1 Jul 92 ?)
Recognised environment variable USRMAN as well as MANDIR.
This version was also by Mike Horwath.
v2.0 (Date Unknown)
This version is by Mike Horwath and shipped with GNO v1.1.
It made use of the environment variable MANDIR which had
to be a single directory.
=====
TO DO:
=====
Makewhatis is not very well integrated with the rest of the package;
there is still duplication of definitions and functions in some files.
Man, catman, and makewhatis need to support preformatting for eqn(1),
vgrind(1), et al.
Makewhatis' "verbose" output could be cleaner.
Performance analysis has not been done. No doubt some things could
improve, including some string matching in util.c
If the stock getenv(3) function is used (as is done here), then the
return value should be duplicated (via strdup) rather than just used.
If the getenv function from the lenviron library is used, this is not
a concern.
Perhaps an "X" version should be done for the Second Sight card. This
will have to wait a while.
Copy makewhatis to /usr/sbin and makewhatis.1 to $(USRMAN)/man1.
Alternately, you can type "dmake install" from this directory.

View File

@ -1 +0,0 @@
.so man1/whatis.1

View File

@ -1,110 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "apropos___";
#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <libc.h>
#include "util.h"
#include "man.h"
extern int optind;
extern char *optarg;
static char *versionstr = "3.0";
static char *nothing = "nothing appropriate";
extern void begin_stack_check(void);
extern int end_stack_check(void);
int main (int argc, char **argv) {
char *path;
int i, matches1, matches2, matches3;
short V_flag, M_flag, m_flag, n_flag, err_flag;
/* make sure Gno is running */
if (needsgno()==0) {
fprintf(stderr,"Requires Gno/ME\n");
return 1;
}
#ifdef STACK_CHECK
begin_stack_check();
#endif
/* initialization */
V_flag = M_flag = m_flag = n_flag = err_flag = 0;
matches1 = matches2 = matches3 = 0;
/* parse command line and check usage */
while((i = getopt(argc,argv,"M:m:nV")) != EOF) {
switch(i) {
case 'M':
if (m_flag) err_flag++;
M_flag++;
path = optarg;
break;
case 'm':
if (M_flag) err_flag++;
m_flag++;
path = optarg;
break;
case 'n':
n_flag++;
break;
case 'V':
V_flag++;
break;
default:
err_flag++;
}
}
if (argc-optind < 1) err_flag++;
if (err_flag || V_flag) {
fprintf(stderr,"%s version %s by Devin Reade\n",
basename(argv[0]),versionstr);
}
if (err_flag) {
fprintf(stderr,
"Usage: %s [[-M path] | [-m path]] [-nV] keyword [keyword ...]\n",
basename(argv[0]));
return 1;
}
/* do the search */
if (M_flag) {
manpath = path;
} else {
manpath = getManpath();
}
matches1 = apropos(argc-optind, &argv[optind], MAN_K_MODE);
if (!M_flag) free(manpath);
if (m_flag) {
manpath = path;
matches2 = apropos(argc-optind, &argv[optind], MAN_K_MODE);
}
if (!n_flag) {
matches3 = apropos(argc-optind, &argv[optind], ORCA_K_MODE);
}
i = 0;
if (matches1>0) i+= matches1;
if ( m_flag && matches2>0) i+=matches2;
if (!n_flag && matches3>0) i+=matches3;
if (i==0) {
fprintf(stderr,"%s: %s\n",basename(argv[0]),nothing);
}
#ifdef STACK_CHECK
fprintf(stderr,"stack usage: %d bytes\n",end_stack_check());
#endif
if ((matches1>=0) && (matches2>=0) && (matches3>=0) && i>0) return 0;
return 1;
}

View File

@ -1,284 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "apropos2__";
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include "util.h"
#include "man.h"
/*
* orcapadding -- return a suitable number of padding tabs based on the
* length of the command
*/
static char *orcapadding (char *command) {
int i;
static char *two ="\t\t";
static char *one ="\t";
static char *zero =" ";
i = strlen(command);
if (i<8) return two;
if (i<16) return one;
return zero;
}
/*
* orcacomment -- return the start of the comment field in a line of
* the Orca SYSCMND file. This _must_ be called before
* orcacommand() is called on the same buffer, because
* orcacommand() modifies the buffer.
*/
static char *orcacomment (char *buffer) {
char *p;
static char *bad_line="malformed SYSCMND line\n";
p = buffer;
/* get past the command name */
while ((*p != ' ') && (*p != '\t') && *p) p++;
if (!*p) return bad_line;
/* get past space */
while ((*p == ' ') || (*p == '\t') && *p) p++;
if (!*p) return bad_line;
if (*p == '*') p++;
switch (*p) {
case 'U': /*FALLTHROUGH*/
case 'u':
p++;
break;
case 'C': /*FALLTHROUGH*/
case 'L': /*FALLTHROUGH*/
case 'c': /*FALLTHROUGH*/
case 'l':
p++;
/* get past space */
while ((*p == ' ') || (*p == '\t') && *p) p++;
if (!*p) return bad_line;
/* get past command or language number */
while (isdigit(*p)) p++;
break;
default:
return bad_line;
break;
}
/* get past any remaining space */
while ((*p == ' ') || (*p == '\t')) p++;
if (!*p) return bad_line;
return p;
}
/*
* orcacommand -- returns the command name that starts the buffer.
* This _must_ be called after orcacomment because it
* modifies the buffer.
*/
static char *orcacommand(char *buffer) {
char *p;
p = buffer;
while (*p && !isspace(*p)) p++;
*p = '\0';
return buffer;
}
/*
* apropos -- print matching lines from WHATIS database. Returns the
* number of matching lines, or -1 on error.
*
* Argv is an array of argc strings, each of which is a keyword.
* Apropos will print out any line that matches any of the
* keywords in argv. The match algorithm depends on the value
* of apropos_mode, which may be one of the following. For the
* first three modes, global variable <manpath> must be set.
*
* MAN_K_MODE -- this is the one used by apropos(1). A
* match is considered to be made if the keyword
* appears anywhere in the WHATIS database line.
* The match is case insensitive.
*
* MAN_F_MODE -- Any leading path component is stripped from
* the keywords, and then a match is attempted
* for any part of the WHATIS database line. The
* match is case insensitive.
*
* WHATIS_MODE -- The WHATIS database line is parsed up to the
* first occurance of a '(' character. If any
* of the keywords are found, then the line is
* printed. The search is case sensitive.
*
* ORCA_K_MODE -- Like MAN_K_MODE but instead of checking
* the various WHATIS databases, it checks
* 15/syscmnd.
*
* ORCA_W_MODE -- Like WHATIS_MODE but instead of checking
* the various WHATIS databases, it checks
* 15/syscmnd.
*
* WARNING: Use of the MAN_F_MODE may alter the contents of argv[].
*/
int apropos(int argc, char **argv, int apropos_mode) {
char **manpath_array;
char *current_path, *p, *q, *r, *keyword;
FILE *fp;
char dirbrk;
int i, j, matches;
#ifdef DEBUG
assert ((apropos_mode == WHATIS_MODE) ||
(apropos_mode == MAN_K_MODE) ||
(apropos_mode == MAN_F_MODE) ||
(apropos_mode == ORCA_K_MODE) ||
(apropos_mode == ORCA_F_MODE) ||
(apropos_mode == ORCA_W_MODE));
#endif
matches = 0;
/*
* if we're doing 'man -f', get the basename for all keywords
*/
if ((apropos_mode == MAN_F_MODE) || (apropos_mode == ORCA_F_MODE)) {
for (i=0; i<argc; i++) {
dirbrk = (strchr(argv[i],':')!=NULL) ? ':' : '/';
if ((q = strrchr(argv[i],dirbrk)) != NULL) {
q++;
p = argv[i];
do {
*p = *q;
p++; q++;
} while (*q);
*p = '\0';
}
}
}
if ((apropos_mode == ORCA_K_MODE) ||
(apropos_mode == ORCA_W_MODE) ||
(apropos_mode == ORCA_F_MODE)) {
/*
* searching the Orca 15/syscmnd file
*/
if ((fp = fopen(SYSCMND,"r")) == NULL) {
fprintf(stderr,"couldn't open %s\n",SYSCMND);
return -1;
}
/* loop over lines in file */
while ((q = fgets(linebuf,BUFFERSIZE,fp)) != NULL) {
if (*linebuf == ';') continue;
/* loop over keywords */
for(i=0; i<argc; i++) {
keyword = argv[i];
if ((apropos_mode == ORCA_K_MODE && ncstrstr(linebuf,keyword)) ||
(apropos_mode == ORCA_F_MODE && strstr(linebuf,keyword)) ||
(apropos_mode == ORCA_W_MODE &&
!strncmp(linebuf,keyword,strlen(keyword)))) {
r = orcacomment(linebuf);
p = orcacommand(linebuf);
q = orcapadding(p);
printf("%s (Orca) %s- %s",p,q,r);
matches++;
}
}
}
fclose(fp);
return matches;
}
if ((manpath_array = makePathArray(manpath)) == NULL) return -1;
/*
* loop over all the paths in MANPATH
*/
i=0;
current_path = manpath_array[i];
while (current_path) {
dirbrk = (strchr(current_path,':')!=NULL) ? ':' : '/';
if (chdir(current_path) == -1) {
fprintf(stderr,"%s: %s\n",current_path,strerror(errno));
} else if ((fp=fopen(WHATIS,"r"))==NULL) {
if (access(WHATIS,F_OK) == -1) {
fprintf(stderr,"%s%c%s: %s\n",current_path,dirbrk,WHATIS,
strerror(ENOENT));
} else {
fprintf(stderr,"error opening %s%c%s\n",current_path,dirbrk,
WHATIS);
}
} else {
/* read each line, looking for a match */
for (;;) {
q = fgets(linebuf,BUFFERSIZE,fp);
if (q != NULL) {
/* search for a match to any keyword */
for (j=0; j<argc; j++) {
keyword = argv[j];
switch (apropos_mode) {
case MAN_F_MODE:
if (strstr(linebuf,keyword)) {
printf("%s",linebuf);
matches++;
}
break;
case MAN_K_MODE:
if (ncstrstr(linebuf,keyword)) {
printf("%s",linebuf);
matches++;
}
break;
case WHATIS_MODE:
/* avoid unnecessary strcpy's */
if (strstr(linebuf,keyword)==NULL) break;
strcpy(linebuf2,linebuf);
if ((p = strchr(linebuf2,'(')) != NULL) *p = '\0';
if (strstr(linebuf2,keyword)) {
printf("%s",linebuf);
matches++;
}
break;
default:
fprintf(stderr,"internal error line %d of %s\n",
__LINE__,__FILE__);
exit(1);
}
}
} else if (ferror(fp)) {
fprintf(stderr,"error reading %s database: %s\n",WHATIS,
strerror(errno));
break;
} else break;
}
fclose(fp);
}
i++;
current_path = manpath_array[i];
} /* endwhile loop over directories */
return matches;
}

View File

@ -1,95 +0,0 @@
.\" Copyright (c) 1995 Devin Reade <gdr@myrias.com>. All rights reserved.
.\"
.TH CATMAN 8 "System Administration" "24 July 95" "Version 1.0"
.SH NAME
catman \- format cat pages from man pages
.SH SYNOPSIS
.BR catman
[
.B -pvV
] [[
.BI -M path
] | [
.BI -m path
]] [
.IR section " ..."
]
.SH DESCRIPTION
.BR catman
creates formatted versions of the on-line manual pages from their
.BR nroff (1)
or
.BR aroff (1)
source.
Manual pages whose formatted versions are missing or out of date are
regenerated.
.LP
If
.IR section
is specified, then
.BR catman
will only created formatted manual pages for the specified
.IR section (s).
.LP
Manual pages that are
.BR nroff (1)
source and are compressed with either
.BR compress (1),
.BR freeze (1),
or
.BR gzip (1)
are recognised provided that they have the suffixes
.BR ".Z" ,
.BR ".F" ,
and
.BR ".gz" ,
respectively. Manual page names, including suffixes, are case sensitive.
.LP
Preformatted manual pages will be created in
.BI cat ?
only if that subdirectory exists.
.SH OPTIONS
.IP \fB-p\fP
Display the commands that would have been executed, but do not actually
execute them.
.IP "\fB-M\fR \fIpath\fR"
Set
.I path
to be the list of paths for which manual pages will be updated.
If not set, the value of
.BR MANPATH ,
.BR USRMAN ,
or
.BR MANDIR
will be used instead. Multiple directories may be specified by
separating them either by colons or by spaces. In the latter case,
be sure to quote
.I path
from the shell.
.IP "\fB-m\fR \fIpath\fR"
Append
.I path
on to the list of paths for which manual pages will be updated.
.IP \fB-V\fR
Display version information and exit.
.IP \fB-v\fR
Verbose. Show processing information.
.SH BUGS
Please report any bugs to Devin Reade, <gdr@myrias.ab.ca>.
.SH SEE ALSO
.BR apropos (1),
.BR man (1),
.BR whatis (1),
.BR gzip (1),
.BR compress (1),
.BR freeze (1),
.BR makewhatis (8).
.SH WARNING
.BR catman
will unlink any out-of-date files in the
.BI cat ?
subdirectories. The files that would be unlinked are listed when
.BR catman
is invoked with the
.BR -p
option.

View File

@ -1,356 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "catman____";
#include <sys/types.h>
#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
#include <libc.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/stat.h>
#include <errno.h>
#include "util.h"
#include "man.h"
#define OVERFLOW_ABORT(line,file) { \
fprintf(stderr,overflowMsg,line,file); \
exit(1); \
}
short v_flag, V_flag, M_flag, m_flag, p_flag, err_flag;
extern int optind;
extern char *optarg;
static char *versionstr = "1.0";
/* This is of the form "man<section>" */
char mandir[FILENAME_MAX];
/*
* These are of the form
* "(man|cat)<section>/<name>.<section>[.<compression_suffix>]"
*/
char manfile[FILENAME_MAX];
char catfile[FILENAME_MAX];
char catfile2[FILENAME_MAX];
char base[FILENAME_MAX];
static char *overflowMsg = "internal buffer overflow at line %d of %s\n";
extern void begin_stack_check(void);
extern int end_stack_check(void);
/*
* catman
*
* Pre: argv is an array of section numbers (character strings), possibly
* empty.
* argc is the number of entries in argv.
* global variable <manpath> is a space- or colon-delimited list
* of pathnames.
*
* Post: for each pathname in <manpath>, catman will preformat the manpages
* within the man* subdirectories and place the result in the
* corresponding cat* subdirectory. If section numbers are specified,
* only those sections will be done.
*
* Returns 0 on success, 1 on failure.
*/
int catman(int argc, char **argv) {
char **manpath_array; /* MANPATH components in array form */
char *current_path; /* the current MANPATH component */
int i; /* an index */
int pathIndex; /* offset into manpath_array[] */
int sectionIndex; /* offset into sections[] */
DIR *manp, *catp; /* directory pointers */
struct dirent *entp; /* current file entry in manp */
char *sec; /* the current section "number" */
int catfile_found; /* have we found a preformatted version */
/* that's newer than the unformatted version? */
fileType *ftype; /* the file type of the man page */
struct stat statbuf1, statbuf2;
char dirbrk;
/* create array of paths to search */
if ((manpath_array = makePathArray(manpath)) == NULL) return 1;
/* loop over paths in MANPATH */
pathIndex=0;
current_path = manpath_array[pathIndex];
while(current_path) {
dirbrk = (strchr(current_path,':')==NULL) ? '/' : ':';
/* go to the current path in MANPATH */
if (v_flag) printf("cd %s\n",current_path);
if (chdir(current_path) == -1) {
pathIndex++;
current_path = manpath_array[pathIndex];
continue;
}
/* loop over sections */
for (sectionIndex=0; sections[sectionIndex].name!=NULL; sectionIndex++){
/*
* if section number was specified and this isn't it, do
* the next loop
*/
if (argc > 0) {
sec = NULL;
for (i=0; i<argc; i++) {
if (!strcmp(argv[i],sections[sectionIndex].name)) {
sec = argv[i];
break;
}
}
if (sec == NULL) continue;
} else sec = sections[sectionIndex].name;
#ifdef DEBUG
assert(sec);
#endif
/*
* we're going to update this section. Open the man? subdir
*/
if (strlen(sec) + 3 >= FILENAME_MAX) {
OVERFLOW_ABORT(__LINE__,__FILE__);
}
sprintf(mandir,"man%s",sec);
if ((manp = opendir(mandir)) == NULL) continue;
/* make sure the cat? directory exists, but leave it closed */
sprintf(catfile,"cat%s",sec);
if ((catp = opendir(catfile)) == NULL) {
closedir(manp);
continue;
} else {
closedir(catp);
}
/* loop over files in this section */
while ((entp = readdir(manp)) != NULL) {
/* skip standard file entries */
if (!strcmp(entp->d_name,".") || !strcmp(entp->d_name,"..")) {
continue;
}
/*
* make the base the name of the man? entry excluding
* any compression suffix
*/
strcpy(base,entp->d_name);
for (i=0; compressArray[i].suffix != NULL; i++) {
size_t len1, len2;
len1 = strlen(compressArray[i].suffix);
len2 = strlen(base);
if (!strcmp(compressArray[i].suffix,
(char *)(base + len2 - len1))) {
*(base + len2 - len1) = '\0';
break;
}
}
/*
* set manfile and catfile properly
*/
sprintf(manfile,"man%s%c%s",sec,dirbrk,entp->d_name);
sprintf(catfile,"cat%s%c%s",sec,dirbrk,base);
if (stat(manfile,&statbuf1) != 0) {
fprintf(stderr,"stat on %s failed: %s: file skipped\n",
manfile, strerror(errno));
continue;
}
/*
* search for an uncompressed file in the cat? directory,
* unlinking any older files.
*/
catfile_found=0;
if (stat(catfile,&statbuf2) == 0) {
if (statbuf1.st_mtime <= statbuf2.st_mtime) {
catfile_found++;
} else {
if (v_flag) printf("rm %s%c%s\n",current_path,dirbrk,catfile);
if (!p_flag) unlink(catfile);
}
}
/*
* search for any compressed files in the cat? directory,
* unlinking any older files.
*/
for(i=0;compressArray[i].suffix != NULL; i++) {
sprintf(catfile2,"cat%s%c%s%s",sec,dirbrk,base,
compressArray[i].suffix);
if (stat(catfile2,&statbuf2) == 0) {
if ((!catfile_found) &&
(statbuf1.st_mtime <= statbuf2.st_mtime)) {
strcpy(catfile,catfile2);
catfile_found++;
} else {
if (v_flag)
printf("rm %s%c%s\n",current_path,dirbrk,catfile2);
if (!p_flag) unlink(catfile2);
}
}
}
if (catfile_found) continue;
/*
* If we got to this point, then we will be preformatting
* the manual page. There is also no version of the man
* page left in cat?.
*/
sprintf(catfile,"cat%s%c%s",sec,dirbrk,base);
i = getSuffixIndex(manfile);
if (i >= 0) {
if (strlen(compressArray[i].extractor) + strlen(manfile) +
strlen(NROFF) + strlen(catfile) + 14 >= BUFFERSIZE) {
OVERFLOW_ABORT(__LINE__,__FILE__);
}
sprintf(linebuf,"%s %s | %s -man - > %s",
compressArray[i].extractor,manfile,NROFF,catfile);
} else {
/* determine which roffer to use based on the file type */
if ((ftype = getFileType(manfile)) == NULL) {
fprintf(stderr,"getFileType failed for %s: %s\n",
manfile,strerror(errno));
continue;
}
if ((ftype->type == 0x50) && (ftype->auxtype == 0x8010)) {
if (strlen(AROFF) + strlen(manfile) + strlen(catfile)
>= BUFFERSIZE) {
OVERFLOW_ABORT(__LINE__,__FILE__);
}
sprintf(linebuf,"%s %s > %s",AROFF,manfile,catfile);
} else if ((ftype->type == TXT) || (ftype->type == BIN) ||
(ftype->type == SRC) || (ftype->type == NON)) {
if (strlen(NROFF) + strlen(manfile) + strlen(catfile)
>= BUFFERSIZE) {
OVERFLOW_ABORT(__LINE__,__FILE__);
}
sprintf(linebuf,"%s -man %s > %s",NROFF,manfile,catfile);
} else {
fprintf(stderr,"illegal file type for %s: file skipped\n",
manfile);
continue;
}
}
if (v_flag) printf("%s\n",linebuf);
if (!p_flag) system(linebuf);
} /* done looping over files */
closedir(manp);
} /* done looping over sections */
/* set up for the next component of MANPATH */
pathIndex++;
current_path = manpath_array[pathIndex];
}
}
int main (int argc, char **argv) {
char *path;
int i, result1, result2;
/* make sure Gno is running */
if (needsgno()==0) {
fprintf(stderr,"Requires Gno/ME\n");
return 1;
}
#ifdef STACK_CHECK
begin_stack_check();
#endif
/* initialization */
v_flag = V_flag = M_flag = m_flag = p_flag = err_flag = 0;
result1 = result2 = 0;
/* parse command line and check usage */
while((i = getopt(argc,argv,"M:m:pVv")) != EOF) {
switch(i) {
case 'M':
if (m_flag) err_flag++;
M_flag++;
path = optarg;
break;
case 'm':
if (M_flag) err_flag++;
m_flag++;
path = optarg;
break;
case 'p':
p_flag++;
v_flag++;
break;
case 'V':
V_flag++;
break;
case 'v':
v_flag++;
break;
default:
err_flag++;
}
}
if (err_flag || V_flag) {
fprintf(stderr,"%s version %s by Devin Reade\n",
basename(argv[0]),versionstr);
}
if (err_flag) {
fprintf(stderr,"Usage: %s [-pVv] [-M path] [-m path] [section ...]\n",
basename(argv[0]));
}
if (err_flag || V_flag) return 1;
/* translate selected "sections" into something more understandable */
for (i=optind; i<argc; i++) {
if (!strcmp(argv[i],"local")) argv[i] = "l";
if (!strcmp(argv[i],"new")) argv[i] = "n";
if (!strcmp(argv[i],"old")) argv[i] = "o";
if (!strcmp(argv[i],"public")) argv[i] = "p";
}
/* do the search */
if (M_flag) {
manpath = path;
} else {
manpath = getManpath();
}
result1 = catman(argc-optind, &argv[optind]);
if (!M_flag) free(manpath);
if (m_flag) {
manpath = path;
result2 = catman(argc-optind, &argv[optind]);
}
#ifdef STACK_CHECK
fprintf(stderr,"stack usage: %d bytes\n",end_stack_check());
#endif
return (result1 || result2);
}

View File

@ -1,29 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "common____";
#include <types.h>
#include <string.h>
#include "man.h"
/*
* getSuffixIndex
*
* return the index into compressArray of the appropriate
* suffix/decompresser. If there is no match, return -1.
*/
int getSuffixIndex(char *name) {
char *p;
int i;
for (i=0; compressArray[i].suffix != NULL; i++) {
p = strstr(name,compressArray[i].suffix);
if (p && !*(p + strlen(compressArray[i].suffix))) return i;
}
return -1;
}

View File

@ -1,50 +0,0 @@
Name: apropos
Version: 3.0 (24 Jul 95)
Author: Devin Reade.
Contact: gdr@myrias.com
Where: /usr/bin
FTP: ftp.cco.caltech.edu, grind.isca.uiowa.edu
Locate commands by keyword. Bundled with catman, makewhatis,
man, and whatis in the manpack30.shk archive.
Name: catman
Version: 1.0 (24 Jul 95)
Author: Devin Reade.
Contact: gdr@myrias.com
Where: /usr/sbin
FTP: ftp.cco.caltech.edu, grind.isca.uiowa.edu
Preformat manual reference pages. Bundled with apropos, makewhatis,
man, and whatis in the manpack30.shk archive.
Name: makewhatis
Version: 1.2 (24 Jul 95)
Author: Devin Reade.
Contact: gdr@myrias.com
Where: /usr/sbin
FTP: ftp.cco.caltech.edu, grind.isca.uiowa.edu
Create the whatis database used by man(1), apropos(1), and whatis(1).
Bundled with apropos, catman, man, and whatis in the manpack30.shk archive.
Name: man
Version: 3.0 (24 Jul 95)
Author: Devin Reade.
Contact: gdr@myrias.com
Where: /usr/bin
FTP: ftp.cco.caltech.edu, grind.isca.uiowa.edu
Display manual reference pages. Bundled with apropos, catman,
makewhatis, and whatis in the manpack30.shk archive.
Name: whatis
Version: 3.0 (24 Jul 95)
Author: Devin Reade.
Contact: gdr@myrias.com
Where: /usr/bin
FTP: ftp.cco.caltech.edu, grind.isca.uiowa.edu
Locate commands by name. Bundled with apropos, catman,
makewhatis, and man in the manpack30.shk archive.

View File

@ -1,38 +1,14 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "makewhatis";
#ifdef __CCFRONT__
#include <14:pragma.h>
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "makewhatis.h"
#define NAME1 "NAME"
#define NAME2 "N\bNA\bAM\bME\bE"
#define NAME3 "N\bN\bN\bNA\bA\bA\bAM\bM\bM\bME\bE\bE\bE"
#define SYNOPSIS1 "SYNOPSIS"
#define SYNOPSIS2 "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS"
#define SYNOPSIS3 "S\bS\bS\bSY\bY\bY\bYN\bN\bN\bNO\bO\bO\bOP\bP\bP\bPS\bS\bS\bSI\bI\bI\bIS\bS\bS\bS"
#define DESCRIPTION1 "DESCRIPTION"
#define DESCRIPTION2 "D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN"
#define DESCRIPTION3 "D\bD\bD\bDE\bE\bE\bES\bS\bS\bSC\bC\bC\bCR\bR\bR\bRI\bI\bI\bIP\bP\bP\bPT\bT\bT\bTI\bI\bI\bIO\bO\bO\bON\bN\bN\bN"
char buffer[BUFFERSIZE]; /* contains the command description */
char titlebuf[BUFFERSIZE]; /* contains the command name */
static char buffer2[BUFFERSIZE]; /* used for chars read from man page */
#ifdef TEST_FILLBUFFER
short v_flag=2;
# define output_fp stdout
# define error_fp stderr
#else
extern FILE *output_fp; /* output file descriptor -- may be stdout */
extern FILE *error_fp; /* error file descriptor -- may be stderr */
#endif
char buffer[BUFFERSIZE];
static char buffer2[BUFFERSIZE];
/* void fillbuffer (char *filename);
*
@ -43,312 +19,101 @@ static char buffer2[BUFFERSIZE]; /* used for chars read from man page */
*
* Post: <buffer> will contain all the text, minus formatting and control
* code, starting from the word "NAME" and ending with either ".SH".
* "SYNOPSIS", or "DESCRIPTION", whichever comes first. <titlebuf>
* will contain all printable text starting with the first printable
* non-whitespace character following "NAME" and ending with the
* last printable character before the first '-' following "NAME".
* "SYNOPSIS", or "DESCRIPTION", whichever comes first.
*
* If an error occurs, <buffer> will be an empty string (ie:
* buffer[0] == '\0')
*
* Warning: This routine was written to be fast at the expense of code
* size. It also has a lot of "special case"ing since it could
* be fed nroff source, aroff'd output, or text files that may
* include formatting control codes. If you're looking for some
* nice neat code, you're not going to find it here.
*/
void fillbuffer (char *filename) {
FILE *fp; /* FILE pointer for filename */
int count; /* how many chars were read into buffer2 */
char *p1; /* points to current char in buffer2 */
FILE *fp; /* FILE pointer for filename */
int count; /* how many chars were read into buffer2 */
char *p1; /* points to current char in buffer2 */
char *p2; /* points to last char (of interest) in buffer2 */
char *p3; /* points to current char in buffer */
char *p6; /* scratch */
short found; /* some flags */
short in_comment;
char *p3; /* points to current char in buffer */
short found; /* some flags */
short in_comment;
short in_format_BR;
short in_format_f;
short foo;
/*
* Set p4 and p5 to the ends of buffer and titlebuf, respectively.
* These are used for error checking, so that we don't overflow the
* buffers. Using pointers will speed things up a bit at the cost
* of four bytes of local storage. They are not global for the sake
* of speed.
*/
char *p4 = buffer + BUFFERSIZE;
char *p5 = titlebuf + BUFFERSIZE;
/*
/*
* open the file
*/
if ((fp = fopen(filename,"rb")) == NULL) {
buffer[0] = '\0';
if (v_flag) fprintf (error_fp,"Open failed for file \"%s\"\n",filename);
buffer[0] = '\0';
return;
}
/*
* see if it includes another man page
*/
if ((fgets(buffer2,4,fp) == NULL) || (strncmp(buffer2,".so",3)==0)) {
buffer[0] = '\0';
titlebuf[0] = '\0';
fclose(fp);
return;
}
fseek(fp,0L,SEEK_SET);
/*
* Make fp point to the first newline following NAME so that the
* next block read will pick it up as the first character. This is
* needed for the next section of code following this one.
* Make p1 point to spot in buffer2 where the first "NAME" occurs.
* Note that if "NAME" is within a comment line (nroff source), it
* will still be picked up.
*/
for(;;) {
/*
* read in buffer2 in a line-oriented fashion at first so that we
* can more easily ignore .\" and .TH lines
*/
if (fgets(buffer2,BUFFERSIZE,fp)==NULL) {
count = fread(buffer2,sizeof(char),BUFFERSIZE-1,fp);
if (count == 0) {
/*
* eof or error, and we haven't found "NAME" yet ... return
* an empty string
*/
buffer[0] = '\0';
titlebuf[0] = '\0';
fclose(fp);
if (v_flag) fprintf (error_fp,
"EOF or error on %s, NAME not found.\n",filename);
return;
}
/* ignore comment lines and any .TH line(s) */
if ((strncmp(buffer2,".\\\"",3)==0) || (strncmp(buffer2,".TH",3)==0))
continue;
/* check the various versions of "NAME" */
if (strstr(buffer2,NAME1) != NULL) break;
if (strstr(buffer2,NAME2) != NULL) break;
if (strstr(buffer2,NAME3) != NULL) break;
}
/* we need the previous newline for the next algorithm to work */
fseek(fp,-1L,SEEK_CUR);
buffer2[count] = '\0';
p1 = strstr(buffer2,"NAME");
if (p1 != NULL) break;
}
/*
* Make p1 point to spot in buffer2 where there occurs the first
* character following '-' which in turn follows "NAME".
* Note that if "NAME" or '-' are within a comment line
* (nroff source), it will still be picked up.
*
* Also copy selected chars to titlebuf until the first '-' is found.
*/
p3 = titlebuf;
found = 0; /* set this when we find '-' */
in_format_BR = 0; /* in the middle of a .BR format */
in_format_f = 0; /* in the middle of a \fI format */
in_comment = 0; /* in the middle of a .\" comment */
foo = 0; /* haven't found the printable character after NAME */
for(;;) {
/* read another block into buffer2. */
count = fread(buffer2,sizeof(char),BUFFERSIZE-1,fp);
for(;;) {
p2 = strchr(p1,'-');
if (p2 != NULL) {
p2++;
break;
}
count = fread(buffer2,sizeof(char),BUFFERSIZE-1,fp);
if (count == 0) {
/* eof or error; empty buffer and titlebuf then return */
buffer[0] = '\0';
titlebuf[0] = '\0';
fclose(fp);
if (v_flag) fprintf (error_fp,
"EOF or error on %s, command name not found.\n",filename);
return;
/*
* eof or error, and we haven't found '-' yet ... return
* an empty string
*/
buffer[0] = '\0';
fclose(fp);
return;
}
buffer2[count] = '\0';
buffer2[count] = '\0';
p1 = buffer2;
/* mark the "end" of buffer2 with p2 */
if ((p2 = strchr(p1,'-')) != NULL) {
found = 1;
} else {
p2 = buffer + count;
}
/*
* If this is not our first iteration, dump any formatting information
* or comments left over from the last interation.
*/
if (in_comment) {
while((p1<p2) && (*p1 != '\r')) p1++;
in_comment = 0;
}
if (in_format_BR) {
while ((p1<p2) && !isspace(*p1)) p1++;
in_format_BR = 0;
}
if (in_format_f) {
p1 = p1 + 3 - in_format_f;
in_format_f = 0;
}
/*
* At this time, p1 points to the start of the key words, p2
* to either the end of the key words or the end of buffer2,
* and p3 into the spot in titlebuf where the next character should
* be put.
*
* Copy *p1 to *p3 while p1<p2 (not at end of titlebuf or key words),
* skipping comments, formatting info, and control chars
*/
for (; p1<p2; p1++) {
/* skip .\" comments */
if (strncmp(p1,"\r.\\\"",4) == 0) {
while ((p1<p2) && (*p1!='\r')) p1++;
if (p1==p2) in_comment = 1;
continue;
}
/* skip .BR-type formatting */
if ((p1<p2) && (*p1=='\r') && (*(p1+1)=='.')) {
p1++;
while ((p1<p2) && !isspace(*p1)) p1++;
if (p1==p2) in_format_BR = 1;
else --p1;
continue;
}
/* skip \fI-type formatting */
if ((p1<p2) && (*p1=='\\') && (*(p1+1)=='f')) {
if ((p1 + 3) < p2) {
p1 += 3;
} else {
in_format_f = p2 - p1;
p1 = p2;
}
continue;
}
/*
* skip whitespace if we haven't got the beginning of the
* description yet.
*/
#ifdef ISGRAPH_FIX
if (isgraph(*p1) && (*p1!=' ')) foo=1;
if (!foo) {
while ((p1<p2) && !(isgraph(*p1) && (*p1!=' '))) p1++;
if ((*p1=='.') && (*(p1-1)=='\r')) p1 -=2;
else --p1;
continue;
}
#else
if (isgraph(*p1)) foo=1;
if (!foo) {
while ((p1<p2) && !isgraph(*p1)) p1++;
if ((*p1=='.') && (*(p1-1)=='\r')) p1 -=2;
else --p1;
continue;
}
#endif
/*
* at this point, *p1 is either a control char or something that
* we want in titlebuf, assuming that p1<p2.
*/
if ((p1<p2) && !iscntrl(*p1)) {
/*
* The conditional below means:
* Copy it so that: 1. There is only one space between words; and
* 2. The buffer doesn't begin with a space.
*/
if ( !((p3>titlebuf) && (*p1 == ' ') && (*(p3-1) == ' ')) &&
!((p3==titlebuf) && (*p3 == ' '))
) {
/* don't let a space precede a comma */
if ((*p1==',') && (*(p3-1)==' ')) {
*(p3-1) = ',';
continue;
} else *p3++ = *p1;
if (p3>=p5) { /* titlebuf overflow? */
if (v_flag)
fprintf(error_fp,"command name buffer overflow on %s\n",
filename);
buffer[0] = '\0';
titlebuf[0] = '\0';
fclose(fp);
return;
}
}
}
}
if (found) { /* we've got all of the key words */
p3--; /* p3 now points to last char, not terminator */
if (*p3=='\\') p3--;
while(isspace(*p3)) p3--;
*(p3+1) = '\0';
break;
}
}
p1 = p2 + 1;
#ifdef ISGRAPH_FIX
while ( (p1 < buffer2 + BUFFERSIZE) &&!(isgraph(*p1) && (*p1 != ' '))) p1++;
#else
while ((p1 < buffer2 + BUFFERSIZE) && !isgraph(*p1)) p1++;
#endif
p1 = p2;
/*
* now copy selected chars to buffer until the next subheading is found
*/
p3 = buffer;
found = 0; /* set this when we find one of the above strings */
in_format_BR = 0; /* in the middle of a .BR format */
in_format_f = 0; /* in the middle of a \fI format */
in_comment = 0; /* in the middle of a .\" comment */
found = 0; /* set this when we find one of the above strings */
in_format_BR = 0; /* in the middle of a .BR format */
in_format_f = 0; /* in the middle of a \fI format */
in_comment = 0; /* in the middle of a .\" comment */
for(;;) {
/* mark the "end" of buffer2 with p2 */
if ( ((p2 = strstr(p1,".SH")) != NULL) ||
((p2 = strstr(p1,SYNOPSIS1)) != NULL) ||
((p2 = strstr(p1,SYNOPSIS2)) != NULL) ||
((p2 = strstr(p1,SYNOPSIS3)) != NULL) ||
((p2 = strstr(p1,DESCRIPTION1)) != NULL) ||
((p2 = strstr(p1,DESCRIPTION2)) != NULL) ||
((p2 = strstr(p1,DESCRIPTION3)) != NULL)
((p2 = strstr(p1,"SYNOPSIS")) != NULL) ||
((p2 = strstr(p1,"DESCRIPTION")) != NULL)
) {
*p2 = '\0';
/*
* this conditional is to cover the wierd case of having the word
* "SYNOPSIS" appearing in the description (or elsewhere), as
* it does for the GNO Intro(1) man page. Blech. Only in
* aroff source or a preformatted page would this matter.
*/
if (((p6 = strstr(p1,SYNOPSIS1)) != NULL) ||
((p6 = strstr(p1,DESCRIPTION1)) != NULL)) {
p2 = p6;
}
found = 1;
found = 1;
} else {
p2 = buffer + count;
p2 = buffer + count;
}
/*
@ -357,17 +122,17 @@ void fillbuffer (char *filename) {
*/
if (in_comment) {
while((p1<p2) && (*p1 != '\r')) p1++;
while((p1<p2) && (*p1 != '\r')) p1++;
in_comment = 0;
}
if (in_format_BR) {
while ((p1<p2) && !isspace(*p1)) p1++;
while ((p1<p2) && !isspace(*p1)) p1++;
in_format_BR = 0;
}
if (in_format_f) {
p1 = p1 + 3 - in_format_f;
p1 = p1 + 3 - in_format_f;
in_format_f = 0;
}
@ -383,26 +148,25 @@ void fillbuffer (char *filename) {
for (; p1<p2; p1++) {
/* skip .\" comments */
/* skip .\" comments */
if (strncmp(p1,"\r.\\\"",4) == 0) {
while ((p1<p2) && (*p1!='\r')) p1++;
while ((p1<p2) && (*p1!='\r')) p1++;
if (p1==p2) in_comment = 1;
}
/* skip .BR-type formatting */
if ((p1<p2) && (*p1=='\r') && (*(p1+1)=='.')) {
p1++;
while ((p1<p2) && !isspace(*p1)) p1++;
if ((p1<p2) && (*p1=='\r') && (*(p1+1)=='.')) {
while ((p1<p2) && !isspace(*p1)) p1++;
if (p1==p2) in_format_BR = 1;
}
/* skip \fI-type formatting */
if ((p1<p2) && (*p1=='\\') && (*(p1+1)=='f')) {
if ((p1 + 3) < p2) {
p1 += 3;
if ((p1<p2) && (*p1=='\\') && (*(p1+1)=='f')) {
if ((p1 + 3) < p2) {
p1 += 3;
} else {
in_format_f = p2 - p1;
p1 = p2;
in_format_f = p2 - p1;
p1 = p2;
}
}
@ -411,55 +175,30 @@ void fillbuffer (char *filename) {
* we want in buffer, assuming that p1<p2.
*/
if ((p1<p2) && !iscntrl(*p1)) {
/*
* The conditional below means:
* Copy it so that: 1. There is only one space between words; and
* 2. The buffer doesn't begin with a space.
*/
if ( !((p3>buffer) && (*p1 == ' ') && (*(p3-1) == ' ')) &&
!((p3==buffer) && (*p3 == ' '))
) {
*p3++ = *p1;
if (p3>=p4) { /* buffer overflow? */
if (v_flag)
fprintf(error_fp,"command description buffer overflow on %s\n",
filename);
buffer[0] = '\0';
titlebuf[0] = '\0';
fclose(fp);
return;
}
}
}
if ((p1<p2) && !iscntrl(*p1)) *p3++ = *p1;
}
if (found) { /* we've got the entire description */
*p3 = '\0';
break;
if (found) { /* we've got the entire description */
*p3 = '\0';
break;
}
/*
* We're part way through the description; read another block
* into buffer2.
*/
*/
count = fread(buffer2,sizeof(char),BUFFERSIZE-1,fp);
count = fread(buffer2,sizeof(char),BUFFERSIZE-1,fp);
if (count == 0) {
/* eof or error; terminate buffer and return */
*p3 = '\0';
fclose(fp);
if (v_flag) fprintf (error_fp,
"EOF or error on %s, description not found.\n",filename);
return;
*p3 = '\0';
fclose(fp);
return;
}
buffer2[count] = '\0';
p1 = buffer2;
}
p1 = buffer2;
}
/*
* close the file
*/
@ -468,3 +207,26 @@ void fillbuffer (char *filename) {
return;
}
#ifdef TEST_FILLBUFFER
int main(int argc, char **argv) {
if (argc != 2) {
printf("Usage: %s <man_page_file_name>\n\n",argv[0]);
return -1;
}
fillbuffer(argv[1]);
if (strlen(buffer) == 0) {
printf("buffer empty\n");
} else {
printf("main: buffer is %u chars long\n%s\n",strlen(buffer),buffer);
}
return 0;
}
#endif

View File

@ -1,42 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
#include <types.h>
#include "man.h"
/*
* The compression suffixes and how to uncompress the files.
* If you use ".l" (that's "ell") as a suffix, you will break the
* algorithm for dereferencing aroff "links".
*/
compressionType compressArray[] = {
{ ".Z", "compress -cd" },
{ ".F", "freeze -cd" },
{ ".gz", "gzip -cd" },
{ NULL, NULL }
};
char linebuf[BUFFERSIZE];
char linebuf2[BUFFERSIZE];
char *manpath;
Section sections[] = {
{ "1", "1" },
{ "2", "2" },
{ "3", "3" },
{ "3f", "3f" },
{ "4", "4" },
{ "5", "5" },
{ "6", "6" },
{ "7", "7" },
{ "8", "8" },
{ "new", "n" }, /* the words "new", "local", "public", */
{ "local", "l" }, /* and "old" can be abbreviated on the */
{ "public", "p" }, /* command line with "n", "l", "p", and */
{ "old", "o" }, /* "o", respectively */
{ NULL, NULL } /* MUST be NULL-terminated! */
};

View File

@ -1,70 +1,47 @@
#
# Makefile for the man package, for use with dmake(1).
# Makefile for dmake(1)
#
# Location for executables. They should normally be /usr/sbin and /usr/bin.
# Location for executable. It should be /usr/sbin
SBINDIR = /usr/sbin
BINDIR = /usr/bin
BINDIR = /usr/sbin
# Location for man pages. Usually /usr/man.
# Location for man pages.
MANDIR = /usr/man
MANDIR = /usr/man
#
# You should not have to change anything below this line
#
# Define: -DDEBUG to produce more debugging info and checks
#
# -DSTACK_CHECK to show stack usage. If you use this
# one, ensure you add -l/usr/lib/stack to your LDLIBS.
# Nothing past this point should have to be changed
#
STACK = -s1270
DEFINES =
CFLAGS = $(DEFINES) $(STACK) -w -v -O -I/usr/include
LDFLAGS = -v
LDLIBS = -l/usr/lib/gnulib -l/usr/lib/stack
CP = /bin/cp -f
CFLAGS = -w -O -v
OBJS = makewhatis.o fillbuffer.o process.o
makewhatis: $(OBJS)
$(CC) $(OBJS) -o makewhatis
build: apropos catman makewhatis man whatis
makewhatis.o: makewhatis.c makewhatis.h
$(CC) -c $(CFLAGS) makewhatis.c
apropos: apropos.o apropos2.o util.o utilgs.o globals.o
$(CC) $(LDFLAGS) $< $(LDLIBS) -o $@
fillbuffer.o: fillbuffer.c makewhatis.h
$(CC) -c $(CFLAGS) fillbuffer.c
catman: catman.o util.o utilgs.o globals.o common.o
$(CC) $(LDFLAGS) $< $(LDLIBS) -o $@
makewhatis: makewhatis.o fillbuffer.o process.o
$(CC) $(LDFLAGS) $< $(LDLIBS) -o $@
man: man.o man2.o apropos2.o util.o utilgs.o globals.o common.o
$(CC) $(LDFLAGS) $< $(LDLIBS) -o $@
whatis: whatis.o apropos2.o util.o utilgs.o globals.o
$(CC) $(LDFLAGS) $< $(LDLIBS) -o $@
clobber:
$(RM) *.o *.root
process.o: process.c makewhatis.h
$(CC) -c $(CFLAGS) process.c
install:
$(CP) apropos man whatis $(BINDIR)
$(CP) catman makewhatis $(SBINDIR)
$(CP) apropos.1 man.1 whatis.1 $(MANDIR)/man1
$(CP) catman.8 makewhatis.8 $(MANDIR)/man8
/bin/cp makewhatis $(BINDIR)
/bin/cp makewhatis.1 $(MANDIR)/man1
# additional dependancies
clean:
/bin/cp -p rm $(OBJS)
apropos.o:: man.h util.h
apropos2.o:: man.h util.h
catman.o:: man.h util.h
common.o:: man.h util.h
fillbuffer.o:: makewhatis.h
globals.o:: man.h
makewhatis.o:: makewhatis.h
man.o:: man.h util.h
man2.o:: man.h util.h
process.o:: makewhatis.h
util.o:: util.h
utilgs.o:: util.h
whatis.o:: man.h util.h
#
# These are just for debugging purposes
#
fillbuffer: fillbuffer.c makewhatis.h
$(CC) $(CFLAGS) -DTEST_FILLBUFFER -o fillbuffer fillbuffer.c
process: process.o fillbuffer.o
$(CC) $(CFLAGS) process.o fillbuffer.o -o process

View File

@ -1,303 +1,190 @@
.TH MAKEWHATIS 8 "System Administration" "24 July 1995" "Version 1.2"
.TH MAKEWHATIS 1 "Commands and Applications" "15 May 1994" "Version 1.0"
.SH NAME
.B makewhatis
\- generate the whatis database file
.SH SYNOPSIS
.B makewhatis
[
.B -c
.I -c
|
.B -C
.I -C
] [
.BI -f " outfile"
.I -ovV
] [
.BI -l " logfile"
.I "-f outfile"
] [
.BI -o " dbfile"
.I "-l logfile"
] [
.BI -p " path"
] [
.BI -v " n"
] [
.B -V
.I "-p path"
]
.SH DESCRIPTION
.B makewhatis
generates the whatis database for
.BR apropos (1),
.BR man (1),
and
.BR whatis (1).
.BR whatis "(1) and " apropos "(1)."
This database is a text file containing line oriented records. Each record
contains a man page name, the section number, and the brief description.
.LP
.B Makewhatis
makes use of one of the environment variables
.BR MANPATH ,
.BR USRMAN ,
or
.BR MANDIR ,
in the listed order of preference. It will use this
By default,
.B makewhatis
makes use of one of the environment variables \fIMANPATH\fR, \fIUSRMAN\fR,
or \fIMANDIR\fR, in the listed order of preference. It will use this
environment variable to determine for which manual pages the whatis
database should be built. If the environment variable contains more than
one path (delimited by either colons or spaces),
then whatis databases will be generated
in all of the specified paths. This may be overridden by the
.BR -p
flag.
one path (delimited by spaces), then whatis databases will be generated
in all of the specified paths.
.LP
The routines used are compatible with man pages in
.BR nroff ,
.BR aroff ,
.BR compress ", or"
.BR freeze
format, as well as text versions of manual pages in the man/catX hierarchy.
.B Makewhatis
assumes that the suffixes \fI.Z\fR and \fI.F\fR are are appended to the
chapter number on file names when those files are in
.BR compress " or " freeze
format, respectively. (For example, a compressed file would be expected
to have a file name similar to
.I foo.3.Z
or \fIbar.3v.Z\fR.)
Any files using the
.I ".l"
(ell) suffix are ignored. All suffix tests are case insensitive.
.LP
By default,
.BR makewhatis
will generate its database from manual pages existing in the
.IB manpath_component /man X
subdirectories (where
.I X
is the section number)
that are either
.BR aroff
or
.BR nroff
source files.
However, since many GNO programmers are providing only preformatted
text versions of their man pages, using the
.I -c
flag will cause
.B makewhatis
to also use manual pages in the
.IB manpath_component /cat X
subdirectories when building the database.
If there is a corresponding manual page in both the
.BI man X
and
.BI cat X
subdirectory, then only the page in the
.BI man X
subdirectory will be used.
.LP
Manual pages which are
.BR nroff
source files in the
.BI man X
subdirectory, or are preformatted text in the
.BI cat X
subdirectory may be compressed by either
.BR compress (1),
.BR freeze (1),
or
.BR gzip (1),
provided that the suffixes on the compressed file are
.BR ".Z" ,
.BR ".F" ,
and
.BR ".gz" ,
respectively. The case of the suffix is significant.
.BR Aroff
source files
.I "must not"
be compressed by any method.
.LP
All
.BR aroff
link files are ignored. A file is assumed to be an
.BR aroff
link file if it ends in
.B ".l"
(dot lower-case ell) and is not within a
.BR manl
(man-ell) or a
.BR catl
(cat-ell) subdirectory.
will only use files in the man/manX hierarchy in the creation of the
database. However, since many Gno programmers are providing only text
versions of their man pages, invoking
.B makewhatis
with the
.I -c
flag will add descriptions for all files in the man/catX hierarchy that
don't have a counterpart in the man/manX hierarchy. This conditional
eliminates the parsing of files in man/catX generated by
.BR catman (1).
.LP
Note that the lines in the whatis database file are created in the order
that the man pages are found. It is suggested that the database files
be sorted after
that the man pages are found. It is suggested that the database be sorted
after
.B makewhatis
is finished. See
.BR sort (1)
or
.BR msort (1) .
.BR sort (1).
.SH OPTIONS
.IP "\fB\-c\fP"
will check
.BI cat X
subdirectories as well as
.BI man X
subdirectories.
.IP \fB\-C\fP
.I -c
will check man/catX sub-directories as well as man/manX
.LP
.I -C
will check
.I only
.BI cat X
subdirectories,
.I not
.BI man X
subdirectories.
.IP "\fB-f\fR \fIoutfile\fR"
.BR only
man/catX sub-directories, not man/manX sub-directories.
.LP
.I "-f outfile"
causes the
.B makewhatis
status output to be placed in
.IR outfile .
Invoking
.B -f
without
.B -v2
produces no output.
.IP "\fB-l\fR \fIlogfile\fR"
will cause any error messages to be printed to
.IR logfile .
Invoking
.B -l
without either
.B -v1
or
.B -v2
produces no output.
.IP "\fB-o\fR \fIdbfile\fR"
status output to be placed in \fIoutfile\fR.
.LP
.I "-l logfile"
will cause any error messages to be printed to \fIlogfile\fR.
.LP
.I "-o dbfile"
will make
.B makewhatis
use
.I dbfile
as the name for the generated whatis databases. While it is possible to
use a full pathname for
.IR dbfile ,
this will result in that file being overwritten for each colon- or
space-delimited entry in
.BR MANPATH .
.IP "\fB-p\fR \fIpath\fR"
as the name for the generated whatis databases.
.LP
.I "-p path"
overrides the environment variables
.B MANPATH
.I MANPATH
et al for determining for which manual page hierarchies the databases must
be generated.
.IP "\fB-v\fR \fIn\fR"
creates verbose status messages during execution. For
.IR n =1
only major error messages are printed out. For
.IR n =2,
the names of processed files are also printed. For
.IR n =3,
the output becomes very verbose with excessive status information, including
listing any missing subdirectores.
.IP \fB-V\fR
.LP
.I -v
creates verbose status messages during execution.
.LP
.I -V
will show version and usage information, then exit.
.SH ENVIRONMENT
.BR MANPATH
\fIMANPATH\fR, \fIUSRMAN\fR, \fIMANDIR\fR:
.br
.BR USRMAN
.br
.BR MANDIR
.RS
Unless the
.B -p
.I -p
flag is used,
.B makewhatis
will use the first that it finds of these environment variables for
determining where database files should be generated. The search
is done in the order shown. While
determining where database files should be generated. While
.B makewhatis
will correctly handle
.RB ` ~ '
.I ~
and
.RB ` . '
being part of these paths, it will not correctly handle
.RB ` .. '.
.sp 1
Either colons or spaces can be used to delimit the individual paths.
If the value of the selected environment variable contains no spaces
nor
.B /
characters (such as
.BR :usr:local:man ),
it is assumed to be a single path, not a list of paths.
.sp 1
Although
.B makewhatis
allows
.BR USRMAN
and
.BR MANDIR
to be each a colon- or space-separated list of pathnames,
it is recommended that for compatibility with
.BR man
(version 2.1 and earlier) these variables, if used, should be
a single pathname.
.RE
.I .
being part of these paths, it will not correctly handle \fI..\fR.
.SH CAVEATS
.B Makewhatis
assumes that the programs
.BR aroff ,
.BR compress ,
.BR freeze ,
and
.BR gzip
are available to the executing shell via the
.BR system (2)
call.
.BR Nroff
is not used and need not be available.
.LP
Because
.B makewhatis
looks for the string
.B NAME
and one of
.BR .SH ,
.BR SYNOPSIS ,
or
.B DESCRIPTION
.I NAME
and one of \fI.SH\fR, \fISYNOPSIS\fR, or
.I DESCRIPTION
when processing files, it can be confused by missing fields or
some methods of formatting. For example, if in a preformatted manual page
.B NAME
is underlined by repeated backspace-_ sequences, then the generated
description for that particular man page is unpredictable,
though usually blank. When parsing preformatted manual pages,
.B makewhatis
will understand the common double- and quadruple-boldfaced
subheadings, provided
that the backspace character (control-H) is used to achieve this effect.
some methods of formatting. For example, if in a man/catX page
.I NAME
is boldfaced by repeated backspace characters as in \fIN^HNA^HAM^HME^HE\fR,
then the generated description for that particular man page is unpredictable,
though usually blank. For any diehards who like placing such information
in their hand-coded man/catX pages, using a string similar to
.I "NAME^H^H^H^HNAME"
will create a proper description in the database file.
.LP
Similarily,
.B makewhatis
expects the subheading
.B NAME
.I NAME
to be in the format:
.nf
NAME
\fIcommand_name\fR [...] - \fIbrief description\fR
<command> - <brief description>
.fi
If this is not so (ignoring whitespace), then the output is unpredictable.
.LP
Man pages must be CR-delimited (ASCII 015, or control\-M).
.LP
Where unpredictable output has been mentioned above, this means that
the description in the database file will either be blank or random
text from the man page. It
.I "does not"
mean that system integrity or that the remainder of the database file
has been affected.
.LP
Any text appearing after
.B NAME
on the NAME header line will be ignored.
.SH BUGS
.B Makewhatis
reads files in blocks of 1024 characters.
If formatting information is split by the end
of the input buffer, you may see formatting infomation such as
.B .BR
in the output. This was not fixed due to the overhead of having to
check for such a condition.
.LP
Please report any additional bugs to Devin Reade, <gdr@myrias.com>.
If a man page describes multiple items and has a NAME subheading such as
.nf
NAME
item1, item2, item3 - This is the description.
.fi
Then
.B makewhatis
should create a database record that reads:
.nf
item1 (3), item2 (3), item3 (3) - This is the description.
.fi
Instead, if item2.l and item3.l are links to item1.3, the created record reads
.nf
item1 (3) - This is the description.
.fi
.SH FILES
.nf
/usr/[share/]man/whatis -- the whatis database
/usr/sbin/makewhatis -- whatis database generator
man/whatis -- the whatis database
.fi
.SH SEE ALSO
.BR apropos (1),
.BR aroff (1),
.BR catman (1),
.BR compress (1),
.BR freeze (1),
.BR gzip (1),
.BR man (1),
.BR nroff (1),
.BR whatis (1)
.BR whatis (1),
.SH AUTHOR
Written by Devin Reade <glyn@cs.ualberta.ca> for the Apple IIgs and Gno.

View File

@ -1,10 +1,6 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "makewhatis";
#ifdef __CCFRONT__
#include <14:pragma.h>
#endif
#include <sys/types.h>
#include <stdio.h>
@ -13,35 +9,28 @@ segment "makewhatis";
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include "getopt.h"
#include <libc.h>
#include "makewhatis.h"
#ifdef STACK_CHECK
extern void begin_stack_check(void);
extern int end_stack_check(void);
#endif
/*
* Options:
*
* -c check cat* subdirectories as well
* -C check _only_ cat* subdirectories, not man* subdirectories.
* -f outfile force whatis status output to <outfile>
* -l logfile log errors to <logfile>
* -o dbfile force whatis database output to <dbfile>
* -p path use the <path> rather than $MANPATH, $USRMAN, or $MANDIR
* -s sort the whatis database by manual page name
* -v{1|2|3} verbose
* -V show version and usage info and exit
* -c check cat* subdirectories as well
* -C check _only_ cat* subdirectories, not man* subdirectories.
* -f outfile force whatis status output to <outfile>
* -l logfile log errors to <logfile>
* -o dbfile force whatis database output to <dbfile>
* -p path use the <path> rather than $MANPATH, $USRMAN, or $MANDIR
* -s sort the whatis database by manual page name
* -v verbose
* -V show version and usage info and exit
*/
char *man_subdir[] = {
"man1",
"man1",
"man2",
"man3",
"man3f",
"man4",
"man5",
"man6",
@ -49,30 +38,7 @@ char *man_subdir[] = {
"man8",
"mann",
"manl",
"manp",
"mano",
NULL
};
/*
* we include cat* since some Gno utility man pages aren't written in
* either nroff or aroff source ... go figure.
*/
char *cat_subdir[] = {
"cat1",
"cat2",
"cat3f",
"cat4",
"cat5",
"cat6",
"cat7",
"cat8",
"catn",
"catl",
"catp",
"cato",
NULL /* _must_ be NULL terminated! */
NULL
};
/* For the various command line flags */
@ -82,10 +48,29 @@ short C_flag = 0;
short o_flag = 0;
short p_flag = 0;
short v_flag = 0;
short errflag = 0; /* This is set if there is a usage error or -V flag */
short errflag = 0; /* This is set if there is a usage error or -V flag */
static char filebuffer[FILENAME_MAX]; /* used when traversing cat* pages */
static char progdir[FILENAME_MAX]; /* the directory where makewhatis started */
static char filebuffer[FILENAME_MAX]; /* used when traversing cat* pages */
static char progdir[FILENAME_MAX]; /* the directory where makewhatis started */
/*
* we include cat* since some Gno utility man pages aren't written in
* either nroff or aroff source ... go figure.
*/
char *cat_subdir[] = {
"cat1",
"cat2",
"cat3",
"cat4",
"cat5",
"cat6",
"cat7",
"cat8",
"catn",
"catl",
NULL /* _must_ be NULL terminated! */
};
FILE *output_fp;
FILE *error_fp;
@ -93,15 +78,15 @@ FILE *error_fp;
int main (int argc, char **argv) {
char *manpath; /* the location of the man pages */
char *path; /* the current path; taken from manpath */
char *p=NULL; /* a temporary pointer */
struct dirent *file; /* the current file we have open */
char tmp_file[L_tmpnam]; /* a scratch file */
FILE *tmp_fp; /* pointer to tmp_file */
FILE *whatis_fp; /* pointer to the current whatis database */
DIR *subdir; /* the current man subdirectory -- eg: /usr/man/man3 */
char *dbfile; /* non-default name of the whatis database */
char *manpath; /* the location of the man pages */
char *path; /* the current path; taken from manpath */
char *p=NULL; /* a temporary pointer */
struct dirent *file; /* the current file we have open */
char tmp_file[L_tmpnam]; /* a scratch file */
FILE *tmp_fp; /* pointer to tmp_file */
FILE *whatis_fp; /* pointer to the current whatis database */
DIR *subdir; /* the current man subdirectory -- eg: /usr/man/man3 */
char *dbfile; /* non-default name of the whatis database */
char *dirsep; /* the directory separator, either "/" or ":" */
int i;
extern int optind;
@ -109,22 +94,18 @@ int main (int argc, char **argv) {
/* make sure Gno is running */
if (needsgno()==0) {
fprintf(stderr,"Requires Gno/ME\n");
fprintf(stderr,"Requires Gno/ME\n");
return 1;
}
#ifdef STACK_CHECK
begin_stack_check();
#endif
/*
* set the defaults
*/
output_fp = stdout;
error_fp = stderr;
if (getwd(progdir) == NULL) {
perror("getwd() failed");
if (getwd(progdir) == NULL) {
perror("getwd() failed");
exit(1);
}
@ -132,87 +113,86 @@ int main (int argc, char **argv) {
* parse the command line
*/
while((i = getopt(argc,argv,"cCf:l:o:p:v:V")) != EOF)
switch(i) {
while((i = getopt(argc,argv,"cCf:l:o:p:vV")) != EOF)
switch(i) {
case 'c':
if (C_flag) errflag++;
if (C_flag) errflag++;
else c_flag++;
break;
case 'C':
if (c_flag) errflag++;
else C_flag++;
if (c_flag) errflag++;
else C_flag++;
break;
case 'f':
output_fp = fopen (optarg,"w");
output_fp = fopen (optarg,"w");
if (output_fp == NULL) {
fprintf(stderr,"Could not open output file %s; using stdout.\n",
optarg);
fprintf(stderr,"Could not open output file %s; using stdout.\n",
optarg);
output_fp = stdout;
}
break;
break;
case 'l':
error_fp = fopen (optarg,"w");
error_fp = fopen (optarg,"w");
if (error_fp == NULL) {
fprintf(stderr,"Could not open log file %s; using stderr.\n",
optarg);
fprintf(stderr,"Could not open log file %s; using stderr.\n",
optarg);
error_fp = stderr;
}
break;
case 'o':
o_flag++;
o_flag++;
dbfile = optarg;
break;
case 'p':
p_flag++;
p_flag++;
p = optarg;
break;
case 'v':
v_flag = (short) atoi(optarg);
if ((v_flag<1) && (v_flag>3)) errflag++;
v_flag++;
break;
case 'V':
fprintf(stderr,
"%s --\n\tCreate the %s database.\n\tVersion %s by Devin Reade\n\n",
fprintf(stderr,
"%s -- Create the %s database.\n\tVersion %s by Devin Reade\n\n",
argv[0],WHATIS,VERSIONSTRING);
errflag++;
break;
default:
errflag++;
errflag++;
break;
}
if (errflag) {
fprintf(error_fp,
"Usage:\n%s\t[-c|-C] [-f outfile] [-l logfile] [-o dbfile] [-p path]\n\
\t\t[-v 1|2] [-V]\n\n\
if (errflag) {
fprintf(error_fp,
"Usage: %s [-c|-C] [-ovV] [-f outfile] [-l logfile] [-p path]\n\n\
-c\t\tCheck catX subdirectories as well\n\
-C\t\tCheck _only_ catX subdirectories, not manX subdirectories.\n\
-f outfile\tForce whatis output to <outfile>.\n\
-l logfile\tLog errors to <logfile>.\n\
-o dbfile\tforce whatis database output to <dbfile>.\n\
-p path\t\tUse the <path> rather than $MANPATH, $USRMAN, or $MANDIR.\n\
-v n\t\t<n>=1: Slightly verbose, only displaying major errors.\n\
\t\t<n>=2: Verbose, displaying processed file names.\n\
\t\t<n>=3: Very verbose, displaying more processing info.\n\
-V\t\tShow version and usage information, then exit.\n",argv[0]);
return -1;
-v\t\tVerbose.\n\
-V\t\tShow version and usage information, then exit.\n",argv[0],WHATIS);
return -1;
}
/*
* get the location of the man pages; p is already set if -p flag used
*/
if (p == NULL) p = getenv("MANPATH");
if (p == NULL) p = getenv("USRMAN");
if (p == NULL) p = getenv("MANDIR");
if (p == NULL) p = DEFAULT_MANPATH;
if (p == NULL) p = getenv("MANPATH");
if (p == NULL) p = getenv("USRMAN");
if (p == NULL) p = getenv("MANDIR");
if (p == NULL) {
fprintf(error_fp,"Location of man pages unknown. You must either define \
environment variables\n$MANPATH, $USRMAN, or $MANDIR, or use the -p flag.\n\n");
return -1;
}
/* define the directory separator */
dirsep = (strchr(p,':')==NULL) ? "/" : ":";
/* make a copy of the location */
if ((manpath = malloc (strlen(p) + 1)) == NULL) {
if (v_flag) fprintf(error_fp,
"malloc failed while making copy of \"%s\"\nAborted.\n",p);
if (v_flag) fprintf(error_fp,"couldn't make copy of \"%s\"",p);
return -1;
}
strcpy(manpath,p);
@ -228,107 +208,100 @@ int main (int argc, char **argv) {
path = strtok (manpath," ");
while (path != NULL) {
if (access(path,F_OK)==0) {
if (access(path,F_OK)==0) {
if (strcmp(path,".") == 0) {
chdir(progdir);
if (strcmp(path,".") == 0) {
chdir(progdir);
} else {
chdir(path);
chdir(path);
}
/* open the whatis database file */
if (!o_flag) dbfile = WHATIS;
whatis_fp = fopen(dbfile,"w");
/* open the whatis database file */
if (!o_flag) dbfile = WHATIS;
whatis_fp = fopen(dbfile,"w");
if (whatis_fp == NULL) {
fprintf (error_fp,
"Could not create whatis database file %s in directory %s.\n\
Aborted.\n",
dbfile,path);
exit(-1);
}
fprintf (error_fp,
"Could not create whatis database file %s in directory %s.\n",
dbfile,path);
exit(-1);
}
/*
/*
* loop over the expected man* subdirectories within path
*/
if (!C_flag) for (i=0; man_subdir[i] != NULL; i++) {
subdir = opendir(man_subdir[i]);
if (subdir != NULL) {
if (!C_flag) for (i=0; man_subdir[i] != NULL; i++) {
subdir = opendir(man_subdir[i]);
if (subdir != NULL) {
/* print status */
if (v_flag>=3) fprintf(output_fp,
"Now working on directory %s\t%s ...\n",path,man_subdir[i]);
/* print status */
if (v_flag) fprintf(output_fp,
"Now working on directory %s\t%s ...\n",path,man_subdir[i]);
/* no need to error check because of opendir() */
chdir(man_subdir[i]);
chdir(man_subdir[i]);
/* loop over files within subdirectory */
while ((file = readdir(subdir)) != NULL) {
process (file->d_name,tmp_file,whatis_fp,&man_subdir[i][3]);
}
closedir(subdir);
} else {
if (v_flag>=3) fprintf(output_fp,
"Could not access files in %s\t%s ...\n",path,man_subdir[i]);
}
chdir(path);
}
/* loop over files within subdirectory */
while ((file = readdir(subdir)) != NULL) {
process (file->d_name,tmp_file,whatis_fp);
}
closedir(subdir);
} else {
if (v_flag) fprintf(output_fp,
"Could not access files in %s\t%s ...\n",path,man_subdir[i]);
}
chdir(path);
}
/*
/*
* loop over the expected cat* subdirectories within path,
* adding only those files without man* versions.
*/
if (c_flag||C_flag) for (i=0; cat_subdir[i] != NULL; i++) {
subdir = opendir(cat_subdir[i]);
if (subdir != NULL) {
if (c_flag||C_flag) for (i=0; cat_subdir[i] != NULL; i++) {
subdir = opendir(cat_subdir[i]);
if (subdir != NULL) {
/* print status */
if (v_flag>=3) fprintf(output_fp,
"Now working on directory %s\t%s ...\n",path,cat_subdir[i]);
/* print status */
if (v_flag) fprintf(output_fp,
"Now working on directory %s\t%s ...\n",path,cat_subdir[i]);
/* no need to error check because of opendir() */
chdir(cat_subdir[i]);
chdir(cat_subdir[i]);
/* make filebuffer contain path to matching man* subdirectory */
/* make filebuffer contain path to matching man* subdirectory */
strcpy(filebuffer,path);
strcat(filebuffer,dirsep);
strcat(filebuffer,man_subdir[i]);
strcat(filebuffer,dirsep);
p = filebuffer + strlen(filebuffer); /* p points to '\0' */
/* loop over files that don't have a man* counterpart */
while ((file = readdir(subdir)) != NULL) {
strcpy(p,file->d_name);
/* loop over files that don't have a man* counterpart */
while ((file = readdir(subdir)) != NULL) {
strcpy(p,file->d_name);
if (access(filebuffer,F_OK)!=0)
process (file->d_name,tmp_file,whatis_fp,
&man_subdir[i][3]);
}
closedir(subdir);
} else {
if (v_flag>=3) fprintf(output_fp,
"Could not access files in %s\t%s ...\n",path,cat_subdir[i]);
}
chdir(path);
}
process (file->d_name,tmp_file,whatis_fp);
}
closedir(subdir);
} else {
if (v_flag) fprintf(output_fp,
"Could not access files in %s\t%s ...\n",path,cat_subdir[i]);
}
chdir(path);
}
/* close the database */
fclose(whatis_fp);
/* close the database */
fclose(whatis_fp);
}
/* get the next path in manpath */
path = strtok (NULL," ");
/* get the next path in manpath */
path = strtok (NULL," ");
}
/* clean up and exit */
unlink(tmp_file);
unlink(tmp_file);
if (output_fp != stdout) fclose(output_fp);
if (error_fp != stderr) fclose(error_fp);
#ifdef STACK_CHECK
fprintf(stderr,"Makewhatis stack usage: %d bytes\n",end_stack_check());
#endif
return 0;
}

View File

@ -1,27 +1,25 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
#define VERSIONSTRING "1.2"
#define ISGRAPH_FIX 1
#define VERSIONSTRING "1.0"
/* The size of the IO buffers */
#define BUFFERSIZE 1024
#define BUFFERSIZE 1024
/* The default name for the whatis database */
#define WHATIS "whatis"
#define WHATIS "whatis"
/* The number of characters per tab in the whatis database */
#define TABLENGTH 8
#define TABLENGTH 8
#define DEFAULT_MANPATH "/usr/man"
extern int chdir (const char *);
extern int system (const char *);
extern int chdir (const char *);
extern int system (const char *);
void fillbuffer (char *filename);
void process (char *filename, char *tmp_file, FILE *whatis_fp, char *sec);
void fillbuffer (char *filename);
void process (char *filename, char *tmp_file, FILE *whatis_fp);
extern short c_flag;
extern short C_flag;
extern short f_flag;
extern short l_flag;
extern short O_flag;
extern short p_flag;
extern short v_flag;
extern short errflag;

View File

@ -1,519 +0,0 @@
.\" This man page copyright (c) 1980 Regents of the University of California.
.\" All rights reserved. The Berkeley software License Agreement
.\" specifies the terms and conditions for redistribution.
.\"
.\" While this manual page is based on one from UCB, the included
.\" C source, makefile, and executables are copyright (c) 1995
.\" by Devin Reade <gdr@myrias.com>. All rights reserved.
.\"
.TH MAN 1 "Commands and Applications" "24 July 95" "Version 3.0"
.SH NAME
man \- display reference manual pages; find reference pages by keyword
.SH SYNOPSIS
.B man
.RB "[\|" \- "\|]"
.RB "[\|" \-t "\|]"
.RB "[\|" \-M
.IR path "\|]"
.RB "[\|" \-T
.IR macro-package "\|]"
.RI "[\|" section "\|] " title "
.br
.B man
.RB "[\|" \-M
.IR path "\|]"
.B \-k
.I keyword
\&.\|.\|.
.br
.B man
.RB "[\|" \-M
.IR path "\|]"
.B \-f
.I filename
\&.\|.\|.
.SH DESCRIPTION
.B man
displays information from the reference manuals.
It can display complete manual pages that you select by
.IR title ,
or one-line summaries selected either by
.I keyword
.RB ( \-k ),
or by the name of an associated file
.RB ( \-f ).
.LP
A
.IR section ,
when given, applies to the
.I title
that follows it on the command line.
.B man
looks in the indicated section of the manual for that
.IR title .
.I section
is either a digit (perhaps followed by a single letter indicating
the type of manual page), or one of the words
.BR new ,
.BR local ,
.BR old ,
or
.BR public .
The
abbreviations
.BR n ,
.BR l ,
.B o
and
.B p
are also allowed.
If
.I section
is omitted,
.B man
searches all reference sections
(giving preference to commands over functions).
If more than one manual page exists for the specified
.IR title ,
each page is displayed in the order in which it is found. The
user is given the option of exiting after each page is displayed.
If no manual page is located,
.B man
prints an error message.
.LP
The reference page sources are typically located in the
.BR /usr/man/man?
directories.
If there are preformatted, up-to-date versions in
corresponding
.B cat?
or
.B fmt?
directories,
.B man
simply displays or prints those versions.
If the preformatted
version of interest is out of date or missing,
.B man
reformats it prior to display.
If directories for the
preformatted versions are not provided,
.B man
reformats a page whenever it is requested.
.LP
If the standard output is not a terminal, or if the
.RB ` \- '
flag is given,
.B man
pipes its output through
.BR cat (1V).
Otherwise,
.B man
pipes its output through
.BR more (1)
to handle paging and underlining on the screen.
.SH OPTIONS
.IP \fB\-t\fP
.B man
arranges for the specified manual pages to be
.BR troff ed
to a suitable raster output device (see
.BR troff (1)
or
.BR vtroff (1)).
If both the
.B \-
and
.B \-t
flags are given,
.B man
updates the
.BR troff ed
versions of each named
.I title
(if necessary), but does not display them.
.IP "\fB\-M\fP \fIpath\fP"
Change the search path for manual pages.
.I path
is a colon- or space-separated list of directories that contain manual page
directory subtrees.
For example,
.B /usr/man/u_man:/usr/man/a_man
makes
.B man
search in the standard System V locations.
The space delimiter is provided for compatibility with GS/OS's
use of the colon as a pathname component delimiter. If the search
path contains no spaces nor
.B /
characters (such as
.BR :usr:local:man ),
it is assumed to be a single path, not a list of paths.
If spaces are used as delimiters, remember to quote
.I path
from the shell.
Each directory in the
.I path
is assumed to contain subdirectories of the form
.BR man[1-8l-p] .
.IP "\fB\-T\fP \fImacro-package\fP"
.B man
uses
.I macro-package
rather than the standard
.B \-man
macros defined in
.B /usr/lib/tmac/tmac.an
for formatting manual pages.
.IP "\fB\-k\fP \fIkeyword .\|.\|.\fP"
.B man
prints out one-line summaries from the
.B whatis
database (table of contents) that contain any of the given
.IR keyword s.
The
.B whatis
database is created using the
.BR makewhatis (8)
command.
.IP "\fB\-f\fP \fIfilename .\|.\|.\fP"
.B man
attempts to locate manual pages related to any of the given
.IR filename s.
It strips the leading pathname components from each
.IR filename ,
and then prints one-line summaries containing the resulting
basename or names.
This option also uses the
.B whatis
database.
.br
.ne 7
.SH "MANUAL PAGES"
.LP
Manual pages are either
.BR nroff (1)/ troff (1)
source files prepared with the
.B \-man
macro package, or
.BR aroff (1)
source files prepared with
.B "Appleworks GS"
(tm) or a compatible word processor.
.SS "Referring to Other Manual Pages"
Other manual pages can be referenced in one of two ways, depending on
whether the target manual page is an
.BR aroff
or
.BR nroff
source file.
.LP
For
.BR aroff
source files, a "link" may be made by creating a file ending in
.BR ".l"
(that's a dot-ell). The file must contain a single line consisting
of the pathname of the target
.BR aroff
source file.
An intentional design limitation was made that disallows this form
of "link" in the
.BR manl
(that's man-ell) subdirectory.
.LP
For
.BR nroff
source files, a "link" may be made by creating a file containing
the
.BR nroff
source (\fB\.so\fP) command. This file should have the same suffix
as the target
.BR nroff
source file.
.B man
does not itself do any processing of the source command.
.LP
With both types of "links" the pathname may be either a full- or
partial-pathname. In the latter case, the pathname must be relative
to the root of the manual page directory subtree.
.LP
.B man
processes the indicated file in place of the current one.
The reference must be expressed as
a pathname relative to the root of
the manual page directory subtree.
.SS "Preprocessing Manual Pages"
If the first line is a string of the form:
.nf
\fB'\|\e"\0 \fR\fIX\fR
.fi
where
.I X
is separated from the
`\fB"\fP'
by a single
.SM SPACE
and consists of any combination of characters in the following list,
.B man
pipes its input to
.BR troff (1)
or
.BR nroff (1)
through the corresponding preprocessors.
.nf
\fBe\fP \fBeqn\fP(1), or \fBneqn\fP for \fBnroff\fP
\fBr\fP \fBrefer\fP(1)
\fBt\fP \fBtbl\fP(1)
\fBv\fP \fBvgrind\fP(1)
.fi
.LP
If
.B eqn
or
.B neqn
is invoked,
it will automatically read the file
.B /usr/pub/eqnchar
(see
.BR eqnchar (7)).
If
.BR nroff (1)
is invoked,
.BR col (1V)
is automatically used.
.SH "COMPRESSED MANUAL PAGES"
.B man
allows its manual pages to be compressed by either
.BR compress ,
.BR freeze ,
or
.BR gzip ,
in which case the manual page must have the suffix
.BR .Z ,
.BR .F ,
or
.BR .gz ,
respectively. Note that the test for these suffixes is case sensitive
and if the incorrect case is used then the compressed file will be passed
to
.B nroff
with unpredictable results.
.LP
Compression may be used on files in either (or both) of the
.BR man? " and " cat?
subdirectories. Do not compress
.BR aroff (1)
source files since compressed files in the
.BR man?
subdirectory are always assumed to be
.BR nroff (1)
source.
.SH ENVIRONMENT
.IP \fBMANPATH\fP
If set,
its value overrides
.B /usr/man
as the default search path.
(The
.B \-M
flag, in turn, overrides this value.)
See the description of the
.B \-M
flag for syntax details.
.IP \fBUSRMAN\fP
If
.B MANPATH
is not set, then the value of
.B USRMAN
(if set) overrides
.B /usr/man
as the default search path.
(The
.B \-M
flag, in turn, overrides this value.)
See the description of the
.B \-M
flag for syntax details.
.IP \fBMANDIR\fP
If neither
.B MANPATH
nor
.B USRMAN
is set, then the value of
.B MANDIR
(if set) overrides
.B /usr/man
as the default search path.
(The
.B \-M
flag, in turn, overrides this value.)
See the description of the
.B \-M
flag for syntax details.
.IP \fBPAGER\fP
A program to use for interactively delivering
.BR man 's
output to the screen.
If not set,
.RB ` "/bin/more" '
(see
.BR more (1))
is used.
.IP \fBTCAT\fP
The name of the program to use to display
.BR troff ed
manual pages.
If not set,
.RB ` "lpr \-t" '
(see
.BR lpr (1))
is used.
.IP \fBTROFF\fP
The name of the formatter to use when the
.B \-t
flag is given.
If not set,
.RB ` "troff \-t" '
is used.
.SH FILES
.B /usr/[share]/man
.RS
root of the standard manual page directory subtree
.RE
.sp
.B /usr/[share]/man/man?/*
.RS
unformatted manual entries
.RE
.sp
.B /usr/[share]/man/cat?/*
.RS
.BR nroff ed
manual entries
.RE
.sp
.B /usr/[share]/man/fmt?/*
.RS
.BR troff ed
manual entries
.RE
.sp
.B /usr/[share]/man/whatis
.RS
table of contents and keyword database
.RE
.sp
.B /usr/[share]/lib/tmac/tmac.an
.RS
standard
.B \-man
macro package
.RE
.sp
.B /usr/pub/eqnchar
.SH "SEE ALSO"
.BR apropos (1),
.BR aroff (1),
.BR cat (1V),
.BR col (1V),
.BR compress (1),
.BR eqn (1),
.BR freeze (1),
.BR gzip (1),
.BR less (1),
.BR lpr (1),
.BR more (1),
.BR nroff (1),
.BR refer (1),
.BR tbl (1),
.BR troff (1),
.BR vgrind (1),
.BR vtroff (1),
.BR whatis (1),
.BR whereis (1),
.BR eqnchar (7),
.BR man (7),
.BR catman (8)
.br
.ne 5
.SH NOTES
.LP
Because
.B troff
is not 8-bit clean,
.B man
has not been made 8-bit clean.
.LP
The
.B \-f
and
.B \-k
options use the
.B whatis
database, which is created by
.BR makewhatis (8).
.br
.ne 4
.LP
Although this version of
.B man
allows
.BR USRMAN " and " MANDIR
to be each a colon- or space-separated list of pathnames, other versions
of
.B man
treat the values of these environment variables as a single pathname.
For compatibility reasons, the use of these two environment variables
is discouraged; use
.B MANPATH
instead.
.SH BUGS
.LP
The manual is supposed to be reproducible
either on a phototypesetter or on an
.SM ASCII
terminal.
However,
on a terminal some information
(indicated by font changes, for instance)
is necessarily lost.
.LP
Some dumb terminals cannot process the vertical motions produced
by the
.B e
.RB ( eqn (1))
preprocessing flag.
To prevent garbled output on these terminals,
when you use
.B e
also use
.BR t ,
to invoke
.BR col (1V)
implicitly.
This workaround has the disadvantage of eliminating superscripts and
subscripts \(em even on those terminals that can display them.
.SM CTRL-Q
will clear a terminal that gets confused by
.BR eqn (1)
output.
.LP
The code which calls the
.BR eqn (1),
.BR refer (1),
.BR tbl (1),
and
.BR vgrind (1)
preprocessors is not yet implemented. Since these preprocessors do
not as yet exist for GNO, this is not too much of a problem.
.LP
Please report any other bugs to Devin Reade, <gdr@myrias.com>.
.SH HISTORY
The GNO version of
.BR man
first appeared in GNO version 1.0 and was written by Mike Horwath.
This version was rewritten from scratch by Devin Reade.

View File

@ -1,154 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "man_______";
#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include <libc.h>
#include <ctype.h>
#include <assert.h>
#include <sgtty.h>
#include <unistd.h>
#include "util.h"
#include "man.h"
#ifdef DEBUG
extern void begin_stack_check(void);
extern int end_stack_check(void);
#endif
char *macroPackage = "an"; /* default /usr/lib/tmac/tmac.an */
char *versionStr = "Version 3.0 by Devin Reade";
char *pager;
char *troff;
char *tcat;
static char *nothing = "nothing appropriate";
short f_flag, k_flag, M_flag, n_flag, t_flag, T_flag, V_flag;
short hyphen_flag, err_flag;
static void usage(char *progname) {
if (err_flag || V_flag) fprintf(stderr,"%s %s\n",progname,versionStr);
if (err_flag) {
fprintf(stderr,"Usage:\n\
\t%s [-] [-nt] [-M path] [-T macro-package] [section] title ...\n\
\t%s [-n] [-M path] -f filename ...\n\
\t%s [-n] [-M path] -k keyword ...\n\n",progname,progname,progname);
exit(1);
}
return;
}
int main (int argc, char **argv) {
int i, result;
char *p;
extern int optind;
extern char *optarg;
/* make sure Gno is running */
if (needsgno()==0) {
fprintf(stderr,"Requires Gno/ME\n");
return 1;
}
#ifdef STACK_CHECK
begin_stack_check();
#endif
/*
* initialization
*/
f_flag = k_flag = M_flag = t_flag = T_flag = V_flag = 0;
n_flag = hyphen_flag = err_flag = 0;
/*
* parse the command line
*/
while((i = getopt(argc,argv,"fkM:ntT:V-")) != EOF) {
switch(i) {
case 'f':
f_flag++;
if (k_flag || t_flag || T_flag || hyphen_flag) err_flag++;
break;
case 'k':
k_flag++;
if (f_flag || t_flag || T_flag || hyphen_flag) err_flag++;
break;
case 'M':
M_flag++;
manpath = Xstrdup(optarg,__LINE__,__FILE__);
break;
case 'n':
n_flag++;
break;
case 't':
t_flag++;
if (k_flag || f_flag) err_flag++;
break;
case 'T':
T_flag++;
macroPackage = optarg;
if (k_flag || f_flag) err_flag++;
break;
case 'V':
V_flag++;
break;
default:
err_flag++;
}
}
/* take care of the '-' option, since getopt isn't smart enough */
for (i=optind; i<argc; i++) {
if (strcmp(argv[i],"-") == 0) {
hyphen_flag++;
if (k_flag || f_flag) err_flag++;
--argc;
for( ; i<argc; i++) {
argv[i] = argv[i+1];
}
}
}
if ((argc == optind) || (!k_flag && !f_flag && (argc-optind > 3))) {
err_flag++;
}
usage(argv[0]);
/* if not already done, set the manpath */
if (!M_flag) manpath = getManpath();
i = 0;
if (k_flag || f_flag) {
result = apropos(argc-optind, &argv[optind],
((k_flag) ? MAN_K_MODE : MAN_F_MODE));
if (!n_flag) {
i = apropos(argc-optind, &argv[optind],
((k_flag) ? ORCA_K_MODE : ORCA_F_MODE));
}
if (result<=0 && i<=0) {
fprintf(stderr,"%s: %s\n",basename(argv[0]),nothing);
}
} else {
if (!isatty(STDOUT_FILENO)) hyphen_flag++;
result = man(argc-optind, &argv[optind]);
}
free(manpath);
result = ((result == 0) && (i == 0)) ? 0 : 1;
#ifdef STACK_CHECK
fprintf(stderr,"stack usage: %d bytes\n",end_stack_check());
#endif
return result;
}

View File

@ -1,95 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
/*
* Configuration info
*/
#define WHATIS "whatis"
#define PAGER "/bin/more"
#define SYSCMND "15/syscmnd"
#define AROFF "aroff"
#define NROFF "nroff"
#define TROFF "troff -t"
#define TCAT "lpr -t"
#define CAT "cat"
#define EQN "eqn"
#define REFER "refer"
#define TBL "tbl"
#define VGRIND "vgrind"
#define NON 0x00
#define TXT 0x04
#define BIN 0x06
#define SRC 0xB0
#define MAN_F_MODE 1
#define MAN_K_MODE 2
#define WHATIS_MODE 3
#define ORCA_F_MODE 4
#define ORCA_K_MODE 5
#define ORCA_W_MODE 6
#define BUFFERSIZE 2048
typedef struct Section_tag {
char *name; /* section name */
char *suffix; /* directory suffix */
} Section;
typedef struct {
char *suffix;
char *extractor;
} compressionType;
/*
* from globals.c
*/
extern compressionType compressArray[];
extern char linebuf[BUFFERSIZE];
extern char linebuf2[BUFFERSIZE];
/*
* from man.c
*/
extern Section sections[];
extern char *manpath;
extern char *pager;
extern char *tcat;
extern char *troff;
extern char *macroPackage;
extern short hyphen_flag;
extern short n_flag;
extern short t_flag;
/*
* from apropos2.c
*/
int apropos(int argc, char **argv, int whole_line);
/*
* from whatis2.c
*/
int whatis(int argc, char **argv);
/*
* from man2.c
*/
int man (int argc, char *argv[]);
/*
* from common.c
*/
int getSuffixIndex(char *name);

View File

@ -1,611 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "man2______";
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sgtty.h>
#include "util.h"
#include "man.h"
#define MAX(a,b) ((a) > (b)) ? (a) : (b)
static char **buildManList(char *suffix, char *name);
static void display(char *list);
static char *getBaseName (char *out, char *in);
static void cleanManList(char **list);
/*
* Pre: argc is the number of strings in argv. It should either be 1 or 2.
* If DEBUG is defined, then any other value of argc will result in
* a failed assert.
*
* argv is an array of strings. If argc==1, then argv[0] is presumed
* to be the name of the man page. If argc==2, then argv[0] is
* presumed to be a section number and argv[1] is the name of the
* man page.
*
* globals:
* manpath must be a malloc'd string. Either ':' or ' ' may
* may be used as a directory delimiter.
* macroPackage must be set to a static string.
* t_flag must be in a defined state (either set or unset)
* hyphen_flag must be in a defined state (either set or unset)
*
* Post: print the man page in whatever form it takes, acting as necessary
* on the -, -M, and -T flags and section number.
*/
int man(int argc, char *argv[]) {
char **manpath_array, **manpagelist;
char *sec, *name, *current_path;
Section *section;
int i, j, k, abort;
short section_found, page_found;
char dirbrk; /* path component separator. either ':' or '/' */
char c, *p;
struct sgttyb termMode;
short oldMode;
/* initialization */
abort = 0;
section_found = 0;
page_found = 0;
if (t_flag) {
if ((tcat = getenv("TCAT")) == NULL) {
tcat = TCAT;
} else tcat = Xstrdup(tcat,__LINE__,__FILE__);
if ((troff = getenv("TROFF")) == NULL) {
troff = TROFF;
} else troff = Xstrdup(troff,__LINE__,__FILE__);
}
if (hyphen_flag) {
pager = CAT;
} else if ((pager = getenv("PAGER")) == NULL) {
pager = PAGER;
}
/* determine name and, if appropriate, sec */
switch (argc) {
case 1:
sec = NULL;
name = argv[0];
break;
case 2:
sec = argv[0];
/* special case some section abbreviations */
if (!strcmp(sec,"l")) {
sec = "local";
} else if (!strcmp(sec,"n")) {
sec = "new";
} else if (!strcmp(sec,"o")) {
sec = "old";
} else if (!strcmp(sec,"p")) {
sec = "public";
}
name = argv[1];
break;
default:
fprintf(stderr,"internal error at line %d in file %s\n",__LINE__,
__FILE__);
exit(1);
}
/* create array of paths to search */
if ((manpath_array = makePathArray(manpath)) == NULL) return 1;
/*
* loop over all the paths in MANPATH
*/
i=0;
current_path = manpath_array[i];
while (!abort && current_path) {
dirbrk = (strchr(current_path,':')!=NULL) ? ':' : '/';
/* go to the current path in MANPATH */
if (chdir(current_path) == -1) {
i++;
current_path = manpath_array[i];
continue;
}
/* loop over sections */
for (j=0; !abort && sections[j].name != NULL; j++) {
/*
* if section number was specified and this isn't it, do
* the next loop
*/
if (sec && (strcmp(sec,sections[j].name) ||
(!isdigit(*sec) &&
strncmp(sec,sections[j].name,strlen(sec))))) continue;
section_found++;
/*
* we're going to check this section. Get the pathnames
* (relative to this directory) of the two files.
*/
manpagelist = buildManList(sections[j].suffix,name);
if (!manpagelist) continue;
page_found++;
for (k=0; !abort && manpagelist[k]; k++) {
display(manpagelist[k]);
if (!hyphen_flag && !t_flag) {
fprintf(stderr,
"type q to quit, or any other key for next man page: ");
c = getcharraw();
if (c == '\0') {
fprintf(stderr,"getcharraw failed line %d of %s: %s\n",
__LINE__,__FILE__,strerror(errno));
exit(1);
}
fputc('\n',stderr);
/* evaluate result */
if ((c == 'q') || (c == 'Q')) abort++;
}
}
cleanManList(manpagelist);
} /* done looping over sections */
i++;
current_path = manpath_array[i];
} /* done looping over paths */
i = 0; /* used here for the return code */
if (sec) {
if (!section_found) {
fprintf(stderr,"there is no section %s in the manual\n",sec);
i++;
} else if (!page_found) {
fprintf(stderr,"there is no %s in section %s\n",name,sec);
i++;
}
} else if (!page_found) {
fprintf(stderr,"there is no %s in the manual\n",name);
i++;
}
return i;
}
#define DIRBUF_LEN 10
static const char *manstr="man";
static const char *catstr="cat";
static char **buildManList(char *suffix, char *name) {
static char buffer1[FILENAME_MAX];
static char buffer2[FILENAME_MAX];
DIR *directory;
struct dirent *entry;
char **list1, **list2, **list3;
size_t len;
int total1, total2, i, j, k;
char *p, *fn;
/* initialization */
list1 = list2 = list3 = NULL;
total1 = total2 = 0;
#ifdef DEBUG
/* sanity check on arguments */
if(MAX(strlen(manstr),strlen(catstr)) + strlen(suffix) >= FILENAME_MAX) {
fprintf(stderr,"internal error: buffer overflow at line %d of %s\n",
__LINE__,__FILE__);
}
#endif
/*
* look in man subdirectory
*/
strcpy(buffer1,manstr);
strcat(buffer1,suffix);
if ((directory = opendir(buffer1)) != NULL) {
while ((entry = readdir(directory)) != (struct dirent *) NULL) {
/* skip if no match */
len = strlen(name);
if (strncmp(entry->d_name,name,len) ||
(entry->d_name[len] != '.')) continue;
if (strlen(manstr) + strlen(suffix) + strlen(entry->d_name) +
strlen(suffix) + 1 >= FILENAME_MAX) {
fprintf(stderr,"internal error: buffer overflow at line %d of %s\n",
__LINE__,__FILE__);
}
sprintf(buffer1,"%s%s:%s",manstr,suffix,entry->d_name);
/* look for "links" to aroff files. (what a kludge) */
if ((buffer1[3] != 'l') &&
(strcmp(".l",&buffer1[strlen(buffer1)-2])==0)) {
FILE *linkptr;
char *tp;
/* dereference the "link" */
if ((linkptr = fopen(buffer1,"r")) == NULL) {
fprintf(stderr,"couldn't open %s\n",buffer1);
} else if (fgets(buffer2,FILENAME_MAX,linkptr)==NULL) {
fprintf(stderr,"couldn't read %s\n",buffer1);
} else {
/* drop trailing space and newline */
tp = buffer2 + strlen(buffer2) -1;
while ((tp>=buffer2) && (isspace(*tp) || *tp == '\n')) {
*tp = '\0';
tp--;
}
fclose(linkptr);
if (access(buffer2,R_OK) == 0) {
list1 = addToStringArray(list1, buffer2);
total1++;
}
}
} else {
/* not a .l "link"; a normal file */
list1 = addToStringArray(list1, buffer1);
total1++;
}
}
closedir(directory);
}
if (!t_flag) {
/*
* look in cat subdirectory
*/
strcpy(buffer1,catstr);
strcat(buffer1,suffix);
if ((directory = opendir(buffer1)) != NULL) {
while ((entry = readdir(directory)) != (struct dirent *) NULL) {
/* skip if no match */
len = strlen(name);
if (strncmp(entry->d_name,name,len) ||
(entry->d_name[len] != '.')) continue;
if (strlen(catstr) + strlen(suffix) + strlen(entry->d_name) +
strlen(suffix) + 1 >= FILENAME_MAX) {
fprintf(stderr,"internal error: buffer overflow at line %d of %s\n",
__LINE__,__FILE__);
}
sprintf(buffer1,"%s%s:%s",catstr,suffix,entry->d_name);
list2 = addToStringArray(list2, buffer1);
total2++;
}
closedir(directory);
}
}
/*
* eliminate files common to both lists
*/
len = strlen(suffix);
for(i=0; i<total1; i++) {
if (list1[i] == NULL) continue;
for (j=0; j<total2; j++) {
if (list2[j] == NULL) continue;
getBaseName(buffer1,list1[i]);
getBaseName(buffer2,list2[j]);
#ifdef DEBUG
if ((strlen(buffer1) < len + 5) ||
(strlen(buffer2) < len + 5)) {
fprintf(stderr,"internal error at line %d of %s\n",__LINE__,
__FILE__);
exit(1);
}
#endif
/* match after the respective "manXX/" and "catXX/" */
if ( strcmp(&buffer1[len+4],&buffer2[len+4]) == 0 ) {
p = newerFile(list1[i],list2[j]);
if (p == list1[i]) {
free(list2[j]);
list2[j] = NULL;
} else if (p == list2[j]) {
free(list1[i]);
list1[i] = NULL;
break;
} else {
fprintf(stderr,"internal error at line %d of %s\n\t%s\n\t%s\n",
__LINE__,__FILE__,
(list1[i]) ? list1[i] : "(NULL)",
(list2[j]) ? list2[j] : "(NULL)");
perror("newerFile failed");
exit(1);
}
} /* endif */
} /* endfor */
} /* endfor */
/*
* combine the two lists
*/
for (i=0;i<total1;i++) {
if (list1[i] != NULL) {
list3 = addToStringArray(list3, list1[i]);
free(list1[i]);
}
}
for (j=0;j<total2;j++) {
if (list2[j] != NULL) {
list3 = addToStringArray(list3, list2[j]);
free(list2[j]);
}
}
free(list1);
free(list2);
return list3;
}
/*
* cleanManList
*
* Pre: list is a NULL-terminated array of strings, where the array
* and each string in the array was allocated by malloc.
*
* Post: all malloc'd memory in list is free'd.
*/
static void cleanManList(char **list) {
int i;
for (i=0; list[i]; i++) {
free(list[i]);
}
free (list);
return;
}
/*
* display
*/
#define MANSUBDIR 0
#define CATSUBDIR 1
#define FORMAT "Formatting manual page, please wait ..."
#define DECOMP "Decompressing manual page, please wait ..."
#define DECFOR "Decompressing and formatting manual page, please wait ..."
#define OVERFLOW "Internal buffer overflow ... aborted."
static void display(char *file) {
int icompress, isubdir;
char *tmac;
char *roffer;
char *compressor;
fileType *ft;
#ifdef DEBUG
if (file == NULL) {
fprintf(stderr,"internal error line %d of %s\n",__LINE__,__FILE__);
exit(1);
}
if (strlen(file) < 4) {
fprintf(stderr,"internal error line %d of %s\n",__LINE__,__FILE__);
exit(1);
}
#endif
/*
* determine which subdirectory this file is in
*/
if (strncmp(file,"cat",3) == 0) {
isubdir = CATSUBDIR;
} else {
isubdir = MANSUBDIR;
}
/*
* if we're troffing a new file to fmt?, make sure the directory
* exists
*/
if (t_flag && hyphen_flag) {
char *p;
struct stat sbuf;
/* ensure the fmt? directory exists */
sprintf(linebuf,"fmt%s",&file[3]);
if ((p = strchr(linebuf,':')) != NULL) {
*p = '\0';
#ifdef DEBUG
} else if ((p = strchr(linebuf,'/')) == NULL) {
fprintf(stderr,"internal error line %d of %s\n",__LINE__,
__FILE__);
exit(1);
#endif
} else *p = '\0';
if (stat(linebuf,&sbuf) != 0) {
fprintf(stderr,"couldn't stat %s: %s. %s skipped\n",
linebuf,strerror(errno),file);
return;
} else if (!(sbuf.st_mode & S_IFDIR)) {
fprintf(stderr,"cannot access %s: %s. %s skipped\n",
linebuf,strerror(ENOTDIR),file);
return;
}
}
/*
* determine the type of compression used, if any
*/
icompress = getSuffixIndex(file);
if (icompress >= 0) {
compressor = compressArray[icompress].extractor;
if (isubdir == MANSUBDIR) {
/*
* compressed nroff source
*/
if (t_flag && hyphen_flag) {
if (strlen(compressor) + 2*strlen(file) + strlen(troff) +
strlen(macroPackage) + strlen(tcat) + 12 > BUFFERSIZE) {
fprintf(stderr,"%s\n",OVERFLOW);
exit(1);
}
sprintf(linebuf,"%s %s | %s -m%s - > fmt%s",
compressor, file, troff, macroPackage, &file[3]);
} else if (t_flag) {
if (strlen(compressor) + strlen(file) + strlen(troff) +
strlen(macroPackage) + strlen(tcat) + 12 > BUFFERSIZE) {
fprintf(stderr,"%s\n",OVERFLOW);
exit(1);
}
sprintf(linebuf,"%s %s | %s -m%s - | %s",
compressor, file, troff, macroPackage, tcat);
} else {
/* not troff, jes' plain old nroff */
if (strlen(compressor) + strlen(file) + strlen(NROFF) +
strlen(macroPackage) + strlen(pager) + 12 > BUFFERSIZE) {
fprintf(stderr,"%s\n",OVERFLOW);
exit(1);
}
if (!hyphen_flag) printf("%s\n",DECFOR);
sprintf(linebuf,"%s %s | %s -m%s - | %s",
compressor, file, NROFF, macroPackage, pager);
}
} else {
/*
* compressed straight text
*/
if (strlen(compressor)+strlen(file)+strlen(pager)+5 > BUFFERSIZE) {
fprintf(stderr,"%s\n",OVERFLOW);
exit(1);
}
if (!hyphen_flag) printf("%s\n",DECOMP);
sprintf(linebuf,"%s %s | %s", compressor, file, pager);
}
} else {
if (isubdir == MANSUBDIR) {
/*
* Can be either aroff or nroff source. If it's nroff source,
* it must either be a TXT, SRC, or BIN file
*/
if (!hyphen_flag && !t_flag) printf("%s\n",FORMAT);
if ((ft = getFileType(file)) == NULL) {
perror(file);
exit(1);
}
if ((ft->type == 0x50) || (ft->auxtype == 0x8010)) {
/*
* AppleworksGS Word Processor format; use 'aroff'
*/
if (t_flag) {
fprintf(stderr,"cannot use troff on aroff source files\n");
return;
}
if (strlen(AROFF)+strlen(file)+strlen(pager)+5 > BUFFERSIZE) {
fprintf(stderr,"%s\n",OVERFLOW);
exit(1);
}
sprintf(linebuf,"%s %s | %s", AROFF, file, pager);
} else if ((ft->type == TXT) || (ft->type == BIN) ||
(ft->type == SRC) || (ft->type == NON)) {
/*
* TeXT, BINary, or SouRCe file; assume nroff source
*/
if (t_flag && hyphen_flag) {
if (strlen(troff) + strlen(macroPackage) +
2 * strlen(file) + 7 >= BUFFERSIZE) {
fprintf(stderr,"%s\n",OVERFLOW);
exit(1);
}
sprintf(linebuf,"%s -m%s %s > fmt%s",
troff, macroPackage, file, &file[3]);
} else if (t_flag) {
if (strlen(troff) + strlen(macroPackage) + strlen(file) +
strlen(tcat) + 7 >= BUFFERSIZE) {
fprintf(stderr,"%s\n",OVERFLOW);
exit(1);
}
sprintf(linebuf,"%s -m%s %s | %s",troff,macroPackage,file,tcat);
} else {
/* not troff, jes' plain old nroff */
if (strlen(NROFF) + strlen(macroPackage) +
strlen(file) + strlen(pager) + 8 >= BUFFERSIZE) {
fprintf(stderr,"%s\n",OVERFLOW);
exit(1);
}
sprintf(linebuf,"%s -m%s %s | %s",NROFF,macroPackage,file,pager);
}
} else {
fprintf(stderr,
"bad file type for %s\n\ttype = %x\n\taux = %lx\n",
file,ft->type,ft->auxtype);
return;
}
} else {
/* assume straight text */
if (strlen(CAT) + strlen(file) + strlen(pager) + 4 >= BUFFERSIZE){
fprintf(stderr,"%s\n",OVERFLOW);
exit(1);
}
sprintf(linebuf,"%s %s | %s", CAT, file, pager);
}
}
#if 0
fprintf(stderr,"DEBUG: BUFFER: %s\n",linebuf);
#endif
system(linebuf);
return;
}
/*
* getBaseName -- copy the filename pointed to by <in> into the buffer
* pointed to by <out>, dropping any compression suffix
* that may be on the base name. The set of compression
* suffixes is defined by the NULL-terminated compressArray[].
*
* It is the user's responsibility to ensure that the
* buffer *out has been allocated with sufficient space
* for the result.
*
* Returns a pointer to <out>.
*/
static char *getBaseName (char *out, char *in) {
char *p;
int i;
strcpy(out,in);
if ((p = strrchr(out,'.')) != NULL) {
for (i=0; compressArray[i].suffix; i++) {
if (strcmp(p,compressArray[i].suffix)==0) {
*p = '\0';
break;
}
}
}
return out;
}

View File

@ -1,10 +1,6 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "makewhatis";
#ifdef __CCFRONT__
#include <14:pragma.h>
#endif
#include <stdio.h>
#include <string.h>
@ -16,178 +12,118 @@ segment "makewhatis";
#include "makewhatis.h"
/* These are the compression types */
#define NO_COMPRESS 0
#define Z_COMPRESS 1
#define F_COMPRESS 2
#define G_COMPRESS 3
#ifdef TEST_PROCESS
short v_flag = 1;
FILE *output_fp;
FILE *error_fp;
#else
extern FILE *output_fp;
extern FILE *error_fp;
short v_flag = 1;
#endif
extern GSString255Ptr __C2GSMALLOC (char *s);
extern GSString255Ptr __C2GSMALLOC (char *s);
extern char buffer[];
extern char titlebuf[];
extern FILE *output_fp;
extern FILE *error_fp;
/*
* void process (char *filename, char *tmp_file, FILE *whatis_fp);
*
* Pre: <filename> is the name of the file to add to the database.
* <tmp_file> is the name for the temporary file. It has not been opened.
* <whatis_fp> is a file pointer to the open whatis database file.
* (sec> is the section "number". We really only care if it is
* either "l" or "local" (because of aroff "links"), otherwise
* it is ignored.
* Pre: <filename> is the name of the file to add to the database.
* <tmp_file> is the name for the temporary file. It has not been opened.
* <whatis_fp> is a file pointer to the open whatis database file.
*
* Post: The name, section number, and description from the man page is
* appended to <whatis_fp>.
* appended to <whatis_fp>.
*/
void process (char *filename, char *tmp_file, FILE *whatis_fp, char *sec) {
void process (char *filename, char *tmp_file, FILE *whatis_fp) {
FileInfoRecGS info_record; /* used to get the file type */
FileInfoRecGS info_record; /* used to get the file type */
char *suffix; /* points to the start of the file suffix */
static char command_buf[255]; /* used to call system(2) */
char *p1; /* a scratch pointer */
int namelength; /* length of 'name (section)' */
char *name; /* points to the file basename */
short compression; /* the compression type (if nec) */
static char command_buf[255]; /* used to call system(2) */
char *p1; /* a scratch pointer */
int namelength; /* length of 'name (section)' */
char *name; /* points to the file basename */
int sufflen; /* length of the filename suffix */
if (v_flag>=2) fprintf(output_fp,"Working on file %s/%s ...\n",sec,filename);
if (v_flag) fprintf(output_fp,"Working on file %s ...\n",filename);
/*
* get the file basename
/*
* get the file basename and suffix
*/
if ((name = malloc (strlen(filename)+1)) == NULL) {
if (v_flag)
fprintf(error_fp,"malloc failed when processing %s -- file skipped\n",
filename);
if (v_flag)
fprintf(error_fp,"malloc failed when processing %s -- file skipped\n",
filename);
return;
}
strcpy(name,filename);
/*
* check for a compression suffix like ".Z" or ".F"
*/
p1 = name + strlen(name) -1; /* p1 points to last char of name */
while ((p1>=name) && (*p1!='.')) p1--;
if (p1<=name) { /* <= because we don't want a name beginning with '.' */
if (v_flag)
fprintf(error_fp,"%s has no suffix -- file skipped\n",
filename);
if ((suffix = strchr(name,'.')) == NULL) {
if (v_flag)
fprintf(error_fp,"%s has no suffix -- file skipped\n",
filename);
return;
}
if (strcmp(p1,".Z")==0) {
compression = Z_COMPRESS;
} else if (strcmp(p1,".F")==0) {
compression = F_COMPRESS;
} else if (strcmp(p1,".gz")==0) {
compression = G_COMPRESS;
} else compression = NO_COMPRESS;
*p1 = '\0';
/*
* define the suffix
*/
if (compression == NO_COMPRESS) {
suffix = p1 + 1;
} else {
while ((p1>=name) && (*p1!='.')) --p1;
if (p1<=name) { /* <= because we don't want a name beginning with '.' */
if (v_flag)
fprintf(error_fp,"%s has deformed file name -- file skipped\n",
filename);
return;
}
*p1 = '\0';
suffix = p1 + 1;
}
*suffix = '\0';
suffix++;
sufflen = strlen(suffix);
/*
* find out the file type
*/
if (compression == NO_COMPRESS) {
info_record.pCount = 5;
info_record.pathname = __C2GSMALLOC(filename);
GetFileInfoGS(&info_record);
if (toolerror()) {
if (v_flag)
fprintf(error_fp,
"malloc failed when processing %s -- file skipped\n", filename);
return;
}
info_record.pCount = 5;
info_record.pathname = __C2GSMALLOC(filename);
GetFileInfoGS(&info_record);
if (toolerror()) {
if (v_flag)
fprintf(error_fp,"malloc failed when processing %s -- file skipped\n",
filename);
return;
}
/*
/*
* Process the file according to type: nroff, aroff, freeze, and compress.
* The digested result is placed in buffer.
*/
if ((compression == NO_COMPRESS) &&
(info_record.fileType == 0x50u) &&
(info_record.auxType == 0x8010u)
) {
if ((info_record.fileType == 0x50u) && (info_record.auxType == 0x8010u)) {
/* is it an Appleworks GS word processor document? Use aroff */
sprintf(command_buf,"aroff -b %s > %s",filename,tmp_file);
if (v_flag>=3) fprintf(stderr,"%s\n",command_buf);
sprintf(command_buf,"aroff -b %s >%s",filename,tmp_file);
system(command_buf);
fillbuffer(tmp_file);
fillbuffer(tmp_file);
} else if (compression == Z_COMPRESS) {
} else if ( (toupper(*(suffix+sufflen-1))=='Z') &&
(*(suffix+sufflen-2)=='.')) {
/* Compressed man page; uncompress it */
sprintf(command_buf,"compress -cd %s > %s",filename,tmp_file);
if (v_flag>=3) fprintf(stderr,"%s\n",command_buf);
system(command_buf);
fillbuffer(tmp_file);
sprintf(command_buf,"compress -dc %s >%s",filename,tmp_file);
system(command_buf);
fillbuffer(tmp_file);
} else if (compression == F_COMPRESS) {
/* fix suffix for printout */
sufflen -= 2;
*(suffix + sufflen) = '\0';
} else if ( (toupper(*(suffix+sufflen-1))=='F') &&
(*(suffix+sufflen-2)=='.')) {
/* Frozen man page; melt it */
sprintf(command_buf,"freeze -cd %s > %s",filename,tmp_file);
if (v_flag>=3) fprintf(stderr,"%s\n",command_buf);
system(command_buf);
fillbuffer(tmp_file);
sprintf(command_buf,"freeze -dc %s >%s",filename,tmp_file);
system(command_buf);
fillbuffer(tmp_file);
} else if (compression == G_COMPRESS) {
/* gzipped man page; zcat it */
sprintf(command_buf,"gzip -cd %s > %s",filename,tmp_file);
if (v_flag>=3) fprintf(stderr,"%s\n",command_buf);
system(command_buf);
fillbuffer(tmp_file);
/* fix suffix for printout */
sufflen -= 2;
*(suffix + sufflen) = '\0';
} else if ((*suffix=='l') && (*(suffix+1)=='\0') &&
strcmp("l",sec) && strcmp("local",sec)) {
/* It's a link to another man page; do nothing. */
return;
} else if ((toupper(*suffix)=='L') && (*(suffix+1)=='\0')) {
/* It's a link to another man page; do nothing. */
return;
} else {
/* Assume that it's a text file */
if (v_flag>=3) fprintf(stderr,"assuming text file\n");
fillbuffer(filename);
}
/*
* If there was an error, or it is an .so reference to another man
* page, then return without writing anything to the database
*/
if ((buffer[0] == '\0') || (titlebuf[0] == '\0')) {
return;
/* Assume that it's a text file */
fillbuffer(filename);
}
/*
@ -196,37 +132,33 @@ void process (char *filename, char *tmp_file, FILE *whatis_fp, char *sec) {
* formatting.
*/
p1 = buffer;
p1 = buffer;
while (isspace(*p1)) p1++;
namelength = strlen(titlebuf) + strlen(suffix) + 4;
namelength = strlen(name) + strlen(suffix) + 4;
if (namelength > (TABLENGTH * 3)) {
fprintf(whatis_fp,"%s (%s) - %s\n", titlebuf, suffix, p1);
if (namelength > (TABLENGTH * 3)) {
fprintf(whatis_fp,"%s (%s) - %s\n", name, suffix, p1);
} else if (namelength > (TABLENGTH * 2)) {
fprintf(whatis_fp,"%s (%s)\t- %s\n", titlebuf, suffix, p1);
fprintf(whatis_fp,"%s (%s)\t- %s\n", name, suffix, p1);
} else if (namelength > TABLENGTH ) {
fprintf(whatis_fp,"%s (%s)\t\t- %s\n", titlebuf, suffix, p1);
fprintf(whatis_fp,"%s (%s)\t\t- %s\n", name, suffix, p1);
} else {
fprintf(whatis_fp,"%s (%s)\t\t\t- %s\n", titlebuf, suffix, p1);
fprintf(whatis_fp,"%s (%s)\t\t\t- %s\n", name, suffix, p1);
}
return;
return;
}
#ifdef TEST_PROCESS
int main (int argc, char **argv) {
output_fp = stdout;
error_fp = stderr;
if (argc != 2) {
fprintf(stderr,"Usage: %s <man_page_file_name>\n",argv[0]);
if (argc != 2) {
printf("Usage: %s <man_page_file_name>\n",argv[0]);
return -1;
}
process (argv[1], ":tmp:garbage", stdout, "2");
process (argv[1], ":tmp:garbage", stdout);
return 0;
}

View File

@ -1,386 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "util______";
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <ctype.h>
#include <sgtty.h>
#include <fcntl.h>
#include "util.h"
/*
* getManpath -- return a malloc'd copy of the MANPATH. If MANPATH
* isn't defined in the environment, then use USRMAN, then
* MANDIR, then if all else fails, use the macro DEFAULT_MANPATH.
* If an error occurs, print the cause via perror and exit.
*/
char *getManpath(void) {
char *manpath;
manpath = getenv("MANPATH");
if (manpath == NULL) manpath = getenv("USRMAN");
if (manpath == NULL) manpath = getenv("MANDIR");
if (manpath == NULL) manpath = DEFAULT_MANPATH;
return Xstrdup(manpath,__LINE__,__FILE__);
}
/*
* Xstrdup - a safe strdup; it will handle error conditions and exit
* one occurs
*
* line and file are arbitrary, but are expected to be the
* values of __LINE__ and __FILE__ respectively.
*/
char *Xstrdup(char *oldstr, int line, char *file) {
char *newstr;
if ((newstr = malloc(strlen(oldstr)+1)) == NULL) {
fprintf(stderr,"Xstrdup failed at line %d in file %s: %s\n",line,
file,strerror(errno));
exit(1);
}
strcpy(newstr,oldstr);
return newstr;
}
/*
* Xmalloc - a safe malloc; it will handle error conditions and exit
* if one occurs.
*
* line and file are arbitrary, but are expected to be the
* values of __LINE__ and __FILE__ respectively.
*/
void *Xmalloc(size_t size, int line, char *file) {
char *p;
if ((p = malloc(size)) == NULL) {
fprintf(stderr,"Xmalloc failed at line %d in file %s: %s\n",line,
file,strerror(errno));
exit(1);
}
return ((void *) p);
}
/*
* Xrealloc - a safe realloc; it will handle error conditions and exit
* if one occurs.
*
* line and file are arbitrary, but are expected to be the
* values of __LINE__ and __FILE__ respectively.
*/
void *Xrealloc(void *oldptr, size_t size, int line, char *file) {
char *p;
if ((p = realloc(oldptr, size)) == NULL) {
fprintf(stderr,"Xrealloc failed at line %d in file %s: %s\n",line,
file,strerror(errno));
exit(1);
}
return ((void *) p);
}
/*
* addToStringArray -- add a string to a NULL-terminated array of strings.
* If oldArray is NULL, then a new array is created,
* otherwise oldArray is expanded.
*
* WARNING: | Because of the allocation scheme used, any oldArray
* | passed to this routine _must_ be the return value
* | of a previous call to this routine. This does not
* | imply that only one array can be expanded by this
* | routine (any number may be expanded).
*
* The value of macro SLOTS_QUANTUM defined below is
* the number of array slots allocated at one time. The
* size of the string array is always a multiple of this
* value.
*
* Returns a pointer to an array that contains the old
* strings with the new one appended. The array is
* NULL-terminated.
*/
#define SLOTS_QUANTUM 10
char **addToStringArray(char **oldArray, char *string) {
char **result;
int slotsAlloced, slotsUsed;
if (oldArray == NULL) {
/*
* This is a new array; do the brute force approach
*/
result = Xmalloc(SLOTS_QUANTUM * sizeof(char *), __LINE__, __FILE__);
result[0] = Xstrdup(string,__LINE__,__FILE__);
result[1] = NULL;
} else {
/*
* adding to and, if necessary, expanding an old array
*/
/* determine slotsUsed and slotsAlloced */
for (slotsUsed=0; oldArray[slotsUsed]; slotsUsed++);
if (slotsUsed % SLOTS_QUANTUM == SLOTS_QUANTUM-1) { /* space for NULL */
slotsAlloced = slotsUsed+1;
} else {
slotsAlloced = ((slotsUsed / SLOTS_QUANTUM) + 1) * SLOTS_QUANTUM;
}
#ifdef DEBUG
assert(slotsUsed < slotsAlloced);
#endif
/* expand number of slots if necessary */
if (slotsUsed+1 < slotsAlloced) {
/* there are enough slots; add it to this array */
result = oldArray;
} else {
/* we need more slots; expand the array */
slotsAlloced += SLOTS_QUANTUM;
result = Xrealloc(oldArray, slotsAlloced * sizeof(char *),
__LINE__, __FILE__);
}
/* add the string to the array */
result[slotsUsed++] = Xstrdup(string, __LINE__, __FILE__);
result[slotsUsed] = NULL;
}
return result;
}
/*
* makePathArray -- parse a path list and break it into a NULL-terminated
* array of paths. The original path is left unchanged.
*
* The delimiter between paths may either be a ' ' or a ':'.
* The delimiter is assumed to be a ':' if <path> contains
* both '/' and ':' characters but no ' ' character,
* otherwise the delimiter is assumed to be a ' '.
*/
char **makePathArray(char *path) {
char *delim, *p, *q, **result;
/* set the delimiter */
if ( strchr(path,' ')==NULL &&
strchr(path,':') &&
strchr(path,'/')) {
delim = ":";
} else {
delim = " ";
}
/* build the array */
p = Xstrdup(path, __LINE__, __FILE__);
q = strtok(p,delim);
result = NULL;
while (q) {
result = addToStringArray(result, q);
q = strtok(NULL,delim);
}
free(p);
return result;
}
/*
* ncstrcmp -- A case insensitive ("no-case") strcmp
*/
int ncstrcmp(char *a, char *b) {
while (*a && *b) {
if (*a == *b) {
a++; b++;
continue;
}
return ((int) *b - *a);
}
if (!*a && !*b) return 0;
return ((int) *b - *a);
}
/*
* ncstrncmp -- A case insensitive ("no-case") strncmp
*/
int ncstrncmp (char *a, char *b, unsigned int count) {
unsigned int i=0;
for (i=0; i<count; i++) {
if (a[i] == b[i]) {
if (!a[i]) break;
else continue;
}
return ((int) b[i]-a[i]);
}
return 0;
}
/*
* ncstrstr -- A case insensitive ("no-case") strstr
*
* This is implemented using a convert-copy-to-single-case-
* then-strstr hack.
* It's speed could be increased by switching
* to a Boyer-Moore scan algorithm anytime strlen(substr) > 5,
* and using a straight-forward search for strlen(substr) <= 5.
*/
char *ncstrstr(char *str, char *substr) {
char *strCopy, *substrCopy, *p;
strCopy = Xstrdup(str,__LINE__,__FILE__);
substrCopy = Xstrdup(substr,__LINE__,__FILE__);
/* convert the strings */
p = strCopy;
while (*p) {
*p = tolower(*p);
p++;
}
p = substrCopy;
while (*p) {
*p = tolower(*p);
p++;
}
p = strstr(strCopy,substrCopy);
free(strCopy);
free(substrCopy);
return p;
}
/*
* newerFile -- Compares the "last modified" time of two paths.
* Returns:
* the name of the newer file if both files exist
* the second file if both exist and have the same mod time
* the name of the existing file if one file doesn't exist
* NULL and sets errno if neither file exists or if there
* is an error.
*/
char *newerFile(char *path1, char *path2) {
static struct stat record1, record2;
int i,j;
/*
* see if both, only one, or neither files exist
*/
i = access(path1, F_OK);
j = access(path2, F_OK);
if (i==-1 && j==-1) {
errno = ENOENT;
return NULL;
} else if (i==-1) {
return path2;
} else if (j==-1) {
return path1;
}
/*
* both files exist; stat them
*/
if (stat(path1,&record1) != 0) return NULL;
if (stat(path2,&record2) != 0) return NULL;
return (record1.st_mtime > record2.st_mtime) ? path1 : path2;
}
/*
* getcharraw() - return the next character from stdin without waiting
* for a CR to be hit. Returns '\0' and sets errno
* on an error.
*/
#define FAILED_CHAR '\0';
char getcharraw(void) {
short oldmode;
struct sgttyb s;
int count;
char c;
/* obtain old terminal mode */
if (gtty(STDIN_FILENO,&s) == -1) return FAILED_CHAR;
oldmode = s.sg_flags;
/* set terminal to CBREAK and obtain keystroke */
s.sg_flags |= CBREAK;
if (stty(STDIN_FILENO,&s) == -1) return FAILED_CHAR;
count = read (STDIN_FILENO, &c, 1);
/* reset old terminal mode */
s.sg_flags = oldmode;
if ((stty(STDIN_FILENO,&s) == -1) || (count == -1)) return FAILED_CHAR;
return c;
}
/*
* basename -- return a pointer to the base filename (all leading
* pathname components removed) of <path>. <path> _must_
* point to a NULL-terminated string.
*/
char *basename (char *path) {
char *p, dirsep;
dirsep = (strchr(path,':')) ? ':' : '/';
if ((p = strrchr(path,dirsep)) != NULL) {
return p+1;
} else {
return path;
}
}
/*
* dirname -- return a pointer to a string consisting of the directory
* component of <path>. This returns a pointer to an internal
* buffer, so the next call to dirname() will overwrite this
* buffer. <path> must be a NULL-terminated string.
*/
char *dirname (const char *path) {
static char buffer[FILENAME_MAX];
char *p, dirsep;
strcpy(buffer,path);
dirsep = (strchr(buffer,':')) ? ':' : '/';
if ((p = strrchr(buffer,dirsep)) != NULL) {
*p = '\0';
}
return buffer;
}

View File

@ -1,37 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
/*
* from util.c
*/
#define DEFAULT_MANPATH "/usr/man"
char *getManpath(void);
char *Xstrdup(char *oldstr, int line, char *file);
void *Xmalloc(size_t size, int line, char *file);
void *Xrealloc(void *oldptr, size_t size, int line, char *file);
char **addToStringArray(char **oldArray, char *string);
char **makePathArray(char *path);
int ncstrcmp(char *a, char *b);
int ncstrncmp (char *a, char *b, unsigned int count);
char *ncstrstr(char *str, char *substr);
char *newerFile(char *path1, char *path2);
char getcharraw(void);
char *basename (char *path);
char *dirname (const char *path);
/*
* from utilgs.c
*/
typedef struct {
unsigned int type;
unsigned long int auxtype;
} fileType, fileTypePtr;
fileType *getFileType (char *file);

View File

@ -1,179 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "utilgs____";
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <gsos.h>
#include <orca.h>
#include "util.h"
extern GSString255Ptr __C2GSMALLOC(char *);
extern int _mapErr(int);
/*
* access -- a replacement for the standard Gno one; this one will actually
* return 0 when testing X_OK on a directory.
*
* This one still has a bug in it: If the file is a shell command or sys
* file, then X_OK will return zero, but not if it is a shell script (as
* with 'chtyp -lexec filename').
*/
int access(char *name, int mode) {
struct stat statbuf;
int realmode=0;
if (stat(name,&statbuf) == -1) return -1;
/* check read permission */
if ((mode & R_OK) && !(statbuf.st_mode & S_IREAD)) return -1;
/* check write permission */
if ((mode & W_OK) && !(statbuf.st_mode & S_IWRITE)) return -1;
/*
* Check execute mode. Assume directories have execute permission
* for GS/OS.
*/
if (mode & X_OK) {
if (statbuf.st_mode & (S_IFDIR | S_IEXEC)) return 0;
else return -1;
}
return 0; /* file merely exists */
}
/*
* chdir -- Replacement for the one normally shipping with Gno.
* Returns -1 and sets errno on failure, instead of always
* returning zero.
*/
int chdir (const char *pathname) {
PrefixRecGS record;
struct stat statbuf;
int result;
errno = 0;
if (stat(pathname,&statbuf) == -1) return -1;
/* verify that it's a directory */
if (!(statbuf.st_mode & S_IFDIR)) {
errno = ENOTDIR;
return -1;
}
/* change directory */
record.pCount = 2;
record.prefixNum = 0; /* prefix 0 is the current directory */
record.buffer.setPrefix = __C2GSMALLOC(pathname);
if (record.buffer.setPrefix == (GSString255Ptr) NULL) {
errno = ENOMEM;
return -1;
}
SetPrefixGS(&record);
/* verify success, clean up, and return */
result = toolerror();
free(record.buffer.setPrefix);
if (result) {
errno = EINVAL;
return -1;
}
return 0;
}
/*
* getFileType -- Get the file type and auxillary file type of a file.
* On success it returns a pointer to an internal buffer
* containing the file type and aux type. On failure
* it returns NULL and sets errno.
*/
fileType *getFileType (char *file) {
static FileInfoRecGS record;
static fileType result;
int i;
/* set the parameters */
record.pCount = 4;
if ((record.pathname = __C2GSMALLOC(file)) == NULL) {
errno = ENOMEM;
return NULL;
}
/* get the info */
GetFileInfoGS(&record);
/* check for errors */
i = toolerror();
free(record.pathname);
if (i) {
errno = _mapErr(i);
return NULL;
}
/* set the return value */
result.type = record.fileType;
result.auxtype = record.auxType;
return &result;
}
#if 0
#include <stdio.h>
int main(int argc, char **argv) {
char *p;
char buf[1024];
int i;
fileType *ft;
if (argc!=2) return -1;
ft = getFileType(argv[1]);
if (ft == NULL) {
perror(argv[1]);
exit(1);
} else {
printf("type = %x\nauxtype = %lx\n",ft->type,ft->auxtype);
}
return 0;
}
printf("F_OK: %d\n",access(argv[1],F_OK));
printf("R_OK: %d\n",access(argv[1],R_OK));
printf("W_OK: %d\n",access(argv[1],W_OK));
printf("X_OK: %d\n",access(argv[1],X_OK));
if (getwd(buf) == NULL) {
perror("getwd failed");
exit(-1);
}
printf("old directory: %s\n",buf);
if ((i = chdir(argv[1])) !=0) perror ("chdir failed");
printf("chdir returned %d\n",i);
if (getwd(buf) == NULL) {
perror("getwd failed");
exit(-1);
}
printf("new directory: %s\n",buf);
return 0;
}
#endif /* 0 */

View File

@ -1,187 +0,0 @@
.\" This man page is based on another man page copyright (c) 1980
.\" by the Regents of the University of California.
.\" All rights reserved. The Berkeley software License Agreement
.\" specifies the terms and conditions for redistribution.
.\"
.\" While this manual page is based on one from UCB, the included
.\" C source, makefile, and executables are copyright (c) 1995
.\" by Devin Reade <gdr@myrias.com>. All rights reserved.
.\"
.TH WHATIS 1 "Commands and Applications" "24 July 95" "Version 3.0"
.SH NAME
whatis, apropos \- locate commands by name or keyword lookup
.SH SYNOPSIS
.BR apropos
[[
.BI \-M path
] | [
.BI \-m path
]] [
.BR -nV
]
.IR keyword " ..."
.br
.BR whatis
[[
.BI \-M path
] | [
.BI \-m path
]] [
.BR -nV
]
.IR keyword ...
.SH DESCRIPTION
.BR whatis
shows the manual page title line for the specified
.IR keyword (s),
while
.BR apropos
shows which manual pages contain instances of any of the given
.IR keyword (s)
in their title line.
Each word is considered separately and, for
.BR apropos ,
the case of letters is ignored.
Words which are part of other words are considered; when looking for
.IR compile ,
.BR apropos
will also list all instances of
.IR compiler .
.LP
If a line output by either of these commands starts with
.nf
\fIname\fR (\fIsection\fR) ...
.fi
you can enter
.BI man " section name"
to get its documentation.
.SH OPTIONS
.IP "\fB\-M\fP \fIpath\fP"
Override the list of standard directories
.BR apropos
or
.BR whatis
search for the
.BR whatis
database.
The supplied
.I path
must be a colon\- or space\-delimited list of directories.
This search path may also be set using the environment variable
.BR MANPATH .
The space delimiter is provided for compatibility with GS/OS's
use of the colon as a pathname component delimiter. If the search
path contains no spaces nor
.B /
characters (such as
.BR :usr:local:man ),
it is assumed to be a single path, not a list of paths.
If spaces are used as delimiters, remember to quote them from the
shell.
.IP "\fB\-m\fP \fIpath\fP"
Augment the list of standard directories
.BR apropos
or
.BR whatis
search for its database.
The supplied
.I path
must be a colon\- or space\-delimited list of directories.
These directories will be searched after the standard directories
or the directories supplied by the
.BR MANPATH
environment variable are searched.
If spaces are used as delimiters, remember to quote them from the
shell.
.IP \fB-n\fP
Normally, in addition to searching the various
.BR whatis
databases,
.BR apropos
and
.BR whatis
will also search the Orca shell
.BR 15/syscmnd
file. Specifying the
.BR -n
flag will keep
.BR apropos
and
.BR whatis
from searching this file.
.IP \fB-V\fP
Show version information.
.SH ENVIRONMENT
.IP \fBMANPATH\fP
If set,
its value overrides
.B /usr/man
as the list of directories where
.BR apropos
and
.BR whatis
search for their databases.
(The
.B \-M
flag, in turn, overrides this value.)
See the description of the
.B \-M
flag for syntax details.
.IP \fBUSRMAN\fP
If
.B MANPATH
is not set, then the value of
.B USRMAN
(if set) overrides
.B /usr/man
as the list of directories where
.BR apropos
and
.BR whatis
search for their databases.
(The
.B \-M
flag, in turn, overrides this value.)
See the description of the
.B \-M
flag for syntax details.
.IP \fBMANDIR\fP
If neither
.B MANPATH
nor
.B USRMAN
is set, then the value of
.B MANDIR
(if set) overrides
.B /usr/man
as the list of directories where
.BR apropos
and
.BR whatis
search for their databases.
(The
.B \-M
flag, in turn, overrides this value.)
See the description of the
.B \-M
flag for syntax details.
.SH FILES
.\" .IP \fB/usr/\fR[\fBshare/\fR]\fBman/whatis\fR
.BR /usr/ [ share/ ] man/whatis " \-"
The
.BR whatis (1)
database.
.SH BUGS
Please report any bugs to Devin Reade, <gdr@myrias.ab.ca>.
.SH SEE ALSO
.BR man (1),
.BR whereis (1),
.BR catman (8),
.BR makewhatis (8)
.SH HISTORY
The GNO version of
.BR apropos
first appeared in GNO version 1.0 and was written by Mike Horwath.
This version was rewritten from scratch by Devin Reade.

View File

@ -1,110 +0,0 @@
/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "apropos___";
#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <libc.h>
#include "util.h"
#include "man.h"
extern int optind;
extern char *optarg;
static char *versionstr = "3.0";
static char *nothing = "nothing appropriate";
extern void begin_stack_check(void);
extern int end_stack_check(void);
int main (int argc, char **argv) {
char *path;
int i, matches1, matches2, matches3;
short V_flag, M_flag, m_flag, n_flag, err_flag;
/* make sure Gno is running */
if (needsgno()==0) {
fprintf(stderr,"Requires Gno/ME\n");
return 1;
}
#ifdef STACK_CHECK
begin_stack_check();
#endif
/* initialization */
V_flag = M_flag = m_flag = n_flag = err_flag = 0;
matches1 = matches2 = matches3 = 0;
/* parse command line and check usage */
while((i = getopt(argc,argv,"M:m:nV")) != EOF) {
switch(i) {
case 'M':
if (m_flag) err_flag++;
M_flag++;
path = optarg;
break;
case 'm':
if (M_flag) err_flag++;
m_flag++;
path = optarg;
break;
case 'n':
n_flag++;
break;
case 'V':
V_flag++;
break;
default:
err_flag++;
}
}
if (argc-optind < 1) err_flag++;
if (err_flag || V_flag) {
fprintf(stderr,"%s version %s by Devin Reade\n",
basename(argv[0]),versionstr);
}
if (err_flag) {
fprintf(stderr,
"Usage: %s [[-M path] | [-m path]] [-nV] keyword [keyword ...]\n",
basename(argv[0]));
return 1;
}
/* do the search */
if (M_flag) {
manpath = path;
} else {
manpath = getManpath();
}
matches1 = apropos(argc-optind, &argv[optind], WHATIS_MODE);
if (!M_flag) free(manpath);
if (m_flag) {
manpath = path;
matches2 = apropos(argc-optind, &argv[optind], WHATIS_MODE);
}
if (!n_flag) {
matches3 = apropos(argc-optind, &argv[optind], ORCA_W_MODE);
}
i = 0;
if (matches1>0) i+= matches1;
if ( m_flag && matches2>0) i+=matches2;
if (!n_flag && matches3>0) i+=matches3;
if (i==0) {
fprintf(stderr,"%s: %s\n",basename(argv[0]),nothing);
}
#ifdef STACK_CHECK
fprintf(stderr,"stack usage: %d bytes\n",end_stack_check());
#endif
if ((matches1>=0) && (matches2>=0) && (matches3>=0) && i>0) return 0;
return 1;
}

View File

@ -1,62 +0,0 @@
whereis v1.1 (Gno)
============
INSTALLATION
============
If you have Gno and dmake, type "dmake install". Otherwise:
FILE: COPY TO:
Gno: Orca/whereis 17/whereis [if desired]
Gno/whereis /usr/bin/whereis
whereis.1 $(USRMAN)/man1/whereis.1
Orca: Orca/whereis 17/whereis
whereis.cat 17/help/whereis
=====
NOTES
=====
Whereis is VERY dependant on pathnames.
This archive consist of both Orca shell and Gno versions. Both versions
will work with both shells, the difference being that in the Gno version
the leading "31" has been stripped from pathnames. (It is no longer needed
because of namespace.)
I strongly recommend _not_ using the Gno version with the Orca shell unless
you have actual partitions named "/usr", "/bin", "/etc", and so on, as you
will get _many_ accesses to all online devices in this case.
A -V flag and rVersion resource have been added to show version information.
A -c flag has been added to provide case-insensitive searches.
The source is released because it is small, and you can change the pathnames
if you wish.
=======
HISTORY
=======
v1.1: Rewritten to take advantage of Gno 2.x's namespace feature.
Separate Gno and Orca versions created.
Prototyped.
Disabled references to the /man volume (both versions).
Fixed up man page.
Added -V flag to show version information.
Added -c flag to force case-insensitive searches.
Added "17" to list of directories to search for binaries.
Added "17/help" to list of directories to search for man pages.
v1.0: Initial release.
=======
AUTHORS
=======
Author of the original original port from BSD to Gno is unknown. (Jawaid?)
v1.1 updated by G. Devin Reade <glyn@cs.ualberta.ca>

View File

@ -1,39 +0,0 @@
# Makefile.mk generated by makedmake (Gno) v1.1.1 for Dennis Vadura's dmake
BINDIR = 17
MANDIR = /usr/man
# development flags
# DEFINES += -DDEBUG -DCASEFLAG
# CFLAGS += -w -s1023 -G25 $(DEFINES)
# LDFLAGS +=
# LDLIBS = /usr/lib/stack.a
# distribution flags
DEFINES += -DCASEFLAG
CFLAGS += -w -s1023 -O $(DEFINES)
LDFLAGS +=
LDLIBS =
all:
echo Targets ...
echo
echo dmake install ... to copy executable file to $(BINDIR) and manual
echo page to $(MANDIR)
echo
echo dmake whereis ... to compile source code. This should not be
echo necessary.
whereis : whereis.o
$(CC) $(LDFLAGS) -o whereis whereis.o $(LDLIBS)
whereis.o : whereis.c
$(CC) $(CFLAGS) -c whereis.c
install :
-$(RM) /usr/bin/whereis
-$(RM) 17/whereis
/bin/cp -f whereis $(BINDIR)
/bin/cp -f whereis.1 $(MANDIR)/man1
.SILENT: all

View File

@ -1,133 +0,0 @@
.\" @(#)whereis.1 1.17 90/02/15 SMI; from UCB 4.2
.TH WHEREIS 1 "Commands and Applications" "2 January 1994" "Orca/Gno Version 1.1"
.SH NAME
whereis \- locate the binary, source, and manual page files for a command
.SH SYNOPSIS
.B whereis
[
.B \-bcmsuV
] [
.B \-BMS
.IR directory .\|.\|.
.B \-f
]
\fIfilename\fP\|
.SH DESCRIPTION
.B whereis
locates source/binary and manuals sections for specified
files.
The supplied names are first stripped of leading pathname components
and any (single) trailing extension of the form
.BR .ext ,
for example,
.BR .c .
Prefixes of
.B s.
resulting from use of source code control are also dealt with.
.B whereis
then attempts to locate the desired program in
a list of standard places:
.RS
.nf
/bin
/usr/bin
/usr/sbin
/usr/games
/usr/include
/usr/hosts
/usr/local
/usr/local/bin
/etc
/man (disabled)
/usr/man
/usr/src/bin
/usr/src/etc
17/
17/help
.fi
.RE
.SH OPTIONS
.B \-b
Search only for binaries.
.LP
.B \-c
Make the search case\-insensitive.
.LP
.B \-f
Terminate the last directory list and signals the start of file names,
and
.I must
be used when any of the
.BR \-B ,
.BR \-M ,
or
.B \-S
options are used.
.LP
.B \-m
Search only for manual sections.
.LP
.B \-s
Search only for sources.
.LP
.B \-u
Search for unusual entries. A file is said to be unusual if it does
not have one entry of each requested type. Therefore
.B "whereis -m -u *"
asks for those files in the current
directory which have no documentation.
.LP
.B \-B
Change or otherwise limit the places where
.B whereis
searches for binaries.
.LP
.B \-M
Change or otherwise limit the places where
.B whereis
searches for
manual sections.
.LP
.B \-S
Change or otherwise limit the places where
.B whereis
searches for sources.
.LP
.B \-V
Print version information.
.SH EXAMPLE
Find all files in
.B /usr/bin
which are not documented
in
.B /usr/share/man/man1
with source in
.BR /usr/src/cmd :
.RS
.nf
example% cd /usr/ucb
example% whereis \-u \-M /usr/share/man/man1 \-S /usr/src/cmd \-f *
.fi
.RE
.SH FILES
.nf
/usr/src/*
/usr/{doc,man}/*
/usr/{lib,bin,ucb,old,new,local}
/etc
.fi
.SH SEE ALSO
.BR chdir (2V)
.SH BUGS
Since
.B whereis
uses
.BR chdir (2V)
to run faster, pathnames given with the
.BR \-M ,
.BR \-S ,
or
.B \-B
must be full; that is, they must begin with a
.BR / .

View File

@ -1,528 +0,0 @@
#ifdef __CCFRONT__
#include <14:pragma.h>
#endif
/*-
* Copyright (c) 1980 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980 The Regents of the University of California.\n\
All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)whereis.c 5.5 (Berkeley) 4/18/91";
#endif /* not lint */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <ctype.h>
#include <libc.h>
/*
* Pointers that will correspond to the GNO_* or ORCA_* structs, below
*/
static char **bindirs;
static char **mandirs;
static char **srcdirs;
/*
* These are the directories to check when running under the Gno shell
*/
static char *GNO_bindirs[] = {
"/bin",
"/usr/bin",
"/usr/sbin",
"/usr/games",
"/usr/include",
"/usr/hosts",
"/usr/local",
"/usr/local/bin",
"17",
"/etc",
0
};
/* This needs to be redone - man pages live with sources */
static char *GNO_mandirs[] = {
/*
These are disabled since /man is not usually present; this eliminates
a long series of accesses to the 3.5" drive.
"/man/man1",
"/man/man2",
"/man/man3",
"/man/man4",
"/man/man5",
"/man/man6",
"/man/man7",
"/man/man8",
"/man/cat1",
"/man/cat2",
"/man/cat3",
"/man/cat4",
"/man/cat5",
"/man/cat6",
"/man/cat7",
"/man/cat8",
*/
"/usr/man/cat1",
"/usr/man/cat2",
"/usr/man/cat3",
"/usr/man/cat4",
"/usr/man/cat5",
"/usr/man/cat6",
"/usr/man/cat7",
"/usr/man/cat8",
"/usr/man/man1",
"/usr/man/man2",
"/usr/man/man3",
"/usr/man/man4",
"/usr/man/man5",
"/usr/man/man6",
"/usr/man/man7",
"/usr/man/man8",
"17/help",
0
};
static char *GNO_srcdirs[] = {
"/usr/src/bin",
"/usr/src/etc",
/* still need libs */
0
};
/*
* These are the directories to check when running under the Orca shell
*/
static char *ORCA_bindirs[] = {
"31/bin",
"31/usr/bin",
"31/usr/sbin",
"31/usr/games",
"31/usr/include",
"31/usr/hosts",
"31/usr/local",
"31/usr/local/bin",
"17",
"31/etc",
0
};
/* This needs to be redone - man pages live with sources */
static char *ORCA_mandirs[] = {
/*
These are disabled since /man is not usually present; this eliminates
a long series of accesses to the 3.5" drive.
"31/man/man1",
"31/man/man2",
"31/man/man3",
"31/man/man4",
"31/man/man5",
"31/man/man6",
"31/man/man7",
"31/man/man8",
"31/man/cat1",
"31/man/cat2",
"31/man/cat3",
"31/man/cat4",
"31/man/cat5",
"31/man/cat6",
"31/man/cat7",
"31/man/cat8",
*/
"31/usr/man/cat1",
"31/usr/man/cat2",
"31/usr/man/cat3",
"31/usr/man/cat4",
"31/usr/man/cat5",
"31/usr/man/cat6",
"31/usr/man/cat7",
"31/usr/man/cat8",
"31/usr/man/man1",
"31/usr/man/man2",
"31/usr/man/man3",
"31/usr/man/man4",
"31/usr/man/man5",
"31/usr/man/man6",
"31/usr/man/man7",
"31/usr/man/man8",
"17/help",
0
};
static char *ORCA_srcdirs[] = {
"31/usr/src/bin",
"31/usr/src/etc",
/* still need libs */
0
};
#ifdef CASEFLAG
int cflag = 0;
#endif
char sflag = 1;
char bflag = 1;
char mflag = 1;
char **Sflag;
int Scnt;
char **Bflag;
int Bcnt;
char **Mflag;
int Mcnt;
char uflag;
char *verstring = "whereis -- Apple IIgs Version 1.2";
void getlist (int *argcp, char ***argvp, char ***flagp, int *cntp);
void zerof(void);
void lookup (register char *cp);
void looksrc (char *cp);
void lookbin (char *cp);
void lookman (char *cp);
void findv (char **dirv, int dirc, char *cp);
void find (char **dirs, char *cp);
void findin (char *dir, char *cp);
int itsit (register char *cp, register char *dp);
#ifdef DEBUG
void begin_stack_check(void);
int end_stack_check(void);
#endif
/*
* whereis name
* look for source, documentation and binaries
*/
int main(int argc, char **argv)
{
#ifdef DEBUG
begin_stack_check();
#endif
argc--, argv++;
if (argc == 0) {
usage:
#ifdef CASEFLAG
fprintf(stderr, "whereis [ -sbmucV ] [ -SBM dir ... -f ] name...\n");
#else /* not CASEFLAG */
fprintf(stderr, "whereis [ -sbmuV ] [ -SBM dir ... -f ] name...\n");
#endif
#ifdef DEBUG
if (getenv("CHECKSTACK"))
printf("Stack Usage: %d\n",end_stack_check());
#endif
exit(1);
}
/* select which directory structures we're going to use */
if (needsgno()) {
bindirs = GNO_bindirs;
mandirs = GNO_mandirs;
srcdirs = GNO_srcdirs;
} else {
bindirs = ORCA_bindirs;
mandirs = ORCA_mandirs;
srcdirs = ORCA_srcdirs;
}
do
if (argv[0][0] == '-') {
register char *cp = argv[0] + 1;
while (*cp) switch (*cp++) {
case 'f':
break;
case 'S':
getlist(&argc, &argv, &Sflag, &Scnt);
break;
case 'B':
getlist(&argc, &argv, &Bflag, &Bcnt);
break;
case 'M':
getlist(&argc, &argv, &Mflag, &Mcnt);
break;
case 's':
zerof();
sflag++;
continue;
case 'u':
uflag++;
continue;
case 'b':
zerof();
bflag++;
continue;
case 'm':
zerof();
mflag++;
continue;
#ifdef CASEFLAG
case 'c':
cflag++;
continue;
#endif /* not CASEFLAG */
case 'V':
printf("%s\n",verstring);
continue;
default:
goto usage;
}
argv++;
} else
lookup(*argv++);
while (--argc > 0);
#ifdef DEBUG
if (getenv("CHECKSTACK"))
printf("Stack Usage: %d\n",end_stack_check());
#endif
exit(0);
}
void getlist (int *argcp, char ***argvp, char ***flagp, int *cntp) {
(*argvp)++;
*flagp = *argvp;
*cntp = 0;
for ((*argcp)--; *argcp > 0 && (*argvp)[0][0] != '-'; (*argcp)--)
(*cntp)++, (*argvp)++;
(*argcp)++;
(*argvp)--;
}
void zerof (void) {
if (sflag && bflag && mflag)
sflag = bflag = mflag = 0;
}
int count;
int print;
void lookup (register char *cp) {
register char *dp;
for (dp = cp; *dp; dp++)
continue;
for (; dp > cp; dp--) {
if (*dp == '.') {
*dp = 0;
break;
}
}
for (dp = cp; *dp; dp++)
if (*dp == '/')
cp = dp + 1;
if (uflag) {
print = 0;
count = 0;
} else
print = 1;
again:
if (print)
printf("%s:", cp);
if (sflag) {
looksrc(cp);
if (uflag && print == 0 && count != 1) {
print = 1;
goto again;
}
}
count = 0;
if (bflag) {
lookbin(cp);
if (uflag && print == 0 && count != 1) {
print = 1;
goto again;
}
}
count = 0;
if (mflag) {
lookman(cp);
if (uflag && print == 0 && count != 1) {
print = 1;
goto again;
}
}
if (print)
printf("\n");
}
void looksrc (char *cp) {
if (Sflag == 0) {
find(srcdirs, cp);
} else
findv(Sflag, Scnt, cp);
}
void lookbin (char *cp) {
if (Bflag == 0)
find(bindirs, cp);
else
findv(Bflag, Bcnt, cp);
}
void lookman (char *cp) {
if (Mflag == 0) {
find(mandirs, cp);
} else
findv(Mflag, Mcnt, cp);
}
void findv (char **dirv, int dirc, char *cp) {
while (dirc > 0)
findin(*dirv++, cp), dirc--;
}
void find (char **dirs, char *cp) {
while (*dirs)
findin(*dirs++, cp);
}
void findin (char *dir, char *cp) {
DIR *dirp;
struct dirent *dp;
dirp = opendir(dir);
if (dirp == NULL)
return;
while ((dp = readdir(dirp)) != NULL) {
if (itsit(cp, dp->d_name)) {
count++;
if (print)
printf(" %s/%s", dir, dp->d_name);
}
}
closedir(dirp);
}
#ifdef CASEFLAG
int itsit (register char *cp, register char *dp) {
register int i = strlen(dp);
if (cflag) {
if ( (dp[0] == 's' || dp[0] == 'S') && dp[1] == '.' && itsit(cp, dp+2))
return (1);
while (*cp && *dp && (tolower(*cp) == tolower(*dp)))
cp++, dp++, i--;
if (*cp == 0 && *dp == 0)
return (1);
while (isdigit(*dp))
dp++;
if (*cp == 0 && *dp++ == '.') {
--i;
/* removed for GNO/ME, cause we want to look up compressed files also. */
/* while (i > 0 && *dp)
if (--i, *dp++ == '.')
return (*dp++ == 'C' && *dp++ == 0);
*/
return (1);
}
} else {
if (dp[0] == 's' && dp[1] == '.' && itsit(cp, dp+2))
return (1);
while (*cp && *dp && *cp == *dp)
cp++, dp++, i--;
if (*cp == 0 && *dp == 0)
return (1);
while (isdigit(*dp))
dp++;
if (*cp == 0 && *dp++ == '.') {
--i;
/* removed for GNO/ME, cause we want to look up compressed files also. */
/* while (i > 0 && *dp)
if (--i, *dp++ == '.')
return (*dp++ == 'C' && *dp++ == 0);
*/
return (1);
}
}
return (0);
}
#else /* not CASEFLAG */
int itsit (register char *cp, register char *dp) {
register int i = strlen(dp);
if (dp[0] == 's' && dp[1] == '.' && itsit(cp, dp+2))
return (1);
while (*cp && *dp && *cp == *dp)
cp++, dp++, i--;
if (*cp == 0 && *dp == 0)
return (1);
while (isdigit(*dp))
dp++;
if (*cp == 0 && *dp++ == '.') {
--i;
/* removed for GNO/ME, cause we want to look up compressed files also. */
/* while (i > 0 && *dp)
if (--i, *dp++ == '.')
return (*dp++ == 'C' && *dp++ == 0);*/
return (1);
}
return (0);
}
#endif

View File

@ -1,140 +0,0 @@
$Id: README,v 1.2 1996/01/22 02:40:43 gdr Exp $
This is the README file for the describe package. This package is
designated as version 1.0.2, and consists of the following utilities:
describe v1.0.2 - show database entries describing the current
status of programs
descc v1.0.2 - the describe source compiler
descu v1.0.2 - the describe source updater
ABOUT DESCRIBE AND DESCC
========================
This is yet another project I've been sitting on for a while, but have
finally decided to release. The basic idea of the 'describe' package
(the descc "compiler" and describe itself) is to provide a quick, easy
way of accessing information related to the utilities which so many
different people are releasing these days. The reason it sat around on
my harddrive so long is I was having qualms about its designated role in
life. I wasn't sure exactly what I wanted it to do. Well, I've decided
to KISS for now: descc simply compiles the utility list, which I maintain,
into a (very) simple "database" located in /usr/local/lib/
[alternatively, the full path given in the environment variable DESCDB will be
used, if it is set. sb]. The companion utility 'describe' is used to
fetch information about a particular utility from this "database".
descc is fairly limited, as is the "database" format itself. Part of the
KISS (or it wouldn't be out now) design philosophy ;). Usage is simple:
when you get a new listing (I'll provide monthly updates), simply "descc
<filename>" where <filename> is the name of the newly released update.
descc will simply write over the old database and replace it with the
new. (Note: No appendages are allowed by descc. See descu.)
As always, coments are appreciated. And, moreso than on other projects,
I'd appreciate some comments about the direction I'm going in, suggestions
as to where to take this, etc. I have a feeling that some fields in the
format (eg, FTP:) are rather useless, and I'd like to know what you guys
out there think.
James Brookes
jamesb@ecst.csuchico.edu
ABOUT DESCU
===========
I think describe and descc were really good ideas; they sure beat the
text file list of Gno utilities that James used to keep. The one major
shortfall I found was having to manually update the describe database
source every time I wanted to include a new entry.
I therefore wrote descu, the describe updater, which is also rather
limited due to following the KISS principle.
For completeness, I have also added the man pages describe.1, descc.8,
and descu.8. I briefly pondered having a describe.5, but alas I was too
lazy; you can find the file formats as part of descc.8.
Devin Reade
gdr@myrias.ab.ca
INSTALLATION
============
You can either type "dmake install", or do the following:
mkdir -p /usr/local/lib
cp ./describe /usr/local/bin
cp ./descc /usr/sbin
cp ./descu /usr/sbin
rm /usr/local/bin/descc
You will also want to do the following, which is NOT done by dmake's
install target:
rehash
descc ./describe.source
CHANGES
=======
This details changes to the entire distribution.
v1.02 October 1995
descc now circumvents a bug in ORCA/C's ftell() function.
describe can now find entries that are not all lower-case.
describe will now print the name of entries in the case
they were entered into the database.
descu now sorts the describe source file case-insensitive.
describe and descc can now find the database in a path given
by the environment variable DESCDB. If DESCDB is not set,
/usr/local/lib/describe is used, as before.
A new "Shell:" field has been added to the format of the database.
v1.01 May 1995
Initial release for descu.
Added -h and -v flags to describe and descc.
Common defines and typedefs were extracted to desc.h.
Descc now exits -1 on failure (vice 0).
In descc, some more error checking and flushing were added. Also,
mygets wasn't dereferencing one of its arguments properly.
Allocated stack size was increased from 512 to 768 bytes.
Describe and descc were modified not to be dependant on the size
of integers.
Ran source files through indent(1).
v1.0 Feb 1994
Initial release for describe and descc.
AUTHORS
=======
The original describe and descc utilities and the describe format were
written by James Brookes <jamesb@ecst.csuchico.edu>.
The descu utility and v1.01 modifications to describe and descc were by
Devin Reade <gdr@myrias.ab.ca>.
v1.02 modifications to describe, descc and descu were by Soenke Behrens
<sbehrens@contech.demon.co.uk>.
LEGALESE
========
The describe and descc utilities are copyright (c) 1994-1995 by James
Brookes. The descu utility is copyright (c) 1995 by Devin Reade.
These programs may be freely copied provided that the archive, including
source files and this README, remain intact. Modified versions of these
programs may not be distributed without the permission of the respective
authors.
Contact the respective authors for permission to include these programs on
any commercial software collections. Permission is granted to Usenet sites
and GEnie Information Services for inclusion in software archives.
The Apple IIGS executable files distributed with this archive contain
material from the ORCA/C Run-Time Libraries, copyright 1987-1995 by
Byte Works, Inc. Used with permission.

View File

@ -0,0 +1,20 @@
About Me
~~~~~~~~~
Um. Not much to say right now. I'll get back to this part later.
About My Source
~~~~~~~~~~~~~~~
I guess I used to feel a bit propriatary about it, but a couple of things
have caused me to change my mind:
1) Losing over half of the eps source, may it rest in peace.
2) Yes, people can profit by and sometimes even improve (gasp!) my
source. And I'd be a grumpy old coot if I didn't let them.
So what this means is that most (not all) of my stuff will be released
with full source from now henceforth. I only ask of you, the humble masses
yearning to be free, please don't distribute modified versions of my programs
without first contacting me. I think this is only fair.
James Brookes
jamesb@ecst.csuchico.edu

View File

@ -1,30 +0,0 @@
#pragma optimize -1
#include <string.h>
#include <stdio.h>
#include <unistd.h>
char *basename (char *name) {
char *p, brk;
/* checking for ':' is GS-specific */
brk = (strchr(name,':')) ? ':' : '/';
p = strrchr(name,brk);
return ((p) ? p+1 : name);
}
#ifdef SHELLCOMD
int main (int argc, char **argv) {
if (argc != 2) {
fprintf(stderr,"Usage: basename file_name\nVersion 1.0\n");
return -1;
}
printf("%s\n",basename(argv[1]));
return 0;
}
#endif /* SHELLCOMD */

View File

@ -1,54 +0,0 @@
/*
* Header file for the describe package. This file is
* used by describe(1), descc(8), and descu(8).
*/
#define QUOTE_CHAR '#'
#define DATABASE "/usr/local/lib/describe"
#define FIELD_LEN 9
#define NAME_LEN 34
#define MAX_LINE_LENGTH 81
#define FIELD_COUNT 7 /* number of fields below, not including comments */
#define NAME "Name: "
#define VERSION "Version: "
#define SHELL "Shell: "
#define AUTHOR "Author: "
#define CONTACT "Contact: "
#define WHERE "Where: "
#define FTP "FTP: "
#define NAME_SHORT "Name:"
#define VERSION_SHORT "Version:"
#define SHELL_SHORT "Shell:"
#define AUTHOR_SHORT "Author:"
#define CONTACT_SHORT "Contact:"
#define WHERE_SHORT "Where:"
#define FTP_SHORT "FTP:"
#ifndef FALSE
# define FALSE 0
# define TRUE 1
#endif
typedef short int2;
typedef long int4;
typedef struct nameEntry_tag {
char name[NAME_LEN];
long int offset;
} nameEntry;
typedef struct descEntryTag {
char *name;
char *data;
} descEntry;
extern int optind;
extern char *optarg;
/* extern int getopt_restart(void); */
extern void begin_stack_check(void);
extern int end_stack_check(void);
extern char *basename(char *);

View File

@ -1,97 +0,0 @@
.TH DESCC 8 "System Administration" "7 May 1995" "Version 1.0.2"
.SH NAME
descc \- the describe(1) source compiler
.SH SYNOPSIS
.BR descc " [" -hV ]
.I sourcefile
.SH DESCRIPTION
.BR descc
compiles the describe source file
.I sourcefile
and saves the result to the system describe database.
.SH OPTIONS
.nf
\fB-h\fR Show usage information.
\fB-V\fR Show version information.
.fi
.SH "FILE FORMATS"
The describe source file consists of comments and records. A comment
is any line starting with the
.BR #
character. Each record consists of eight fields. The first
seven consist of one line of text and begin with the following identifiers:
.nf
Name: (The name of the program.)
Version: (The current version number.)
Shell: (The shell(s) the program was written for.)
Author: (The author or maintainer of the program.)
Contact: (How to contact the Author, typically an
email address.)
Where: (Where the program should be installed.)
FTP: (An ftp site from which the program may be
obtained.)
.fi
The last field consists of multiple lines of text. It should be
a brief description of the program. The following is an example of
a complete record:
.nf
Name: describe
Version: 1.0.2
Shell: ORCA/Shell, GNO/ME
Author: James Brookes
Contact: jamesb@ecst.csuchico.edu
Where: /usr/local/bin
FTP: ftp.cco.caltech.edu
Print a multi-line description obtained from the compiled
'describe' database; giving utility name, version, intended shell,
author, author's contact, where the utility is, as well as where the
utility can be FTPd from on the InterNet.
.fi
.LP
The describe database file consists of a
.BR Header ,
a set of
.BR "Name Entries" ,
and a set of
.BR Records ,
in the following format:
.nf
Header
2 bytes: Short Int, number of \fBName Entries\fR
Name Entries
34 bytes: NULL-terminated string; name of the utility.
4 bytes: Long Int, offset of the \fBrecord\fR in file.
Records
8 variable-length NULL-terminated strings.
.fi
.SH FILES
/usr/local/lib/describe \- the system
.B describe
database. If the environment variable
.B DESCDB
is set, its value will be used instead.
.SH ENVIRONMENT
.IP DESCDB
Full path to the system describe database. If
.B DESCDB
is set, its value is used instead of the default location
/usr/local/lib/describe.
.SH AUTHOR
James Brookes <jamesb@ecst.csuchico.edu>.
.SH "SEE ALSO"
.BR apropos (1),
.BR describe (1),
.BR man (1),
.BR whatis (1),
.BR descu (8).

View File

@ -1,15 +1,15 @@
#ifndef _ORCAC_
#define _ORCAC_
#endif
#ifdef _ORCAC_
#pragma optimize -1
#pragma stacksize 512
#endif /* _ORCAC_ */
/* */
/* descc - compile info file into describe database file */
/* */
/* v1.0.2 - One bug removed. Recompiled to accomodate new */
/* SHELL line and DESCDB environment var */
/* Soenke Behrens [Sun Oct 22 1995] */
/* */
/* v1.0.1 - Added -h and -V flags [Sat May 06 1995] */
/* Extracted certain #defines to "desc.h" */
/* Now uses getopt for command line parsing. */
/* Fixed some potential bugs. */
/* */
/* v1.0.0 - James Brookes [Sat Oct 23 1993] */
/* released [Thu Mar 31 1994] [!!!!!!!!!!!] */
/* */
@ -30,248 +30,202 @@
/* */
/* Records */
/* */
/* 8 variable-length Null-terminated strings. */
/* 7 variable-length Null-terminated strings. */
/* */
#pragma optimize 15
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <assert.h>
#include "desc.h"
#define _VERSION_ "v1.0.2"
#pragma lint -1
/* prototypes */
void usage(char *callname);
void version(char *callname);
void puke(int error,int lines);
int mygets(char *buffer, int2 *lines, FILE *FInPtr);
int mygets(char *buffer, int *lines, FILE *FInPtr);
int Vflag;
/* defines */
/* version - print it out */
typedef struct nameEntry_tag
void version (char *callname) {
Vflag++;
fprintf(stderr,"%s version %s\n",callname,_VERSION_);
return;
}
{
char name[34];
long int offset;
}nameEntry;
#define _VERSION_ "v1.0.0"
#define QUOTE_CHAR '#'
#define OUTFILE "/usr/local/lib/describe"
#define FIELD_LEN 9
#define NAME "Name: "
#define VERSION "Version: "
#define AUTHOR "Author: "
#define CONTACT "Contact: "
#define WHERE "Where: "
#define FTP "FTP: "
/* */
/* usage - you know what to do */
/* */
void usage (char *callname) {
if (!Vflag) version(callname);
fprintf(stderr,"usage: %s [-hV] <describe_sourcefile>\n",callname);
exit(-1);
}
void usage (char *callname)
{
fprintf(stderr,"%s %s\n",callname,_VERSION_);
fprintf(stderr,"usage: %s <describe sourcefile>\n",callname);
exit(0);
}
/* */
/* puke - stdlib errors */
/* */
void puke (int error,int lines) {
fprintf(stderr,"\nError $%x in line %d of script\n",error,lines);
fflush(stdout);
exit(error);
}
void puke (int error,int lines)
{
fprintf(stderr,"\nError $%x in line %d of script\n",error,lines);
fflush(stdout);
exit(error);
}
/* */
/* mygets - get a line (skipping commented lines) and increment line count */
/* */
int mygets (char *buffer, int2 *lines, FILE *FInPtr) {
char *p, c;
int mygets (char *buffer, int *lines, FILE *FInPtr)
do {
if (fgets(buffer,MAX_LINE_LENGTH,FInPtr)==NULL) {
return(-1);
}
p = buffer + strlen(buffer) - 1; /* remove trailing \n */
if (*p == '\n') {
*p = '\0';
} else {
fprintf(stderr,"Line %d exceeds %d characters. Remainder ignored.\n",
*lines,MAX_LINE_LENGTH-1);
do {
c = fgetc(FInPtr);
} while ((c!='\n') && !feof(FInPtr));
}
(*lines)++;
} while(buffer[0] == QUOTE_CHAR || buffer[0] == '\n');
return(0);
}
{
int i;
do
{
if (fgets(buffer,80,FInPtr)==NULL)
return(-1);
buffer[strlen(buffer)-1] = '\0'; /* remove trailing \n */
lines++;
}
while(buffer[0] == QUOTE_CHAR || buffer[0] == '\n');
return(0);
}
/* */
/* Mainline */
/* */
int main (int argc, char **argv) {
FILE *FInPtr, *FOutPtr;
long int *record_locs, currLoc, endOfFile;
char *buffer;
int2 lines, namecount, i, j;
nameEntry nameStruct;
int c, errflag;
char *db_path;
int main (int argc, char **argv)
/* initialize globals */
Vflag=0;
errflag=0;
#ifdef STACK_CHECK
begin_stack_check();
#endif
{
FILE *FInPtr, *FOutPtr;
long int *record_locs, currLoc, endOfFile;
char *tmpPtr, *buffer;
int lines, namecount, c, i, j;
nameEntry nameStruct;
assert(sizeof(int2)==2);
assert(sizeof(int4)==4);
if (argc != 2)
usage(argv[0]);
/* Get database path: If DESCDB is set, use it,
otherwise use DATABASE */
/* open input and output files */
if (getenv("DESCDB") == 0)
{
if ((db_path = strdup(DATABASE)) == 0)
{
fprintf(stderr,"couldn't allocate path variable\n");
exit (-1);
}
} else {
if ((db_path = strdup(getenv("DESCDB"))) == 0)
{
fprintf(stderr,"couldn't allocate path variable\n");
exit (-1);
}
}
/* parse command line */
while ((c = getopt(argc, argv, "hV")) != EOF) {
switch (c) {
case 'V':
version(basename(argv[0]));
break;
case 'h': /*FALLTHROUGH*/
default:
errflag++;
break;
}
}
if (errflag || (argc-optind != 1))
{
free (db_path);
usage(basename(argv[0]));
}
buffer = (char *) malloc (81);
if ((FInPtr = fopen(argv[1],"r")) == NULL)
{
fprintf(stderr,"Error opening %s; exiting.\n",argv[1]);
free(buffer);
exit(1);
}
/* open input and output files */
if ((FOutPtr = fopen(OUTFILE,"w+")) == NULL)
if ((buffer = malloc (MAX_LINE_LENGTH)) == NULL) {
fprintf(stderr,"couldn't allocate line buffer\n");
free (db_path);
exit (-1);
}
if ((FInPtr = fopen(argv[argc-1],"r")) == NULL) {
fprintf(stderr,"Error opening %s; exiting.\n",argv[argc-1]);
free (db_path);
free(buffer);
exit(1);
}
{
fprintf(stderr,"Error opening output file %s; exiting.\n",OUTFILE);
free(buffer);
exit(1);
}
if ((FOutPtr = fopen(db_path,"wb+")) == NULL) {
fprintf(stderr,"Error opening database file %s; exiting.\n",db_path);
free (db_path);
free(buffer);
exit(1);
}
/* Compile array of names */
/* Compile array of names */
lines = 0;
namecount = 0;
lines = 0;
namecount = 0;
fseek(FOutPtr,2,SEEK_CUR); /* space for # of array entries */
/* space for # of array entries */
fwrite((void *)&namecount,sizeof(namecount),1,FOutPtr);
while(mygets(buffer,&lines,FInPtr) != -1)
while(mygets(buffer,&lines,FInPtr) != -1) {
if (!strncmp(buffer,NAME,FIELD_LEN)) { /* found a match */
strncpy(nameStruct.name,&buffer[FIELD_LEN],NAME_LEN-1);
nameStruct.name[NAME_LEN-1] = '\0';
fwrite((void *)&nameStruct,sizeof(nameStruct),1,FOutPtr);
namecount++;
}
}
if ((record_locs = malloc (namecount*sizeof(long int)))==NULL) {
fprintf(stderr,"malloc of record_locs failed (%ld bytes); exiting\n",
(long) namecount*sizeof(long int));
exit(-1);
}
rewind(FInPtr);
buffer[0] = '\0';
lines = 0;
fputc('\t',FOutPtr);
/* Increment to first field */
while (strncmp(buffer,NAME,FIELD_LEN)) /* found a match! */
mygets(buffer,&lines,FInPtr);
{ /* BUGBUG 22/10/95 Soenke Behrens */
/* ORCA/C does not advance the file position indicator */
/* correctly after above fputc(). This tries to remedy */
/* the situation. Take out once library has been fixed */
fprintf(FOutPtr,"Junk");
fseek(FOutPtr,-4,SEEK_CUR);
}
/* Write out records and keep track of their file offsets */
for (i = 0; i < namecount; i++) {
record_locs[i] = ftell(FOutPtr);
/* print out <Version>, <Shell>, <Author>, <Contact>, <Where>, <FTP> */
for (j = 0; j < FIELD_COUNT-1; j++) {
buffer[FIELD_LEN] = '\0';
mygets(buffer,&lines,FInPtr);
fprintf(FOutPtr,"%s\n",&buffer[FIELD_LEN]);
}
{
if (!strncmp(buffer,NAME,FIELD_LEN)) /* found a match */
/* handle <description> field */
for (;;) {
if (mygets(buffer,&lines,FInPtr) == -1) break;
if (!strncmp(buffer,NAME,FIELD_LEN)) break;
fprintf(FOutPtr,"%s ",buffer);
}
fputc('\n',FOutPtr);
}
{
tmpPtr = &buffer[FIELD_LEN];
strcpy(nameStruct.name,tmpPtr);
fwrite(&nameStruct,sizeof(nameStruct),1,FOutPtr);
namecount++;
}
}
endOfFile = ftell(FOutPtr);
fflush(FOutPtr); /*gdr 1*/
rewind(FOutPtr);
fwrite((void *)&namecount,sizeof(namecount),1,FOutPtr);
fflush(FOutPtr); /*gdr 1*/
record_locs = (long int *) malloc (namecount*sizeof(long int));
rewind(FInPtr);
buffer[0] = '\0';
lines = 0;
fprintf(FOutPtr,"\t");
/* Increment to first field */
/* time to go through the record_locs array and backpatch in */
/* all the record locations. A little slower than necessary */
/* perhaps, but it gets the job done. */
while (strncmp(buffer,NAME,FIELD_LEN)) /* found a match! */
mygets(buffer,&lines,FInPtr);
for (i = 0; i < namecount; i++) {
fread(&nameStruct,sizeof(nameStruct),1,FOutPtr);
fseek(FOutPtr,-(sizeof(nameStruct)),SEEK_CUR);
nameStruct.offset = record_locs[i];
fwrite((void *)&nameStruct,sizeof(nameStruct),(size_t) 1,FOutPtr);
fflush(FOutPtr);
}
for (i = 0; i < namecount; i++)
fseek(FOutPtr,endOfFile,SEEK_SET);
fclose(FOutPtr);
free(db_path);
free(record_locs);
free(buffer);
{
record_locs[i] = ftell(FOutPtr);
for (j = 0; j < 5; j++) /* parse additional info */
#ifdef STACK_CHECK
fprintf(stderr,"stack usage: %d bytes\n",end_stack_check());
#endif
return 0;
}
{
mygets(buffer,&lines,FInPtr);
tmpPtr = &buffer[FIELD_LEN];
fprintf(FOutPtr,"%s\n",tmpPtr); /* print out fields */
}
/* handle comment field */
while (1)
{
if (mygets(buffer,&lines,FInPtr) == -1)
break;
if (!strncmp(buffer,NAME,FIELD_LEN)) /* until next field */
break;
fprintf(FOutPtr,"%s ",buffer);
}
fprintf(FOutPtr,"\n");
}
endOfFile = ftell(FOutPtr);
rewind(FOutPtr);
fwrite(&namecount,2,1,FOutPtr);
/* time to go through the record_locs array and backpatch in */
/* all the record locations. A little slower than necessary */
/* perhaps, but it gets the job done. */
for (i = 0; i < namecount; i++)
{
currLoc = ftell(FOutPtr);
fread(&nameStruct,sizeof(nameStruct),1,FOutPtr);
fseek(FOutPtr,-(sizeof(nameEntry)),SEEK_CUR);
nameStruct.offset = record_locs[i];
fwrite(&nameStruct,sizeof(nameStruct),1,FOutPtr);
}
fseek(FOutPtr,endOfFile,SEEK_SET);
fclose(FOutPtr);
free(record_locs);
free(buffer);
}

View File

@ -1,10 +0,0 @@
Name: descc
Version: 1.0.2
Shell: ORCA/Shell, GNO/ME
Author: James Brookes
Contact: jamesb@ecst.csuchico.edu
Where: /usr/sbin
FTP: ftp.cco.caltech.edu
Compile a source file into a 'describe' database file.

View File

@ -1,56 +0,0 @@
.TH DESCRIBE 1 "Commands and Applications" "7 May 1995" "Version 1.0.2"
.SH NAME
describe \- show information about a program
.SH SYNOPSIS
.BR describe " [" -hvV ]
.I program
.SH DESCRIPTION
.BR describe
will show current information about
.IR program .
This information includes:
.nf
The name of the program;
The program version number;
The shell the program was written for;
The author (or the person currently maintaining the program);
Contact information for the author;
Where the utility should be installed;
An FTP site from which the program may be obtained, and;
A brief description of the program.
.fi
.LP
.BR describe
uses a database compiled by
.BR descc (8).
.SH OPTIONS
.nf
\fB-h\fR Show usage information.
\fB-v\fR Verbose debugging mode.
\fB-V\fR Show version information.
.fi
.SH FILES
/usr/local/lib/describe \- the system
.B describe
database. If the environment variable
.B DESCDB
is set, its value will be used instead.
.SH ENVIRONMENT
.IP DESCDB
Full path to the system describe database. If
.B DESCDB
is set, its value is used instead of the default location
/usr/local/lib/describe.
.SH AUTHOR
James Brookes <jamesb@ecst.csuchico.edu>.
.SH "SEE ALSO"
.BR apropos (1),
.BR man (1),
.BR whatis (1),
.BR descc (8),
.BR descu (8).

View File

@ -1,22 +1,16 @@
/*
* describe(1) -- Copyright 1993-1995 James Brookes. See the README and
* man page for details.
*
* We have to have this pragma in here; Orca/C's bit 5 optimization
* (loop invariant removal) kills code somewhere in this file, resulting
* in a system panic.
*/
#pragma optimize 31
#pragma optimize 15
#pragma stacksize 512
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
#include "desc.h"
#define _VERSION_ "v1.0.2"
#pragma lint -1
#ifdef STACK_CHECK
void begin_stack_check(void);
int end_stack_check(void);
#endif
/* prototypes */
@ -24,214 +18,188 @@ void usage(char *callname);
void print_entry(FILE *FInPtr, long int index);
void myprintf(char *string, int wordwrap_size);
int Vflag;
/* defines */
void version (char *callname) {
Vflag++;
fprintf(stderr,"%s version %s\n",callname,_VERSION_);
return;
}
typedef struct nameEntry_tag
void usage(char *callname) {
if (!Vflag) version(callname);
fprintf(stderr,"usage: %s [-hv] <utility_name>\n",callname);
exit(-1);
}
{
char name[34];
long int offset;
}nameEntry;
void myprintf(char *string, int wordwrap_size) {
int length = 0;
char *headString, *tailString;
headString = tailString = string;
printf("\n");
while (1) {
tailString++; length++;
if (*tailString == '\0') {
printf("%s",headString);
return;
} else if (length == wordwrap_size) {
while (*tailString != ' ')
tailString--;
*tailString = '\0';
printf("%s\n",headString);
headString = tailString+1;
length = 0;
}
}
}
void print_entry(FILE *FInPtr, long int index) {
char *buffer;
int i;
if ((buffer = (char *) malloc (1024)) == 0)
{
fprintf(stderr,"couldn't allocate buffer\n");
exit (-1);
}
fseek(FInPtr,index,SEEK_SET);
printf("%s",VERSION);
fgets(buffer,MAX_LINE_LENGTH,FInPtr);
printf("%s",buffer);
printf("%s",SHELL);
fgets(buffer,MAX_LINE_LENGTH,FInPtr);
printf("%s",buffer);
printf("%s",AUTHOR);
fgets(buffer,MAX_LINE_LENGTH,FInPtr);
printf("%s",buffer);
printf("%s",CONTACT);
fgets(buffer,MAX_LINE_LENGTH,FInPtr);
printf("%s",buffer);
printf("%s",WHERE);
fgets(buffer,MAX_LINE_LENGTH,FInPtr);
printf("%s",buffer);
printf("%s",FTP);
fgets(buffer,MAX_LINE_LENGTH,FInPtr);
printf("%s",buffer);
fgets(buffer,1024,FInPtr);
myprintf(buffer,75);
free(buffer);
#ifdef STACK_CHECK
printf("Stack: %d\n",end_stack_check());
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
exit(0);
}
int main (int argc, char **argv) {
FILE *FInPtr;
char searchName[NAME_LEN];
int2 verbose, numOfEntries, cmp, offset1, offset2, check, i;
nameEntry nameStruct;
int c, errflag;
char *p, *tmp;
char *db_path;
#define _VERSION_ "v1.0"
#define INFILE "/usr/local/lib/describe"
#ifdef STACK_CHECK
begin_stack_check();
#endif
verbose = FALSE;
Vflag = FALSE;
errflag = FALSE;
#define NAME "Name: "
#define VERSION "Version: "
#define AUTHOR "Author: "
#define CONTACT "Contact: "
#define WHERE "Where: "
#define FTP "FTP: "
/* Get database path: If DESCDB is set, use it,
otherwise use DATABASE */
void usage(char *callname)
if (getenv("DESCDB") == 0)
{
if ((db_path = strdup(DATABASE)) == 0)
{
fprintf(stderr,"couldn't allocate path variable\n");
exit (-1);
}
} else {
if ((db_path = strdup(getenv("DESCDB"))) == 0)
{
fprintf(stderr,"couldn't allocate path variable\n");
exit (-1);
}
}
{
fprintf(stderr,"Describe %s\n",_VERSION_);
fprintf(stderr,"usage: %s -[v] <utilityname>\n",callname);
exit(0);
}
while ((c = getopt(argc,argv,"hvV")) != EOF) {
switch (c) {
case 'v':
verbose = TRUE;
break;
case 'V':
version(basename(argv[0]));
break;
case 'h':
default:
errflag = TRUE;
break;
}
}
if (errflag || (argc-optind != 1))
{
free (db_path);
usage(basename(argv[0]));
}
void myprintf(char *string, int wordwrap_size)
{
int length = 0;
char *headString, *tailString;
headString = tailString = string;
printf("\n");
while (1)
if ((FInPtr = fopen(db_path,"rb")) == NULL) {
perror("couldn't open database");
free (db_path);
exit(-1);
}
fread(&numOfEntries,2,1,FInPtr);
offset1 = 0;
offset2 = numOfEntries-1;
{
tailString++; length++;
if (*tailString == '\0')
strcpy(searchName,argv[optind]);
i=0;
p = searchName;
while (*p) {
*p = tolower(*p);
p++;
}
{
printf("%s",headString);
return;
}
if (verbose)
printf("Searching...\n");
else if (length == wordwrap_size)
while (1) {
check = ((offset2-offset1)/2) + offset1;
fseek(FInPtr,2+(check*sizeof(nameEntry)),SEEK_SET);
fread(&nameStruct,sizeof(nameEntry),1,FInPtr);
{
while (*tailString != ' ')
tailString--;
*tailString = '\0';
printf("%s\n",headString);
headString = tailString+1;
length = 0;
}
if((tmp = strdup(nameStruct.name)) == 0)
{
fprintf(stderr,"couldn't copy name string\n");
free (db_path);
exit (-1);
}
p = nameStruct.name;
while (*p) {
*p = tolower(*p);
p++;
}
cmp = strcmp(nameStruct.name,searchName);
if (verbose)
printf(" checked %s\n",tmp);
if (cmp > 0) { /* name bigger than searchName */
offset2 = check-1;
} else if (cmp < 0) { /* name smaller than searchName */
offset1 = check+1;
} else {
if (verbose) {
printf("Found entry %s!\n",tmp);
#ifdef STACK_CHECK
printf("Stack: %d\n",end_stack_check());
#endif
free (db_path);
free (tmp);
exit(0);
}
printf("%s%s\n",NAME,tmp);
free (db_path);
free (tmp);
print_entry(FInPtr,nameStruct.offset);
}
}
if (offset1 > offset2) {
printf("Entry '%s' not found in describe database.\n",searchName);
void print_entry(FILE *FInPtr, long int index)
{
char *buffer;
buffer = (char *) malloc (1024);
fseek(FInPtr,index,SEEK_SET);
printf("%s",VERSION);
fgets(buffer,80,FInPtr);
printf("%s",buffer);
printf("%s",AUTHOR);
fgets(buffer,80,FInPtr);
printf("%s",buffer);
printf("%s",CONTACT);
fgets(buffer,80,FInPtr);
printf("%s",buffer);
printf("%s",WHERE);
fgets(buffer,80,FInPtr);
printf("%s",buffer);
printf("%s",FTP);
fgets(buffer,80,FInPtr);
printf("%s",buffer);
fgets(buffer,1024,FInPtr);
myprintf(buffer,75);
free(buffer);
#ifdef STACK_CHECK
printf("Stack: %d\n",end_stack_check());
printf("Stack: %d\n",end_stack_check());
#endif
free (db_path);
free (tmp);
exit(1);
}
}
}
exit(0);
}
int main (int argc, char **argv)
{
FILE *FInPtr;
char searchName[34];
long int index;
int verbose, argind, numOfEntries, cmp, offset1, offset2, check, i;
nameEntry nameStruct;
#ifdef STACK_CHECK
begin_stack_check();
#endif
verbose = FALSE;
argind = 1;
if ((argc == 3) && (!strcmp(argv[1],"-v")))
{
verbose = TRUE;
argind++;
}
else if (argc != 2)
usage(argv[0]);
FInPtr = fopen(INFILE,"r");
fread(&numOfEntries,2,1,FInPtr);
offset1 = 0;
offset2 = numOfEntries-1;
strcpy(searchName,argv[argind]);
i=0;
while(searchName[i] = tolower(searchName[i++]));
if (verbose)
printf("Searching...\n");
while (1)
{
check = ((offset2-offset1)/2) + offset1;
fseek(FInPtr,2+(check*sizeof(nameEntry)),SEEK_SET);
fread(&nameStruct,sizeof(nameEntry),1,FInPtr);
cmp = strcmp(nameStruct.name,searchName);
if (verbose)
printf(" checked %s\n",nameStruct.name);
if (cmp > 0)
offset2 = check-1;
else if (cmp < 0)
offset1 = check+1;
else
{
if (verbose)
{
printf("Found entry %s!\n",searchName);
exit(0);
}
printf("%s%s\n",NAME,searchName);
print_entry(FInPtr,nameStruct.offset);
}
if (offset1 > offset2)
{
printf("Entry '%s' not found in describe database.\n",searchName);
exit(1);
}
}
}

View File

@ -1,13 +0,0 @@
Name: describe
Version: 1.0.2
Shell: ORCA/Shell, GNO/ME
Author: James Brookes
Contact: jamesb@ecst.csuchico.edu
Where: /usr/local/bin
FTP: ftp.cco.caltech.edu
Print a multi-line description obtained from the compiled 'describe'
database; giving utility name, version, intended shell, author, author's
contact, where the utility is, as well as where the utility can be FTPd
from on the InterNet.

File diff suppressed because it is too large Load Diff

View File

@ -1,58 +0,0 @@
.TH DESCU 8 "System Administration" "7 May 1995" "Version 1.0.2"
.SH NAME
descu \- the describe(1) source updater
.SH SYNOPSIS
.BR descu " [" -hV ]
.I sourcefile
.I patchfile1
[
.IR patchfile2 " ..."
]
.SH DESCRIPTION
.BR descu
updates the describe source file
.I sourcefile
by applying the new and updated records from the \fIpatchfile\fRs
and prints the result to standard output.
.LP
.IR Patchfile s
are just one or more describe source entries as defined in
.BR descc (8).
(They have nothing to do with
.BR patch (1).)
.LP
.IR Patchfile s
are assumed to contain at most one entry (in all listed
.IR patchfile s)
for a given program, keyed on the
.BR Name:
field. If an entry in
.IR patchfile
is already in
.IR sourcefile ,
it replaces the original; otherwise the entry is appended. In both
cases, the output is sorted lexicographically (ignoring case), based on
the
.BR Name:
field.
.LP
.BR descu
will create the file
.B descu.rej
in the current directory. This contains all records that were removed
from
.IR sourcefile .
.SH OPTIONS
.nf
\fB-h\fR Show usage information.
\fB-V\fR Show version information.
.fi
.SH AUTHOR
Devin Reade <gdr@myrias.ab.ca>
.SH "SEE ALSO"
.BR apropos (1),
.BR describe (1),
.BR man (1),
.BR whatis (1),
.BR descc (8).

View File

@ -1,519 +0,0 @@
/*
* descu - describe(1) update utility for maintaining describe source files
*
* Usage: descu [-hV] sourcefile patchfile1 [patchfile2 ...]
*
* Options:
* -h show usage information and exit.
* -V show version information
*
* Copyright 1995 by Devin Reade for James Brookes' describe(1) utility.
* See the included README file and man page for details.
*
* $Id: descu.c,v 1.2 1996/01/22 02:40:49 gdr Exp $
*/
#pragma optimize -1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <getopt.h>
#include "desc.h"
#define _VERSION_ "v1.0.2"
#define MAX_BUFFER 65534
#define SLOTS_QUANTUM 20
#define REJECT_FILE "descu.rej"
#ifndef __ORCAC__
ssize_t read(int, void *, size_t);
#endif
char *strerror(int);
void convert (char *);
int my_stricmp (const char *cs, const char *ct);
char *versionStr = _VERSION_;
static char *header=NULL; /* comments before the first describe entry */
static char *trailer=NULL; /* comments after the last describe entry */
short oflag;
short Vflag;
short errflag;
descEntry **entryArray1=NULL;
descEntry **entryArray2=NULL;
int array1SlotsAlloced=0;
int array2SlotsAlloced=0;
int array1SlotsUsed=0;
int array2SlotsUsed=0;
/*
* inhale - read file into buffer
*
* Pre: <pathname> is the path name of the file to read in
*
* Post: returns a malloc'd NULL-terminated buffer containing the contents
* of file <pathname>. On error, returns NULL and prints a suitable
* message.
*
* On the Apple IIgs, CR's are also converted to LF's
*/
char *inhale (char *pathname) {
char *buffer;
long bytecount, bytes_read;
ssize_t i;
int fd;
/* open the file */
if ((fd = open(pathname,O_RDONLY))==-1) {
fprintf(stderr,"inhale: open of %s failed: %s\n",
pathname,strerror(errno));
return NULL;
}
/* create the buffer */
bytecount = lseek(fd,(off_t) 0,SEEK_END);
if (bytecount > MAX_BUFFER) {
fprintf(stderr,"descu internal error: cannot handle files greater"
"than %d bytes\n due to a compiler bug. Sorry.\n",
MAX_BUFFER);
exit(-1);
}
lseek(fd,(off_t) 0, SEEK_SET);
if ((buffer = malloc(bytecount+1))==NULL) {
fprintf(stderr,"inhale: malloc of %ld-byte buffer failed for file %s:%s\n",
bytecount+1,pathname,strerror(errno));
close(fd);
return NULL;
}
/* read file into the buffer */
bytes_read=0;
while (bytes_read < bytecount) {
i = read(fd,&buffer[bytes_read],(size_t)bytecount-bytes_read);
if (i==-1) {
fprintf(stderr,"inhale: read failed on file %s:%s\n",
pathname,strerror(errno));
free(buffer);
close(fd);
return NULL;
}
bytes_read += i;
}
/* clean up and return buffer */
close(fd);
buffer[bytecount] = '\0';
#ifdef __ORCAC__
/* convert CR to LF */
{
char *p;
for (p=buffer; *p ; p++) {
if (*p == 0x0D) *p = 0x0A;
}
}
#endif
return buffer;
}
/*
* extract_info -- take a string buffer containing the describe information
* and return a malloc'd descEntry structure containing
* pointers into the buffer of the various parts. Also
* modifies the buffer so that there is a '\0' character
* between the parts.
*/
descEntry *extract_info(char *source) {
char *p;
descEntry *entry;
if ((entry = malloc(sizeof(descEntry))) == NULL) {
perror("add_entry: couldn't allocate new entry");
exit(1);
}
/* extract out name */
if (((entry->name = strstr(source,NAME_SHORT))==NULL) ||
((p = strchr(source,'\n'))==NULL)) {
fprintf(stderr,"bad or missing describe field: \"%s\"\n"
"describe entry is:\n%s\n",NAME,source);
free(entry);
return NULL;
}
/* extract out data */
entry->data = p+1;
/* terminate the name, dropping trailing space */
do { --p; } while (isspace(*p));
*(p+1) = '\0';
return entry;
}
/*
* add_entry -- add entry to the descTable, even if it already exists.
*/
void add_entry(descEntry *entry, int initial_buffer) {
descEntry **e, ***array;
int *slotsAlloced, *slotsUsed;
if (initial_buffer) {
array = &entryArray1;
slotsAlloced = &array1SlotsAlloced;
slotsUsed = &array1SlotsUsed;
} else {
array = &entryArray2;
slotsAlloced = &array2SlotsAlloced;
slotsUsed = &array2SlotsUsed;
}
/* grow array if necessary */
if (*slotsAlloced == *slotsUsed) {
*slotsAlloced += SLOTS_QUANTUM;
if (*array) {
e = realloc(*array,(*slotsAlloced) * sizeof(descEntry *));
} else {
e = malloc((*slotsAlloced) * sizeof(descEntry *));
}
if (e == NULL) {
perror("couldn't grow describe array");
exit(1);
}
*array = e;
}
/* add in the entry */
(*array)[*slotsUsed] = entry;
(*slotsUsed)++;
return;
}
/*
* insert - insert all entries contained in buffer into the descTable.
* If initial_buffer is non-zero, then use any comments preceeding
* the first entry as the output file header, and any comments
* following the last entry as the output file trailer. If
* initial_buffer is zero, then the respective comment blocks are
* ignored, effectively deleting them from the output.
*/
void insert(char *buffer, int initial_buffer) {
char *p, *q;
descEntry *entry;
/* pull out the header (if nec) and init p */
if (initial_buffer) header = buffer;
p = strstr(buffer,NAME_SHORT);
if(!p) return; /* buffer doesn't have any describe entries! */
*(p-1)='\0';
/* add all but the last entry */
while ((q=strstr(p+1,NAME_SHORT))!=NULL) {
*(q-1)='\0';
entry = extract_info(p);
if (entry) add_entry(entry, initial_buffer);
p=q;
}
/* extract out the trailer and add the last entry */
if ((q = strstr(p,"\n#"))==NULL) {
if (initial_buffer) trailer="";
} else {
if (initial_buffer) trailer=q+1;
*q = '\0';
}
entry = extract_info(p);
if (entry) add_entry(entry,initial_buffer);
return;
}
/*
* sortArray - do a heapsort on <array> consisting of <slotsUsed> elements.
* The sort is based on the field array[i]->name, sorted
* lexicographically ignoring case.
*/
void sortArray(descEntry **array, int slotsUsed) {
int l, j, ir, i;
descEntry *rra;
if (slotsUsed==1) return; /* no need to sort one element */
--array; /* fudge since the algorithm was designed */
/* for a unit-indexing */
l = (slotsUsed>>1) + 1;
ir = slotsUsed;
/*
* The index l will be decremented from its initial value down to 0 during
* the heap creation phase. Once it reaches 0, the index ir will be
* decremented from its initial value down to 0 during the heap selection
* phase.
*/
for (;;) {
if (l > 1) /* still in creation phase */
rra = array[--l];
else { /* in selection phase */
rra= array[ir]; /* clear a space at the end of array */
array[ir] = array[1]; /* retire the top of the heap into it */
if (--ir == 1) { /* done with the last promotion */
array[1] = rra;
return;
}
}
i = l; /* set up to sift down element rra to its proper place */
j = l << 1;
while (j<=ir) {
if (j<ir && (my_stricmp(array[j]->name,array[j+1]->name)<0)) ++j;
if (my_stricmp(rra->name,array[j]->name)<0) { /* demote rra */
array[i] = array[j];
i = j;
j += i;
} else j = ir + 1; /* this is rra's level; set j to terminate */
} /* the sift-down */
array[i] = rra;
}
}
/*
* int my_stricmp (const char *cs, const char *ct);
*
* Compare the two strings cs and ct case-insensitive. Return
* <0 if cs<ct, 0 if cs == ct, >0 if cs>ct.
*
*/
int my_stricmp (const char *cs, const char *ct)
{
char a, b;
while ((a = tolower(*cs)) && (b = tolower(*ct))) {
if (a < b) return -1;
if (a > b) return 1;
cs++; ct++;
}
if (*cs == *ct) return 0;
else if (*cs) return -1;
else return 1;
}
/*
* ns_strcmp (no-space string compare) -- compare two strings, ignoring
* a leading NAME_SHORT and whitespace, and ignoring trailing
* whitespace.
*
* Returns zero if strings are equal, -1 if a<b, 1 if a>b.
* The following are therefore equal:
* "Name: test "
* "Name: test "
* The following are inequal:
* "Name: one"
* "Name: One"
*/
int ns_strcmp (char *a, char *b) {
char *p;
size_t len;
/* strip NAME_SHORT and leading space */
len = strlen(NAME_SHORT);
a+=len;
b+=len;
while (isspace(*a)) a++;
while (isspace(*b)) b++;
/* strip trailing space */
p = a + strlen(a);
do {
--p;
} while (isspace(*p));
*(p+1) = '\0';
p = b + strlen(b);
do {
--p;
} while (isspace(*p));
*(p+1) = '\0';
/* do the string comparison */
while (*a && *b) {
if (*a < *b) return -1;
if (*a > *b) return 1;
a++; b++;
}
if (*a == *b) return 0;
else if (*a) return -1;
else return 1;
}
void version (char *progName) {
fprintf(stderr,
"%s version %s Copyright 1995 Devin Reade\n"
"Freeware. See the manual page for copying restrictions.\n",
progName,versionStr);
return;
}
/*
* Usage -- print usage info and exit
*/
void usage(char *progName) {
if (!Vflag || errflag) {
fprintf(stderr,
"%s -- describe(1) source update utility\n"
"Usage: %s [-hV] sourcefile patchfile1 [patchfile2 ...]\n"
"\t-h\tshow usage information\n"
"\t-V\tshow version information\n\n",
progName,progName);
}
version(progName);
exit(1);
}
/*
* need I say it?
*/
int main(int argc, char **argv) {
char *buffer;
int i, j;
FILE *outfp, *rejfp;
int c;
char *outputfile=NULL;
int compare;
#ifdef STACK_CHECK
begin_stack_check();
#endif
/* initialize */
errflag=0;
oflag=0;
/* parse command line */
while ((c=getopt(argc,argv,"ho:V"))!=EOF) {
switch (c) {
case 'o':
outputfile = optarg;
oflag++;
break;
case 'V':
Vflag++;
break;
case 'h':
default:
errflag++;
}
}
/* error and exit if necessary */
if (errflag || (argc-optind<2)) usage(basename(argv[0]));
/* show version info */
if (Vflag) version(basename(argv[0]));
/* open output (if nec) and reject file */
if (oflag) {
if ((outfp = fopen(outputfile,"w+"))==NULL) {
perror("main: couldn't open output file");
exit(1);
}
} else {
outfp = stdout;
}
if ((rejfp = fopen(REJECT_FILE,"w+"))==NULL) {
perror("main: couldn't open rejects file");
exit(1);
}
/* read in original describe source file */
buffer = inhale(argv[optind]);
insert(buffer,1);
/* insert describe patch files */
for (optind++; optind<argc; optind++) {
buffer = inhale(argv[optind]);
insert(buffer,0);
}
/* sort the two arrays */
sortArray(entryArray1,array1SlotsUsed);
sortArray(entryArray2,array2SlotsUsed);
/*
* merge the two arrays, printing out the result
*/
i=0; j=0;
/* print the header */
fprintf(outfp,"%s\n",header);
/* first stage; merge while we have two arrays */
while ((i<array1SlotsUsed) && (j<array2SlotsUsed)) {
compare = ns_strcmp (entryArray1[i]->name, entryArray2[j]->name);
if (compare < 0) {
fprintf(outfp,"%s\n%s\n",entryArray1[i]->name,entryArray1[i]->data);
i++;
} else if (compare > 0) {
fprintf(outfp,"%s\n%s\n",entryArray2[j]->name,entryArray2[j]->data);
j++;
} else {
fprintf(rejfp,"%s\n%s\n",entryArray1[i]->name,entryArray1[i]->data);
fprintf(outfp,"%s\n%s\n",entryArray2[j]->name,entryArray2[j]->data);
i++; j++;
}
}
/* second stage; print out remaining list */
while (i<array1SlotsUsed) {
fprintf(outfp,"%s\n%s\n",entryArray1[i]->name,entryArray1[i]->data);
i++;
}
while (j<array2SlotsUsed) {
fprintf(outfp,"%s\n%s\n",entryArray2[j]->name,entryArray2[j]->data);
j++;
}
/* print the trailer */
fprintf(outfp,"%s",trailer);
/* close the files and exit */
fclose(rejfp);
if (oflag) fclose(outfp);
#ifdef STACK_CHECK
fprintf(stderr,"stack usage: %d bytes\n",end_stack_check());
#endif
return 0;
}

View File

@ -1,10 +0,0 @@
Name: descu
Version: 1.0.2
Shell: ORCA/Shell, GNO/ME
Author: Devin Reade
Contact: gdr@myrias.ab.ca
Where: /usr/sbin
FTP: ftp.cco.caltech.edu
Update a 'describe' source file.

View File

@ -1,52 +0,0 @@
#
# This is the makefile for the describe(1) package. It is for use
# with dmake(1).
#
# Use -DSTACK_CHECK in CFLAGS to show stack usage.
CFLAGS += -O -w -v -I/usr/include -s768
LDFLAGS += -v
LDLIBS += -l/usr/lib/lgetopt -l/usr/lib/stack
BINDIR = /usr/local/bin
SBINDIR = /usr/sbin
MANDIR = /usr/man
INSTALL = /bin/cp
build: describe descc descu
descc: descc.o basename.o descc.r
@purge
$(CC) $(LDFLAGS) $< -o $@ $(LDLIBS)
copyfork descc.r descc
describe: describe.o basename.o describe.r
@purge
$(CC) $(LDFLAGS) $< -o $@ $(LDLIBS)
copyfork describe.r describe
descu: descu.o basename.o descu.r
@purge
$(CC) $(LDFLAGS) $< -o $@ $(LDLIBS)
copyfork descu.r descu
basename.o: basename.c
$(CC) -c $(CFLAGS) basename.c
descc.o: descc.c desc.h
$(CC) -c $(CFLAGS) descc.c
describe.o: describe.c desc.h
$(CC) -c $(CFLAGS) describe.c
descu.o: descu.c desc.h
$(CC) -c $(CFLAGS) descu.c
install:
$(RM) -f /usr/local/bin/descc
$(INSTALL) describe $(BINDIR)
$(INSTALL) descc $(SBINDIR)
$(INSTALL) descu $(SBINDIR)
$(INSTALL) describe.1 $(MANDIR)/man1
$(INSTALL) descc.8 $(MANDIR)/man8
$(INSTALL) descu.8 $(MANDIR)/man8

View File

@ -0,0 +1,31 @@
About Describe
~~~~~~~~~~~~~~
First off: make sure the directory /usr/local/lib exists!!!
This is yet another project I've been sitting on for a while, but have
finally decided to release. The basic idea of the 'describe' package
(the descc "compiler" and describe itself) is to provide a quick, easy
way of accessing information related to the utilities which so many
different people are releasing these days. The reason it sat around on
my harddrive so long is I was having qualms about its designated role in
life. I wasn't sure exactly what I wanted it to do. Well, I've decided
to KISS for now: descc simply compiles the utility list, which I maintain,
into a (very) simple "database" located in /usr/local/lib/. The companion
utility 'describe' is used to fetch information about a particular utility
from this "database".
descc is fairly limited, as is the "database" format itself. Part of the
KISS (or it wouldn't be out now) design philosophy ;). Usage is simple:
when you get a new listing (I'll provide monthly updates), simply "descc
<filename>" where <filename> is the name of the newly released update.
descc will simply write over the old database and replace it with the
new (note: no appendages allowed).
As always, coments are appreciated. And, moreso than on other projects,
I'd appreciate some comments about the direction I'm going in, suggestions
as to where to take this, etc. I have a feeling that some fields in the
format (eg, FTP:) are rather useless, and I'd like to know what you guys
out there think.
James Brookes
jamesb@ecst.csuchico.edu

View File

@ -1,63 +0,0 @@
#
# Makefile for udl
# Copyright (c) 1993-1996 Soenke Behrens
#
# This makefile should be used with dmake.
#
# $Id: Makefile.gs,v 1.8 1996/01/22 01:01:30 gdr Exp $
#
# Where do we put the binaries and man page?
BINDIR = /usr/local/bin
MANDIR = /usr/local/man
# OS-dependant macros. See the README for an explanation of these.
DEFINES = -DGNO -D_POSIX_C_SOURCE -D_POSIX_SOURCE -DHAS_ATEXIT \
-DOVERFLOW_CHECK
# Use optimization and a 2k stack.
CFLAGS = $(DEFINES) -O -w -s2048
LDFLAGS = -s2048
# Depending on how you have your libraries set up, you may not need
# this next line. In that case, just comment it out.
LDLIBS = -l/usr/lib/gnulib
#
# You should not have to modify anything beyond this point
#
OBJS = udl.o udluse.o common.o globals.o
udl: $(OBJS) udl.r help/udl
$(CC) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
copyfork udl.r $@ -r
udl.o: udlgs.c common.h
$(CC) -c $(CFLAGS) -o udl.o udlgs.c
install:
cp -f udl $(BINDIR)
cp -f udl.1 $(MANDIR)
help:
mkdir $@
help/udl: udl.1 help
nroff -man udl.1 > $@
clean:
-$(RM) *.o *.root udl.r
clobber: clean
-$(RM) -rf udl help
dist:
@echo "Sorry, automatic packing not supported yet"
common.o:: common.h
globals.o:: common.h

View File

@ -1,94 +0,0 @@
#
# Makefile for udl
# (c) 1993-1996 Soenke Behrens
#
# $Id: Makefile.unx,v 1.7 1996/01/22 01:01:31 gdr Exp $
#
# $(CC) _must_ be an ANSI compiler.
CC = cc
BINDIR = /usr/local/bin
MANDIR = /usr/local/man/man1
INSTALL = /usr/bin/install
# These are arguments to $(INSTALL)
MODE644 = -m 644
MODE755 = -m 755
OWNER_GROUP = -o bin -g sys
# You should not have to modify anything beyond this point
##########################################################
#
# OS-dependant macros. See the README for an explanation of these.
#
DEFINES_AIX = -DBROKEN_REALLOC -D_POSIX_C_SOURCE -D_POSIX_SOURCE
DEFINES_Linux = -DREADDIR_RETURNS_DOT -D_POSIX_C_SOURCE -D_POSIX_SOURCE \
-DHAS_ATEXIT
DEFINES_Solaris = -DREADDIR_RETURNS_DOT -D_POSIX_C_SOURCE -D_POSIX_SOURCE \
-DBROKEN_DIRENT_STRUCT
LDLIBS_Solaris = -lucb
DEFINES_SunOS = -DREADDIR_RETURNS_DOT -D_POSIX_C_SOURCE -D_POSIX_SOURCE \
-DBROKEN_REALLOC
CFLAGS = $(DEFINES_$(OS)) -O
LDFLAGS = $(LDFLAGS_$(OS)) -s
LDLIBS = $(LDLIBS_$(OS))
OBJS = udl.o udluse.o common.o globals.o
build:
@os_string=`uname -sr | tr ' ' '_'`; \
case $$os_string in \
SunOS_4*) os=SunOS;; \
SunOS_5*) os=Solaris;; \
AIX*) os=AIX;; \
Linux*) os=Linux;; \
*) echo "don't know about OS $$os_string"; \
exit -1;; \
esac; \
$(MAKE) udl -f Makefile.unx OS=$$os
udl: $(OBJS)
$(CC) $(LDFLAGS) -o udl $(OBJS) $(LDLIBS)
udl.o: udlunix.c common.h
$(CC) -c $(CFLAGS) -o udl.o udlunix.c
newudl.1: udl.1
@echo "creating newudl.1"; \
echo '/^.TH/ c\' > sed.script; \
echo '.TH UDL 1 "15 January 1996" "Version 1.15"\
"Commands and Applications"' >>sed.script; \
sed -f sed.script <udl.1 >newudl.1; \
rm -f sed.script
install: newudl.1 udl
$(INSTALL) $(MODE755) $(OWNER_GROUP) udl $(BINDIR)
$(INSTALL) $(MODE644) $(OWNER_GROUP) newudl.1 $(MANDIR)/udl.1
rm -f newudl.1
clean:
-rm -f *.o *~ core
clobber: clean
-rm -rf udl newudl.1 help
dist: clobber
@echo "creating archive"; \
cwd=`pwd`; \
parent=`dirname $$cwd`; \
dir=`basename $$cwd`; \
cd $$parent; \
archive=$$dir.tar.Z; \
if [ -f $$archive ]; then \
echo "please move $$parent/$$archive out of the way, first"; \
exit -1; \
fi; \
tar -cf - $$dir | compress > $$archive
udluse.o common.o globals.o:: common.h

View File

@ -1,230 +0,0 @@
=============================================================================
udl - Convert EOL formats freely between MS-DOS (CR/LF), Unix/Amiga (LF),
and Apple (CR).
(c) 1993-1996 Soenke Behrens, Devin Reade
Version 1.15: $Id: README,v 1.8 1996/01/22 01:01:32 gdr Exp $
=============================================================================
Udl converts text files between CR, LF and CR/LF (Apple, Unix and MS-DOS).
It is a very fast utility that ensures that the integrity of the file
cannot be compromised during the translation. It is also much easier
to use than tr(1).
=========
Compiling:
=========
There are two makefiles included:
Makefile.gs - for use on the Apple IIgs running GNO
Makefile.unx - for use with Unix systems.
Although udl on the IIgs can be run from either GNO or ORCA shells,
it cannot be built with the standard ORCA installation due to a lack
of additional libraries.
The IIgs distribution should contain a binary of udl, including a
resource fork. Therefore, you should be able to skip straight to the
section on installation. For those who must know, however, building the
binaries under GNO should just be a matter of typing 'dmake -f Makefile.gs'.
If you are compiling on Unix operating systems that have been previously
tested, you should be able to just type 'make -f Makefile.unx'. This
will select the appropriate DEFINES for your system. For an explanation
the various DEFINES, see the section below on "DEFINES Definitions".
Note that compilation of udl _requires_ an ANSI C compiler.
If you are compiling to a new system, add in another set of defines
and let us know about them.
Note that udl.c assumes that getopt() is declared in <unistd.h> and that
the function strdup() exists in <string.h>. You might have to change
these includes if that's not the case. Ensure you use cpp conditional
compilations to match your platform (and to avoid breaking the code for
other platforms).
============
Installation
============
Apple IIgs with GNO
^^^^^^^^^^^^^^^^^^^
Type 'dmake install -f Makefile.gs'. By default this copies the binary
into "/usr/local/bin" and the man page into "/usr/local/man/man1". (You
_are_ using version 3.x of 'man', are you not? *blatent plug*) If you
don't like these locations, either modify the BINDIR and MANDIR
macros in the makefile or install the files by hand.
If you have describe(1) installed, you can update the udl(1) entry
with the file "describe.udl". See the descu(8) and descc(8) man pages
for details.
Apple IIgs with Orca/Shell
^^^^^^^^^^^^^^^^^^^^^^^^^^
Copy the following files to their respective destinations:
udl to 17
help/udl to 17/help
Unix systems
^^^^^^^^^^^^
Type 'make -f Makefile.unx install'. By default the binary will
go into /usr/local/bin and the man page into /usr/local/man/man1.
This assumes root access. If this does not match your plans and/or
access permissions, either copy the files by hand or change the
BINDIR, MANDIR, and OWNER_GROUP macros in the makefile.
===================
DEFINES Definitions
===================
If you have problems compiling or are porting udl to a new operating
system, define the following macros in the makefile as necessary.
They should be used as the value of $(DEFINES_$(OS)) where $(OS) is
your operating system as returned by `uname -sr | tr ' ' '_'`.
HAS_ATEXIT if your system has atexit()
_POSIX_C_SOURCE and _POSIX_SOURCE if your compiler is Posix compliant
READDIR_RETURNS_DOT if your direct readdir() function will return
entries for "." and "..". SunOS 4.x and 5.x (Solaris) are known to
do this.
BROKEN_REALLOC if your realloc() doesn't behave like malloc() when
passed a NULL pointer as the first argument.
BROKEN_DIRENT_STRUCT if you find that the first two letters of
filenames obtained during directory recursion (as shown when the
"-v" flag is used) seem to be missing. Some installations of
Solaris are known to do this.
GNO if you are compiling on the IIgs. This will allow for both
':' and '/' as pathname separators.
OVERFLOW_CHECK Udl uses one recursive subroutine. Define this if
you want to check for stack overflows for this routine (independent
of any compiler flags). Strongly recommended.
CHECK_STACK if you want stack usage to be displayed (IIgs only).
You will also have to specify -l/usr/lib/stack in LDFLAGS.
The following are the DEFINES values for tested operating systems:
APPLE IIGS: (use "dmake -f Makefile.gs")
^^^^^^^^^^
ORCA/Shell and GNO/ME: (tested with occ)
-DGNO -D_POSIX_C_SOURCE -D_POSIX_SOURCE -DHAS_ATEXIT
-DOVERFLOW_CHECK
TESTED UNIX OS's: (use "make -f Makefile.unx")
^^^^^^^^^^^^^^^^
SunOS 4.x: (tested with gcc)
-DREADDIR_RETURNS_DOT -DBROKEN_REALLOC
-D_POSIX_C_SOURCE -D_POSIX_SOURCE
SunOS 5.x (Solaris): (tested with SUNWspro cc)
-DREADDIR_RETURNS_DOT -DBROKEN_DIRENT_STRUCT
-D_POSIX_C_SOURCE -D_POSIX_SOURCE
AIX 3.2: (tested with xlc)
-DBROKEN_REALLOC -D_POSIX_C_SOURCE -D_POSIX_SOURCE
Linux 1.2.3: (tested with gcc)
-DREADDIR_RETURNS_DOT -D_POSIX_C_SOURCE -D_POSIX_SOURCE
-DHAS_ATEXIT
================
Revision History:
================
v1.01
Tabs are left alone now. Also recognizes CR/LF (MeSsy-DOS).
v1.02
Does no longer read in the complete file, instead creates a temp
file in prefix 3/.
v1.03
Fixed a bug, allocated not enough mem for strncpy.
v1.1
Changed to use static GS/OS strings again. Made faster by factor
5.8.
v1.11
Cleaned the code up a bit, wrote a Makefile, all output by udl is
prefixed with the name it was invoked with.
v1.12
Sped up Apple <-> Unix conversion further (factor 1.5).
v1.12 (Unix)
(December 1993)
Modified source to produce a Unix version
v1.13
(Updated by Devin Reade, November 1994)
Added ability to recurse through directories (-R flag).
Changed behavior to ignore binary files rather than exiting.
Merged Unix and Apple IIgs versions.
No message is printed out when a binary file (or, in the IIgs
implementation, a non-TXT or non-SRC file) is encountered
unless the -v option is specified.
v1.14
(Soenke Behrens, Devin Reade, February 1995)
udl creates a temporary file in the directory of the
source file, not in /tmp. This reduces the likelihood of
data loss in the event of a system crash or powerdown.
udl now accepts something like "udl -R directory/" without
affixing an extra '/' to "directory/".
Fixed bug (via the BROKEN_DIRENT_STRUCT macro) that was causing
filename-munging on Solaris. It seems that the sys/stat.h header
file doesn't agree with the stat implementation.
Modified Makefile.gs to properly write the new executable over
the old resource fork for udl. The resource fork originates with
the file udl.r.
Added suggested defines to the README for various Unix platforms.
Man page changes, including grammar and the deletion of a bug that
no longer exists.
Fixed bug where invoking 'udl -u directory' would attempt to
deref a NULL pointer, causing either memory tromping (IIgs) or
a core dump (Unix).
Tested under SunOS 4.x, SunOS 5.x (Solaris), and AIX.
v1.15
(Devin Reade, January 1996)
Changed Makefile.unx to select what should be the proper
defines automatically, based on the result of `uname -sr`.
Added Linux defines.
Changed references and definition of "mktemp" to "Mktemp". There
is a discrepancy between the internal implementation and
other common Unix versions.
Added a section to this README on installation, and moved the
description of the DEFINES from the makefiles to here.
On the IIgs version, the resource fork is now created from a
resource source file that is compiled, rather than using
an interactive tool to create the resource fork.
Changed source filenames to use the 8.3 format in anticipation of
MS-DOS support. This does not affect the file names upon which
udl operates.
=======
Authors
=======
Original code by Soenke Behrens <sbehrens@contech.demon.co.uk>
with modifications and version-merging by Devin Reade <gdr@myrias.com>
==========
Legalities:
==========
This program contains material from the Orca/C Run-Time Libraries,
copyright 1987-1996 by Byte Works, Inc. Used with permission.
=============================================================================

View File

@ -1,928 +0,0 @@
/*
* udl - Convert EOL formats freely between MS-DOS (CR/LF), Unix/Amiga (LF),
* and Apple (CR).
*
* Routines common to both the Unix and Apple IIgs versions.
*
* $Id: common.c,v 1.8 1996/01/22 01:01:32 gdr Exp $
*
* Copyright (c) 1993-1995 Soenke Behrens, Devin Reade
*/
#ifdef GNO
#pragma noroot
#endif
#include "common.h"
extern char *strdup(const char *);
/*
* convert_gs() ... convert files to use CR as EOL
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* None
*/
void convert_gs(FILE *infile, FILE *outfile) {
unsigned char a;
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile,BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
while (file_remain != 0) {
a = *in_bufpos;
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile,BUFFERSIZE);
in_bufpos = in_buffer;
}
/* a = fgetc (infile); */
if(a == '\n') {
*out_bufpos = '\r';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\r',outfile); */
} else if(a == '\r') {
*out_bufpos = '\r';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\r',outfile); */
if (*in_bufpos == '\n' && file_remain != 0) {
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
in_bufpos = in_buffer;
}
}
/* if ((a = fgetc (infile)) != '\n')
ungetc (a,infile); */
} else {
*out_bufpos = a;
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc(a,outfile); */
}
}
/* Check for remainder in output buffer */
if (out_bufpos != out_buffer)
my_fwrite(out_buffer,outfile,out_bufpos - out_buffer);
}
/*
* convert_messy() ... convert files to use CR/LF as EOL
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* None
*/
void convert_messy (FILE *infile, FILE *outfile) {
unsigned char a;
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
while (file_remain != 0) {
a = *in_bufpos;
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
in_bufpos = in_buffer;
}
/* a = fgetc (infile); */
if(a == '\n') {
*out_bufpos = '\r';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\r',outfile); */
*out_bufpos = '\n';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\n',outfile); */
} else if(a == '\r') {
*out_bufpos = '\r';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\r',outfile); */
*out_bufpos = '\n';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\n',outfile); */
if (*in_bufpos == '\n' && file_remain != 0) {
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
in_bufpos = in_buffer;
}
}
/* if ((a = fgetc (infile)) != '\n')
ungetc (a,infile); */
} else {
*out_bufpos = a;
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc(a,outfile); */
}
}
/* Check for remained in output buffer */
if (out_bufpos != out_buffer)
my_fwrite(out_buffer,outfile,out_bufpos - out_buffer);
}
/*
* convert_tunix() ... convert files to use LF as EOL
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* None
*/
void convert_tunix (FILE *infile, FILE *outfile) {
unsigned char a;
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
while (file_remain != 0) {
a = *in_bufpos;
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
in_bufpos = in_buffer;
}
/* a = fgetc (infile); */
if(a == '\r') {
*out_bufpos = '\n';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\n',outfile); */
if (*in_bufpos == '\n' && file_remain != 0) {
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
in_bufpos = in_buffer;
}
}
/* if ((a = fgetc (infile)) != '\n')
ungetc (a,infile); */
} else {
*out_bufpos = a;
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc(a,outfile); */
}
}
/* Check for remainder in output buffer */
if (out_bufpos != out_buffer)
my_fwrite(out_buffer,outfile,out_bufpos - out_buffer);
}
/*
* convert_fast_gs() ... convert files to use CR as EOL
* Do not care about differing EOL chars in the same file,
* do not allow '\0' bytes, and replace in-vitro if possible.
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* int FALSE if no conversion took place, TRUE otherwise
*/
int convert_fast_gs(FILE *infile, FILE *outfile) {
unsigned char a;
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
enum file_format infile_type;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile,BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
*in_bufend = '\0';
infile_type = get_file_format (in_buffer);
switch (infile_type) {
case apple:
if (verbose)
printf("%s: %s is already in Apple format, skipping.\n",
program_name,current_file);
return (FALSE);
break;
case tunix:
/* Replace "in-vitro", so out_buffer isn't used */
while (file_remain != 0) {
a = *in_bufpos;
if (a == '\n')
*in_bufpos++ = '\r';
else if (a == '\0') { /* End of buffer reached */
/* Write changed buffer out */
my_fwrite(in_buffer,outfile,in_bufend - in_buffer);
/* And reload it */
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
*in_bufend = '\0';
in_bufpos = in_buffer;
} else in_bufpos++;
}
return (TRUE);
break;
case dos:
/* This I couldn't speed up, so use the existing thing */
convert_gs (infile, outfile);
return (TRUE);
break;
case binary:
return (FALSE);
break;
default:
fprintf(stderr,"%s: Fatal internal error\n",program_name);
exit (EXIT_FAILURE);
break;
} /* switch */
}
/*
* convert_fast_messy() ... convert files to use CR/LF as EOL
* Just check if it's already in DOS format.
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* int FALSE if no conversion took place, TRUE otherwise
*/
int convert_fast_messy (FILE *infile, FILE *outfile) {
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
enum file_format infile_type;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
*in_bufend = '\0';
infile_type = get_file_format (in_buffer);
switch (infile_type) {
case dos:
if (verbose)
printf("%s: %s is already in MS-DOS format, skipping.\n",
program_name,current_file);
return (FALSE);
break;
case tunix: /* drop through */
case apple:
/* Wasn't able to speed this up, call old routine */
convert_messy (infile, outfile);
return (TRUE);
break;
case binary:
return (FALSE);
break;
default:
fprintf(stderr,"%s: Fatal internal error\n",program_name);
exit (EXIT_FAILURE);
break;
} /* switch */
}
/*
* convert_fast_tunix() ... convert files to use LF as EOL
* Do not care about differing EOL chars in the same file,
* do not allow '\0' bytes, and replace in-vitro if possible.
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* int FALSE if no conversion took place, TRUE otherwise
*/
int convert_fast_tunix (FILE *infile, FILE *outfile) {
unsigned char a;
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
enum file_format infile_type;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
*in_bufend = '\0';
infile_type = get_file_format (in_buffer);
switch (infile_type) {
case tunix:
if (verbose)
printf("%s: %s is already in Unix format, skipping.\n",
program_name,current_file);
return (FALSE);
break;
case apple:
/* Replace "in-vitro", so out_buffer isn't used */
while (file_remain != 0) {
a = *in_bufpos;
if (a == '\r')
*in_bufpos++ = '\n';
else if (a == '\0'){ /* End of buffer reached */
/* Write changed buffer out */
my_fwrite(in_buffer,outfile,in_bufend - in_buffer);
/* And reload */
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
*in_bufend = '\0';
in_bufpos = in_buffer;
} else in_bufpos++;
}
return (TRUE);
break;
case dos:
/* Couldn't speed it up, so use old routine */
convert_tunix (infile, outfile);
return (TRUE);
break;
case binary:
return (FALSE);
break;
default:
fprintf(stderr,"%s: Fatal internal error\n", program_name);
exit (EXIT_FAILURE);
break;
} /* switch */
}
/*
* get_file_format() ... look at a buffer and find out what the EOL
* character is. If no EOL character is found, print an error message
* and exit.
*
* Inputs:
* unsigned char *buffer Buffer to search through, terminated
* by '\0'.
*
* Output:
* enum file_format tunix, dos, apple, or binary
*/
enum file_format get_file_format (unsigned char *buffer) {
unsigned char c;
enum file_format result = 0;
while ((c = *buffer++) != '\0') {
if (c == '\n') {
result = tunix;
break;
} else if (c == '\r') {
if (*buffer == '\n')
result = dos;
else
result = apple;
break;
}
}
if (result == 0) {
if (verbose)
printf("%s: No EOL found on the first %d bytes "
"of %s. Might be a binary file. File skipped\n",
program_name,BUFFERSIZE, current_file);
result = binary;
}
return (result);
}
/*
* tryopen() ... try to open a file, exit if unsuccesful
*
* Inputs:
* char *name Name of file to be opened
* char *mode Mode string for fopen() call
*
* Output:
* FILE * File identifier of successful fopen()
*/
FILE *tryopen (char *name, char *mode) {
FILE *tmp;
if ((tmp = fopen(name,mode)) == NULL) {
fprintf(stderr,"%s: Unable to open file %s\n",program_name, name);
exit (EXIT_FAILURE);
} else
return (tmp);
}
/*
* my_fread() ... read data into global buffer and exit if I fail
*
* Inputs:
* FILE *infile File to read from
* int howmuch Number of bytes to read
*
* Output:
* int Number of bytes actually read
*/
int my_fread(FILE *infile, int howmuch) {
int result;
result = fread(in_buffer, 1, howmuch, infile);
if (ferror(infile)) {
fprintf(stderr,"%s: Error while reading data\n",program_name);
exit (EXIT_FAILURE);
}
return (result);
}
/*
* my_fwrite() ... write data from global buffer to file
*
* Inputs:
* unsigned char *buffer Buffer to write out
* FILE *outfile File to write to
* int howmuch Number of bytes to write
*
* Output:
* None
*/
void my_fwrite (unsigned char *buffer, FILE *outfile, int howmuch) {
fwrite(buffer, 1, howmuch, outfile);
if (ferror(outfile)) {
fprintf(stderr,"%s: Error while writing data\n",program_name);
exit (EXIT_FAILURE);
}
return;
}
/*
* cleanup() ... called in case of an exit(). Frees memory I allocated.
*
* Inputs:
* None
*
* Output:
* None
*/
void cleanup (void) {
char **p;
free (program_name);
free (current_file);
free (in_buffer);
free (out_buffer);
free (tempfile);
if (pathList) {
p = pathList;
while(*p) free(*p++);
free (pathList);
}
if (tempfile)
remove (tempfile);
}
/*
* usage() ... print out a usage string gotten from udluse.c
*
* Inputs:
* None
*
* Outputs:
* None
*/
void usage (void) {
extern char use1[]; /* from udluse.c */
#ifdef GNO
extern char use2[];
#endif
fprintf(stderr,"%s",use1);
#ifdef GNO
if(!needsgno())
fprintf(stderr,"%s",use2);
#endif
return;
}
/*
* build_file_list() build the list of files to process
*
* Precondition:
* file is the file name to be added to the pathList
* recurse if non-zero, directories will be recursed
*
* Postcondition:
* pathList will be a NULL-terminated array of strings. Each
* string is a partial pathname (relative to rootdir) of a file
* to convert.
*
* Note: This is a recursive routine that uses up (3 * sizeof(char *))
* bytes of stack with each level of subdirectories.
*/
void build_file_list(char *file, short recurse) {
char *thisdir;
DIR *dir;
struct dirent *entry;
/* check for stack overflow */
recursionDepth++;
#ifdef OVERFLOW_CHECK
if ((recursionDepth * BYTES_PER_DEPTH + BASESIZE) > STACKSIZE) {
fprintf(stderr,"%s: Exceeded permitted nesting depth (%d levels)\n"
"Aborted.\n",program_name,recursionDepth);
exit(EXIT_FAILURE);
}
#endif
if (stat(file,&tstat)!=0) {
fprintf(stderr,"%s: Couldn't stat %s. File skipped\n",program_name,file);
--recursionDepth;
return;
}
if (recurse && S_ISDIR(tstat.st_mode)) {
char tstr[2];
/*
* It is a directory. recurse through it.
*/
/* save our state */
tstr[0] = dirbrk;
tstr[1] = '\0';
if (*currentDirectory) {
thisdir = strdup(currentDirectory);
} else {
thisdir = malloc(1);
if (thisdir != NULL) *thisdir='\0';
}
if (thisdir == NULL) {
perror("Couldn't duplicate current directory");
exit (EXIT_FAILURE);
}
if (*currentDirectory) strcat(currentDirectory,tstr);
strcat(currentDirectory,file);
if (currentDirectory[strlen(currentDirectory)-1] == dirbrk)
currentDirectory[strlen(currentDirectory)-1] = '\0';
/* recurse */
if ((dir = opendir(file)) == NULL) {
fprintf(stderr,"%s: Couldn't open %s. Directory skipped.\n",
program_name,currentDirectory);
} else {
if (chdir(file) !=0) {
fprintf(stderr,"couldn't cd to %s\n",currentDirectory);
exit (EXIT_FAILURE);
}
#ifdef READDIR_RETURNS_DOT
entry = readdir(dir); /* for "." */
entry = readdir(dir); /* for ".." */
#endif
while ((entry = readdir(dir))!=NULL) {
/* ignore hidden files */
#ifdef BROKEN_DIRENT_STRUCT
if (*(entry->d_name)!='.') build_file_list((entry->d_name)-2,1);
#else
if (*(entry->d_name)!='.') build_file_list(entry->d_name,1);
#endif
}
if (*thisdir) {
if ((chdir(rootdir)!=0) || (chdir(thisdir)!=0)) {
fprintf(stderr,"couldn't cd to %s\n",thisdir);
exit (EXIT_FAILURE);
}
} else {
if (chdir(rootdir)!=0) {
fprintf(stderr,"couldn't cd to calling directory\n");
exit (EXIT_FAILURE);
}
}
}
/* restore our state */
strcpy(currentDirectory,thisdir);
free(thisdir);
} else if (S_ISREG(tstat.st_mode)) {
/* It is a normal file. Add it to the pathList */
add_to_pathList(currentDirectory, file);
}
--recursionDepth;
return;
}
void add_to_pathList(char *thisdir, char *file) {
char **p;
/* expand the pathList if necessary */
if (pathSlotsUsed >= pathSlots) {
pathSlots += PATHLIST_QUANTUM;
#if BROKEN_REALLOC
if ((pathList==NULL) &&
((pathList = malloc((pathSlots+1) * sizeof(char *)))==NULL)) {
fprintf(stderr,"%s: Couldn't expand pathList\n",program_name);
exit (EXIT_FAILURE);
} else {
if ((p = realloc(pathList, (pathSlots+1) * sizeof(char *)))==NULL) {
fprintf(stderr,"%s: Couldn't expand pathList\n",program_name);
exit (EXIT_FAILURE);
}
pathList = p;
}
#else
if ((p = realloc(pathList,(pathSlots+1) * sizeof(char *)))==NULL) {
fprintf(stderr,"%s: Couldn't expand pathList\n",program_name);
exit (EXIT_FAILURE);
} else pathList = p;
#endif
}
/* add in the current directory and filename to the pathList */
pathList[pathSlotsUsed] = malloc(strlen(thisdir)+strlen(file)+2);
if (pathList[pathSlotsUsed] == NULL) {
fprintf(stderr,"%s: Couldn't duplicate filename %s%c%s\n",program_name,
thisdir,dirbrk,file);
exit (EXIT_FAILURE);
}
if (*thisdir) {
sprintf(pathList[pathSlotsUsed],"%s%c%s",thisdir,dirbrk,file);
} else {
strcpy(pathList[pathSlotsUsed],file);
}
pathSlotsUsed++;
pathList[pathSlotsUsed] = NULL;
return;
}
/* Mktemp() construct a unique file name
*
* This routine is slightly different than the Unix standard one,
* thus the capitalization.
*
* Inputs:
* base Template to construct the name upon. It should
* be in the format "nameXXXXXX" where all "X" are replaced
* in such a way that the resulting name is unique. There
* should be at least one, at most 15 "X" in the base name.
* base may contain a full or partial path.
*
* Outputs:
* Mktemp() returns a pointer to a dynamically allocated string
* containing a unique file name.
*
*/
char *Mktemp(const char *base)
{
static char id[16] = "AAAAAAAAAAAAAAA";
char *p1,*p2,*st;
if ((st = malloc(strlen(base) + 1)) == NULL)
{
fprintf(stderr,"%s: memory allocation failure\n", program_name);
exit (EXIT_FAILURE);
}
st = strcpy(st,base);
if (*st == '\0')
{
free (st);
if ((st = strdup("TXXXXXXX")) == NULL)
{
fprintf(stderr,"%s: memory allocation failure\n", program_name);
exit (EXIT_FAILURE);
}
}
/* Replace all "X" with part of ID string */
for(p1 = st + strlen(st) - 1,p2 = &id[14];
p1 >= st && p2 >= id && *p1 == 'X';
p1--,p2--)
*p1 = *p2;
/* Update ID string to "count" one further */
for(p1 = &id[14];p1 >= id;)
if(*p1 == 'Z')
{
*p1 = 'A';
p1--;
} else {
*p1 += 1;
break;
}
/* Make sure the file name does not already exist */
#ifdef GNO
if (needsgno() == TRUE) {
#endif
if (stat(st,&tstat) == 0)
{
free (st);
st = Mktemp (base);
}
#ifdef GNO
} else { /* ORCA/Shell doesn't like stat one little bit */
FILE *fp;
if ((fp = fopen(st,"r")) != NULL)
{
fclose(fp);
free (st);
st = Mktemp (base);
} else if ((fp = fopen(st,"a")) == NULL) {
free(st);
st = Mktemp (base);
} else {
fclose(fp);
}
}
#endif
return st;
}
/* get_path() ... extract path from filename
*
* Inputs:
* name A file name containing a full, partial or no path.
*
* Outputs:
* Pointer to a string in static memory containing the path
* to the given file, or an empty string if "name" contained
* no path. The string can hold MAXPATHLEN characters.
*/
char *get_path (const char *name)
{
int i;
strcpy(filebuffer, name);
for (i = strlen(filebuffer) - 1; i > 0 && filebuffer[i] != dirbrk; i--)
; /* empty loop to find end of path in name */
if (i != 0)
++i;
filebuffer[i] = '\0';
return filebuffer;
}
/* End Of File */

View File

@ -1,99 +0,0 @@
/*
* udl - Convert EOL formats freely between MS-DOS (CR/LF), Unix/Amiga (LF),
* and Apple (CR).
*
* Header file for routines common to both the Unix and Apple IIgs versions.
*
* $Id: common.h,v 1.8 1996/01/22 01:01:33 gdr Exp $
*
* Copyright (c) 1993-1995 Soenke Behrens, Devin Reade
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
#define BUFFERSIZE 0x2000
#define PATHLIST_QUANTUM 20
#define UDL_VERSION "Version 1.14"
#define STACKSIZE 2048
#define BYTES_PER_DEPTH 40
#define BASESIZE 700
#ifndef FALSE
# define FALSE 0
# define TRUE !FALSE
#endif
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
# define EXIT_SUCCESS 0
#endif
#ifdef HAS_ATEXIT
# define EXIT(a) exit(a)
#else
# define EXIT(a) { cleanup(); exit(a); }
#endif
enum file_format { tunix = 1, dos, apple, binary };
/* Since udl is so small, I dare to use some globals :) */
extern char *program_name; /* How was udl invoked? */
extern char *current_file; /* Name of current file */
extern char *tempfile; /* Name of temporary file */
extern unsigned char *in_buffer; /* My own buffering scheme instead of */
extern unsigned char *out_buffer; /* setvbuf() */
extern int verbose;
extern char filebuffer[MAXPATHLEN]; /* a scratch buffer for file names */
extern char currentDirectory[MAXPATHLEN];
extern char rootdir[MAXPATHLEN]; /* the initial directory */
extern struct stat tstat; /* temporary variable used to stat files */
extern int pathSlotsUsed; /* number of used and available slots in pathList,*/
extern int pathSlots; /* respectively. Both are initially zero. */
extern char **pathList; /* the list of files to process, given relative */
/* to the initial directory. Initially NULL, */
/* and NULL terminated. */
extern char dirbrk; /* the character used to separate parts of a path name */
extern int recursionDepth; /* levels of subdirectories that we've traversed */
extern int optind; /* part of getopt library */
extern int opterr;
/* Prototypes of functions in common.c */
extern void convert_gs (FILE *infile, FILE *outfile);
extern void convert_messy (FILE *infile, FILE *outfile);
extern void convert_tunix (FILE *infile, FILE *outfile);
extern int convert_fast_gs (FILE *infile, FILE *outfile);
extern int convert_fast_messy (FILE *infile, FILE *outfile);
extern int convert_fast_tunix (FILE *infile, FILE *outfile);
extern enum file_format get_file_format (unsigned char *buffer);
extern FILE *tryopen (char *file, char *mode);
extern int my_fread (FILE *infile, int howmuch);
extern void my_fwrite (unsigned char *buffer, FILE *outfile, int howmuch);
extern void cleanup (void);
extern void usage (void);
extern void build_file_list(char *file, short recurse);
extern void add_to_pathList(char *thisdir, char *file);
extern char *get_path(const char *name);
extern char *Mktemp(const char *base);
extern int needsgno(void);
/* not strictly necessary, but it cuts down on warnings from gcc */
#if defined(__GNUC__) || defined(_AIX)
extern char *getwd(char *);
#endif
#ifdef __GNUC__
extern char getopt(int, char **, char *);
#endif
/* End Of File */

View File

@ -1,9 +0,0 @@
Name: udl
Version: 1.15
Author: Soenke Behrens, Devin Reade
Contact: sbehrens@contech.demon.co.uk, gdr@myrias.ab.ca
Where: /usr/local/bin
FTP: ftp.cco.caltech.edu, grind.isca.uiowa.edu
Converts text between the CR, LF and CR/LF forms. Also available for Unix
machines, reasonably fast yet secure.

View File

@ -1,36 +0,0 @@
/*
* udl - Convert EOL formats freely between MS-DOS (CR/LF), Unix/Amiga (LF),
* and Apple (CR).
*
* Contains definitions of global variables declared in common.h
*
* $Id: globals.c,v 1.5 1996/01/22 01:01:34 gdr Exp $
*
* Copyright (c) 1993-1995 Soenke Behrens, Devin Reade
*/
#ifdef GNO
#pragma noroot
#endif
#include "common.h"
char *program_name; /* How was udl invoked? */
char *current_file; /* Name of current file */
char *tempfile; /* Name of temporary file */
unsigned char *in_buffer; /* My own buffering scheme instead of */
unsigned char *out_buffer; /* setvbuf() */
int verbose;
char filebuffer[MAXPATHLEN]; /* a scratch buffer for file names */
char currentDirectory[MAXPATHLEN];
char rootdir[MAXPATHLEN]; /* the initial directory */
struct stat tstat; /* temporary variable used to stat files */
int pathSlotsUsed; /* number of used and available slots in pathList,*/
int pathSlots; /* respectively. Both are initially zero. */
char **pathList; /* the list of files to process, given relative */
/* to the initial directory. Initially NULL, */
/* and NULL terminated. */
char dirbrk; /* the character used to separate parts of a path name */
int recursionDepth; /* levels of subdirectories that we've traversed */
/* End Of File */

View File

@ -1,95 +0,0 @@
.\" Copyright (c) 1993-1995 Soenke Behrens, Devin Reade
.\" $Id: udl.1,v 1.8 1996/01/22 01:01:34 gdr Exp $
.\"
.TH UDL 1 "Commands and Applications" "21 January 1996" "Version 1.15"
.SH NAME
udl - convert text files between different architectures
.SH SYNOPSIS
.BR udl
.BR -u | m | g
[
.B -Rvp
]
.I file1
[
.IR file2 " ..."
]
.SH DESCRIPTION
.B udl
converts files between different computer systems by changing the EOL
(End-Of-Line) character.
.PP
On the Apple IIgs,
.B udl
will skip any file that is not of type TXT or SRC.
No notice is given of this unless the
.B -v
flag is used.
Since Unix file systems do not have file types
.BR udl
is limited in the types of checks which it can carry out,
so the user must take care that
it is not invoked on object files or the like. On both platforms, if
.I file
appears to be a binary file (that is, no EOL is
found in the first part of the file) then
.I file
will be skipped.
Again, no notice is given of this unless the
.B -v
flag is used.
.PP
During file conversion
.B udl
creates a temporary file in the same directory as the original file.
The temporary file is close to or exactly the same size as the original
file.
.PP
When running under Byteworks' ORCA shell, the Orca shell wildcards
.BR =
and
.BR ?
are properly expanded in file names.
.SH OPTIONS
.IP \fB\-u\fP
Convert to use LF as EOL (Unix/Amiga).
.IP \fB\-m\fP
Convert to use CR/LF as EOL (MS-DOS).
.IP \fB\-g\fP
Convert to use CR as EOL (Apple).
.IP \fB\-p\fP
Be pedantic, only affects Unix<->Apple conversions, see below.
.IP \fB\-R\fP
Recurse through subdirectories.
.IP \fB\-v\fP
Be verbose, show the file udl is currently working on.
.PP
If you specify the
.B -p
switch,
.B udl
is pedantic while doing the conversion. This means: The input file may
contain bytes with a value of zero (0), and the input file may contain
different EOL characters (ie: MS-DOS and Unix style might be mixed in
one file). For conversions to or from MS-DOS
.B udl
is always pedantic, so this only affects conversions from Unix to Apple
or vice versa. Being pedantic slows udl down by a factor of 1.5.
.SH LIMITATIONS
When running under Gno on the Apple IIgs, there is a limit to the nesting
depth when recusing on subdirectories. This is because the routine that
is responsible for this behavior is itself recursive. The default 2k
stack size will allow about 33 levels of nested directories, so this limit
should not normally be a problem. If the limit is exceeded,
.BR udl
will exit with an error message before any files are changed, and before
the stack actually overflows.
.SH BUGS
Bug reports should be directed to one of the two addresses below.
.SH AUTHOR
Soenke Behrens <sbehrens@contech.demon.co.uk> with contributions by
Devin Reade <gdr@myrias.ab.ca>.
.SH VERSION
This is
.B udl
version 1.15.

View File

@ -1,22 +0,0 @@
#include "Types.Rez"
resource rVersion (0x1, purgeable1, nocrossbank) {
{ 1, 1, 5, /* version 1.1.4 */
release, /* development|alpha|beta|final|release */
0 /* non-final release number */
},
verBritain,
"udl",
"Copyright 1993-1996,\n"
"S" $"9A" "nke Behrens, Devin Reade"
};
resource rComment (0x1) {
"Text File Conversion Program\n"
"Converts files between CR, CR/LF, and LF.\n"
"(Apple, MS-DOS, and Unix)"
};
resource rComment (0x2) {
"Requires ORCA/Shell or GNO/ME"
};

View File

@ -1,417 +0,0 @@
/*
* udl - Convert EOL formats freely between MS-DOS (CR/LF), Unix/Amiga (LF),
* and Apple (CR).
*
* Apple IIgs specific routines.
*
* $Id: udlgs.c,v 1.9 1996/02/04 01:34:29 gdr Exp $
*
* Copyright (c) 1993-1995 Soenke Behrens, Devin Reade
*/
#include <orca.h>
#include <shell.h>
#include <gsos.h>
#include <getopt.h>
#include "common.h"
#define QUITFLAG 0x4000 /* udl is restartable */
#define DIRECTORY 0x0F
/*
* Globals
*/
int theType, theAuxType; /* Hold type of current file */
Next_WildcardGSPB NextWild; /* for handling ORCA/Shell style wildcards */
Init_WildcardGSPB InitWild;
extern pascal void SystemQuitFlags (unsigned);
extern pascal void SystemQuitPath (GSString255Ptr);
extern int needsgno(void);
extern void begin_stack_check(void);
extern int end_stack_check(void);
/*
* Prototypes of functions in this file
*/
extern int CheckGSOSType (char *name);
extern void SetGSOSType (char *name, int type, int auxtype);
extern int right_shell_version (void);
int main(int argc,char *argv[]) {
FILE *infile, *outfile;
int Tunix = FALSE;
int Messy = FALSE;
int GS = FALSE;
int careful = FALSE;
int converted;
int c;
static GSString255 gsp;
static ResultBuf255 rsp;
int R_flag = FALSE;
char **p;
verbose = FALSE;
recursionDepth = 0;
program_name = NULL;
tempfile = NULL;
current_file = NULL;
NextWild.pathName = NULL;
in_buffer = out_buffer = NULL;
pathSlotsUsed = 0;
pathSlots = 0;
pathList = NULL;
*currentDirectory = '\0';
recursionDepth=0;
#ifdef CHECK_STACK
begin_stack_check();
#endif
/* In case of exit(), free the mem I allocated */
atexit (cleanup);
/* Make udl restartable */
SystemQuitFlags (QUITFLAG);
SystemQuitPath (NULL);
if (right_shell_version() == FALSE) {
fprintf(stderr,"%s requires at least ORCA/Shell 2.0"
" or GNO/ME 1.0\n", argv[0]);
exit (EXIT_FAILURE);
}
if ((program_name = strdup (argv[0])) == NULL) {
fprintf(stderr,"%s: memory allocation failure\n",argv[0]);
exit (EXIT_FAILURE);
}
if (argc < 3) {
usage();
exit (EXIT_FAILURE);
}
/* Get and process arguments */
optind = 0;
opterr = 1;
while ((c = getopt (argc, argv, "pvugmR")) != EOF) {
switch (c) {
case 'v':
verbose = TRUE;
break;
case 'p':
careful = TRUE;
break;
case 'u':
if (Tunix == TRUE || Messy == TRUE || GS == TRUE) {
fprintf(stderr, "%s: You may not "
"specify more than one conversion option\n",program_name);
exit (EXIT_FAILURE);
}
Tunix = TRUE;
break;
case 'm':
if (Tunix == TRUE || Messy == TRUE || GS == TRUE) {
fprintf(stderr, "%s: You may not "
"specify more than one conversion option\n",program_name);
exit (EXIT_FAILURE);
}
Messy = TRUE;
break;
case 'g':
if (Tunix == TRUE || Messy == TRUE || GS == TRUE) {
fprintf(stderr, "%s: You may not "
"specify more than one conversion option\n",program_name);
exit (EXIT_FAILURE);
}
GS = TRUE;
break;
case 'R':
R_flag++;
break;
case '?':
usage();
exit (EXIT_FAILURE);
default:
fprintf (stderr, "%s: Internal getopt error\n", program_name);
exit (EXIT_FAILURE);
break;
}
}
if (optind == argc) { /* no files specified */
usage();
exit (EXIT_FAILURE);
}
if (Tunix == FALSE && GS == FALSE && Messy == FALSE) {
fprintf(stderr,"%s: You have to specify a destination "
"format.\n",program_name);
exit (EXIT_FAILURE);
}
if (verbose == TRUE) {
printf ("%s version %s\n",program_name,UDL_VERSION);
}
if ((in_buffer = malloc(BUFFERSIZE+1)) == NULL ||
(out_buffer = malloc(BUFFERSIZE+1)) == NULL) {
fprintf(stderr,"%s: Unable to buffer files\n",program_name);
exit (EXIT_FAILURE);
}
/* Orca Shell: expand wildcards */
if (!needsgno()) {
NextWild.pCount = 1;
InitWild.pCount = 2;
rsp.bufSize = 259;
NextWild.pathName = &rsp;
InitWild.wFile = &gsp;
if (R_flag) {
InitWild.flags = 0x2000 | 0x1000;
} else {
InitWild.flags = 0;
}
dirbrk = ':'; /* enforced by NextWildcardGS */
/* loop through all command line args */
for (; optind < argc; optind++) {
size_t i;
int num_of_files;
i = strlen(argv[optind]);
strncpy (gsp.text,argv[optind],i);
gsp.length = i;
InitWildcardGS (&InitWild);
num_of_files = 0;
/* loop through all matches of wildcards */
for (;;) {
NextWildcardGS (&NextWild);
if (toolerror()) {
fprintf(stderr,"%s: Fatal internal error, "
"exiting\n", program_name);
exit (EXIT_FAILURE);
}
/* No further file found by NextWildcardGS */
if(!rsp.bufString.length)
break;
num_of_files++;
if((current_file = calloc(1,rsp.bufString.length + 1)) == NULL) {
fprintf(stderr,"%s: memory allocation failure\n",program_name);
exit (EXIT_FAILURE);
}
strncpy(current_file, rsp.bufString.text,rsp.bufString.length);
add_to_pathList("",current_file);
free(current_file);
current_file = NULL;
} /* for (;;) */
if (num_of_files == 0)
fprintf(stderr,"%s: No files found that match %s\n",
program_name,argv[optind]);
} /* for (; optind < argc; optind++) */
}
/* gsh or other Gno shell */
else {
/* save the directory we're in */
if (getwd(rootdir)==NULL) {
fprintf(stderr,"%s: Couldn't stat .\n",program_name);
exit (EXIT_FAILURE);
}
for (; optind<argc; optind++) {
/* set the directory separator character. */
dirbrk = (strchr(argv[optind],':')!=NULL) ? ':' : '/';
build_file_list(argv[optind],R_flag);
chdir(rootdir);
*currentDirectory = '\0';
}
}
/* files were all directories and no -R flag given */
if (!pathList) {
if (verbose) printf("%s: no files to process\n",program_name);
exit(EXIT_SUCCESS);
}
p = pathList;
while(*p) {
current_file = *p;
if (CheckGSOSType (current_file) == FALSE) {
p++;
continue;
}
if (verbose == TRUE) {
printf("%s: Working on %s\n",program_name,current_file);
}
infile = tryopen(current_file,"rwb");
tempfile = Mktemp(strcat(get_path(current_file), "udltmpXX"));
outfile = tryopen(tempfile,"wb");
if (careful) {
converted = TRUE; /* always */
if (GS)
convert_gs(infile,outfile);
else if (Tunix)
convert_tunix(infile,outfile);
else
convert_messy(infile,outfile);
} else {
if (GS)
converted = convert_fast_gs(infile,outfile);
else if (Tunix)
converted = convert_fast_tunix(infile,outfile);
else
converted = convert_fast_messy(infile,outfile);
}
if (fclose (infile) == EOF || fclose (outfile) == EOF) {
perror ("closing files");
exit (EXIT_FAILURE);
}
if (converted) { /* Temp file contains converted data */
if (remove (current_file) != 0) {
perror ("removing original file");
exit (EXIT_FAILURE);
}
if (rename (tempfile,current_file) != 0) {
perror ("cannot rename temporary file");
exit (EXIT_FAILURE);
}
} else
remove (tempfile);
free (tempfile); tempfile = NULL;
SetGSOSType (current_file, theType, theAuxType);
p++;
} /* end while */
#ifdef CHECK_STACK
fprintf(stderr,"stack usage: %d bytes\n",end_stack_check());
#endif
return (EXIT_SUCCESS);
}
/*
* CheckGSOSType() ... check if a file is of type TXT or SRC
*
* Inputs:
* char *name Name of file to check
*
* Outputs:
* int Boolean, TRUE if file type is TXT or SRC, FALSE otherwise
*/
int CheckGSOSType(char *name) {
#define TXT 0x04
#define SRC 0xB0
static GSString255 gst;
static FileInfoRecGS fir = {5};
size_t i;
i = strlen (name);
gst.length = i;
strncpy(gst.text,name,i);
fir.pathname = &gst;
GetFileInfoGS(&fir);
if (toolerror()) {
fprintf (stderr,"%s: GS/OS error on %s: 0x%04X\n",
program_name,name,toolerror());
exit (EXIT_FAILURE);
}
if ((fir.fileType != TXT) && (fir.fileType != SRC)) {
if (verbose && (fir.fileType != DIRECTORY))
fprintf(stderr,"%s: %s is not of type TXT or "
"SRC ... skipping\n",program_name,current_file);
return (FALSE);
} else {
theType = fir.fileType;
theAuxType = fir.auxType;
return (TRUE);
}
}
/*
* SetGSOSType() ... set file and auxtype of a file.
*
* Inputs:
* char *name Name of file to be affected
* int type File type it should be set to
* int auxtype Auxiliary type it should be set to
*
* Outputs:
* None
*/
void SetGSOSType (char *name, int type, int auxtype) {
static GSString255 gst;
static FileInfoRecGS fir = {4, NULL, 0xE3};
size_t i;
i = strlen (name);
gst.length = i;
strncpy(gst.text,name,i);
fir.pathname = &gst;
fir.fileType = type;
fir.auxType = auxtype;
SetFileInfoGS(&fir);
if (toolerror()) {
fprintf (stderr,"%s: GS/OS error on %s: 0x%04X\n",
program_name,name,toolerror());
exit (EXIT_FAILURE);
}
}
/*
* right_shell_version() ... check if at least ORCA/Shell 2.0 or
* GNO/ME 1.0 is active.
*
* Inputs:
* None
*
* Output:
* int Boolean, TRUE if shell is satisfactory, FALSE otherwise
*/
int right_shell_version (void) {
static VersionPB vpb;
VERSION(&vpb);
if (vpb.version[0] < '2' || strcmp (shellid(),"BYTEWRKS") != 0)
return FALSE;
else
return TRUE;
}
/* End Of File */

View File

@ -1,214 +0,0 @@
/*
* udl - Convert EOL formats freely between MS-DOS (CR/LF), Unix/Amiga (LF),
* and Apple (CR).
*
* Unix specific routines.
*
* $Id: udlunix.c,v 1.8 1996/01/22 01:01:35 gdr Exp $
*
* Copyright (c) 1993-1995 Soenke Behrens, Devin Reade
*/
#include "common.h"
extern char *strdup(const char *);
int main(int argc,char *argv[]) {
FILE *infile, *outfile;
char *p;
int Tunix = FALSE;
int Messy = FALSE;
int GS = FALSE;
int careful = FALSE;
int converted;
int c;
int R_flag = FALSE;
verbose = FALSE;
program_name = NULL;
tempfile = NULL;
current_file = NULL;
in_buffer = out_buffer = NULL;
pathSlotsUsed = 0;
pathSlots = 0;
pathList = NULL;
*currentDirectory = '\0';
recursionDepth=0;
/* In case of exit(), free the mem I allocated */
#ifdef HAS_ATEXIT
atexit (cleanup);
#endif
if ((program_name = strdup (argv[0])) == NULL) {
fprintf(stderr,"%s: memory allocation failure\n",argv[0]);
exit (EXIT_FAILURE);
}
if (argc < 3) {
usage();
exit (EXIT_FAILURE);
}
/* Get and process arguments */
opterr = 1;
while ((c = getopt (argc, argv, "pvugmR")) != EOF) {
switch (c) {
case 'v':
verbose = TRUE;
break;
case 'p':
careful = TRUE;
break;
case 'u':
if (Tunix == TRUE || Messy == TRUE || GS == TRUE) {
fprintf(stderr, "%s: You may not "
"specify more than one conversion option\n",program_name);
exit (EXIT_FAILURE);
}
Tunix = TRUE;
break;
case 'm':
if (Tunix == TRUE || Messy == TRUE || GS == TRUE) {
fprintf(stderr, "%s: You may not specify more than one "
"conversion option\n",program_name);
exit (EXIT_FAILURE);
}
Messy = TRUE;
break;
case 'g':
if (Tunix == TRUE || Messy == TRUE || GS == TRUE) {
fprintf(stderr, "%s: You may not specify more than one "
"conversion option\n",program_name);
exit (EXIT_FAILURE);
}
GS = TRUE;
break;
case 'R':
R_flag++;
break;
case '?':
usage();
exit (EXIT_FAILURE);
default:
fprintf (stderr, "%s: Internal getopt error\n", program_name);
exit (EXIT_FAILURE);
break;
}
}
/* no files specified */
if (optind == argc) {
usage();
exit (EXIT_FAILURE);
}
if (Tunix == FALSE && GS == FALSE && Messy == FALSE) {
fprintf(stderr,"%s: You have to specify a destination "
"format.\n",program_name);
exit (EXIT_FAILURE);
}
if (verbose == TRUE) {
printf ("%s %s\n",program_name,UDL_VERSION);
}
/* Now process the files I got */
if ((in_buffer = malloc(BUFFERSIZE+1)) == NULL ||
(out_buffer = malloc(BUFFERSIZE+1)) == NULL) {
fprintf(stderr,"%s: Unable to buffer files\n",program_name);
exit (EXIT_FAILURE);
}
/* save the directory we're in */
if (getwd(rootdir)==NULL) {
fprintf(stderr,"%s: Couldn't stat .\n",program_name);
exit (EXIT_FAILURE);
}
/* set the directory separator character. */
dirbrk = '/';
/* build the list of files to process */
for (; optind<argc; optind++) {
build_file_list(argv[optind],R_flag);
chdir(rootdir);
*currentDirectory = '\0';
}
/* files were all directories and no -R flag given */
if (!pathList) {
if (verbose) printf("%s: no files to process\n",program_name);
exit(EXIT_SUCCESS);
}
for (c=0; pathList[c]; c++) {
if((current_file = strdup(pathList[c])) == NULL) {
fprintf(stderr,"%s: memory allocation failure\n", program_name);
exit (EXIT_FAILURE);
}
if (verbose == TRUE) {
printf("%s: Working on %s\n",program_name,
current_file);
}
infile = tryopen(current_file,"rwb");
tempfile = Mktemp(strcat(get_path(current_file), "udltmpXX"));
outfile = tryopen(tempfile,"wb");
if (careful) {
converted = TRUE; /* always */
if (GS)
convert_gs(infile,outfile);
else if (Tunix)
convert_tunix(infile,outfile);
else
convert_messy(infile,outfile);
} else {
if (GS)
converted = convert_fast_gs(infile,outfile);
else if (Tunix)
converted = convert_fast_tunix(infile,outfile);
else
converted = convert_fast_messy(infile,outfile);
}
if (fclose (infile) == EOF || fclose (outfile) == EOF) {
perror ("closing files");
exit (EXIT_FAILURE);
}
if (converted) { /* Temp file contains converted data */
if (remove (current_file) != 0) {
perror ("removing original file");
exit (EXIT_FAILURE);
}
if (rename (tempfile,current_file) != 0) {
perror ("cannot rename temporary file");
exit (EXIT_FAILURE);
}
} else
remove (tempfile);
free (tempfile); tempfile = NULL;
free(current_file);
current_file = NULL;
} /* for (c=0; pathList[c]; c++) */
return (EXIT_SUCCESS);
}
/* End Of File */

View File

@ -1,32 +0,0 @@
/*
* udl - Convert EOL formats freely between MS-DOS (CR/LF), Unix/Amiga (LF),
* and Apple (CR).
*
* Usage strings.
*
* $Id: udluse.c,v 1.8 1996/01/22 01:01:36 gdr Exp $
*
* Copyright (c) 1993-1995 Soenke Behrens, Devin Reade
*/
#ifdef GNO
#pragma noroot
#endif
char use1 [] =
"udl 1.15 by Soenke Behrens, Devin Reade\n"
"Usage: udl -u|g|m [-Rvp] file1 [file2 ...]\n\n"
"Options:\n"
" -u Convert file to use LF as EOL character.\n"
" -g Convert file to use CR as EOL character.\n"
" -m Convert file to use LF/CR as EOL character.\n"
" -R Recurse through subdirectories.\n"
" -p Be pedantic.\n"
" -v Be verbose about it.\n\n"
"udl creates a temporary file in the directory of the original file.\n"
"The original file is overwritten after conversion.\n";
char use2 [] =
"\nFiles may contain ORCA/Shell style wildcards.\n";
/* End Of File */