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

⟦b694d967c⟧ TextFile

    Length: 6354 (0x18d2)
    Types: TextFile
    Notes: UNIX file
    Names: »file.c«

Derivation

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

TextFile

/*
 * Look at a file and try to
 * figure out its type. Knows about the various
 * flavours of filesystem entries, object files of various
 * types, C programs, input to one of the various flavours
 * of text formatter, etc.
 */
#include <stdio.h>
#include <ctype.h>
#include <stat.h>
#include "n.out.h"
#include <canon.h>
#include <ar.h>

/* UNIX archive magic numbers */
#define	UARMAG	0177545		/* UNIX v7 archives */
#define	OUARMAG	0177555		/* UNIX v6 and previous archives */

#define	EXEC	(S_IEXEC|(S_IEXEC<<3)|(S_IEXEC<<6))

/*
 * The first BUFSIZ bytes of the
 * file in question are read into this
 * union. It contains members for accessing
 * the possible file structures.
 */
union	iobuf
{
	char	u_buf[BUFSIZ];		/* General data */
	struct	ldheader u_ld;		/* \f

Object file header */
	int	u_armag;		/* Archive number */
};

union	iobuf	iobuf;
char	*file();
char	*textclass();
char	*objclass();
char	*dirtype();
char	*mtype();
char	*strcat();

main(argc, argv)
char *argv[];
{
	struct stat sb;
	register char *p;
	register int i;
	register int estat;

	if (argc < 2) {
		fprintf(stderr, "Usage: file name ...\n");
		exit(1);
	}
	estat = 0;
	for (i=1; i<argc; i++) {
		p = argv[i];
		if (stat(p, &sb) < 0) {
			fprintf(stderr, "file: %s: not accessible\n", p);
			estat = 1;
			continue;
		}
		printf("%s: %s\n", p, file(&sb, p));
	}
	exit(estat);
}

/*
 * Routine to guess filetype
 */
char *
file(sbp, fn)
struct stat *sbp;
char *fn;
{
	static char buf[50];
	int magic;
	register int i, nb;
	register int fd = -1;

	if ((sbp->st_mode&S_IFMT) != S_IFREG) {
		switch (sbp->st_mode & S_IFMT) {
		case S_IFDIR:
			return (dirtype(fn));

		case S_IFBLK:
			sprintf(buf, "block special file %d/%d",
			    major(sbp->st_rdev), minor(sbp->st_rdev));
			return (buf);

		case S_IFCHR:
			sprintf(buf, "character special file %d/%d",
			    major(sbp->st_rdev), minor(sbp->st_rdev));
			return (buf);

		case S_IFMPB:
			return ("block multiplexor file");

		case S_IFMPC:
			return ("character multiplexor file");

		case S_IFPIP:
			return ("named pipe");

		default:
			return ("invalid filetype");
		}
	}
	if ((fd = open(fn, 0)) < 0)
		return ("unreadable");
	if ((nb = read(fd, (char *) &iobuf, sizeof(iobuf))) < 0) {
		close(fd);
		return ("read error");
	}
	close(fd);
	if (nb == 0)
		return ("empty");
	if (nb >= sizeof(struct ldheader)) {
		magic = iobuf.u_ld.l_magic;
		canint(magic);
		if (magic == L_MAGIC) {
			canint(iobuf.u_ld.l_flag);
			canint(iobuf.u_ld.l_machine);
			return (objclass(fd, &iobuf.u_ld));
		}
	}
	if (nb >= sizeof (int)) {
		magic = iobuf.u_armag;
		canint(magic);
		if (magic == ARMAG)
			return ("archive");
		if (magic == UARMAG)
			return ("seventh edition archive");
		if (magic == OUARMAG)
			return ("sixth edition archive");
	}
	if (hasnonascii((unsigned char *) &iobuf, nb))
		return ("binary data");
	if ((sbp->st_mode&EXEC) != 0)
		return ("commands");
	return (textclass((unsigned char *) &iobuf, nb));
}

/*
 * Return the type of the directory.
 * Currently, only "s.*" is recognised as SCCS directory.
 */
char *
dirtype(dn)
register char *dn;
{
	register char *cp;

	for (cp=dn; *cp!='\0'; cp++)
		;
	while (cp > dn)
		if (*--cp == '/') {
			cp++;
			break;
		}
	if (cp[0]=='s' && cp[1]=='.')
		return ("SCCS directory");
	return ("directory");
}

/*
 * Return true if there ar characters
 * in the buffer that do not look like good
 * ascii characters.
 * This routine knows that ascii is a seven
 * bit code.
 */
hasnonascii(bp, nb)
register unsigned char *bp;
register nb;
{
	while (nb--) {
		if (!isascii(*bp))
			return (1);
		if (!(isprint(*bp) || isspace(*bp) || *bp=='\b'))
			return (1);
		bp++;
	}
	return (0);
}

/*
 * Classify the first `nb'
 * bytes of a text file.
 */
char *
textclass(bp, nb)
register unsigned char *bp;
register nb;
{
	register int c;
	int nlf = 1;
	int nlbrace;
	int nrbrace;
	int nsharps;
	int nsemi;
	int xmail;
	char *sbp = bp;

	nlbrace = 0;
	nrbrace = 0;
	nsharps = 0;
	nsemi = 0;
	xmail = 0;
	while (nb--) {
		c = *bp++;
		if (c=='.' && strncmp(bp, "globl", 5)==0)
			return ("assembler");
		if (nlf) {
			if (c == '.')
				return ("nroff, tbl or eqn input");
			else if (c == ':')
				return ("commands");
			else if (c == '#')
				++nsharps;
			else if (c=='%')
				if (*bp=='%' || *bp=='{' || *bp=='}')
					return ("yacc or lex input");
		}
		if (c == '{')
			++nlbrace;
		else if (c == '}')
			++nrbrace;
		if (c == '\n') {
			nlf = 1;
			if (bp[-2] == ';')
				nsemi++;
			if (((bp-sbp) % 22) == 0) {
				if (bp[-2]==' ' || bp[-2]=='!')
					xmail++;
			} else
				xmail = 0;
		} else
			nlf = 0;
	}
	if (xmail)
		return ("xmail encoded text");
	if ((nsharps || nsemi) && (nlbrace || nrbrace))
		return ("C program");
	return ("probably text");
}

/*
 * Figure out the type of an
 * object file. Tag it with the machine
 * id if not for the machine upon which the
 * command is running.
 */
char *
objclass(fd, lhp)
register struct ldheader *lhp;
{
	static char type[64];
	register char *mch;
	struct ldsym lds;
	register size_t stbase;
	register i;

	type[0] = '\0';
	if ((lhp->l_flag&LF_32) != 0)
		strcat(type, "32 bit ");
	if ((lhp->l_flag&LF_SLIB) != 0)
		strcat(type, "shared library ");
	if ((lhp->l_flag&LF_SLREF) != 0)
		strcat(type, "libref ");
	if ((lhp->l_flag&LF_SHR) != 0)
		strcat(type, "shared ");
	if ((lhp->l_flag&LF_SEP) != 0)
		strcat(type, "separate ");
	if ((lhp->l_flag&LF_KER) != 0) {
		register unsigned ssize;

		ssize = sizeof (lds);
		if ((lhp->l_flag & LF_32) == 0) {
			stbase = sizeof(*lhp) - 2*sizeof(int);
			ssize -= sizeof (int);
		} else {
			canshort(lhp->l_tbase);
			stbase = lhp->l_tbase;
		}
		for (i=L_SHRI; i<L_SYM; ++i)
			if (i!=L_BSSI && i!=L_BSSD) {
				cansize(lhp->l_ssize[i]);
				stbase += lhp->l_ssize[i];
			}
		lseek(fd, stbase, 0);
		cansize(lhp->l_ssize[L_SYM]);
		while (lhp->l_ssize[L_SYM] != 0) {
			if (read(fd, &lds, ssize) != ssize)
				break;
			canshort(lds.ls_type);
			if (strncmp(lds.ls_id, "conftab_", NCPLN) == 0
			&& (lds.ls_type&LR_SEG) != L_REF)
				break;
			lhp->l_ssize[L_SYM] -= ssize;
		}
		strcat(type, lhp->l_ssize[L_SYM]==0?"kernel ":"driver ");
	}
	strcat(type, "executable");
	if ((lhp->l_flag&LF_NRB) == 0)
		strcat(type, " with relocation");
	if ((mch = mtype(lhp->l_machine)) == NULL)
		mch = "Unknown machine type";
	sprintf(type, "%s (%s)", type, mch);
	return (type);
}