mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 00:14:25 +00:00
753 lines
11 KiB
C
753 lines
11 KiB
C
/*
|
|
Copyright 1981
|
|
Alcyon Corporation
|
|
8474 Commerce Av.
|
|
San Diego, Ca. 92121
|
|
*/
|
|
#include "machine.h"
|
|
#include "iobuf.h"
|
|
#include "cout.h"
|
|
|
|
#define BLKSIZE 512
|
|
char buff[BLKSIZE]={0};
|
|
|
|
/* flags for cp1file*/
|
|
#define IEVEN 1
|
|
#define OEVEN 2
|
|
#define WHDR 4
|
|
|
|
#define DIR 0100000
|
|
#define CHR 040000
|
|
#define BLK 020000
|
|
#define ROWN 0400
|
|
#define WOWN 0200
|
|
#define XOWN 0100
|
|
#define RGRP 040
|
|
#define WGRP 020
|
|
#define XGRP 010
|
|
#define ROTH 04
|
|
#define WOTH 02
|
|
#define XOTH 01
|
|
|
|
#define LIBMAGIC 0177545
|
|
|
|
#define LNAMLEN 14
|
|
struct lib2hdr {
|
|
char l2fname[LNAMLEN];
|
|
long l2modti;
|
|
char l2userid;
|
|
char l2gid;
|
|
short l2fimode;
|
|
long l2fsize;
|
|
short l2junk;
|
|
} libhd={0};
|
|
|
|
struct {
|
|
int f_devnum;
|
|
int f_inum;
|
|
int f_fimode;
|
|
char f_nlinks;
|
|
char f_userid;
|
|
char f_gid;
|
|
char f_size0;
|
|
int f_size1;
|
|
int f_addr[8];
|
|
long f_acti;
|
|
long f_modti;
|
|
};
|
|
|
|
short libmagic LIBMAGIC;
|
|
|
|
int rflg=0, dflg=0, xflg=0, tflg=0, vflg=0;
|
|
int uflg=0;
|
|
int pflg=0;
|
|
int areof=0;
|
|
int arfd=0;
|
|
int tempfd=0;
|
|
int aflg=0, bflg=0;
|
|
int psflg=0;
|
|
int matchflg=0;
|
|
char *psname=0;
|
|
|
|
char *arname=0,tempname[80]={0,0,0};
|
|
/************************/
|
|
#ifdef UNIX /* */
|
|
char *dname="/tmp/"; /* UNIX */
|
|
#else /* CP/M and VMS */
|
|
char *dname=""; /* Disk Name */
|
|
#endif /************************/
|
|
#ifdef UNIX /* */
|
|
char *tname="arXXXXXX"; /* Unix temp file name */
|
|
#else /* CP/M and VMS */
|
|
char *tname="ar68.tmp"; /* Temp file name */
|
|
#endif /************************/
|
|
|
|
long lseek();
|
|
long fixlong();
|
|
long filesize();
|
|
int endit();
|
|
|
|
int (*docom)()=0;
|
|
int replace();
|
|
int delete();
|
|
int extract();
|
|
int tell();
|
|
#ifdef JUNK
|
|
long mklong();
|
|
#endif
|
|
int print();
|
|
#ifdef VAX
|
|
struct {
|
|
short loword;
|
|
short hiword;
|
|
};
|
|
#endif
|
|
|
|
#ifdef PDP11
|
|
struct {
|
|
short loword;
|
|
short hiword;
|
|
};
|
|
#endif
|
|
|
|
#ifdef MC68000
|
|
struct {
|
|
short hiword;
|
|
short loword;
|
|
};
|
|
#endif
|
|
|
|
main(argc,argv)
|
|
char **argv;
|
|
{
|
|
|
|
register char *p1, *p2;
|
|
register char **ap;
|
|
register int i;
|
|
register long l;
|
|
register long k;
|
|
long kk;
|
|
if(argc < 3) {
|
|
usage:
|
|
error("usage: ar68 drtwx[abiv][f d:] [opmod] archive obmod1 [obmod2] ... [>filespec]\n");
|
|
|
|
endit();
|
|
}
|
|
/* signal(1,endit); */
|
|
ap = &argv[1];
|
|
p1 = *ap++;
|
|
i = argc-3;
|
|
while(*p1) {
|
|
switch(*p1++) {
|
|
|
|
case 'r':
|
|
rflg++;
|
|
docom = replace;
|
|
break;
|
|
|
|
case 'a':
|
|
aflg++;
|
|
psname = *ap++;
|
|
i--;
|
|
break;
|
|
|
|
/* These options removed because they don't work!
|
|
|
|
case 'b':
|
|
case 'i':
|
|
bflg++;
|
|
i--;
|
|
psname = *ap++;
|
|
break;
|
|
|
|
*/
|
|
case 'd':
|
|
dflg++;
|
|
docom = delete;
|
|
break;
|
|
|
|
case 'x':
|
|
xflg++;
|
|
docom = extract;
|
|
break;
|
|
|
|
case 't':
|
|
tflg++;
|
|
docom = tell;
|
|
break;
|
|
|
|
case 'w':
|
|
pflg++;
|
|
docom = print;
|
|
break;
|
|
|
|
case 'v':
|
|
vflg++;
|
|
break;
|
|
|
|
case 'f': /* Drive for temp files */
|
|
dname = *ap++; /* Set proper disk name */
|
|
break;
|
|
default:
|
|
error("invalid option flag: %c\n",*--p1);
|
|
endit();
|
|
}
|
|
}
|
|
uflg = rflg+dflg;
|
|
if((uflg+xflg+tflg+pflg) != 1) {
|
|
error("one and only one of drtwx flags required\n");
|
|
endit();
|
|
}
|
|
psflg = aflg+bflg;
|
|
if(psflg > 1) {
|
|
error("only one of abi flags allowed\n");
|
|
endit();
|
|
}
|
|
strcat (tempname,dname); /* Form 1st part of string */
|
|
strcat (tempname,tname); /* Add in file name */
|
|
|
|
#ifdef UNIX /* For UNIX, make temp file*/
|
|
mktemp(tempname);
|
|
#endif
|
|
|
|
arname = *ap++;
|
|
arfd = openar(arname,rflg);
|
|
if(i==0 && tflg) {
|
|
listall();
|
|
endit();
|
|
}
|
|
if(i<=0)
|
|
goto usage;
|
|
if( xflg == 0 ) {
|
|
if((tempfd=creat(tempname,0644,1)) < 0) {
|
|
error("cannot create %s\n",tempname);
|
|
endit();
|
|
}
|
|
if(write(tempfd,&libmagic,sizeof libmagic) != sizeof libmagic)
|
|
{
|
|
error("temp file write error\n");
|
|
endit();
|
|
}
|
|
}
|
|
while(i) {
|
|
excom(*ap++);
|
|
i--;
|
|
}
|
|
excom(0L); /*end of arg list*/
|
|
if (xflg == 0)
|
|
{
|
|
k = lseek(tempfd,0L,1); /* Fetch file size */
|
|
#ifndef UNIX
|
|
l = lseek(tempfd,0L,0); /* Rewind temp file */
|
|
if (l < 0) /* Error? */
|
|
{
|
|
printf("seek error on %s\n",tempname);
|
|
exit(-1);
|
|
}
|
|
#else
|
|
close(tempfd);
|
|
if((tempfd=open(tempname,0,1)) < 0)
|
|
{
|
|
printf("Cannot re-open %s\n",tempname);
|
|
exit(-1);
|
|
}
|
|
#endif
|
|
close(arfd); /* Close input file */
|
|
unlink(arname); /* Delete the file */
|
|
arfd=creat(arname,0666,1); /* Create the file again*/
|
|
if(arfd < 0) /* Error? */
|
|
{
|
|
printf("Unable to re-create %s -- archive is in %s\n",
|
|
arname,tempname);
|
|
exit(-1);
|
|
}
|
|
i = 1; /* Klutz */
|
|
while (i > 0 && k > 0) /* Copy the file back */
|
|
{
|
|
i = (k > BLKSIZE) ? BLKSIZE : k;
|
|
i = read(tempfd,buff,i);
|
|
if(i < 0)
|
|
{
|
|
printf("Read error on %s\n",tempname);
|
|
exit(-1);
|
|
}
|
|
else if (i > 0)
|
|
{
|
|
if(write(arfd,buff,i) != i)
|
|
{
|
|
printf("Write error on %s\n",arname);
|
|
exit (-1);
|
|
}
|
|
}
|
|
k -= i;
|
|
}
|
|
kk = 0;
|
|
write(arfd,&kk,sizeof(k)); /* Put 0 on end of file */
|
|
close (tempfd);
|
|
unlink(tempname);
|
|
}
|
|
endit();
|
|
}
|
|
|
|
openar(arp,crfl)
|
|
char *arp;
|
|
{
|
|
|
|
register i;
|
|
int ib;
|
|
|
|
if((i=open(arp,2,1)) < 0) { /*does not exist*/
|
|
areof = 1;
|
|
if((i = creat(arp,0666,1)) < 0)
|
|
{
|
|
printf("Cannot Create %s\n",arname);
|
|
exit(-1);
|
|
}
|
|
else
|
|
return(i);
|
|
}
|
|
if(read(i,&ib,sizeof libmagic) != sizeof libmagic || ib != LIBMAGIC) {
|
|
notar:
|
|
error("not archive format: %s\n",arp);
|
|
endit();
|
|
}
|
|
return(i);
|
|
}
|
|
|
|
/* execute one command -- call with filename or 0*/
|
|
|
|
excom(ap)
|
|
char *ap;
|
|
{
|
|
|
|
register char *p;
|
|
if(p=ap)
|
|
{
|
|
if(p[1] == ':') /* CP/M Drive number */
|
|
p += 2; /* Bump to file name */
|
|
}
|
|
if((p) && (matchflg==0)) { /*look thru archive for file name*/
|
|
while(areof==0 && nextar()) { /*get next ar file header*/
|
|
if(streq(p,&libhd.l2fname[0]))
|
|
break;
|
|
if(psflg && streq(psname,&libhd.l2fname[0])) {
|
|
break;
|
|
}
|
|
skcopy(uflg); /*skip or copy*/
|
|
}
|
|
}
|
|
(*docom)(ap); /*exec requested command*/
|
|
}
|
|
|
|
tell(ap)
|
|
char *ap;
|
|
{
|
|
|
|
register char *p;
|
|
register i;
|
|
register char *p1;
|
|
|
|
if(ap==0)
|
|
endit();
|
|
if(vflg) { /*long list*/
|
|
pmode(libhd.l2fimode);
|
|
printf(" %d/%d %6ld ",libhd.l2userid,libhd.l2gid,
|
|
libhd.l2fsize);
|
|
/* p1 = ctime(&libhd.l2modti);
|
|
p1[24] = '\0';
|
|
p1 =+ 4;
|
|
printf(" %s ",p1); */
|
|
}
|
|
pfname();
|
|
skcopy(0);
|
|
}
|
|
|
|
pfname()
|
|
{
|
|
printf("%.14s\n",libhd.l2fname);
|
|
}
|
|
|
|
replace(ap)
|
|
char *ap;
|
|
{
|
|
|
|
register i;
|
|
int ifd;
|
|
register long l;
|
|
register char *p1;
|
|
|
|
if( ap == 0 ) {
|
|
if( bflg && areof == 0 ) {
|
|
l = -(sizeof libhd);
|
|
lseek(arfd,l,1);
|
|
}
|
|
cprest();
|
|
return;
|
|
}
|
|
if((ifd=open(ap,0,1)) < 0) {
|
|
error("cannot open %s\n",ap);
|
|
endit();
|
|
}
|
|
if(areof && psflg) {
|
|
error("%s not in library\n",psname);
|
|
endit();
|
|
}
|
|
if((bflg|aflg) && matchflg==0) { /*copy archive file before appending*/
|
|
if(aflg)
|
|
skcopy(1);
|
|
matchflg++;
|
|
}
|
|
p1 = (ap[1] == ':') ? ap + 2 : ap; /* Drive name */
|
|
copystr(p1,&libhd.l2fname[0],LNAMLEN);
|
|
if(areof|aflg) {
|
|
inform('a');
|
|
}
|
|
else if(bflg) {
|
|
inform('i');
|
|
}
|
|
else {
|
|
inform('r');
|
|
skcopy(0); /*skip old copy*/
|
|
}
|
|
p1 = buff;
|
|
libhd.l2modti = 0;
|
|
libhd.l2userid = 0;
|
|
libhd.l2gid = 0;
|
|
libhd.l2fimode = 0666;
|
|
libhd.l2fsize = filesize(&ifd,ap);
|
|
cp1file(ifd,tempfd,WHDR+OEVEN,ap,tempname);
|
|
close(ifd);
|
|
}
|
|
|
|
struct iobuf ssbuf={0};
|
|
long filesize(fdp,fname)
|
|
int *fdp;
|
|
char *fname;
|
|
{
|
|
struct hdr tcout;
|
|
register long size;
|
|
register short *p;
|
|
register int i;
|
|
|
|
close(*fdp);
|
|
if( fopen(fname,&ssbuf,1) < 0 )
|
|
error("cannot open %s\n",fname);
|
|
p = &tcout;
|
|
for( i = 0; i < (sizeof tcout)/2; i++ )
|
|
*p++ = getw(&ssbuf);
|
|
close(ssbuf.fildes);
|
|
if( tcout.ch_magic != MAGIC )
|
|
error("not object file: %s\n",fname);
|
|
size = tcout.ch_tsize + tcout.ch_dsize;
|
|
if( tcout.ch_rlbflg == 0 )
|
|
size =+ size;
|
|
size =+ tcout.ch_ssize;
|
|
if( (*fdp=open(fname,0,1)) < 0 )
|
|
error("cannot reopen %s\n",fname);
|
|
size =+ sizeof tcout;
|
|
#ifndef UNIX
|
|
size = ((size+3)/4)*4; /*turkey round-up to long for VAX*/
|
|
#endif
|
|
return(size);
|
|
}
|
|
|
|
struct { char byt1; char byt2; char byt3; char byt4; };
|
|
long fixlong(l)
|
|
long l;
|
|
{
|
|
long tl;
|
|
|
|
tl.byt1 = l.byt4;
|
|
tl.byt2 = l.byt3;
|
|
tl.byt3 = l.byt2;
|
|
tl.byt4 = l.byt1;
|
|
return(tl);
|
|
}
|
|
fixshort(i)
|
|
int i;
|
|
{
|
|
int ti;
|
|
|
|
ti.byt1 = i.byt2;
|
|
ti.byt2 = i.byt1;
|
|
}
|
|
|
|
delete(ap)
|
|
char *ap;
|
|
{
|
|
|
|
if(ap==0) {
|
|
cprest();
|
|
return;
|
|
}
|
|
inform('d');
|
|
skcopy(0);
|
|
}
|
|
|
|
extract(ap)
|
|
char *ap;
|
|
{
|
|
|
|
register ofd;
|
|
register long l;
|
|
register i;
|
|
|
|
if(ckafile(ap))
|
|
return;
|
|
if((ofd=creat(ap,0666)) < 0) {
|
|
error("cannot create %s\n",ap);
|
|
endit();
|
|
}
|
|
inform('x');
|
|
cp1file(arfd,ofd,IEVEN,arname,ap);
|
|
close(ofd);
|
|
}
|
|
|
|
print(ap)
|
|
char *ap;
|
|
{
|
|
|
|
if(ckafile(ap))
|
|
return;
|
|
cp1file(arfd,1,IEVEN,arname,"std output");
|
|
}
|
|
|
|
endit()
|
|
{
|
|
|
|
exit();
|
|
}
|
|
|
|
/* list all file in the library*/
|
|
|
|
listall()
|
|
{
|
|
|
|
while(nextar()) {
|
|
tell(-1);
|
|
}
|
|
}
|
|
|
|
/*read next ar file header into libhd*/
|
|
|
|
nextar()
|
|
{
|
|
|
|
if( read(arfd,&libhd,sizeof libhd) != sizeof libhd ||
|
|
libhd.l2fname[0] == '\0' ) {
|
|
areof++;
|
|
return(0);
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/* call with cpflag=0 for skip, cpflag=1 for copy*/
|
|
skcopy(cpflag)
|
|
{
|
|
|
|
register long l;
|
|
register int i;
|
|
|
|
if(areof)
|
|
return;
|
|
l = libhd.l2fsize;
|
|
if(l&1)
|
|
l++;
|
|
if(cpflag) {
|
|
inform('c');
|
|
cp1file(arfd,tempfd,WHDR+OEVEN+IEVEN,arname,tempname);
|
|
}
|
|
else {
|
|
if(lseek(arfd,l,1) < 0) {
|
|
error("seek error on library\n");
|
|
endit();
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef JUNK
|
|
char *mktemp(ap)
|
|
char *ap;
|
|
{
|
|
|
|
register char *p;
|
|
register i,j;
|
|
|
|
/* i = getpid(); /*process id*/
|
|
/* p = ap;
|
|
while(*p)
|
|
p++;
|
|
for(j=0; j<5; j++) {
|
|
*--p = ((i&7) + '0');
|
|
i =>> 3;
|
|
}
|
|
*/ return(ap);
|
|
}
|
|
#endif
|
|
|
|
streq(s1, s2)
|
|
char *s1, *s2;
|
|
{
|
|
register char *p1, *p2;
|
|
|
|
p1 = s1;
|
|
p2 = s2;
|
|
while(*p1++ == *p2)
|
|
if(*p2++ == 0)
|
|
return(1);
|
|
return(0);
|
|
}
|
|
|
|
|
|
int m1[] { 1, ROWN, 'r', '-' };
|
|
int m2[] { 1, WOWN, 'w', '-' };
|
|
int m3[] { 1, XOWN, 'x', '-' };
|
|
int m4[] { 1, RGRP, 'r', '-' };
|
|
int m5[] { 1, WGRP, 'w', '-' };
|
|
int m6[] { 1, XGRP, 'x', '-' };
|
|
int m7[] { 1, ROTH, 'r', '-' };
|
|
int m8[] { 1, WOTH, 'w', '-' };
|
|
int m9[] { 1, XOTH, 'x', '-' };
|
|
|
|
int *m[] { m1, m2, m3, m4, m5, m6, m7, m8, m9};
|
|
|
|
pmode(aflg1)
|
|
{
|
|
register int **mp;
|
|
|
|
for (mp = &m[0]; mp < &m[9];)
|
|
select(*mp++,aflg1);
|
|
}
|
|
|
|
select(pairp,flg)
|
|
int *pairp;
|
|
int flg;
|
|
{
|
|
register int n, *ap, f;
|
|
|
|
ap = pairp;
|
|
f = flg;
|
|
n = *ap++;
|
|
while (--n>=0 && (f&*ap++)==0)
|
|
ap++;
|
|
putchar(*ap);
|
|
}
|
|
|
|
inform(cc)
|
|
char cc;
|
|
{
|
|
|
|
if(vflg) {
|
|
putchar(cc);
|
|
putchar(' ');
|
|
pfname();
|
|
}
|
|
}
|
|
|
|
copystr(ap1,ap2,alen)
|
|
char *ap1, *ap2;
|
|
{
|
|
|
|
register char *p1, *p2;
|
|
register len;
|
|
|
|
p1 = ap1;
|
|
p2 = ap2;
|
|
len = alen;
|
|
while(len) {
|
|
if(!(*p2++ = *p1++))
|
|
break;
|
|
len--;
|
|
}
|
|
while(--len > 0)
|
|
*p2++ = '\0';
|
|
}
|
|
|
|
#ifdef JUNK
|
|
long mklong(ai1,ai2)
|
|
{
|
|
|
|
long l;
|
|
|
|
l.hiword = ai1;
|
|
l.loword = ai2;
|
|
return(l);
|
|
}
|
|
#endif
|
|
|
|
cprest()
|
|
{
|
|
|
|
while(areof==0 && nextar())
|
|
skcopy(1); /*copy rest of library*/
|
|
}
|
|
|
|
cp1file(ifd,ofd,aflags,iname,oname)
|
|
char *iname, *oname;
|
|
{
|
|
|
|
register i;
|
|
register int j;
|
|
register long l;
|
|
register flags;
|
|
|
|
flags = aflags;
|
|
if(flags&WHDR) {
|
|
if(write(ofd,&libhd,sizeof libhd) != sizeof libhd) {
|
|
iwrerr:
|
|
error("write error on %s\n",oname);
|
|
endit();
|
|
}
|
|
}
|
|
for( l = libhd.l2fsize; l > BLKSIZE; l =- BLKSIZE ) {
|
|
if((i=read(ifd,buff,BLKSIZE)) != BLKSIZE) {
|
|
irderr:
|
|
error("read error on %s\n",iname);
|
|
endit();
|
|
}
|
|
if(write(ofd,buff,BLKSIZE) != BLKSIZE) {
|
|
goto iwrerr;
|
|
}
|
|
}
|
|
if( l > 0 ) {
|
|
i = l;
|
|
if((j=read(ifd,buff,i)) != i)
|
|
goto irderr;
|
|
if(flags&OEVEN) {
|
|
if(i&1) {
|
|
buff[i] = '\0';
|
|
i++;
|
|
}
|
|
}
|
|
if(write(ofd,buff,i) != i)
|
|
goto iwrerr;
|
|
}
|
|
if(flags&IEVEN)
|
|
if(l&1)
|
|
read(ifd,buff,1);
|
|
}
|
|
|
|
ckafile(ap)
|
|
char *ap;
|
|
{
|
|
|
|
if(ap==0)
|
|
endit();
|
|
if(areof) {
|
|
error("%s not in archive file\n",ap);
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
error(x1,x2,x3,x4,x5,x6)
|
|
int x1, x2, x3, x4, x5, x6;
|
|
{
|
|
printf(x1,x2,x3,x4,x5,x6);
|
|
if( tempfd ) {
|
|
close(tempfd);
|
|
unlink(tempname);
|
|
}
|
|
exit();
|
|
}
|