[comp.os.minix] file

bert@bebux.UUCP (Bert Reuling) (12/27/88)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
#                 "End of archive"
#
# Contents:
#
#   README
#   Makefile
#   file.c
#   file.1
#   expargs.c
#   stat.c
#   types.h
#   stat.h
#
# Wrapped by bert@tjilp on Thu Dec 26 21:17:37 1988
PATH=/bin:/usr/bin:/usr/local/bin ; export PATH
if test -f 'README' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: README"
else
   echo "x - README (1882 characters)"
sed 's/^X//' <<\END_OF_SHAR >README
X
X
X                             file(1)
X
X                        Copyright (c) 1988
X
X                           Bert Reuling
X
X            This file(1) program may be copied freely.
X
X
X
X     A  few  #ifdef's  are added for HP9000: s200, s500 and s800,
X     Sequent: BALANCE and SYMMETRY, DEC:  VAX  and  PDP11,  AT&T:
X     3B20, 3B2 and 3B5 and I386 executables. Just compile with cc
X     -o file -DBALANCE file.c if you want  file(1)  to  recognize
X     Sequent BALANCE executables, or -DALL if you want file(1) to
X     recognize  ALL  magic  numbers.   The   magic   numbers   in
X     executables  for  SYMMETRY,  VAX,  M68K,  AT&T 3B20 and AT&T
X     3B2/5 remain untested.
X
X     Two functions are included in this distribution  to  aid  in
X     porting  of Unix/Minix programs to GEM/MSDOS (i.e. expargs()
X     and stat(2)). file(1) has been ported  to  MSDOS  v3.20  (HP
X     Vectra)  with  the  aid  of  these functions and the Lattice
X     v3.20 compiler. It has been ported to GEMDOS v0.19 (AtariST)
X     using the Megamax v1.1 compiler and the same functions.
X
X     One  remaining problem is the definition of magic's in MINIX
X     executables. Minix-PC didn't have  real  object  files,  but
X     packed  assembler.  The magic numbers for MINIX object files
X     for this program came from the actual object files as  found
X     on MINIX-ST v1.1. This might not be the right number for the
X     current MINIX-PC version (1.3b?).
X
X     Please send reports on magic numbers, bugs,  fixes,  etc,...
X     to:
X
X
X                       ...!mcvax!bebux!bert
X
X
X                 /             /      Bert Reuling
X                /-,  ,--, ,-, /-      p/a Radio Holland bv
X               /  / /--- /   /        Jan Rebelstraat 20
X               `-'  `--  `   `--      1069 CC Amsterdam
X                                      The Netherlands
X
X                  MINIX werkgroep UNIXgg/HCC
END_OF_SHAR
   if test 1882 -ne `wc -c <'README'`
   then
      echo "$0: unpacked with wrong size: README"
   fi
fi
if test -f 'Makefile' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: Makefile"
else
   echo "x - Makefile (658 characters)"
sed 's/^X//' <<\END_OF_SHAR >Makefile
X#
X#  Makefile for *file* v1.3 Copyright (c) 1988 Bert Reuling
X#
X#  specify system e.g. MINIX, GEMDOS, MSDOS, BALANCE, etc,...
X#
XSYSTEM=ALL
X#
X#  for unix/minix version:
X#
Xfile: file.o
X	cc -o file file.o
Xfile.o: file.c
X	cc -c -D$(SYSTEM) -O file.c
X#
X#  for GEMDOS/MSDOS version
X#
X# specify NATIVE=GEMDOS or NATIVE=MSDOS
X#
X#NATIVE=MSDOS
X#
X#file: file.o
X#	cc -o file file.o stat.o expargs.o
X#file.o: file.c
X#	cc -c -D$(SYSTEM) -DWILDCARDS -O file.c
X#stat.o: stat.c types.h stat.h
X#	cc -c -D$(NATIVE) -O stat.c
X#expargs.o: expargs.c
X#	cc -c -D$(NATIVE) -O expargs.c
X#
Xarchive:
X	shar README Makefile file.c file.1 expargs.c stat.c types.h stat.h >file.shar
X#
X#
X#
X
END_OF_SHAR
   if test 658 -ne `wc -c <'Makefile'`
   then
      echo "$0: unpacked with wrong size: Makefile"
   fi
fi
if test -f 'file.c' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: file.c"
else
   echo "x - file.c (15892 characters)"
sed 's/^X//' <<\END_OF_SHAR >file.c
X/*
X *  file  -  determine file type. Copyright (c) 1988 Bert Reuling
X */
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#ifndef TRUE
X#define TRUE          1
X#define FALSE         0
X#endif
X
X#define PROBESIZ     512    /* test size       */
X#define MAXFNAME     256    /* max filename    */
X
X#ifdef ALL
X#define HP9000      /* Hewlett & Packard hp9000 HP-UX   */
X#define SEQUENT     /* Sequent Balance & Symmetry DYNIX */
X#define ATT         /* AT&T 3B2 Unix System V           */
X#define PDP11       /* DEC pdp11 Unix version 7         */
X#define VAX         /* DEC VAX ULTRIX                   */
X#define MC68K       /* Motorola mc680x0 Unix System V   */
X#define I386        /* iNTEL iAPX386 Unix System V      */
X#define MINIX       /* MC68000 Minix-ST v1.1            */
X#define MSDOS       /* PC/XT/AT/PS2 Microsoft MS-DOS    */
X#define GEMDOS      /* ATARI-ST Digital Research GEMDOS */
X#endif
X
X#ifdef HP9000
X#define s200        /* Motorola mc68010/mc68020 HP-UX   */
X#define s500        /* Motorola mc68010/mc68020 HP-UX   */
X#define s800        /* HP Precision Architecture (RISC) */
X#endif
X
X#ifdef SEQUENT
X#define BALANCE     /* National Sem. NS32000 DYNIX      */
X#define SYMMETRY    /* iNTEL iAPX80386 DYNIX            */
X#endif
X
X#ifndef S_IFMT
X#define S_IFMT   0170000    /* type of file    */
X#endif
X#ifndef S_IFIFO
X#define S_IFIFO  0010000    /* fifo special    */
X#endif
X#ifndef S_IFNWK
X#define S_IFNWK  0110000    /* network special */
X#endif
X#ifndef S_IFLNK
X#define S_IFLNK  0120000    /* symbolic link   */
X#endif
X#ifndef S_IFSOCK
X#define S_IFSOCK 0140000    /* socket          */
X#endif
X
Xstatic char *Copyright = "\0file v1.3 Copyright (c) 1988 Bert Reuling";
X
Xunsigned char probe[PROBESIZ];
Xint relax, probesiz;
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X   int mode, fd;
X   char fname[MAXFNAME];
X   struct stat buf;
X   extern unsigned char probe[];
X   extern int probesiz;
X   void guess();
X
X#ifdef WILDCARDS
X   expargs(&argc, &argv);
X#endif
X   relax = FALSE;
X   while (--argc > 0) {
X      strcpy(fname, *++argv);
X      strcat(fname, ":");
X      printf("%-15s ", fname);
X      if (stat(*argv, &buf) == -1)
X         printf("can't stat");
X      else {
X         switch(buf.st_mode & S_IFMT) {
X            case S_IFIFO:
X               printf("fifo");
X               break;
X            case S_IFCHR:
X               printf("character special");
X               break;
X            case S_IFDIR:
X               printf("directory");
X               break;
X            case S_IFBLK:
X               printf("block special");
X               break;
X            case S_IFREG:
X               if ((fd = open(*argv, 0)) == -1)
X                 printf("can't open");
X               else {
X                  probesiz = read(fd, probe, PROBESIZ);
X                  if (probesiz == -1)
X                     printf("can't read");
X                  else if (probesiz == 0)
X                     printf("empty");
X                  else {
X                     if (probesiz < (PROBESIZ / 2)) {
X                        printf("short ");
X                        relax = TRUE;
X                     }
X                     if (! magic()) {
X                        if (istar())
X                           printf("tar archive");
X                        else
X                           guess();
X                     }
X                  }
X                  close(fd);
X               }
X               break;
X            case S_IFNWK:
X               printf("network special");
X               break;
X            case S_IFLNK:
X               printf("symbolic link");
X               break;
X            case S_IFSOCK:
X               printf("socket");
X               break;
X            default:
X               printf("%07o special", buf.st_mode & S_IFMT);
X               break;
X         }
X      }
X      putchar('\n');
X   }
X   exit(0);
X}
X
X/*
X *  magic  -  test if file has a known magic number
X */
Xmagic()
X{
X   int found;
X   unsigned int magic1, magic2;
X   extern unsigned char probe[];
X
X   if (probesiz < 4) {
X      printf("file");
X      return (TRUE);
X   }
X   /*
X    *  assemble magics. Note that this gets around the byte-ordering problem
X    */
X   magic1 = probe[0] << 8 | probe[1];
X   magic2 = probe[2] << 8 | probe[3];
X
X   found = FALSE;
X   switch(magic1) {
X      case 0177545: /* ok */
X         printf("pre System V ar(1) archive");
X         found = TRUE;
X         break;
X      case 0177555: /* ok */
X         printf("pre v7 ar(1) archive");
X         found = TRUE;
X         break;
X      case '<a': /* ok */
X         if (strncmp(probe, "<ar>", 4) == 0) {
X            printf("System V.1 ar(1) archive");
X            found = TRUE;
X         }
X         break;
X      case '!<': /* ok */
X         if (strncmp(probe, "!<arch>", 7) == 0) {
X            printf("System V ar(1) archive");
X            found = TRUE;
X         }
X         break;
X      case 017436: /* ok */
X         printf("packed data");
X         found = TRUE;
X         break;
X      case 017635: /* ok */
X         printf("compressed data");
X         if (probe[2] & 0x80)
X            printf(", block compressed");
X         printf(", %d bits", probe[2] & 0x1f);
X         found = TRUE;
X         break;
X      case 0xc771: /* ok */
X         printf("cpio archive (swapped bytes)");
X         found = TRUE;
X         break;
X      case 070707: /* ok */
X         printf("cpio archive");
X         found = TRUE;
X         break;
X      case '07': /* ok */
X         if (magic2 == '07') {
X            printf("ascii cpio archive");
X            found = TRUE;
X         }
X         break;
X      case 0x65ff: /* not tested */
X         if (magic2 == 0x0000) {
X            printf("VAX 3.0 archive");
X            found = TRUE;
X         }
X         break;
X      case 0x8000: /* ok */
X         printf("lif archive");
X         found = TRUE;
X         break;
X      case 0x1a08: /* ok */
X         printf("arc ");
X         break;
X#ifdef s200
X      case 0x020c:
X         switch (magic2) {
X            case 0x0106: /* ok */
X               printf("s200 relocatable executable");
X               found = TRUE;
X               break;
X            case 0x0107: /* ok */
X               printf("s200 executable");
X               found = TRUE;
X               break;
X            case 0x0108: /* ok */
X               printf("s200 pure executable");
X               found = TRUE;
X               break;
X            case 0x010b: /* ok */
X               printf("s200 demand-load executable");
X               found = TRUE;
X               break;
X         }
X         break;
X      case 0x020a:
X         switch (magic2) {
X            case 0x0107: /* ok */
X               printf("s200 (2.x release) executable");
X               found = TRUE;
X               break;
X            case 0x0108: /* ok */
X               printf("s200 (2.x release) pure executable");
X               found = TRUE;
X               break;
X         }
X         break;
X#endif
X#ifdef s500
X      case 0x0208:
X         switch (magic2) {
X            case 0x0106: /* ok */
X               printf("s500 relocatable executable");
X               found = TRUE;
X               break;
X            case 0x0107: /* ok */
X               printf("s500 executable");
X               found = TRUE;
X               break;
X            case 0x0108: /* ok */
X               printf("s500 pure executable");
X               found = TRUE;
X               break;
X         }
X         break;
X#endif
X#ifdef s800
X      case 0x020b:
X         switch (magic2) {
X            case 0x0106: /* ok */
X               printf("s800 relocatable object");
X               found = TRUE;
X               break;
X            case 0x0107: /* ok */
X               printf("s800 executable");
X               found = TRUE;
X               break;
X            case 0x0108: /* ok */
X               printf("s800 shared executable");
X               found = TRUE;
X               break;
X         }
X         break;
X#endif
X#ifdef BALANCE
X      case 0xea00: /* ok */
X         if (magic2 == 0x0000) {
X            printf("BALANCE NS32000 object");
X            found = TRUE;
X         }
X         break;
X      case 0xea10: /* ok */
X         if (magic2 == 0x0000) {
X            printf("BALANCE NS32000 executable (0 @ 0)");
X            found = TRUE;
X         }
X         break;
X      case 0xea20: /* ok */
X         if (magic2 == 0x0000) {
X            printf("BALANCE NS32000 executable (invalid @ 0)");
X            found = TRUE;
X         }
X         break;
X      case 0xea30: /* ok */
X         if (magic2 == 0x0000) {
X            printf("BALANCE NS32000 stand alone executable");
X            found = TRUE;
X         }
X         break;
X#endif
X#ifdef SYMMETRY
X      case 0xeb12: /* not tested */
X         if (magic2 == 0x0000) {
X            printf("SYMMETRY I386 object");
X            found = TRUE;
X         }
X         break;
X      case 0xeb22: /* not tested */
X         if (magic2 == 0x0000) {
X            printf("SYMMETRY I386 executable (0 @ 0)");
X            found = TRUE;
X         }
X         break;
X      case 0xeb32: /* not tested */
X         if (magic2 == 0x0000) {
X            printf("SYMMETRY I386 executable (invalid @ 0)");
X            found = TRUE;
X         }
X         break;
X      case 0xeb42: /* not tested */
X         if (magic2 == 0x0000) {
X            printf("SYMMETRY I386 stand alone executable");
X            found = TRUE;
X         }
X         break;
X#endif
X#ifdef ATT
X      case 0550: /* not tested */
X         printf("3b20 executable");
X         found = TRUE;
X         break;
X      case 0551: /* not tested */
X         printf("3b20 executable (TV)");
X         found = TRUE;
X         break;
X      case 0560: /* not tested */
X         printf("3b2/3b5 executable");
X         found = TRUE;
X         break;
X      case 0561: /* not tested */
X         printf("3b2/3b5 excutable (TV)");
X         found = TRUE;
X         break;
X#endif
X#ifdef PDP11
X      case 0000:
X         switch(magic2) {
X            case 0405: /* ok */
X               printf("pdp11 overlay");
X               found = TRUE;
X               break;
X            case 0407: /* ok */
X               printf("pdp11 executable");
X               found = TRUE;
X               break;
X            case 0410: /* ok */
X               printf("pdp11 shared executable");
X               found = TRUE;
X               break;
X            case 0411: /* ok */
X               printf("pdp11 executable, separate I & D");
X               found = TRUE;
X               break;
X            case 0437: /* ok */
X               printf("pdp11 kernel overlay");
X               found = TRUE;
X               break;
X         }
X         break;
X#endif
X#ifdef VAX
X      case 0570: /* not tested */
X         printf("VAX executable");
X         found = TRUE;
X         break;
X      case 0575: /* not tested */
X         printf("VAX pure executable");
X         found = TRUE;
X         break;
X#endif
X#ifdef M68K
X      case 0520: /* not tested */
X         printf("mc68k executable");
X         found = TRUE;
X         break;
X      case 0521: /* not tested */
X         printf("mc68k shared executable");
X         found = TRUE;
X         break;
X      case 0522: /* not tested */
X         printf("mc68k shared executable (demand paged)");
X         found = TRUE;
X         break;
X#endif
X#ifdef I386
X      case 0x4c01: /* ok */
X         printf("iAPX386 executable");
X         found = TRUE;
X         break;
X#endif
X#ifdef MINIX
X      case 0026377: /* ok */
X         printf("minix ar(1) archive");
X         found = TRUE;
X         break;
X      case 0x0102: /* ok */
X         printf("minix object");
X         found = TRUE;
X         break;
X      case 0x0410: /* ok */
X         if (magic2 == 0x0301) {
X            printf("minix executable");
X            found = TRUE;
X         }
X         break;
X      case 0x0420: /* ok */
X         if (magic2 == 0x0301) {
X            printf("minix executable, separate I & D");
X            found = TRUE;
X         }
X         break;
X#endif
X#ifdef MSDOS
X      case 0x4d5a: /* ok */
X         printf("msdos executable");
X         found = TRUE;
X         break;
X      case 0xf00d: /* ok */
X         printf("msdos lib");
X         found = TRUE;
X         break;
X      case 0xffff: /* ok */
X         if (magic2 == 0xffff) {
X            printf("msdos device driver");
X            found = TRUE;
X         }
X         break;
X      case 'ac': /* ok */
X         printf("autocad ");
X         break;
X#endif
X#ifdef GEMDOS
X      case 0x601a: /* ok */
X         printf("gemdos executable");
X         found = TRUE;
X         break;
X      case 0x1abc: /* ok */
X         printf("megamax object");
X         found = TRUE;
X         break;
X      case 0x2abc: /* ok */
X         printf("megamax lib");
X         found = TRUE;
X         break;
X      case 0xfb01:
X         printf("gst");
X         switch (probe[2]) {
X            case 0: /* ok */
X               printf(" object");
X               found = TRUE;
X               break;
X            case 9: /* ok */
X               printf(" lib");
X               found = TRUE;
X               break;
X         }
X         break;
X#endif
X   }
X   return(found);
X}
X
X/*
X *  istar  -  check if probe is a tar(1) header
X */
Xistar()
X{
X   int i, check;
X   long checksum;
X   extern unsigned char probe[];
X   extern int probesiz;
X
X   if (probesiz < 0x102)
X      return (FALSE);
X
X   check = 0x100;
X   checksum = 0L;
X   for (i = 0x94; i < 0x9c; i++) {
X      if ((probe[i] >= '0') && (probe[i] <= '7')) {
X         checksum <<= 3;
X         checksum += (long) (probe[i] - '0');
X      }
X   }
X   for (i = 0x00; i < 0x94; i++)
X      check += probe[i];
X   for (i = 0x9c; i < 0x102; i++)
X      check += probe[i];
X   if (check == (int) checksum)
X      return (TRUE);
X   else
X      return (FALSE);
X}
X
X/*
X *  guess  -  try to guess type / language
X */
Xvoid guess()
X{
X   int i, decide, guessed, isdata, data, c, pascal, f77, sh, as;
X   extern int probesiz;
X   extern unsigned char probe[];
X
X   guessed = isdata = FALSE;
X   data = c = pascal = f77 = sh = as = 0;
X
X   for (i = 0; i < probesiz; i++)
X      if (!isascii(probe[i]))
X         data++;
X
X   if (match("#define ")) c++;
X   if (match("#include ")) c++;
X   if (match("int ")) c++;
X   if (match("char ")) c++;
X   if (match("/*")) c++;
X
X   if (match("PROGRAM ")) pascal++;
X   if (match("VAR")) pascal++;
X   if (match("INTEGER")) pascal++;
X   if (match("OUTPUT")) pascal++;
X   if (match("BEGIN")) pascal++;
X
X   if (match("CONTINUE")) f77++;
X   if (match("DIMENSION ")) f77++;
X   if (match("DO ")) f77++;
X   if (match("C     ")) f77++;
X   if (match(".EQ.")) f77++;
X
X   if (match("case $")) sh++;
X   if (match("if ")) sh++;
X   if (match("echo ")) sh++;
X   if (match(" in ")) sh++;
X   if (match("$1")) sh++;
X
X   if (match(".text")) as++;
X   if (match(".data")) as++;
X   if (match(".bss")) as++;
X   if (match("jmp")) as++;
X   if (match("mov")) as++;
X
X   decide = (relax) ? 1 : 2;
X
X   if (((c + pascal + f77 + sh + as) < 5) && (data > decide)) {
X      printf("data ");
X      isdata = TRUE;
X      guessed = TRUE;
X   }
X
X   if (((pascal + f77 + sh + as) < 4) && (c > decide) && !guessed) {
X      printf("c source ");
X      guessed = TRUE;
X   }
X
X   if (((c + pascal + f77 + as) < 4) && (sh > decide) && !guessed) {
X      printf("commands ");
X      guessed = TRUE;
X   }
X
X   if (((c + f77 + sh + as) < 4) && (pascal > decide) && !guessed) {
X      printf("pascal source ");
X      guessed = TRUE;
X   }
X
X   if (((c + pascal + sh + as) < 4) && (f77 > decide) && !guessed) {
X      printf("fortran source ");
X      guessed = TRUE;
X   }
X
X   if (((c + pascal + f77 + sh) < 4) && (as > decide) && !guessed) {
X      printf("assembler source ");
X      guessed = TRUE;
X   }
X
X   if (! guessed)
X      printf("ascii ");
X
X   if (! isdata)
X      printf("text");
X}
X
X/*
X *  match  -  match keyword
X */
Xmatch(keyword)
Xchar *keyword;
X{
X   int i, l;
X   char c, *s, *y;
X   extern unsigned char probe[];
X   extern int probesiz;
X
X   for (i = 0, l = strlen(keyword); i < probesiz - l; i++) {
X      s = keyword; y = (char *) &probe[i];
X      while (((c = *s++) == *y++) && (c != 0));
X         if (c == '\0')
X            return (TRUE);
X   }
X   return (FALSE);
X}
X
END_OF_SHAR
   if test 15892 -ne `wc -c <'file.c'`
   then
      echo "$0: unpacked with wrong size: file.c"
   fi
fi
if test -f 'file.1' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: file.1"
else
   echo "x - file.1 (1106 characters)"
sed 's/^X//' <<\END_OF_SHAR >file.1
X.ad
X.fi
X.he 'FILE(1)'MINIX reference manual'FILE(1)'
X.in 5
X.ul
X.ti 0
XNAME
X.br
Xfile  -  determine file type
X.br
X.bl
X.ul
X.ti 0
XSYNOPSIS
X.br
X.ul
Xfile
Xfile ...
X.br
X.bl
X.ul
X.ti 0
XDESCRIPTION
X.br
X.ul
XFile
Xperforms a series of tests on each argument in an attempt to classify it.
XIf an argument is a regular file,
X.ul
Xfile
Xexamines the first 512 bytes and performs a series of tests. The first test
Xis a magic number search. Unlike the UNIX System V
X.ul
Xfile
X, this
X.ul
Xfile
Xdoes not use the /etc/magic
Xfile : it has all magic numbers compiled into it.
XThen, if no conclusive magic number could be found,
X.ul
Xfile
Xperforms a checksum test in order to classify it as a tar(1) archive file.
XIf this test fails,
X.ul
Xfile
Xtries to guess the language of the file. At present, C, pascal, fortran,
Xshell scripts and assembler source texts are recognized as such (with a
Xbit of luck).
X.br
X.bl
X.ul
X.ti 0
XBUGS
X.br
X.ul
XFile
Xcan make mistakes. The magic numbers for the Sequent SYMMETRY, AT&T 3B20,
XAT&T 3B2/5 and M68K remain untested.
X.br
X.bl
X.ul
X.ti 0
XAUTHOR
X.br
X.ul
Xfile
Xwas developed by Bert Reuling. {mcvax!bebux!bert}
X
END_OF_SHAR
   if test 1106 -ne `wc -c <'file.1'`
   then
      echo "$0: unpacked with wrong size: file.1"
   fi
fi
if test -f 'expargs.c' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: expargs.c"
else
   echo "x - expargs.c (3483 characters)"
sed 's/^X//' <<\END_OF_SHAR >expargs.c
X/*
X *  expargs  -  expand arguments. Copyright (c) 1988 Bert Reuling
X *
X *  call "expargs(&argc, &argv);" just after "main(argc, argv)" for
X *  "commandline expansion". Note that wildcards are in GEM/MSDOS
X *  style rather than UN*X style.
X *
X *  MSDOS:  Lattice C v3.20
X *  GEMDOS: Megamax v1.1, Mark Williams C
X */
X
X#ifdef MSDOS
X#include <dos.h>
X#endif
X
X#ifdef GEMDOS
X#include <osbind.h>
Xstruct FILEINFO {
X   unsigned char sys[21]; /* 8 bit   */
X   unsigned char attr;    /* 8 bits  */
X   unsigned long time;    /* 32 bits */
X   unsigned long size;    /* 32 bits */
X   char name[14];         /* string  */
X};
X#endif
X
X#ifndef NULL
X#define NULL    ((char *) 0) /* NULL pointer                       */
X#endif
X#define MAXARGC          512 /* max number of arguments allowed    */
X#define MAXARGLEN        256 /* save maximum length for arguments  */
X#define MAXPATH           65 /* maximum path length for GEM/MSDOS  */
X#define LOWARGS              /* define for arguments in lower case */
X
X/*
X *  expargs  -  wildcard expansion for GEM/MSDOS
X */
Xexpargs(argc, argv)
Xint *argc;
Xchar ***argv;
X{
X   int new_argc = 0;
X   char *s, *l, *d, **ov, *strdup();
X   char pattern[MAXARGLEN], path[MAXPATH], newarg[MAXPATH];
X   static char *new_argv[MAXARGC];
X   struct FILEINFO info;
X
X#ifdef MSDOS
X   s = **argv;
X   d = l = NULL;
X   while (*s != '\0') {
X      if (*s == '\\')
X         l = s;
X      if (*s == '.')
X         d = s;
X      s++;
X   }
X   if (d != NULL)
X      *d = '\0';
X   if (l != NULL) {
X      if (*(l + 1) == '\0')
X         *l = '\0';
X      else
X         l++;
X#ifdef LOWARGS
X      strlwr(l);
X#endif
X   }
X   else
X      l = **argv;
X
X   new_argv[new_argc++] = l;
X#endif
X#ifdef GEMDOS
X   new_argv[new_argc++] = "\0";  /* suggestions anyone ? */
X#endif
X   ov = *argv;
X#ifdef GEMDOS
X   Fsetdta(&info);
X#endif
X   while (--*argc > 0) {
X      strcpy(pattern, *++ov);
X      strcpy(path, pattern);
X      s = path;
X      l = NULL;
X      while (*s != '\0') {
X         if (*s == '\\')
X            l = s;
X         s++;
X      }
X      if (l != NULL) {
X         if (*++l != '\0')
X            *l = '\0';
X      }
X      else
X         path[0] = '\0';
X#ifdef MSDOS
X      if (dfind(&info, pattern, (unsigned) 0377) != 0) {
X#endif
X#ifdef GEMDOS
X      if (Fsfirst(pattern, (unsigned) 0377) != 0) {
X#endif
X         new_argv[new_argc++] = strdup(pattern);
X         continue;
X      }
X      else {
X         strcpy(newarg, path);
X         strcat(newarg, info.name);
X#ifdef LOWARGS
X         strlwr(newarg);
X#endif
X         new_argv[new_argc++] = strdup(newarg);
X      }
X#ifdef MSDOS
X      while (dnext(&info) == 0) {
X#endif
X#ifdef GEMDOS
X      while (Fsnext() == 0) {
X#endif
X         strcpy(newarg, path);
X         strcat(newarg, info.name);
X#ifdef LOWARGS
X         strlwr(newarg);
X#endif
X         new_argv[new_argc++] = strdup(newarg);
X      }
X   }
X   if (new_argc > MAXARGC) {
X      write(2, new_argv[0], strlen(new_argv[0]));
X      write(2, ": argv table overflow\n", 22);
X      exit(-1);
X   }
X   *argc = new_argc;  /* these two line may look the same, */
X   *argv = new_argv;  /* but they are entirely different   */
X}
X
X/*
X *  strdup  -  duplicate a string
X */
Xchar *strdup(s)
Xchar *s;
X{
X   char *p, *calloc();
X
X   if ((p = calloc(1, strlen(s) + 1)) != NULL)
X      strcpy(p, s);
X   return (p);
X}
X
X/*
X *  strlwr  -  convert string to lower case
X */
Xchar *strlwr(s)
Xchar *s;
X{
X   char c, *p;
X
X   while ((c = *p) != '\0') {
X      if ((c >= 'A') && (c <= 'Z'))
X         *p |= 0x20;
X      p++;
X   }
X   return(s);
X}
X
END_OF_SHAR
   if test 3483 -ne `wc -c <'expargs.c'`
   then
      echo "$0: unpacked with wrong size: expargs.c"
   fi
fi
if test -f 'stat.c' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: stat.c"
else
   echo "x - stat.c (2806 characters)"
sed 's/^X//' <<\END_OF_SHAR >stat.c
X/* 
X *  stat.c  - UN*X stat(2) for GEM/MSDOS. Copyright (c) 1988 Bert Reuling
X */ 
X
X#ifdef MSDOS 
X#include <dos.h> 
X#endif 
X
X#ifdef GEMDOS 
X#include <osbind.h> 
Xstruct FILEINFO { 
X   unsigned char sys[21]; /* 8 bit   */ 
X   unsigned char attr;    /* 8 bits  */ 
X   unsigned long time;    /* 32 bits */ 
X   unsigned long size;    /* 32 bits */ 
X   char name[14];         /* string  */ 
X}; 
X#endif 
X
X#include <sys\types.h>
X#include <sys\stat.h>
X 
X#define X_IFMT   0377  /* type of file */ 
X#define X_IFBIT7 0200  /* unused bit 7 */ 
X#define X_IFBIT6 0100  /* unused bit 6 */ 
X#define X_IFAR   0040  /* archived     */ 
X#define X_IFDIR  0020  /* directory    */ 
X#define X_IFLBL  0010  /* volume label */ 
X#define X_IFSYS  0004  /* system file  */ 
X#define X_IFHID  0002  /* hidden file  */ 
X#define X_IREAD  0001  /* read-only    */ 
X
X/*
X *  stat  -  get file statistics (UNIX)
X */
Xint stat(path, st) 
Xchar *path; 
Xstruct stat *st; 
X{ 
X   int i, leap; 
X   long ticks; 
X   static int nmonth[2][13] = { 
X      { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 
X      { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 
X   }; 
X   struct FILEINFO info; 
X#ifdef MSDOS 
X   union { 
X      unsigned long time; 
X      struct { 
X         unsigned hour   : 5; 
X         unsigned minute : 6; 
X         unsigned second : 5; 
X         unsigned year   : 7; 
X         unsigned month  : 4; 
X         unsigned day    : 5; 
X      } ms; 
X   } dos; 
X 
X   if (dfind(&info, path, X_IFMT) != 0) 
X      return(-1); 
X#endif 
X 
X#ifdef GEMDOS 
X   union {
X      unsigned long time;
X      struct {
X         unsigned second : 5;
X         unsigned minute : 6;
X         unsigned hour   : 5;
X         unsigned day    : 5;
X         unsigned month  : 4;
X         unsigned year   : 7;
X      } ms;
X   } dos;
X
X   Fsetdta(&info); 
X   if (Fsfirst(path, X_IFMT) != 0) 
X      return(-1); 
X#endif 
X 
X   if (info.attr & X_IFDIR) 
X      st->st_mode = S_IFDIR | S_IRWXU; 
X   else if (info.attr & X_IFLBL) 
X      st->st_mode = 0 | S_IRWXU; 
X   else if (info.attr & X_IREAD) 
X      st->st_mode = S_IFREG | S_IREAD; 
X   else 
X      st->st_mode = S_IFREG | S_IRWXU; 
X   st->st_uid = 0; 
X   st->st_gid = 0; 
X   st->st_size = (off_t) info.size; 
X   dos.time = info.time; 
X   ticks = 315532800L; 
X   ticks += (long) dos.ms.second * 2L + 
X            (long) dos.ms.minute * 60L + 
X            (long) dos.ms.hour * 3600L + 
X            (long) (dos.ms.day - 1) * 86400L;
X   leap = ((dos.ms.year % 4) == 0) ? 1 : 0; 
X   for (i = 1; i < dos.ms.month; i++) 
X      ticks += (long) nmonth[leap][i] * 86400L; 
X   for (i = 0; i < dos.ms.year; i++) 
X      ticks += ((i % 4) == 0) ? 31622400L : 31536000L;
X   st->st_atime = ticks; 
X   st->st_mtime = ticks; 
X   st->st_ctime = ticks; 
X   st->st_dev = 0;
X   st->st_ino = 0;
X   st->st_nlink = 0;
X   st->st_rdev = 0;
X} 
END_OF_SHAR
   if test 2806 -ne `wc -c <'stat.c'`
   then
      echo "$0: unpacked with wrong size: stat.c"
   fi
fi
if test -f 'types.h' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: types.h"
else
   echo "x - types.h (427 characters)"
sed 's/^X//' <<\END_OF_SHAR >types.h
X/*
X *  types.h - UN*X <sys/types.h> for GEM/MSDOS
X */
X#ifndef TYPES_INCLUDED
X#define TYPES_INCLUDED
X
Xtypedef unsigned char u_char;
Xtypedef unsigned int u_int;
Xtypedef unsigned short u_short;
Xtypedef unsigned long u_long;
Xtypedef long daddr_t;
Xtypedef char * caddr_t;
Xtypedef unsigned int  uint;
Xtypedef unsigned short ushort;
Xtypedef long time_t;
Xtypedef long off_t;
Xtypedef long paddr_t;
Xtypedef unsigned short dev_t;
X
X#endif
END_OF_SHAR
   if test 427 -ne `wc -c <'types.h'`
   then
      echo "$0: unpacked with wrong size: types.h"
   fi
fi
if test -f 'stat.h' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: stat.h"
else
   echo "x - stat.h (2154 characters)"
sed 's/^X//' <<\END_OF_SHAR >stat.h
X/*
X *  stat.h  -  UN*X <sys/stat.h> for GEM/MSDOS
X */
X#ifndef STAT_INCLUDED
X#define STAT_INCLUDED
X
Xstruct stat {
X   dev_t   st_dev;
X   ushort  st_ino;
X   ushort  st_mode;
X   ushort  st_nlink;
X   ushort  st_uid;
X   ushort  st_gid;
X   dev_t   st_rdev;
X   off_t   st_size;
X   time_t  st_atime;
X   time_t  st_mtime;
X   time_t  st_ctime;
X};
X
X#define S_IFMT    0170000   /* type of file                     */
X#define S_IFDIR   0040000   /* directory                        */
X#define S_IFCHR   0020000   /* character special                */
X#define S_IFBLK   0060000   /* block special                    */
X#define S_IFREG   0100000   /* regular                          */
X#define S_IFIFO   0010000   /* fifo                             */
X#define S_IFNWK   0110000   /* network special                  */
X#define S_IFLNK   0120000   /* symbolic link                    */
X#define S_IFSOCK  0140000   /* socket                           */
X#define S_ISUID   0004000   /* set user ID on execution         */
X#define S_ISGID   0002000   /* set group ID on execution        */
X#define S_ENFMT   0002000   /* record locking enforcement flag  */
X#define S_IREAD   0000400   /* read permission: owner           */
X#define S_IWRITE  0000200   /* write permission: owner          */
X#define S_IEXEC   0000100   /* execute/search permission: owner */
X#define S_IRWXU   0000700   /* read, write, execute: owner      */
X#define S_IRUSR   0000400   /* read permission: owner           */
X#define S_IWUSR   0000200   /* write permission: owner          */
X#define S_IXUSR   0000100   /* execute/search permission: owner */
X#define S_IRWXG   0000070   /* read, write, execute: group      */
X#define S_IRGRP   0000040   /* read permission: group           */
X#define S_IWGRP   0000020   /* write permission: group          */
X#define S_IXGRP   0000010   /* execute/search permission: group */
X#define S_IRWXO   0000007   /* read, write, execute: other      */
X#define S_IROTH   0000004   /* read permission: other           */
X#define S_IWOTH   0000002   /* write permission: other          */
X#define S_IXOTH   0000001   /* execute/search permission: other */
X
X#endif
END_OF_SHAR
   if test 2154 -ne `wc -c <'stat.h'`
   then
      echo "$0: unpacked with wrong size: stat.h"
   fi
fi
echo "End of archive"
exit 0
#
#
#