[comp.os.os9] tar for OS-9/68k

stp@ethz.UUCP (Stephan Paschedag) (08/16/89)

#! /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 shell archive."
# Contents:  readme makefile tar.c
# Wrapped by stp@ethz on Wed Aug 16 14:17:38 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'readme' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'readme'\"
else
echo shar: Extracting \"'readme'\" \(924 characters\)
sed "s/^X//" >'readme' <<'END_OF_FILE'
X
Xthis version of tar has originally been Simmule Turners tar for OS-9/6809.
XI've adapted it to OS-9/68k and added some new features.
XI did this in a manner that it still should be able to be compiled on a
X6809 system (but i haven't been able to test it).
X
Xnew features :
X
X   it's now possible to extract a single file from an archive
X   all missing directories are now automatically created
X   extraction of entire directories in now possible
X   directories from UNIX-written archives are now correctly created
X   
Xexamples:
X
X   tar x archive test/abc     extract file 'test/abc' from archive
X                               directory 'test' is automatically created
X
X   tar x archive test         extracts entire directory 'test'
X
Xplease send more ideas or bug reports to me :
X
XStephan Paschedag           paschedag@strati.ethz.ch  or  stp@ethz.UUCP
XSwiss Federal Institute Of Technology Zurich          ..!cernvax!ethz!stp
END_OF_FILE
if test 924 -ne `wc -c <'readme'`; then
    echo shar: \"'readme'\" unpacked with wrong size!
fi
# end of 'readme'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(118 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
XCFLAGS=-qit=/r0
XCC=cc
X
X.makedate: tar.c
X     $(CC) $(CFLAGS) -fd=tar tar.c
X     @attr tar -ea
X     @touch .makedate
X
X
END_OF_FILE
if test 118 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
if test -f 'tar.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tar.c'\"
else
echo shar: Extracting \"'tar.c'\" \(19127 characters\)
sed "s/^X//" >'tar.c' <<'END_OF_FILE'
Xchar scid[]="$Header: tar.c,v 1.5  08/06/89 SrT/stp $";
X
X/*
X * Modified for use under OS-9/68k  (08/03/89)
X * Stephan Paschedag  stp@ethz.uucp   ..cernvax!ethz!stp
X *
X * Compilation for OS-9/68k:  cc -qi tar.c
X *
X * 08/06/89  V1.5  Allow extraction of entire directories,
X *                 allow extraction of single files in subdirectories,
X *                 creates automatically missing directories.
X *                 continues now correctly after some errors
X *                 handles directories from unix archives correctly (stp)
X *
X * Modified for use under OS-9/6809
X * Simmule Turner   simmy@nu.cs.fsu.edu   70651,67
X *
X * Compilation for OS-9/6809:  cc -m=3k tar.c
X *     Use extra memory for recursive directory descents.
X *
X * 07/17/88  V1.4  Allow extraction of specified file(s)....
X *                 from archive named on the command line
X *                 with wildcard matching *,?. (SrT)
X *
X * 07/14/88  V1.3  Added verbose TOC ala unix.  Cleaned up
X *                 printing routines, use decimal instead of
X *                 octal. Removed conditional compilation. (SrT)
X *
X * 07/13/88  V1.2  Tries to set the correct file permissions.
X *                 Send diagnostics to stderr.  Use lseek's
X *                 for TOC generation when a rbf device. (SrT)
X *
X * 07/12/88  V1.1  Added option of reading/writing
X *                 archive to stdin/stdout (SrT)
X *
X * 07/12/88  V1.0  Initial port (SrT)
X *                 added dummy fv options
X * SrT */
X
X/* tar - tape archiver          Author: Michiel Huisjes */
X
X/* Usage: tar [cxt][v] tapefile [files]
X *
X * Bugs:
X *  This tape archiver should only be used as a program to read or make
X *  simple tape archives. Its basic goal is to read (or build) UNIX V7 tape
X *  archives and extract the named files. It is not wise to use it on
X *  raw magnetic tapes. It doesn't know anything about linked files,
X *  except when the involved fields are filled in.
X */
X
X#include <stdio.h>
X#include <direct.h>
X#include <modes.h>
X#include <sgstat.h>
X#include <time.h>
X#ifndef OSK
X#  include <utime.h>
X#else
X#  include <types.h>
X#  include <errno.h>
X#  include <strings.h>
X#endif
X
X#define STDIN   0
X#define STDOUT  1
X
Xtypedef char BOOL;
X#define TRUE    1
X#define FALSE   0
X
X#define HEADER_SIZE     512
X#define NAME_SIZE       100
X#define BLOCK_BOUNDARY   20
X
Xtypedef union {
X  char hdr_block[HEADER_SIZE];
X  struct m {
X    char m_name[NAME_SIZE];
X    char m_mode[8];
X    char m_uid[8];
X    char m_gid[8];
X    char m_size[12];
X    char m_time[12];
X    char m_checksum[8];
X    char m_linked;
X    char m_link[NAME_SIZE];
X  } member;
X} HEADER;
X
XHEADER header;
X
X#define INT_TYPE    (sizeof(header.member.m_uid))
X#define LONG_TYPE   (sizeof(header.member.m_size))
X
X#define NIL_HEADER  ((HEADER *) 0)
X#define NIL_PTR     ((char *) 0)
X#define BLOCK_SIZE  512
X
X#define flush()     print(NIL_PTR)
X
XBOOL show_fl, creat_fl, ext_fl, verbose_fl, modtime_fl;
X
Xchar modestr[11], stbuf[132];
Xstruct sgbuf opts;
Xstruct fildes ofdbuf;
X#ifdef OSK
Xchar *dummy = NULL;
X#endif
X
Xint tar_fd;
X#ifdef OSK
Xchar usage[] = "Syntax : tar [ctx][mfv] tarfile [file(s)...]\nFunction: Builds and extracts from Unix tape archive files\nOptions:\n   c : create archive\n   t : list contents\n   x : extract from archive";
X#else
Xchar usage[] = "Usage: tar [ctx][mfv] tarfile [file(s)...]";
X#endif
Xchar io_buffer[BLOCK_SIZE];
X
Xint total_blocks;
Xlong convert();
Xchar **match();
X
Xblock_size() {
X    return ((int) ((convert(header.member.m_size, LONG_TYPE)
X            + (long) BLOCK_SIZE - 1) / (long) BLOCK_SIZE));
X}
X
Xerror(s1, s2)
Xchar *s1, *s2;
X{
X#ifdef OSK
X  fprintf(stderr,"%s %s\n", s1, s2 ? s2 : "");
X  exit(1);
X#else
X  string_print(NIL_PTR, "%s %s\r\l", s1, s2 ? s2 : "");
X  flush();
X  exit(1);
X#endif
X}
X
Xmain(argc, argv)
Xint argc;
Xregister char *argv[];
X{
X    register char *ptr;
X#ifdef OSK
X    char **p = &dummy;
X#else
X    char **p = "\0";
X#endif
X    int i;
X
X  pflinit();
X
X  if (argc < 3)
X    error(usage, NIL_PTR);
X
X  for (ptr = argv[1]; *ptr; ptr++) {
X    switch (*ptr) {
X        case 'c' :
X            creat_fl = TRUE;
X            break;
X        case 't' :
X            show_fl = TRUE;
X            break;
X        case 'x' :
X            ext_fl  = TRUE;
X            if (argc > 3)
X                p = &argv[3];
X            break;
X/*
X * Modifiers
X * SrT */
X        case 'f':
X            break;
X        case 'm':
X            modtime_fl = TRUE;
X            break;
X        case 'v':
X            verbose_fl = TRUE;
X            break;
X        default :
X            error(usage, NIL_PTR);
X    }
X  }
X
X  if (creat_fl + ext_fl + show_fl != 1)
X    error(usage, NIL_PTR);
X
X  if (argv[2][0] == '-')
X     tar_fd = creat_fl ? STDOUT : STDIN;
X  else
X     tar_fd = creat_fl ? creat(argv[2],3) : open(argv[2],1);
X
X  if (tar_fd < 0) {
X#ifdef OSK
X    exit(_errmsg(errno,"cannot open archive. "));
X#else
X    error("Cannot open ", argv[2]);
X#endif
X  }
X
X  if (creat_fl) {
X    for (i = 3; i < argc; i++)
X      add_file(argv[i]);
X    adjust_boundary();
X  }
X  else
X    tarfile (p);
X
X  flush();
X  exit(0);
X}
X
XBOOL get_header()
X{
X  register int check,c;
X
X  mread(tar_fd, &header, sizeof(header));
X  if (header.member.m_name[0] == '\0')
X    return FALSE;
X
X  check = (int) convert(header.member.m_checksum, INT_TYPE);
X
X  if (check != (c = checksum()))
X    error("tar: header checksum error.", NIL_PTR);
X
X  return TRUE;
X}
X
Xtarfile(p)
X    char **p;
X{
X  register char *ptr;
X  register char *mem_name;
X  char *atime();
X  int i;
X  register char **q;
X  register char *pp;
X
X  _gs_opt(tar_fd,&opts);
X
X  while (get_header()) {
X    mem_name = header.member.m_name;
X    if (ext_fl) {
X        if (*p) {
X/* extract entire directories (08/05/89 stp) */
X            if (mem_name[strlen(mem_name)-1] == '/') {
X              mem_name[strlen(mem_name)-1] = '\0';
X              if (q=match(p,mem_name)) {
X                pp = (char *) malloc(strlen(mem_name)+3);
X                strcpy(pp,mem_name);
X                strncat(pp,"/*",3);
X                *q = pp;
X                mkdir(mem_name);
X              }
X            }
X            else {
X              if (match(p,mem_name)) {
X                extract(mem_name);
X              }
X              else
X                skip_entry();
X            }
X        }
X        else {
X            if (is_dir(mem_name)) {
X                for (ptr = mem_name; *ptr != '/'; ptr++);
X                *ptr = '\0';
X                mkdir(mem_name);
X            }
X            else {
X              extract(mem_name);
X            }
X        }
X    }
X    else  {
X        if (!verbose_fl)
X#ifdef OSK
X            printf("%s",mem_name);
X#else
X            string_print(NIL_PTR, "%s", mem_name);
X#endif
X        else {
X            u29mode((int) convert(header.member.m_mode,INT_TYPE));
X#ifdef OSK
X            printf("%s ",modestr);
X#else
X            string_print(NIL_PTR, "%s ",modestr);
X#endif
X            sprintf(stbuf,"%3d/%3d %8ld %s %s",
X                (int) convert(header.member.m_uid, INT_TYPE),
X                (int) convert(header.member.m_gid, INT_TYPE),
X                      convert(header.member.m_size,LONG_TYPE),
X                      atime(convert(header.member.m_time,LONG_TYPE)),
X                      header.member.m_name);
X#ifdef OSK
X            printf("%s",stbuf);
X        }
X        printf("\n");
X#else
X            print(stbuf);
X        }
X        print("\r\l");
X#endif
X        skip_entry();
X    }
X    flush();
X  }
X}
X
Xskip_entry()
X{
X  register int blocks = block_size();
X
X    if (opts.sg_class == 1) {
X        long pos;
X
X        pos = ((long) blocks) * BLOCK_SIZE;
X        lseek(tar_fd,pos,1);
X    }
X    else {
X        while (blocks--)
X            read(tar_fd, io_buffer, BLOCK_SIZE);
X    }
X}
X
Xextract(file)
Xregister char *file;
X{
X  register int fd;
X
X  if (header.member.m_linked == '1') {
X#ifdef OSK
X    fprintf(stderr,"Cannot link %s (symbolic links not supportet)\n",header.member.m_link);
X#else
X    string_print(NIL_PTR,"Cannot link %s\r\l",header.member.m_link);
X#endif
X    skip_entry();
X    return;
X  }
X
X  if ((fd = creat(file, 3)) < 0) {
X/* create missing directories (08/06/89) stp */
Xregister char *s,*pp;
X    pp = file;
X#ifdef OSK
X    while (s = index(pp,'/')) {
X#else
X    while (s = strchr(pp,'/')) {
X#endif
X      pp = (char *) malloc(s-file+1);
X      strncpy(pp,file,s-file);
X      pp[s-file] = '\0';
X      mkdir(pp);
X      free(pp);
X      pp = s+1;
X    }
X    if ((fd = creat(file, 3)) < 0) {
X#ifdef OSK
X      fprintf(stderr, "Cannot create %s : ", file); fflush(stderr);
X      prerr(0,errno);
X#else
X      string_print(NIL_PTR, "Cannot create %s\r\l", file);
X#endif
X      skip_entry();
X      return;
X    }
X  }
X
X  copy(file, tar_fd, fd, convert(header.member.m_size, LONG_TYPE));
X
X    _ss_attr(fd, u29mode((int) convert(header.member.m_mode, INT_TYPE)));
X
X    if (!modtime_fl)
X#ifdef OSK
X        if (_gs_gfd(fd,&ofdbuf,sizeof(ofdbuf)) != -1) {
X#else
X        if (_gs_gfd(fd,&ofdbuf,sizeof(ofdbuf)) != ERROR) {
X#endif
X
X            struct tm     *utm;
X            struct sgtbuf otm;
X            long clock;
X
X            clock = convert(header.member.m_time,LONG_TYPE);
X            utm = localtime(&clock);
X            u2otime(&otm,utm);
X            _strass(&ofdbuf.fd_date[0], &otm, 5);
X            _ss_pfd(fd,&ofdbuf);
X        }
X
X    close(fd);
X    flush();
X}
X
Xcopy(file, from, to, bytes)
Xchar *file;
Xint from, to;
Xregister long bytes;
X{
X  register int rest;
X  int blocks = (int) ((bytes + (long) BLOCK_SIZE - 1) / (long) BLOCK_SIZE);
X
X  if (verbose_fl) {
X     if (to == tar_fd)
X#ifdef OSK
X        printf("a %s, %d tape blocks\n",file,blocks);
X#else
X        sprintf(stbuf,"a %s, %d tape blocks\r\l",file,blocks);
X#endif
X     else
X#ifdef OSK
X        printf("x %s, %ld bytes, %d tape blocks\n",file,bytes,blocks);
X#else
X        sprintf(stbuf,"x %s, %ld bytes, %d tape blocks\r\l",file,bytes,blocks);
X     print(stbuf);
X     flush();
X#endif
X  }
X
X  while (blocks--) {
X    read(from, io_buffer, BLOCK_SIZE);
X    rest = (bytes > (long) BLOCK_SIZE) ? BLOCK_SIZE : (int) bytes;
X    mwrite(to, io_buffer, (to == tar_fd) ? BLOCK_SIZE : rest);
X    bytes -= (long) rest;
X  }
X}
X
Xlong convert(str, type)
Xchar str[];
Xint type;
X{
X  register long ac = 0L;
X  register int i;
X
X  for (i = 0; i < type; i++) {
X    if (str[i] >= '0' && str[i] <= '7') {
X        ac <<= 3;
X        ac += (long) (str[i] - '0');
X    }
X  }
X
X  return ac;
X}
X
Xmkdir(dir_name)
Xchar *dir_name;
X{
X  if (mknod(dir_name,3) < 0) {
X     return;
X  }
X  else {
X    int fd;
X    if ((fd = open(dir_name,0x83)) > 0) {
X        _ss_attr(fd, S_IFDIR | u29mode((int) convert(header.member.m_mode, INT_TYPE)));
X        close(fd);
X    }
X  }
X}
X
Xchecksum()
X{
X  register char *ptr = header.member.m_checksum;
X  register int ac = 0;
X
X  while (ptr < &header.member.m_checksum[INT_TYPE])
X    *ptr++ = ' ';
X
X  ptr = header.hdr_block;
X  while (ptr < &header.hdr_block[BLOCK_SIZE])
X    ac += *ptr++;
X
X  return ac;
X}
X
Xis_dir(file)
Xregister char *file;
X{
X  while (*file++ != '\0') ;
X  return (*(file - 2) == '/');
X}
X
Xchar path[NAME_SIZE];
X
Xchar pathname[NAME_SIZE];
Xchar *path_name(file)
Xregister char *file;
X{
X
X  string_print(pathname, "%s%s", path, file);
X  return pathname;
X}
X
Xadd_path(name)
Xregister char *name;
X{
X  register char *path_ptr = path;
X
X  while (*path_ptr)
X    path_ptr++;
X
X  if (name == NIL_PTR) {
X    while (*path_ptr-- != '/')
X        ;
X    while (*path_ptr != '/' && path_ptr != path)
X        path_ptr--;
X    if (*path_ptr == '/')
X        path_ptr++;
X    *path_ptr = '\0';
X  }
X  else {
X    while (*name) {
X        if (path_ptr == &path[NAME_SIZE])
X            error("tar: Pathname too long", NIL_PTR);
X        *path_ptr++ = *name++;
X    }
X    *path_ptr++ = '/';
X    *path_ptr = '\0';
X  }
X}
X
Xadd_file(file)
Xregister char *file;
X{
X  struct fildes st;
X  struct dirent dir;
X  register int fd;
X#ifdef OSK
X  unsigned long siz;
X  u_char *sip = (u_char*) st.fd_fsize;
X#endif
X
X  if ((fd = open(file,0x81)) < 0)
X     if ((fd = open(file, 1)) < 0) {
X#ifdef OSK
X        fprintf(stderr, "Cannot open '%s' ", file); fflush(stderr);
X        prerr(0,errno);
X#else
X        string_print(NIL_PTR, "Cannot open %s\r\l", file);
X#endif
X        return;
X     }
X  if (_gs_gfd(fd,&st,sizeof(st)) < 0) {
X#ifdef OSK
X     fprintf(stderr, "Cannot get file descriptor for %s",file); fflush(stderr);
X     prerr(0,errno);
X#else
X     string_print(NIL_PTR, "Cannot get file descriptor for %s\r\l",file);
X#endif
X     close(fd);
X     return;
X  }
X  siz = (((((sip[0] << 8) + sip[1]) << 8) + sip[2]) << 8) + sip[3];
X
X  make_header(path_name(file), &st);
X  mwrite(tar_fd, &header, sizeof(header));
X  if (!(st.fd_att & S_IFDIR))
X#ifdef OSK
X     copy(path_name(file), fd, tar_fd, siz);
X#else
X     copy(path_name(file), fd, tar_fd, st.fd_fsize);
X#endif
X  else if (st.fd_att & S_IFDIR) {
X    if (chdir(file) < 0)
X        string_print(NIL_PTR, "Cannot chdir to %s\n", file);
X    else {
X        add_path(file);
X        mread(fd, &dir, sizeof(dir));       /* "." */
X        mread(fd, &dir, sizeof(dir));       /* ".." */
X        while (read(fd, &dir, sizeof(dir)) == sizeof(dir)) {
X#ifdef OSK
X            if (dir.dir_addr) {
X#else
X            if (dir.dir_addr[0] || dir.dir_addr[1] || dir.dir_addr[2]) {
X#endif
X                strhcpy(dir.dir_name,dir.dir_name);
X                if (*dir.dir_name)
X                  add_file(dir.dir_name);
X            }
X        }
X        chdir("..");
X        add_path(NIL_PTR);
X    }
X  }
X  else
X#ifdef OSK
X    _errmsg("unknown file type. Not added. ",0);
X#else
X    print("tar: unknown file type. Not added.\r\l");
X#endif
X
X  close(fd);
X}
X
Xmake_header(file, st)
Xchar *file;
Xregister struct fildes *st;
X{
X  register char *ptr = header.member.m_name;
X  char tbuf[6];
X#ifdef OSK
X  u_char *sip = (u_char*) st->fd_fsize;
X  unsigned long siz = (((((sip[0] << 8) + sip[1]) << 8) +
X                         sip[2]) << 8) + sip[3];
X  u_char *owp = (u_char*) st->fd_own;
X  unsigned short own = owp[1];
X  unsigned short group = owp[0];
X#endif
X
X  clear_header();
X
X  while (*ptr++ = *file++)
X    ;
X
X  if (st->fd_att &  S_IFDIR) {
X    *(ptr - 1) = '/';
X#ifdef OSK
X    siz = 0;
X#else
X    st->fd_fsize = 0L;
X#endif
X  }
X
X  _strass(tbuf,st->fd_date,5);
X  tbuf[5] = 0;
X  string_print(header.member.m_mode, "%I ", o2umode(st->fd_att));
X#ifdef OSK
X  string_print(header.member.m_uid,  "%I ", own);
X  string_print(header.member.m_gid,  "%I ", group);
X  string_print(header.member.m_size, "%L ", siz);
X#else
X  string_print(header.member.m_uid,  "%I ", st->fd_own);
X  string_print(header.member.m_gid,  "%I ", 101);
X  string_print(header.member.m_size, "%L ", st->fd_fsize);
X#endif
X  string_print(header.member.m_time, "%L ", o2utime(tbuf));
X  header.member.m_linked = ' ';
X  string_print(header.member.m_checksum, "%I", checksum());
X}
X
Xclear_header()
X{
X  register char *ptr = header.hdr_block;
X
X  while (ptr < &header.hdr_block[BLOCK_SIZE])
X    *ptr++ = '\0';
X}
X
Xadjust_boundary()
X{
X  clear_header();
X  mwrite(tar_fd, &header, sizeof(header));
X
X  while (total_blocks++ < BLOCK_BOUNDARY)
X    mwrite(tar_fd, &header, sizeof(header));
X  close(tar_fd);
X}
X
Xmread(fd, address, bytes)
Xint fd, bytes;
Xchar *address;
X{
Xregister int r;
X
X  if ((r = read(fd, address, bytes)) != bytes) {
X#ifdef OSK
X    if (r == 0)
X      errno = E_EOF;
X    exit(_errmsg(errno,"read error. "));
X#else
X    error("tar: read error.", NIL_PTR);
X#endif
X  }
X}
X
Xmwrite(fd, address, bytes)
Xint fd, bytes;
Xchar *address;
X{
X  if (write(fd, address, bytes) != bytes) {
X#ifdef OSK
X    exit(_errmsg(errno,"write error. "));
X#else
X    error("tar: write error.", NIL_PTR);
X#endif
X  }
X  total_blocks++;
X}
X
Xchar output[BLOCK_SIZE];
Xprint(str)
Xregister char *str;
X{
X  static int index = 0;
X
X  if (str == NIL_PTR) {
X    write(2, output, index);
X    index = 0;
X    return;
X  }
X
X  while (*str) {
X    output[index++] = *str++;
X    if (index == BLOCK_SIZE) {
X        write(2, output, BLOCK_SIZE);
X        index = 0;
X    }
X  }
X}
X
Xchar *num_out(number)
Xregister long number;
X{
X  static char num_buf[13];
X  char temp[13];
X  register int i;
X
X  for (i = 0; i < 11; i++) {
X    temp[i] = (number & 07) + '0';
X    number >>= 3;
X  }
X
X  for (i = 0; i < 11; i++)
X    num_buf[i] = temp[10 - i];
X
X  return num_buf;
X}
X
X/* VARARGS */
Xstring_print(buffer, fmt, args)
Xchar *buffer;
Xregister char *fmt;
Xint args;
X{
X  register char *buf_ptr;
X  char *scan_ptr;
X  char buf[NAME_SIZE];
X  int *argptr = &args;
X  BOOL pr_fl, i;
X
X  if (pr_fl = (buffer == NIL_PTR))
X    buffer = buf;
X
X  buf_ptr = buffer;
X  while (*fmt) {
X    if (*fmt == '%') {
X        fmt++;
X        switch (*fmt++) {
X            case 's':
X                scan_ptr = (char *) *argptr;
X                break;
X            case 'I':
X                scan_ptr = num_out((long) *argptr) + 5;
X/*                for (i = 0; i < 5; i++)
X                    scan_ptr++; */
X                break;
X            case 'L':
X                scan_ptr = num_out(*((long *) argptr));
X                argptr++;
X                break;
X            default:
X                scan_ptr = "";
X        }
X        while (*buf_ptr++ = *scan_ptr++)
X            ;
X        buf_ptr--;
X        argptr++;
X    }
X    else
X        *buf_ptr++ = *fmt++;
X  }
X  *buf_ptr = '\0';
X
X  if (pr_fl)
X    print(buffer);
X}
X
X o2umode(mode)
X    char mode;
X{
X    int ret_mode=0;
X
X    if (mode & S_IFDIR)
X        ret_mode |= 040000;
X    if (mode & S_IREAD)
X        ret_mode |= 0400;
X    if (mode & S_IWRITE)
X        ret_mode |= 0200;
X    if (mode & S_IEXEC)
X        ret_mode |= 0100;
X    if (mode & S_IOREAD)
X        ret_mode |= 04;
X    if (mode & S_IOWRITE)
X        ret_mode |= 02;
X    if (mode & S_IOEXEC)
X        ret_mode |= 01;
X
X    return(ret_mode);
X}
X
X u29mode(mode)
X    int mode;
X{
X    int ret_mode=0;
X
X    strcpy(modestr,"-----------");
X
X    if (mode & 040000) {
X        ret_mode  |= S_IFDIR;
X        modestr[0] = 'd';
X    }
X
X    if (mode & 0400) {
X        ret_mode  |= S_IREAD;
X        modestr[1] = 'r';
X    }
X
X    if (mode & 0200) {
X        ret_mode  |= S_IWRITE;
X        modestr[2] = 'w';
X    }
X
X    if (mode & 0100) {
X        ret_mode  |= S_IEXEC;
X        modestr[3] = 'x';
X    }
X
X    if (mode & 04) {
X        ret_mode  |= S_IOREAD;
X        modestr[7] = 'r';
X    }
X
X    if (mode & 02) {
X        ret_mode  |= S_IOWRITE;
X        modestr[8] = 'w';
X    }
X
X    if (mode & 01) {
X        ret_mode  |= S_IOEXEC;
X        modestr[9] = 'x';
X    }
X
X    return(ret_mode);
X}
X
Xchar *atime(clock)
X    long clock;
X{
X    static char buf[26];
X    int i;
X
X    strcpy(buf,ctime(&clock));
X
X    for (i=4; i< 16; i++)
X        buf[i-4] = buf[i];
X    buf[12] = ' ';
X
X    for (i=20; i<24; i++)
X        buf[i-7] = buf[i];
X    buf[17] = 0;
X
X    return(buf);
X}
X
Xchar **match(p,name)
X    char **p, *name;
X{
Xchar **q = p;
X
X  while (*q) {
X#ifdef OSK
X    if (!_cmpnam(name,*q,strlen(*q))) {
X#else
X    if (patmatch(*q,name,1)) {
X#endif
X       return(q);
X    }
X    q++;
X  }
X  return(NULL);
X}
X
X#ifdef OSK
Xu2otime(om,um)
Xstruct sgtbuf *om;
Xstruct tm     *um;
X{
X  om->t_year = um->tm_year;
X  om->t_month = um->tm_mon+1;
X  om->t_day = um->tm_mday;
X  om->t_hour = um->tm_hour;
X  om->t_minute = um->tm_min;
X  om->t_second = um->tm_sec;
X}
X
Xlong o2utime(om)
Xstruct sgtbuf *om;
X{
Xstruct tm um;
X
X  um.tm_year = om->t_year;
X  um.tm_mon = om->t_month-1;
X  um.tm_mday = om->t_day;
X  um.tm_hour = om->t_hour;
X  um.tm_min = om->t_minute;
X  um.tm_sec = om->t_second;
X  return mktime(&um);
X}
X#endif
END_OF_FILE
if test 19127 -ne `wc -c <'tar.c'`; then
    echo shar: \"'tar.c'\" unpacked with wrong size!
fi
# end of 'tar.c'
fi
echo shar: End of shell archive.
exit 0