|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 6354 (0x18d2)
Types: TextFile
Notes: UNIX file
Names: »file.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/file.c«
/*
* 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);
}