mirror of
https://github.com/bobbimanners/GNO-Extras.git
synced 2025-01-07 00:30:01 +00:00
725 lines
15 KiB
Plaintext
725 lines
15 KiB
Plaintext
/* find COMPILE: cc -o find -s -O -i find.c -lS */
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/dir.h>
|
|
#include <sys/stat.h>
|
|
#define A_DAY 86400L /* a day full of seconds */
|
|
#define EQ(x, y) (strcmp(x, y)==0)
|
|
|
|
int Randlast;
|
|
char Pathname[200];
|
|
|
|
struct anode {
|
|
int (*F)();
|
|
struct anode *L, *R;
|
|
} Node[100];
|
|
int Nn; /* number of nodes */
|
|
char *Fname;
|
|
long Now;
|
|
int Argc,
|
|
Ai,
|
|
Pi;
|
|
char **Argv;
|
|
/* cpio stuff */
|
|
int Cpio;
|
|
short *Buf, *Dbuf, *Wp;
|
|
int Bufsize = 5120;
|
|
int Wct = 2560;
|
|
|
|
long Newer;
|
|
|
|
struct stat Statb;
|
|
|
|
struct anode *exp(),
|
|
*e1(),
|
|
*e2(),
|
|
*e3(),
|
|
*mk();
|
|
char *nxtarg();
|
|
char Home[128];
|
|
long Blocks;
|
|
char *rindex();
|
|
char *sbrk();
|
|
main(argc, argv) char *argv[];
|
|
{
|
|
struct anode *exlist;
|
|
int paths;
|
|
register char *cp, *sp = 0;
|
|
FILE *pwd, *popen();
|
|
|
|
time(&Now);
|
|
pwd = popen("pwd", "r");
|
|
fgets(Home, 128, pwd);
|
|
pclose(pwd);
|
|
Home[strlen(Home) - 1] = '\0';
|
|
Argc = argc; Argv = argv;
|
|
if(argc<3) {
|
|
usage: pr("Usage: find path-list predicate-list\n");
|
|
exit(1);
|
|
}
|
|
for(Ai = paths = 1; Ai < (argc-1); ++Ai, ++paths)
|
|
if(*Argv[Ai] == '-' || EQ(Argv[Ai], "(") || EQ(Argv[Ai], "!"))
|
|
break;
|
|
if(paths == 1) /* no path-list */
|
|
goto usage;
|
|
if(!(exlist = exp())) { /* parse and compile the arguments */
|
|
pr("find: parsing error\n");
|
|
exit(1);
|
|
}
|
|
if(Ai<argc) {
|
|
pr("find: missing conjunction\n");
|
|
exit(1);
|
|
}
|
|
for(Pi = 1; Pi < paths; ++Pi) {
|
|
sp = 0;
|
|
chdir(Home);
|
|
strcpy(Pathname, Argv[Pi]);
|
|
if(cp = rindex(Pathname, '/')) {
|
|
sp = cp + 1;
|
|
*cp = '\0';
|
|
if(chdir(*Pathname? Pathname: "/") == -1) {
|
|
pr("find: bad starting directory\n");
|
|
exit(2);
|
|
}
|
|
*cp = '/';
|
|
}
|
|
Fname = sp? sp: Pathname;
|
|
descend(Pathname, Fname, exlist); /* to find files that match */
|
|
}
|
|
if(Cpio) {
|
|
strcpy(Pathname, "TRAILER!!!");
|
|
Statb.st_size = 0;
|
|
cpio();
|
|
}
|
|
exit(0);
|
|
}
|
|
|
|
/* compile time functions: priority is exp()<e1()<e2()<e3() */
|
|
|
|
struct anode *exp() { /* parse ALTERNATION (-o) */
|
|
int or();
|
|
register struct anode * p1;
|
|
|
|
p1 = e1() /* get left operand */ ;
|
|
if(EQ(nxtarg(), "-o")) {
|
|
Randlast--;
|
|
return(mk(or, p1, exp()));
|
|
}
|
|
else if(Ai <= Argc) --Ai;
|
|
return(p1);
|
|
}
|
|
struct anode *e1() { /* parse CONCATENATION (formerly -a) */
|
|
int and();
|
|
register struct anode * p1;
|
|
register char *a;
|
|
|
|
p1 = e2();
|
|
a = nxtarg();
|
|
if(EQ(a, "-a")) {
|
|
And:
|
|
Randlast--;
|
|
return(mk(and, p1, e1()));
|
|
} else if(EQ(a, "(") || EQ(a, "!") || (*a=='-' && !EQ(a, "-o"))) {
|
|
--Ai;
|
|
goto And;
|
|
} else if(Ai <= Argc) --Ai;
|
|
return(p1);
|
|
}
|
|
struct anode *e2() { /* parse NOT (!) */
|
|
int not();
|
|
|
|
if(Randlast) {
|
|
pr("find: operand follows operand\n");
|
|
exit(1);
|
|
}
|
|
Randlast++;
|
|
if(EQ(nxtarg(), "!"))
|
|
return(mk(not, e3(), (struct anode *)0));
|
|
else if(Ai <= Argc) --Ai;
|
|
return(e3());
|
|
}
|
|
struct anode *e3() { /* parse parens and predicates */
|
|
int exeq(), ok(), glob(), mtime(), atime(), ctime(), user(),
|
|
group(), size(), perm(), links(), print(),
|
|
type(), ino(), cpio(), newer();
|
|
struct anode *p1;
|
|
int i;
|
|
register char *a, *b, s;
|
|
|
|
a = nxtarg();
|
|
if(EQ(a, "(")) {
|
|
Randlast--;
|
|
p1 = exp();
|
|
a = nxtarg();
|
|
if(!EQ(a, ")")) goto err;
|
|
return(p1);
|
|
}
|
|
else if(EQ(a, "-print")) {
|
|
return(mk(print, (struct anode *)0, (struct anode *)0));
|
|
}
|
|
b = nxtarg();
|
|
s = *b;
|
|
if(s=='+') b++;
|
|
puts(b);
|
|
if(EQ(a, "-name"))
|
|
return(mk(glob, (struct anode *)b, (struct anode *)0));
|
|
else if(EQ(a, "-mtime"))
|
|
return(mk(mtime, (struct anode *)atoi(b), (struct anode *)s));
|
|
else if(EQ(a, "-atime"))
|
|
return(mk(atime, (struct anode *)atoi(b), (struct anode *)s));
|
|
else if(EQ(a, "-ctime"))
|
|
return(mk(ctime, (struct anode *)atoi(b), (struct anode *)s));
|
|
else if(EQ(a, "-user")) {
|
|
if((i=getunum("/etc/passwd", b)) == -1) {
|
|
if(gmatch(b, "[0-9][0-9][0-9]*")
|
|
|| gmatch(b, "[0-9][0-9]")
|
|
|| gmatch(b, "[0-9]"))
|
|
return mk(user, (struct anode *)atoi(b), (struct anode *)s);
|
|
pr("find: cannot find -user name\n");
|
|
exit(1);
|
|
}
|
|
return(mk(user, (struct anode *)i, (struct anode *)s));
|
|
}
|
|
else if(EQ(a, "-inum"))
|
|
return(mk(ino, (struct anode *)atoi(b), (struct anode *)s));
|
|
else if(EQ(a, "-group")) {
|
|
if((i=getunum("/etc/group", b)) == -1) {
|
|
if(gmatch(b, "[0-9][0-9][0-9]*")
|
|
|| gmatch(b, "[0-9][0-9]")
|
|
|| gmatch(b, "[0-9]"))
|
|
return mk(group, (struct anode *)atoi(b), (struct anode *)s);
|
|
pr("find: cannot find -group name\n");
|
|
exit(1);
|
|
}
|
|
return(mk(group, (struct anode *)i, (struct anode *)s));
|
|
} else if(EQ(a, "-size"))
|
|
return(mk(size, (struct anode *)atoi(b), (struct anode *)s));
|
|
else if(EQ(a, "-links"))
|
|
return(mk(links, (struct anode *)atoi(b), (struct anode *)s));
|
|
else if(EQ(a, "-perm")) {
|
|
for(i=0; *b ; ++b) {
|
|
if(*b=='-') continue;
|
|
i <<= 3;
|
|
i = i + (*b - '0');
|
|
}
|
|
return(mk(perm, (struct anode *)i, (struct anode *)s));
|
|
}
|
|
else if(EQ(a, "-type")) {
|
|
i = s=='d' ? S_IFDIR :
|
|
s=='b' ? S_IFBLK :
|
|
s=='c' ? S_IFCHR :
|
|
s=='f' ? 0100000 :
|
|
0;
|
|
return(mk(type, (struct anode *)i, (struct anode *)0));
|
|
}
|
|
else if (EQ(a, "-exec")) {
|
|
i = Ai - 1;
|
|
while(!EQ(nxtarg(), ";"));
|
|
return(mk(exeq, (struct anode *)i, (struct anode *)0));
|
|
}
|
|
else if (EQ(a, "-ok")) {
|
|
i = Ai - 1;
|
|
while(!EQ(nxtarg(), ";"));
|
|
return(mk(ok, (struct anode *)i, (struct anode *)0));
|
|
}
|
|
else if(EQ(a, "-cpio")) {
|
|
if((Cpio = creat(b, 0666)) < 0) {
|
|
pr("find: cannot create "), pr(s), pr("\n");
|
|
exit(1);
|
|
}
|
|
Buf = (short *)sbrk(512);
|
|
Wp = Dbuf = (short *)sbrk(5120);
|
|
return(mk(cpio, (struct anode *)0, (struct anode *)0));
|
|
}
|
|
else if(EQ(a, "-newer")) {
|
|
if(stat(b, &Statb) < 0) {
|
|
pr("find: cannot access "), pr(b), pr("\n");
|
|
exit(1);
|
|
}
|
|
Newer = Statb.st_mtime;
|
|
return mk(newer, (struct anode *)0, (struct anode *)0);
|
|
}
|
|
err: pr("find: bad option "), pr(a), pr("\n");
|
|
exit(1);
|
|
}
|
|
struct anode *mk(f, l, r)
|
|
int (*f)();
|
|
struct anode *l, *r;
|
|
{
|
|
Node[Nn].F = f;
|
|
Node[Nn].L = l;
|
|
Node[Nn].R = r;
|
|
return(&(Node[Nn++]));
|
|
}
|
|
|
|
char *nxtarg() { /* get next arg from command line */
|
|
static strikes = 0;
|
|
|
|
if(strikes==3) {
|
|
pr("find: incomplete statement\n");
|
|
exit(1);
|
|
}
|
|
if(Ai>=Argc) {
|
|
strikes++;
|
|
Ai = Argc + 1;
|
|
return("");
|
|
}
|
|
return(Argv[Ai++]);
|
|
}
|
|
|
|
/* execution time functions */
|
|
and(p)
|
|
register struct anode *p;
|
|
{
|
|
return(((*p->L->F)(p->L)) && ((*p->R->F)(p->R))?1:0);
|
|
}
|
|
or(p)
|
|
register struct anode *p;
|
|
{
|
|
return(((*p->L->F)(p->L)) || ((*p->R->F)(p->R))?1:0);
|
|
}
|
|
not(p)
|
|
register struct anode *p;
|
|
{
|
|
return( !((*p->L->F)(p->L)));
|
|
}
|
|
glob(p)
|
|
register struct { int f; char *pat; } *p;
|
|
{
|
|
return(gmatch(Fname, p->pat));
|
|
}
|
|
print()
|
|
{
|
|
puts(Pathname);
|
|
return(1);
|
|
}
|
|
mtime(p)
|
|
register struct { int f, t, s; } *p;
|
|
{
|
|
return(scomp((int)((Now - Statb.st_mtime) / A_DAY), p->t, p->s));
|
|
}
|
|
atime(p)
|
|
register struct { int f, t, s; } *p;
|
|
{
|
|
return(scomp((int)((Now - Statb.st_atime) / A_DAY), p->t, p->s));
|
|
}
|
|
ctime(p)
|
|
register struct { int f, t, s; } *p;
|
|
{
|
|
return(scomp((int)((Now - Statb.st_ctime) / A_DAY), p->t, p->s));
|
|
}
|
|
user(p)
|
|
register struct { int f, u, s; } *p;
|
|
{
|
|
return(scomp(Statb.st_uid, p->u, p->s));
|
|
}
|
|
ino(p)
|
|
register struct { int f, u, s; } *p;
|
|
{
|
|
return(scomp((int)Statb.st_ino, p->u, p->s));
|
|
}
|
|
group(p)
|
|
register struct { int f, u; } *p;
|
|
{
|
|
return(p->u == Statb.st_gid);
|
|
}
|
|
links(p)
|
|
register struct { int f, link, s; } *p;
|
|
{
|
|
return(scomp(Statb.st_nlink, p->link, p->s));
|
|
}
|
|
size(p)
|
|
register struct { int f, sz, s; } *p;
|
|
{
|
|
return(scomp((int)((Statb.st_size+511)>>9), p->sz, p->s));
|
|
}
|
|
perm(p)
|
|
register struct { int f, per, s; } *p;
|
|
{
|
|
register i;
|
|
i = (p->s=='-') ? p->per : 07777; /* '-' means only arg bits */
|
|
return((Statb.st_mode & i & 07777) == p->per);
|
|
}
|
|
type(p)
|
|
register struct { int f, per, s; } *p;
|
|
{
|
|
return((Statb.st_mode&S_IFMT)==p->per);
|
|
}
|
|
exeq(p)
|
|
register struct { int f, com; } *p;
|
|
{
|
|
fflush(stdout); /* to flush possible `-print' */
|
|
return(doex(p->com));
|
|
}
|
|
ok(p)
|
|
struct { int f, com; } *p;
|
|
{
|
|
int c; int yes;
|
|
yes = 0;
|
|
fflush(stdout); /* to flush possible `-print' */
|
|
pr("< "), pr(Argv[p->com]), pr(" ... "), pr(Pathname), pr(" >? ");
|
|
fflush(stderr);
|
|
if((c=getchar())=='y') yes = 1;
|
|
while(c!='\n')
|
|
if(c==EOF)
|
|
exit(2);
|
|
else
|
|
c = getchar();
|
|
if(yes) return(doex(p->com));
|
|
return(0);
|
|
}
|
|
|
|
#define MKSHORT(v, lv) {U.l=1L;if(U.c[0]) U.l=lv, v[0]=U.s[1], v[1]=U.s[0]; else U.l=lv, v[0]=U.s[0], v[1]=U.s[1];}
|
|
union { long l; short s[2]; char c[4]; } U;
|
|
long mklong(v)
|
|
short v[];
|
|
{
|
|
U.l = 1;
|
|
if(U.c[0] /* VAX */)
|
|
U.s[0] = v[1], U.s[1] = v[0];
|
|
else
|
|
U.s[0] = v[0], U.s[1] = v[1];
|
|
return U.l;
|
|
}
|
|
cpio()
|
|
{
|
|
#define MAGIC 070707
|
|
struct header {
|
|
short h_magic,
|
|
h_dev,
|
|
h_ino,
|
|
h_mode,
|
|
h_uid,
|
|
h_gid,
|
|
h_nlink,
|
|
h_rdev;
|
|
short h_mtime[2];
|
|
short h_namesize;
|
|
short h_filesize[2];
|
|
char h_name[256];
|
|
} hdr;
|
|
register ifile, ct;
|
|
static long fsz;
|
|
register i;
|
|
|
|
hdr.h_magic = MAGIC;
|
|
strcpy(hdr.h_name, !strncmp(Pathname, "./", 2)? Pathname+2: Pathname);
|
|
hdr.h_namesize = strlen(hdr.h_name) + 1;
|
|
hdr.h_uid = Statb.st_uid;
|
|
hdr.h_gid = Statb.st_gid;
|
|
hdr.h_dev = Statb.st_dev;
|
|
hdr.h_ino = Statb.st_ino;
|
|
hdr.h_mode = Statb.st_mode;
|
|
MKSHORT(hdr.h_mtime, Statb.st_mtime);
|
|
hdr.h_nlink = Statb.st_nlink;
|
|
fsz = hdr.h_mode & S_IFREG? Statb.st_size: 0L;
|
|
MKSHORT(hdr.h_filesize, fsz);
|
|
hdr.h_rdev = Statb.st_rdev;
|
|
if(EQ(hdr.h_name, "TRAILER!!!")) {
|
|
bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize);
|
|
for(i = 0; i < 10; ++i)
|
|
bwrite(Buf, 512);
|
|
return;
|
|
}
|
|
if(!mklong(hdr.h_filesize)) {
|
|
bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize);
|
|
return;
|
|
}
|
|
if((ifile = open(Fname, 0)) < 0) {
|
|
cerror:
|
|
pr("find: cannot copy "), pr(hdr.h_name), pr("\n");
|
|
return;
|
|
}
|
|
bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize);
|
|
for(fsz = mklong(hdr.h_filesize); fsz > 0; fsz -= 512) {
|
|
ct = fsz>512? 512: fsz;
|
|
if(read(ifile, (char *)Buf, ct) < 0)
|
|
goto cerror;
|
|
bwrite(Buf, ct);
|
|
}
|
|
close(ifile);
|
|
return;
|
|
}
|
|
newer()
|
|
{
|
|
return Statb.st_mtime > Newer;
|
|
}
|
|
|
|
/* support functions */
|
|
scomp(a, b, s) /* funny signed compare */
|
|
register a, b;
|
|
register char s;
|
|
{
|
|
if(s == '+')
|
|
return(a > b);
|
|
if(s == '-')
|
|
return(a < (b * -1));
|
|
return(a == b);
|
|
}
|
|
|
|
doex(com)
|
|
{
|
|
register np;
|
|
register char *na;
|
|
static char *nargv[50];
|
|
static ccode;
|
|
|
|
ccode = np = 0;
|
|
while (na=Argv[com++]) {
|
|
if(strcmp(na, ";")==0) break;
|
|
if(strcmp(na, "{}")==0) nargv[np++] = Pathname;
|
|
else nargv[np++] = na;
|
|
}
|
|
nargv[np] = 0;
|
|
if (np==0) return(9);
|
|
if(fork()) /*parent*/ wait(&ccode);
|
|
else { /*child*/
|
|
chdir(Home);
|
|
execvp(nargv[0], nargv, np);
|
|
exit(1);
|
|
}
|
|
return(ccode ? 0:1);
|
|
}
|
|
|
|
getunum(f, s) char *f, *s; { /* find user/group name and return number */
|
|
register i;
|
|
register char *sp;
|
|
register c;
|
|
char str[20];
|
|
FILE *pin;
|
|
|
|
i = -1;
|
|
pin = fopen(f, "r");
|
|
c = '\n'; /* prime with a CR */
|
|
do {
|
|
if(c=='\n') {
|
|
sp = str;
|
|
while((c = *sp++ = getc(pin)) != ':')
|
|
if(c == EOF) goto RET;
|
|
*--sp = '\0';
|
|
if(EQ(str, s)) {
|
|
while((c=getc(pin)) != ':')
|
|
if(c == EOF) goto RET;
|
|
sp = str;
|
|
while((*sp = getc(pin)) != ':') sp++;
|
|
*sp = '\0';
|
|
i = atoi(str);
|
|
goto RET;
|
|
}
|
|
}
|
|
} while((c = getc(pin)) != EOF);
|
|
RET:
|
|
fclose(pin);
|
|
return(i);
|
|
}
|
|
|
|
descend(name, fname, exlist)
|
|
struct anode *exlist;
|
|
char *name, *fname;
|
|
{
|
|
int dir = 0, /* open directory */
|
|
offset,
|
|
dsize,
|
|
entries,
|
|
dirsize;
|
|
struct direct dentry[32];
|
|
register struct direct *dp;
|
|
register char *c1, *c2;
|
|
int i;
|
|
int rv = 0;
|
|
char *endofname;
|
|
|
|
if(stat(fname, &Statb)<0) {
|
|
pr("find: bad status-- "), pr(name), pr("\n");
|
|
return(0);
|
|
}
|
|
(*exlist->F)(exlist);
|
|
if((Statb.st_mode&S_IFMT)!=S_IFDIR)
|
|
return(1);
|
|
|
|
for(c1 = name; *c1; ++c1);
|
|
if(*(c1-1) == '/')
|
|
--c1;
|
|
endofname = c1;
|
|
dirsize = Statb.st_size;
|
|
|
|
if(chdir(fname) == -1)
|
|
return(0);
|
|
for(offset=0 ; offset < dirsize ; offset += 512) { /* each block */
|
|
dsize = 512<(dirsize-offset)? 512: (dirsize-offset);
|
|
if(!dir) {
|
|
if((dir=open(".", 0))<0) {
|
|
pr("find: cannot open "), pr(name), pr("\n");
|
|
rv = 0;
|
|
goto ret;
|
|
}
|
|
if(offset) lseek(dir, (long)offset, 0);
|
|
if(read(dir, (char *)dentry, dsize)<0) {
|
|
pr("find: cannot read "), pr(name), pr("\n");
|
|
rv = 0;
|
|
goto ret;
|
|
}
|
|
if(dir > 10) {
|
|
close(dir);
|
|
dir = 0;
|
|
}
|
|
} else
|
|
if(read(dir, (char *)dentry, dsize)<0) {
|
|
pr("find: cannot read "), pr(name), pr("\n");
|
|
rv = 0;
|
|
goto ret;
|
|
}
|
|
for(dp=dentry, entries=dsize>>4; entries; --entries, ++dp) { /* each directory entry */
|
|
if(dp->d_ino==0
|
|
|| (dp->d_name[0]=='.' && dp->d_name[1]=='\0')
|
|
|| (dp->d_name[0]=='.' && dp->d_name[1]=='.' && dp->d_name[2]=='\0'))
|
|
continue;
|
|
c1 = endofname;
|
|
*c1++ = '/';
|
|
c2 = dp->d_name;
|
|
for(i=0; i<14; ++i)
|
|
if(*c2)
|
|
*c1++ = *c2++;
|
|
else
|
|
break;
|
|
*c1 = '\0';
|
|
if(c1 == endofname) { /* ?? */
|
|
rv = 0;
|
|
goto ret;
|
|
}
|
|
Fname = endofname+1;
|
|
if(!descend(name, Fname, exlist)) {
|
|
*endofname = '\0';
|
|
chdir(Home);
|
|
if(chdir(Pathname) == -1) {
|
|
pr("find: bad directory tree\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rv = 1;
|
|
ret:
|
|
if(dir)
|
|
close(dir);
|
|
if(chdir("..") == -1) {
|
|
*endofname = '\0';
|
|
pr("find: bad directory "), pr(name), pr("\n");
|
|
rv = 1;
|
|
}
|
|
return(rv);
|
|
}
|
|
|
|
gmatch(s, p) /* string match as in glob */
|
|
register char *s, *p;
|
|
{
|
|
if (*s=='.' && *p!='.') return(0);
|
|
return amatch(s, p);
|
|
}
|
|
|
|
amatch(s, p)
|
|
register char *s, *p;
|
|
{
|
|
register cc;
|
|
int scc, k;
|
|
int c, lc;
|
|
|
|
scc = *s;
|
|
lc = 077777;
|
|
switch (c = *p) {
|
|
|
|
case '[':
|
|
k = 0;
|
|
while (cc = *++p) {
|
|
switch (cc) {
|
|
|
|
case ']':
|
|
if (k)
|
|
return(amatch(++s, ++p));
|
|
else
|
|
return(0);
|
|
|
|
case '-':
|
|
k |= lc <= scc & scc <= (cc=p[1]);
|
|
}
|
|
if (scc==(lc=cc)) k++;
|
|
}
|
|
return(0);
|
|
|
|
case '?':
|
|
caseq:
|
|
if(scc) return(amatch(++s, ++p));
|
|
return(0);
|
|
case '*':
|
|
return(umatch(s, ++p));
|
|
case 0:
|
|
return(!scc);
|
|
}
|
|
if (c==scc) goto caseq;
|
|
return(0);
|
|
}
|
|
|
|
umatch(s, p)
|
|
register char *s, *p;
|
|
{
|
|
if(*p==0) return(1);
|
|
while(*s)
|
|
if (amatch(s++, p)) return(1);
|
|
return(0);
|
|
}
|
|
|
|
bwrite(rp, c)
|
|
register short *rp;
|
|
register c;
|
|
{
|
|
register short *wp = Wp;
|
|
|
|
c = (c+1) >> 1;
|
|
while(c--) {
|
|
if(!Wct) {
|
|
again:
|
|
if(write(Cpio, (char *)Dbuf, Bufsize)<0) {
|
|
Cpio = chgreel(1, Cpio);
|
|
goto again;
|
|
}
|
|
Wct = Bufsize >> 1;
|
|
wp = Dbuf;
|
|
++Blocks;
|
|
}
|
|
*wp++ = *rp++;
|
|
--Wct;
|
|
}
|
|
Wp = wp;
|
|
}
|
|
chgreel(x, fl)
|
|
{
|
|
register f;
|
|
char str[22];
|
|
FILE *devtty;
|
|
struct stat statb;
|
|
|
|
pr("find: can't "), pr(x? "write output": "read input"), pr("\n");
|
|
fstat(fl, &statb);
|
|
if((statb.st_mode&S_IFMT) != S_IFCHR)
|
|
exit(1);
|
|
again:
|
|
pr("If you want to go on, type device/file name when ready\n");
|
|
devtty = fopen("/dev/tty", "r");
|
|
fgets(str, 20, devtty);
|
|
str[strlen(str) - 1] = '\0';
|
|
if(!*str)
|
|
exit(1);
|
|
close(fl);
|
|
if((f = open(str, x? 1: 0)) < 0) {
|
|
pr("That didn't work");
|
|
fclose(devtty);
|
|
goto again;
|
|
}
|
|
return f;
|
|
}
|
|
pr(s)
|
|
char *s;
|
|
{
|
|
fputs(s, stderr);
|
|
}
|