home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug100.arc
/
AR.C
< prev
next >
Wrap
Text File
|
1979-12-31
|
9KB
|
336 lines
/*
** AR -- File Archiver
**
** usage: ar -{dptux} arcfile [file...]
**
** Ar collects text files into a single archive file.
** Files can be extracted, new ones added,
** old ones replaced or deleted, and
** a list of the archive contents produced.
**
** The first argument is a switch from the following set.
** The second argument is the name of the archive file.
** The third and subsequent arguments are file names.
**
** -d delete named files from the library.
** -p print named, or all, files on stdout.
** -t table of contents of named, or all, files to stdout.
** -u update the archive by adding/replacing files
** (used to create a new library).
** If no file names are specified in the command line,
** they are obtained from stdin.
** -x extract named, or all, files.
**
** Control-S to pause execution and control-C to abort.
**
** This program was given as a class assignment in the
** Computer Science Department at the University of Arizona.
** It was contributed by Ernext Payne. Orignially it was
** written to work with tape archives, but this version has
** been modified for higher speed operation with diskette
** archives under CP/M.
*/
#include stdio.h
#define NAMESIZE 20
#define MAXLINE 500
#define MAXFILES 20
#define HDR ">>>"
#define AUXSIZE 4096
char tname[]=" ar.$$$";
int fnptr[MAXFILES];
int fstat[MAXFILES];
int nfiles;
int errchk;
main(argc,argv) int argc, argv[]; {
char cmd[3], aname[NAMESIZE];
if(getarg(1, cmd, 3,argc,argv) == EOF) usage();
if(getarg(2,aname,NAMESIZE,argc,argv) == EOF) usage();
if(aname[1] == ':') {
tname[0] = aname[0];
tname[1] = aname[1];
}
else left(tname);
getfns(argc,argv);
switch(toupper(cmd[1])) {
case 'D': drop(aname);
break;
case 'T': table(aname);
break;
case 'U': update(aname);
break;
case 'X':
case 'P': extract(aname, toupper(cmd[1]));
break;
default: usage();
}
}
/* acopy - copy size characters from fpi to fpo */
acopy(fpi,fpo,size) int fpi, fpo; int size; {
int c;
while(size-- > 0) {
poll(YES);
if((c = getc(fpi)) == EOF)
break;
putc(c,fpo);
}
}
/* addfile - add file "name" to archive */
addfile(name,fp) char *name; int fp; {
int nfp;
if((nfp = fopen(name,"r")) == NULL) {
fprintf(stderr,"%s: can't open\n",name);
errchk = 1;
}
if (errchk == 0) {
if(name[1] == ':') name += 2;
fprintf(fp,"%s %s %d\n",HDR,name,fsize(nfp));
fcopy(nfp,fp);
fclose(nfp);
fprintf(stderr, " copied new %s\n", name);
}
}
/* amove - move file1 to file2 */
amove(file1,file2) char *file1, *file2; {
if(errchk) {
printf("fatal errors - archive not altered\n");
unlink(file1);
exit(7);
}
unlink(file2);
if(file2[1] == ':') file2 += 2;
if(rename(file1, file2)) {
printf("can't rename %s to %s\n", file1, file2);
exit(7);
}
}
/* cant - print file name and die */
cant(name) char *name; {
fprintf(stderr,"%s: can't open\n",name);
exit(7);
}
/* drop - delete files from archive */
drop(aname) char *aname; {
int afp, tfp;
if(nfiles <= 0) /* protect innocents */
error("delete by name only");
afp = mustopen(aname,"r");
tfp = mustopen(tname,"w");
auxbuf(tfp, AUXSIZE);
replace(afp,tfp,'d');
notfound();
fclose(afp);
fclose(tfp);
amove(tname,aname);
}
/* error - print message and die */
error(msg) char *msg; {
fprintf(stderr,"%s\n",msg);
exit(7);
}
/* extract - extract files from archive */
extract(aname,cmd) char *aname, cmd; {
int afp, efp;
char ename[NAMESIZE], in[MAXLINE];
int size;
afp = mustopen(aname,"r");
auxbuf(afp, AUXSIZE);
if(cmd == 'P') efp = stdout;
else efp = NULL;
while((size = gethdr(afp,in,ename)) >= 0)
if(!fmatch(ename, YES)) fskip(afp,size);
else {
if(efp != stdout) efp = fopen(ename,"w");
if(efp == NULL) {
fprintf(stderr,"%s: can't create\n",ename);
errchk = 1;
fskip(afp,size);
}
else {
acopy(afp,efp,size);
if(cmd == 'P') fprintf(stderr, "printed %s\n", ename);
else fprintf(stderr, "created %s\n", ename);
if(efp != stdout) fclose(efp);
}
}
notfound();
fclose(afp);
}
/* fcopy - copy file in to file out */
fcopy(in,out) int in, out; {
int c;
while((c = getc(in)) != EOF) {
poll(YES);
putc(c,out);
}
}
/* fmatch - check if name matches argument list */
fmatch(name, quit) char *name; int quit; {
int i, done;
char *fnp;
if(nfiles <= 0) return(1);
done = YES;
for(i=0;i<nfiles;++i) {
fnp = fnptr[i];
if(fnp[1] == ':') fnp += 2;
if(strcmp(name,fnp) == 0) {
fstat[i] = 1;
return(1);
}
if(fstat[i] == 0) done = NO;
}
if(quit && done) exit(0);
return(0);
}
/* fsize - size of file in characters */
fsize(fp) int fp; {
int i;
for(i=0; getc(fp) != EOF; ++i) ;
rewind(fp);
return(i);
}
/* fskip - skip n characters on file fp */
fskip(fp,n) int fp, n; {
while(n-- > 0) {
poll(YES);
if(fgetc(fp) == EOF) break;
}
}
/* getfns - get file names into fname, check for duplicates */
getfns(argc,argv) int argc, argv[]; {
int i, j;
nfiles = argc - 3;
if(nfiles > MAXFILES)
error("too many file names");
for(i=0,j=3; i<nfiles; i++,j++)
fnptr[i] = argv[j];
for(i = 0; i < nfiles-1; ++i)
for(j = i+1; j < nfiles; ++j) {
if(strcmp(fnptr[i],fnptr[j]) == 0) {
fprintf(stderr,"%s:duplicate file names\n",fnptr[i]);
exit(7);
}
}
}
/* gethdr - get header info from fp */
gethdr(fp,buf,name) int fp; char *buf, *name; {
if(fgets(buf,MAXLINE,fp) == NULL)
return(-1);
buf = getwrd(buf,name);
if(strcmp(name,HDR) != 0)
error("archive not in proper format");
buf = getwrd(buf,name);
return(atoi(buf));
}
/* getwrd - copy first word of s to t */
getwrd(s,t) char *s, *t; {
while(isspace(*s)) ++s;
while(*s != '\0' && !isspace(*s)) *t++ = *s++;
*t = '\0';
return(s);
}
/* mustopen - open file or die */
mustopen(name,mode) char *name, *mode; {
int fp;
if(fp = fopen(name,mode)) return(fp);
cant(name);
}
/* notfound - print "not found" message */
notfound() {
int i;
for(i=0;i<nfiles;++i)
if(fstat[i] == 0) {
fprintf(stderr,"%s not in archive\n",fnptr[i]);
errchk = 1;
}
}
/* replace - replace or delete files */
replace(afp,tfp,cmd) int afp, tfp; char cmd; {
char in[MAXLINE], uname[NAMESIZE];
int size;
while((size = gethdr(afp,in,uname)) >= 0) {
if(fmatch(uname, NO)) {
if(cmd == 'u') /* add new one */
addfile(uname,tfp);
fskip(afp,size); /* discard old one */
fprintf(stderr, "dropped old %s\n", uname);
}
else {
fputs(in,tfp);
acopy(afp,tfp,size);
}
}
}
/* table - print table of archive contents */
table(aname) char *aname; {
char in[MAXLINE], lname[NAMESIZE];
int afp, size;
afp = mustopen(aname,"r");
while((size = gethdr(afp,in,lname)) >= 0) {
poll(YES);
if(fmatch(lname, YES)) printf("%s\n", lname);
fskip(afp,size);
}
notfound();
fclose(afp);
}
/* update - update existing files, add new ones at end */
update(aname) char *aname; {
int afp, i, tfp;
char fn[NAMESIZE];
if((afp = fopen(aname,"r+")) == NULL)
/* maybe archive does not exist yet */
afp = mustopen(aname,"w+");
tfp = mustopen(tname,"w+");
auxbuf(tfp, AUXSIZE);
replace(afp,tfp,'u'); /* update existing */
if(nfiles > 0) {
for(i=0;i<nfiles;++i) /* add new ones */
if(fstat[i] == 0) {
addfile(fnptr[i],tfp);
if(errchk) break;
fstat[i] = 1;
}
}
else
while(1) {
poll(YES);
if(iscons(stdin)) fprintf(stdout,"file - ");
if(!fgets(fn, NAMESIZE, stdin) || *fn == '\n') break;
for(i=0; fn[i]; i++)
if((fn[i] = toupper(fn[i])) == '\n') fn[i] = NULL;
addfile(&fn[0], tfp);
if(errchk) break;
}
fclose(afp);
fclose(tfp);
amove(tname,aname);
}
/* usage - abort with a usage message */
usage() {
error("usage: ar -{dptux} arcfile [file...]");
}