DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦b3f17544e⟧ TextFile

    Length: 4880 (0x1310)
    Types: TextFile
    Notes: UNIX file
    Names: »help.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦f4b8d8c84⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »cmd/help.c« 

TextFile

/*
 * Command to give help on various command's usages.
 * Also, this command allows user-specific information
 * to be kept.
 */

#include <stdio.h>
#include <sys/stat.h>

#define	NLINE	512		/* Longest helpfile line */

char	doc[50];
char	buf[BUFSIZ];
char	*list[2];

char	helpline[NLINE];
char	helpfile[] = "/etc/helpfile";
FILE	*shf;			/* System helpfile */
FILE	*uhf;			/* User helpfile */

/*
 * Structure to speed lookup time.
 */
struct	look	{
	long	l_seek;
	char	*l_name;
};

struct	look	*lread();

char	helpuse[] = "\
The 'help' command prints a brief description of the usage of a command.\n\
For example, to get information about the 'who' command, type:\n\
	help who\n\
The 'man' command provides more detailed descriptions of commands.\n\
\n\
";

char	noinf[] = "No information on %s\n";
char	*getenv();

main(argc, argv)
char *argv[];
{
	register char **ap;
	register int estat = 0;
	char *fn;

	shf = fopen(helpfile, "r");
	if ((fn = getenv("HELP")) != NULL)
		uhf = fopen(fn, "r");
	setbuf(stdout, buf);
	ap = argv+1;
	if (argc < 2) {
		fprintf(stderr, helpuse);
		ap = list;
		if ((*ap = getenv("LASTERROR")) == NULL)
			exit(0);
	}
	while (*ap != NULL) {
		if (help(*ap)) {
			printf(noinf, *ap);
			estat |= 1;
		}
		if (*++ap != NULL)
			putchar('\n');
		fflush(stdout);
	}
	exit(estat);
}

/*
 * This routine looks for information
 * in the on-line documentation for
 * the specified command.
 * The information is bracketed by `.HS'
 * and `.HE'.
 * If nothing is found, search the other two places.
 */
help(command)
char *command;
{
	register int bad = 1;
	register FILE *hf;

	sprintf(doc, "/usr/man/cmd/%s", command);
	if ((hf = fopen(doc, "r")) == NULL) {
		strcat(doc, "m");
		if ((hf = fopen(doc, "r")) == NULL)
			goto other;
	}
	for (;;) {
		if (fgets(helpline, NLINE, hf) == NULL)
			break;
		if (strcmp(helpline, ".HS\n") == 0) {
			bad = 0;
			break;
		}
	}
	if (!bad)
		while (fgets(helpline, NLINE, hf) != NULL
		    && strcmp(helpline, ".HE\n") != 0)
			fputs(helpline, stdout);
	fclose(hf);
other:
	if (bad)
		if (bad = lookup(command, shf, "/etc/helpindex"))
			bad = lookup(command, uhf, NULL);
	return (bad);
}

/*
 * Lookup a command in the given file.
 * The format is to look for # lines.
 * The index-file is provided to speed up
 * the lookup in situations where there is a very
 * large system help file.
 */
lookup(com, fp, ind)
register char *com;
FILE *fp;
char *ind;
{
	if (fp == NULL)
		return (1);
	if (fastlook(com, fp, ind))
		return (1);
	while (fgets(helpline, NLINE, fp) != NULL)
		if (helpline[0] == '#') {
			helpline[strlen(helpline)-1] = '\0';
			if (strcmp(com, helpline+1) == 0) {
				while (fgets(helpline, NLINE, fp) != NULL) {
					if (helpline[0] == '#')
						break;
					fputs(helpline, stdout);
				}
				return (0);
			}
		}
	return (1);
}

/*
 * Possibly seek the helpfile to the right place
 * based on an index file.
 * Return non-zero only when it is impossible to
 * find it.
 * If the index file is out of date, re-build it.
 */
fastlook(com, fp, ind)
char *com;
FILE *fp;
char *ind;
{
	register char *cp, *ep;
	register struct look *lp;
	struct look look;
	FILE *ifp;
	long seek = 0;
	int found = 0;
	static struct stat sb;
	long htime;

	fstat(fileno(fp), &sb);
	htime = sb.st_mtime;
	if (stat(ind, &sb) < 0)
		goto rebuild;
	if (htime < sb.st_mtime) {
		if ((ifp = fopen(ind, "r")) == NULL)
			goto rebuild;
		while ((lp = lread(ifp)) != NULL)
			if (strcmp(com, lp->l_name) == 0) {
				seek = lp->l_seek;
				found++;
				break;
			}
		fclose(ifp);
		if (found) {
			fseek(fp, seek, 0);
			return (0);
		}
		return (1);
	}

rebuild:
	/*
	 * Re-build the index file.
	 */
	if ((ifp = fopen(ind, "w")) == NULL)
		return (0);
	for (;;) {
		look.l_seek = ftell(fp);
		if (fgets(helpline, NLINE, fp) == NULL)
			break;
		cp = helpline;
		if (*cp++ != '#')
			continue;
		while (*cp==' ' && *cp=='\t')
			cp++;
		ep = cp;
		while (*ep!='\n' && *ep!='\0' && *ep!=' ' && *ep!='\t')
			ep++;
		*ep = '\0';
		look.l_name = cp;
		if (strcmp(com, cp) == 0) {
			seek = look.l_seek;
			found++;
		}
		lwrite(&look, ifp);
	}
	fclose(ifp);
	if (found) {
		fseek(fp, seek, 0);
		return (0);
	}
	return (1);
}

/*
 * Read in a look structure.  Return NULL
 * on end of file or error.
 */
struct look *
lread(fp)
register FILE *fp;
{
	register char *cp;
	register int c;
	static struct look look;
	static char name[50];

	look.l_name = name;
	if (fread(&look.l_seek, sizeof look.l_seek, 1, fp) != 1)
		return (NULL);
	for (cp = name; cp<&name[49]; cp++) {
		if ((c = getc(fp)) == EOF)
			return (NULL);
		*cp = c;
		if (c == '\0')
			break;
	}
	return (&look);
}

/*
 * Write out a structure to the
 * given file pointer.
 */
lwrite(lp, fp)
register struct look *lp;
FILE *fp;
{
	register char *cp;

	fwrite(&lp->l_seek, 1, sizeof lp->l_seek, fp);
	cp = lp->l_name; do {
		putc(*cp, fp);
	} while (*cp++ != '\0');
}