xref: /csrg-svn/local/local.cmd/cpio.c (revision 33397)
111240Smckusick /* Copyright (c) 1983 Regents of the University of California */
211240Smckusick 
311240Smckusick #ifndef lint
4*33397Smckusick static char sccsid[] = "@(#)cpio.c	4.3	(Berkeley)	01/26/88";
511240Smckusick #endif not lint
611240Smckusick 
711240Smckusick /*	cpio	COMPILE:	cc -O cpio.c -s -i -o cpio
811240Smckusick 	cpio -- copy file collections
911240Smckusick 
1011240Smckusick */
1111240Smckusick #include <stdio.h>
1211240Smckusick #include <sys/types.h>
1311240Smckusick #include <sys/stat.h>
1411240Smckusick #include <signal.h>
1511240Smckusick #ifdef RT
1611240Smckusick #define S_IFEXT 0120000	/*  allocated by extents  */
1711240Smckusick #define S_IF1EXT 0130000	/*  one extent  */
1811240Smckusick #endif
1911240Smckusick #define EQ(x,y)	(strcmp(x,y)==0)
2011240Smckusick /* for VAX, Interdata, ... */
2111240Smckusick #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];}
2211240Smckusick #define MAGIC	070707
2311240Smckusick #define IN	1
2411240Smckusick #define OUT	2
2511240Smckusick #define PASS	3
2611240Smckusick #define HDRSIZE	((sizeof Hdr)-256)
2711240Smckusick #define LINKS	1000
2811240Smckusick #define MERT 0
2911240Smckusick #define CHARS 76
3011240Smckusick #ifdef RT
3111240Smckusick #define MERT 1	/* yes = 1 ;  no = 0 */
3211240Smckusick extern long filespace;
3311240Smckusick #endif
3411240Smckusick 
3511240Smckusick struct	stat	Statb, Xstatb;
3611240Smckusick 
3711240Smckusick struct header {
3811240Smckusick 	short	h_magic,
3911240Smckusick 		h_dev;
4011240Smckusick 	unsigned short	h_ino,
4111240Smckusick 		h_mode,
4211240Smckusick 		h_uid,
4311240Smckusick 		h_gid;
4411240Smckusick 	short	h_nlink,
4511240Smckusick 		h_rdev,
4611240Smckusick 		h_mtime[2],
4711240Smckusick 		h_namesize,
4811240Smckusick 		h_filesize[2];
4911240Smckusick 	char	h_name[256];
5011240Smckusick } Hdr;
5111240Smckusick 
5211240Smckusick int	Bufsize = 512;
5311240Smckusick short	Buf[256], *Dbuf;
5411240Smckusick char    BBuf[512];
5511240Smckusick char    *Cbuf;
5611240Smckusick int	Wct,Wc;
5711240Smckusick short	*Wp;
5811240Smckusick char    *Cp;
5911240Smckusick #ifdef RT
6011240Smckusick short Actual_size[2];	/* MERT variable */
6111240Smckusick struct{
6211240Smckusick 	long long_size;
6311240Smckusick };
6411240Smckusick #endif
6511240Smckusick 
6611240Smckusick short	Option,
6711240Smckusick 	Dir,
6811240Smckusick 	Uncond,
6911240Smckusick 	Link,
7011240Smckusick 	Rename,
7111240Smckusick 	Toc,
7211240Smckusick 	Verbose,
7311240Smckusick 	Select,
7411240Smckusick 	Mod_time,
7511240Smckusick 	Acc_time,
7611240Smckusick 	Cflag,
7711240Smckusick 	Swap;
7811240Smckusick 
7911240Smckusick int	Ifile,
8011240Smckusick 	Ofile,
8111240Smckusick 	Input = 0,
8211240Smckusick 	Output = 1;
8311240Smckusick long	Blocks,
8411240Smckusick 	Longfile,
8511240Smckusick 	Longtime;
8611240Smckusick 
8711240Smckusick char	Fullname[256],
8811240Smckusick 	Name[256];
8911240Smckusick int	Pathend;
9011240Smckusick 
9111240Smckusick FILE	*Rtty,
9211240Smckusick 	*Wtty;
9311240Smckusick 
9411240Smckusick char	*Pattern[100];
9511240Smckusick char	Strhdr[500];
9611240Smckusick char	*Chdr = Strhdr;
9711240Smckusick short	Dev,
9811240Smckusick 	Uid,
9911240Smckusick 	Gid,
10011240Smckusick 	A_directory,
10111240Smckusick 	A_special,
10211240Smckusick #ifdef RT
10311240Smckusick 	One_extent,
10411240Smckusick 	Multi_extent,
10511240Smckusick #endif
10611240Smckusick 	Filetype = S_IFMT;
10711240Smckusick #ifdef RT
10811240Smckusick short Remove_mode = 0007777;
10911240Smckusick short New_mode;
11011240Smckusick #endif
11111240Smckusick 
11211240Smckusick extern	errno;
11311240Smckusick char	*malloc();
11411240Smckusick char 	*cd();
11511240Smckusick char	*Cd_name;
11611240Smckusick FILE 	*popen();
11711240Smckusick 
11811240Smckusick union { long l; short s[2]; char c[4]; } U;
11911240Smckusick 
12011240Smckusick /* for VAX, Interdata, ... */
mklong(v)12111240Smckusick long mklong(v)
12211240Smckusick short v[];
12311240Smckusick {
12411240Smckusick 	U.l = 1;
12511240Smckusick 	if(U.c[0])
12611240Smckusick 		U.s[0] = v[1], U.s[1] = v[0];
12711240Smckusick 	else
12811240Smckusick 		U.s[0] = v[0], U.s[1] = v[1];
12911240Smckusick 	return U.l;
13011240Smckusick }
13111240Smckusick 
main(argc,argv)13211240Smckusick main(argc, argv)
13311240Smckusick char **argv;
13411240Smckusick {
13511240Smckusick 	register ct;
13611240Smckusick 	long	filesz;
13711240Smckusick 	long lng;
13811240Smckusick 	register char *fullp;
13911240Smckusick 	register i;
14011240Smckusick 
14111240Smckusick 	signal(SIGSYS, 1);
14211240Smckusick 	if(*argv[1] != '-')
14311240Smckusick 		usage();
14411240Smckusick 	Uid = getuid();
14511240Smckusick 	umask(0);
14611240Smckusick 	Gid = getgid();
14711240Smckusick 	Pattern[0] = "*";
14811240Smckusick 
14911240Smckusick 	while(*++argv[1]) {
15011240Smckusick 		switch(*argv[1]) {
15111240Smckusick 		case 'a':
15211240Smckusick 			Acc_time++;
15311240Smckusick 			break;
15411240Smckusick 		case 'B':
15511240Smckusick 			Bufsize = 5120;
15611240Smckusick 			break;
15711240Smckusick 		case 'i':
15811240Smckusick 			Option = IN;
15911240Smckusick 			if(argc > 2 ) {
16011240Smckusick 				for(i = 0; (i+2) < argc; ++i)
16111240Smckusick 					Pattern[i] = argv[i+2];
16211240Smckusick 			}
16311240Smckusick 			break;
16411240Smckusick 		case 'o':
16511240Smckusick 			if(argc != 2)
16611240Smckusick 				usage();
16711240Smckusick 			Option = OUT;
16811240Smckusick 			break;
16911240Smckusick 		case 'p':
17011240Smckusick 			if(argc != 3)
17111240Smckusick 				usage();
17211240Smckusick 			if(access(argv[2], 2) == -1) {
17311240Smckusick accerr:
17411240Smckusick 				err("cannot write in <%s>\n", argv[2]);
17511240Smckusick 				exit(2);
17611240Smckusick 			}
17711240Smckusick 			strcpy(Fullname, argv[2]);
17811240Smckusick 			strcat(Fullname, "/");
17911240Smckusick 			stat(Fullname, &Xstatb);
18011240Smckusick 			if((Xstatb.st_mode&S_IFMT) != S_IFDIR)
18111240Smckusick 				goto accerr;
18211240Smckusick 			Option = PASS;
18311240Smckusick 			Dev = Xstatb.st_dev;
18411240Smckusick 			break;
18511240Smckusick 		case 'c':
18611240Smckusick 			Cflag++;
18711240Smckusick 			break;
18811240Smckusick 		case 'd':
18911240Smckusick 			Dir++;
19011240Smckusick 			break;
19111240Smckusick 		case 'l':
19211240Smckusick 			Link++;
19311240Smckusick 			break;
19411240Smckusick 		case 'm':
19511240Smckusick 			Mod_time++;
19611240Smckusick 			break;
19711240Smckusick 		case 'r':
19811240Smckusick 			Rename++;
19911240Smckusick 			Rtty = fopen("/dev/tty", "r");
20011240Smckusick 			Wtty = fopen("/dev/tty", "w");
20111240Smckusick 			if(Rtty==NULL || Wtty==NULL) {
20211240Smckusick 				err(
20311240Smckusick 				  "Cannot rename (/dev/tty missing)\n");
20411240Smckusick 				exit(2);
20511240Smckusick 			}
20611240Smckusick 			break;
20711240Smckusick 		case 's':
20811240Smckusick 			Swap++;
20911240Smckusick 			break;
21011240Smckusick 		case 't':
21111240Smckusick 			Toc++;
21211240Smckusick 			break;
21311240Smckusick 		case 'u':
21411240Smckusick 			Uncond++;
21511240Smckusick 			break;
21611240Smckusick 		case 'v':
21711240Smckusick 			Verbose++;
21811240Smckusick 			break;
21911240Smckusick 		case '6':
22011240Smckusick 			Filetype = 060000;
22111240Smckusick 			break;
22211240Smckusick 		default:
22311240Smckusick 			usage();
22411240Smckusick 		}
22511240Smckusick 	}
22611240Smckusick 	if(!Option) {
22711240Smckusick 		err("Options must include o|i|p\n");
22811240Smckusick 		exit(2);
22911240Smckusick 	}
23011240Smckusick 
23111240Smckusick 	if (Cflag && Swap)  {
23211240Smckusick 		err("Swap flag is ignored with Cflag\n");
23311240Smckusick 		Swap = 0;
23411240Smckusick 	}
23511240Smckusick 
23611240Smckusick 	if(Option != PASS)  {
23711240Smckusick 		Wp = Dbuf = (short *)malloc(Bufsize);
23811240Smckusick 		Cp = Cbuf = (char *)malloc(Bufsize);
23911240Smckusick 	}
24011240Smckusick 	     Wct = Bufsize >> 1;
24111240Smckusick 	     Wc = Bufsize;
24211240Smckusick 
24311240Smckusick 	if(Option == PASS && Rename) {
24411240Smckusick 		err("Pass and Rename cannot be used together");
24511240Smckusick 		exit(2);
24611240Smckusick 	}
24711240Smckusick 	switch(Option) {
24811240Smckusick 
24911240Smckusick 	case OUT:
25011240Smckusick 		while(getname()) {
25111240Smckusick 			if( mklong(Hdr.h_filesize) == 0L) {
25211240Smckusick 				if ( Cflag )
25311240Smckusick 				     writehdr(Chdr,CHARS+Hdr.h_namesize);
25411240Smckusick 				else
25511240Smckusick 				     bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
25611240Smckusick #ifdef RT
25711240Smckusick 				if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
25811240Smckusick 					|| ((Hdr.h_mode & Filetype) == S_IFEXT))) {
25911240Smckusick 					actsize();
26011240Smckusick 					bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
26111240Smckusick 				}
26211240Smckusick #endif
26311240Smckusick 				continue;
26411240Smckusick 			}
26511240Smckusick 			if((Ifile = open(Hdr.h_name, 0)) < 0) {
26611240Smckusick 				err("<%s> ?\n", Hdr.h_name);
26711240Smckusick 				continue;
26811240Smckusick 			}
26911240Smckusick 			if ( Cflag )
27011240Smckusick 			     writehdr(Chdr,CHARS+Hdr.h_namesize);
27111240Smckusick 			else
27211240Smckusick 			     bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
27311240Smckusick #ifdef RT
27411240Smckusick 			if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
27511240Smckusick 				|| ((Hdr.h_mode & Filetype) == S_IFEXT))) {
27611240Smckusick 				actsize();
27711240Smckusick 				bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
27811240Smckusick 			}
27911240Smckusick #endif
28011240Smckusick 			for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= 512){
28111240Smckusick 				ct = filesz>512? 512: filesz;
28211240Smckusick 				   if(read(Ifile, Cflag? BBuf: (char *)Buf, ct) < 0) {
28311240Smckusick 					err("Cannot read %s\n", Hdr.h_name);
28411240Smckusick 					continue;
28511240Smckusick 				   }
28611240Smckusick 				Cflag? writehdr(BBuf,ct): bwrite(Buf,ct);
28711240Smckusick 			}
28811240Smckusick 			close(Ifile);
28911240Smckusick 			if(Acc_time)
29011240Smckusick 				utime(Hdr.h_name, &Statb.st_atime);
29111240Smckusick 			if(Verbose)
29211240Smckusick 				err("%s\n", Hdr.h_name);
29311240Smckusick 		}
29411240Smckusick 		strcpy(Hdr.h_name, "TRAILER!!!");
29511240Smckusick 		Hdr.h_magic = MAGIC;
29611240Smckusick 		MKSHORT(Hdr.h_filesize, 0L);
29711240Smckusick 		Hdr.h_namesize = strlen("TRAILER!!!") + 1;
29811240Smckusick 		if ( Cflag )  {
29911240Smckusick 		     lng = 0;
30011240Smckusick 		     bintochar(lng);
30111240Smckusick 		     writehdr(Chdr,CHARS+Hdr.h_namesize);
30211240Smckusick 		}
30311240Smckusick 		else
30411240Smckusick 		     bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
30511240Smckusick 		Cflag? writehdr(Cbuf, Bufsize): bwrite(Dbuf, Bufsize);
30611240Smckusick 		break;
30711240Smckusick 
30811240Smckusick 	case IN:
30911240Smckusick 		pwd();
31011240Smckusick 		while(gethdr()) {
31111240Smckusick 			Ofile = ckname(Hdr.h_name)? openout(Hdr.h_name): 0;
31211240Smckusick 			for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= 512){
31311240Smckusick 				ct = filesz>512? 512: filesz;
31411240Smckusick 				Cflag? readhdr(BBuf, ct): bread(Buf, ct);
31511240Smckusick 				if(Ofile) {
31611240Smckusick 					if(Swap)
31711240Smckusick 						swap(Buf, ct);
31811240Smckusick 					   if(write(Ofile, Cflag? BBuf: (char *)Buf, ct) < 0) {
31911240Smckusick 					      err("Cannot write %s\n", Hdr.h_name);
32011240Smckusick 					      continue;
32111240Smckusick 					   }
32211240Smckusick 				}
32311240Smckusick 			}
32411240Smckusick 			if(Ofile) {
32511240Smckusick 				close(Ofile);
32611240Smckusick 				set_time(Cd_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
32711240Smckusick 			}
32811240Smckusick 			if(!Select)
32911240Smckusick 				continue;
33011240Smckusick 			if(Verbose)
33111240Smckusick 				if(Toc)
33211240Smckusick 					pentry(Hdr.h_name);
33311240Smckusick 				else
33411240Smckusick 					puts(Hdr.h_name);
33511240Smckusick 			else if(Toc)
33611240Smckusick 				puts(Hdr.h_name);
33711240Smckusick 		}
33811240Smckusick 		break;
33911240Smckusick 
34011240Smckusick 	case PASS:
34111240Smckusick 		fullp = Fullname + strlen(Fullname);
34211240Smckusick 
34311240Smckusick 		while(getname()) {
34411240Smckusick 			if(!ckname(Hdr.h_name))
34511240Smckusick 				continue;
34611240Smckusick 			strcpy(fullp, Hdr.h_name);
34711240Smckusick 
34811240Smckusick 			if(Link
34911240Smckusick 			&& !A_directory
35011240Smckusick 			&& Dev == Statb.st_dev) {
35111240Smckusick /* ???			&& (Uid == Statb.st_uid || !Uid)) {*/
35211240Smckusick 				if(link(Hdr.h_name, Fullname) < 0) { /* missing dir.? */
35311240Smckusick 					unlink(Fullname);
35411240Smckusick 					missdir(Fullname);
35511240Smckusick 					if(link(Hdr.h_name, Fullname) < 0) {
35611240Smckusick 						err(
35711240Smckusick 						 "Cannot link <%s> & <%s>\n",
35811240Smckusick 						 Hdr.h_name, Fullname);
35911240Smckusick 						continue;
36011240Smckusick 					}
36111240Smckusick 				}
36211240Smckusick 				set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
36311240Smckusick 				goto ckverbose;
36411240Smckusick 			}
36511240Smckusick 			if(!(Ofile = openout(Fullname)))
36611240Smckusick 				continue;
36711240Smckusick 			if((Ifile = open(Hdr.h_name, 0)) < 0) {
36811240Smckusick 				err("<%s> ?\n", Hdr.h_name);
36911240Smckusick 				close(Ofile);
37011240Smckusick 				continue;
37111240Smckusick 			}
37211240Smckusick 			filesz = Statb.st_size;
37311240Smckusick 			for(; filesz > 0; filesz -= 512) {
37411240Smckusick 				ct = filesz>512? 512: filesz;
37511240Smckusick 				    if(read(Ifile, Buf, ct) < 0) {
37611240Smckusick 					err("Cannot read %s\n", Hdr.h_name);
37711240Smckusick 					break;
37811240Smckusick 				    }
37911240Smckusick 				if(Ofile)
38011240Smckusick 					if(write(Ofile, Buf, ct) < 0) {
38111240Smckusick 					  err("Cannot write %s\n", Hdr.h_name);
38211240Smckusick 					  break;
38311240Smckusick 					}
38411240Smckusick 				++Blocks;
38511240Smckusick 			}
38611240Smckusick 			close(Ifile);
38711240Smckusick 			if(Acc_time)
38811240Smckusick 				utime(Hdr.h_name, &Statb.st_atime);
38911240Smckusick 			if(Ofile) {
39011240Smckusick 				close(Ofile);
39111240Smckusick 				set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime));
39211240Smckusick ckverbose:
39311240Smckusick 				if(Verbose)
39411240Smckusick 					puts(Fullname);
39511240Smckusick 			}
39611240Smckusick 		}
39711240Smckusick 	}
39811240Smckusick 	err("%ld blocks\n", Blocks * (Bufsize>>9));
39911240Smckusick 	exit(0);
40011240Smckusick }
usage()40111240Smckusick usage()
40211240Smckusick {
40311240Smckusick 	err("Usage: cpio -o[acvB] <name-list >collection\n%s\n%s\n",
40411240Smckusick 	"       cpio -i[cdmrstuvB6] [pattern ...] <collection",
40511240Smckusick 	"       cpio -p[adlmruv] directory <name-list");
40611240Smckusick 	exit(2);
40711240Smckusick }
40811240Smckusick 
getname()40911240Smckusick getname()
41011240Smckusick {
41111240Smckusick 	register char *namep = Name;
41211240Smckusick 	long tlong;
41311240Smckusick 
41411240Smckusick 	for(;;) {
41511240Smckusick 		if(gets(namep) == NULL)
41611240Smckusick 			return 0;
41711240Smckusick 		if(*namep == '.' && namep[1] == '/')
41811240Smckusick 			namep += 2;
41911240Smckusick 		strcpy(Hdr.h_name, namep);
42011240Smckusick 		if(stat(namep, &Statb) < 0) {
42111240Smckusick 			err("< %s > ?\n", Hdr.h_name);
42211240Smckusick 			continue;
42311240Smckusick 		}
42411240Smckusick 		A_directory = (Statb.st_mode & Filetype) == S_IFDIR;
42511240Smckusick 		A_special = ((Statb.st_mode & Filetype) == S_IFBLK)
42611240Smckusick 			|| ((Statb.st_mode & Filetype) == S_IFCHR);
42711240Smckusick #ifdef RT
42811240Smckusick 		if(MERT) {
42911240Smckusick 			One_extent = (Statb.st_mode & Filetype) == S_IF1EXT;
43011240Smckusick 			Multi_extent = (Statb.st_mode & Filetype) == S_IFEXT;
43111240Smckusick 		}
43211240Smckusick #endif
43311240Smckusick 		Hdr.h_magic = MAGIC;
43411240Smckusick 		Hdr.h_namesize = strlen(Hdr.h_name) + 1;
43511240Smckusick 		Hdr.h_uid = Statb.st_uid;
43611240Smckusick 		Hdr.h_gid = Statb.st_gid;
43711240Smckusick 		Hdr.h_dev = Statb.st_dev;
43811240Smckusick 		Hdr.h_ino = Statb.st_ino;
43911240Smckusick 		Hdr.h_mode = Statb.st_mode;
44011240Smckusick 		MKSHORT(Hdr.h_mtime, Statb.st_mtime);
44111240Smckusick 		Hdr.h_nlink = Statb.st_nlink;
44211240Smckusick 		tlong = Hdr.h_mode & S_IFREG? Statb.st_size: 0L;
44311240Smckusick 		MKSHORT(Hdr.h_filesize, tlong);
44411240Smckusick 		Hdr.h_rdev = Statb.st_rdev;
44511240Smckusick 		if(Cflag)
44611240Smckusick 			bintochar(tlong);
44711240Smckusick 		return 1;
44811240Smckusick 	}
44911240Smckusick }
45011240Smckusick 
bintochar(t)45111240Smckusick bintochar(t)
45211240Smckusick long t;
45311240Smckusick {
45411240Smckusick 	sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s",
45511240Smckusick 		MAGIC,Statb.st_dev,Statb.st_ino,Statb.st_mode,Statb.st_uid,
45611240Smckusick 		Statb.st_gid,Statb.st_nlink,Statb.st_rdev & 00000177777,
45711240Smckusick 		Statb.st_mtime,(short)strlen(Hdr.h_name)+1,t,Hdr.h_name);
45811240Smckusick }
45911240Smckusick 
chartobin()46011240Smckusick chartobin()
46111240Smckusick {
462*33397Smckusick 	sscanf(Chdr,"%6ho%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo",
46311240Smckusick 		&Hdr.h_magic,&Hdr.h_dev,&Hdr.h_ino,&Hdr.h_mode,&Hdr.h_uid,
46411240Smckusick 		&Hdr.h_gid,&Hdr.h_nlink,&Hdr.h_rdev,&Longtime,&Hdr.h_namesize,
46511240Smckusick 		&Longfile);
46611240Smckusick 	MKSHORT(Hdr.h_filesize, Longfile);
46711240Smckusick 	MKSHORT(Hdr.h_mtime, Longtime);
46811240Smckusick }
46911240Smckusick 
gethdr()47011240Smckusick gethdr()
47111240Smckusick {
47211240Smckusick 
47311240Smckusick 	if ( Cflag )  {
47411240Smckusick 		readhdr(Chdr,CHARS);
47511240Smckusick 		chartobin();
47611240Smckusick 	}
47711240Smckusick 	else
47811240Smckusick 		bread(&Hdr, HDRSIZE);
47911240Smckusick 
48011240Smckusick 	if(Hdr.h_magic != MAGIC) {
48127508Sbloom 		err("Out of phase--get help\n");
48211240Smckusick 		exit(2);
48311240Smckusick 	}
48411240Smckusick 	if(!Cflag)
48511240Smckusick 	     bread(Hdr.h_name, Hdr.h_namesize);
48611240Smckusick 	else
48711240Smckusick 	     readhdr(Hdr.h_name, Hdr.h_namesize);
48811240Smckusick 	if(Swap)
48911240Smckusick 		swap(Hdr.h_name, Hdr.h_namesize);
49011240Smckusick 	if(EQ(Hdr.h_name, "TRAILER!!!"))
49111240Smckusick 		return 0;
49211240Smckusick 	A_directory = (Hdr.h_mode & Filetype) == S_IFDIR;
49311240Smckusick 	A_special =((Hdr.h_mode & Filetype) == S_IFBLK)
49411240Smckusick 		|| ((Hdr.h_mode & Filetype) == S_IFCHR);
49511240Smckusick #ifdef RT
49611240Smckusick 	if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
49711240Smckusick 		|| ((Hdr.h_mode & Filetype) == S_IFEXT))) {
49811240Smckusick 		One_extent = (Hdr.h_mode & Filetype) == S_IF1EXT;
49911240Smckusick 		Multi_extent = (Hdr.h_mode & Filetype) == S_IFEXT;
50011240Smckusick 		Actual_size[0] = Hdr.h_filesize[0];
50111240Smckusick 		Actual_size[1] = Hdr.h_filesize[1];
50211240Smckusick 		bread(&Hdr, HDRSIZE);
50311240Smckusick 		if(Hdr.h_magic != MAGIC) {
50427508Sbloom 			err("Out of phase--get MERT help\n");
50511240Smckusick 			exit(2);
50611240Smckusick 		}
50711240Smckusick 		bread(Hdr.h_name, Hdr.h_namesize);
50811240Smckusick 	}
50911240Smckusick #endif
51011240Smckusick 	return 1;
51111240Smckusick }
51211240Smckusick 
ckname(namep)51311240Smckusick ckname(namep)
51411240Smckusick register char *namep;
51511240Smckusick {
51611240Smckusick 	++Select;
51711240Smckusick 	if(!nmatch(namep, Pattern)) {
51811240Smckusick 		Select = 0;
51911240Smckusick 		return 0;
52011240Smckusick 	}
52111240Smckusick 	if(Rename && !A_directory) {
52211240Smckusick 		fprintf(Wtty, "Rename <%s>\n", namep);
52311240Smckusick 		fflush(Wtty);
52411240Smckusick 		fgets(namep, 128, Rtty);
52511240Smckusick 		if(feof(Rtty))
52611240Smckusick 			exit(2);
52711240Smckusick 		namep[strlen(namep) - 1] = '\0';
52811240Smckusick 		if(EQ(namep, "")) {
52911240Smckusick 			printf("Skipped\n");
53011240Smckusick 			return 0;
53111240Smckusick 		}
53211240Smckusick 	}
53311240Smckusick 	return !Toc;
53411240Smckusick }
53511240Smckusick 
openout(namep)53611240Smckusick openout(namep)
53711240Smckusick register char *namep;
53811240Smckusick {
53911240Smckusick 	register f;
54011240Smckusick 	register char *np;
54111240Smckusick 
54211240Smckusick 	if(!strncmp(namep, "./", 2))
54311240Smckusick 		namep += 2;
54411240Smckusick 	np = namep;
54511240Smckusick 	if(Option == IN)
54611240Smckusick 		Cd_name = namep = cd(namep);
54711240Smckusick 	if(A_directory) {
54811240Smckusick 		if(!Dir
54911240Smckusick 		|| Rename
55011240Smckusick 		|| EQ(namep, ".")
55111240Smckusick 		|| EQ(namep, "..")
55211240Smckusick 		|| stat(namep, &Xstatb) == 0)
55311240Smckusick 			return 0;
55411240Smckusick 
55511240Smckusick 		if(!makdir(namep)) {
55611240Smckusick 			missdir(namep);
55711240Smckusick 		}
55811240Smckusick ret:
55911240Smckusick 		chmod(namep, Hdr.h_mode);
56011240Smckusick 		if(Uid == 0)
56111240Smckusick 			chown(namep, Hdr.h_uid, Hdr.h_gid);
56211240Smckusick 		set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
56311240Smckusick 		return 0;
56411240Smckusick 	}
56511240Smckusick 	if(Hdr.h_nlink > 1)
56611240Smckusick 		if(!postml(namep, np))
56711240Smckusick 			return 0;
56811240Smckusick 	if(A_special) {
56911240Smckusick s_again:
57011240Smckusick 		if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) {
57111240Smckusick 			if(missdir(namep))
57211240Smckusick 				goto s_again;
57311240Smckusick 			err("Cannot mknod <%s>\n", namep);
57411240Smckusick 			return 0;
57511240Smckusick 		}
57611240Smckusick 		goto ret;
57711240Smckusick 	}
57811240Smckusick 	if(stat(namep, &Xstatb) == 0) {
57911240Smckusick 		if(Uncond && !(Xstatb.st_mode & S_IWRITE))
58011240Smckusick 			unlink(namep);
58111240Smckusick 		if(!Uncond && (mklong(Hdr.h_mtime) < Xstatb.st_mtime)) {
58211240Smckusick 			err("current <%s> newer\n", namep);
58311240Smckusick 			return 0;
58411240Smckusick 		}
58511240Smckusick 	}
58611240Smckusick 	if(Option == PASS
58711240Smckusick 	&& Hdr.h_ino == Xstatb.st_ino
58811240Smckusick 	&& Hdr.h_dev == Xstatb.st_dev) {
58911240Smckusick 		err("Attempt to pass file to self!\n");
59011240Smckusick 		exit(2);
59111240Smckusick 	}
59211240Smckusick #ifdef RT
59311240Smckusick one_again:
59411240Smckusick 	if(One_extent || Multi_extent) {
59511240Smckusick 		if((f = falloc(namep, Hdr.h_mode, Hdr.h_filesize[0].long_size)) < 0) {
59611240Smckusick 			if(missdir(namep))
59711240Smckusick 				goto one_again;
59811240Smckusick 			err("Cannot create <%s> (errno:%d)\n", namep, errno);
59911240Smckusick 			return 0;
60011240Smckusick 		}
60111240Smckusick 		if(filespace < Hdr.h_filesize[0].long_size){
60211240Smckusick 			err("Cannot create contiguous file <%s> proper size\n", namep);
60311240Smckusick 			err("    <%s> will be created as a regular file\n", namep);
60411240Smckusick 			if(unlink(Fullname) != 0)
60511240Smckusick 				err("<%s> not removed\n", namep);
60611240Smckusick 			New_mode = Hdr.h_mode & Remove_mode;
60711240Smckusick 			New_mode = New_mode | S_IFREG;
60811240Smckusick once_again:
60911240Smckusick 			if((f = creat(namep, New_mode)) < 0){
61011240Smckusick 				if(missdir(namep))
61111240Smckusick 					goto once_again;
61211240Smckusick 				err("Cannot create <%s> (errno:%d)\n", namep, errno);
61311240Smckusick 				return (0);
61411240Smckusick 			}
61511240Smckusick 		}
61611240Smckusick 	}
61711240Smckusick #endif
61811240Smckusick #ifdef RT
61911240Smckusick 	if(MERT && (One_extent || Multi_extent))
62011240Smckusick 		goto skip_c;
62111240Smckusick #endif
62211240Smckusick c_again:
62311240Smckusick 	if((f = creat(namep, Hdr.h_mode)) < 0) {
62411240Smckusick 		if(missdir(namep))
62511240Smckusick 			goto c_again;
62611240Smckusick 		err("Cannot create <%s> (errno:%d)\n", namep, errno);
62711240Smckusick 		return 0;
62811240Smckusick 	}
62911240Smckusick #ifdef RT
63011240Smckusick skip_c:
63111240Smckusick #endif
63211240Smckusick 	if(Uid == 0)
63311240Smckusick 		chown(namep, Hdr.h_uid, Hdr.h_gid);
63411240Smckusick 	return f;
63511240Smckusick }
63611240Smckusick 
bread(b,c)63711240Smckusick bread(b, c)
63811240Smckusick register c;
63911240Smckusick register short *b;
64011240Smckusick {
64111240Smckusick 	static nleft = 0;
64211240Smckusick 	static short *ip;
64311240Smckusick 	register short *p = ip;
64411240Smckusick 
64511240Smckusick 	c = (c+1)>>1;
64611240Smckusick 	while(c--) {
64711240Smckusick 		if(!nleft) {
64811240Smckusick again:
64911240Smckusick 			if(read(Input, Dbuf, Bufsize)!=Bufsize) {
65011240Smckusick 				Input = chgreel(0, Input);
65111240Smckusick 				goto again;
65211240Smckusick 			}
65311240Smckusick 			nleft = Bufsize >> 1;
65411240Smckusick 			p = Dbuf;
65511240Smckusick 			++Blocks;
65611240Smckusick 		}
65711240Smckusick 		*b++ = *p++;
65811240Smckusick 		--nleft;
65911240Smckusick 	}
66011240Smckusick 	ip = p;
66111240Smckusick }
66211240Smckusick 
readhdr(b,c)66311240Smckusick readhdr(b, c)
66411240Smckusick register c;
66511240Smckusick register char *b;
66611240Smckusick {
66711240Smckusick 	static nleft = 0;
66811240Smckusick 	static char *ip;
66911240Smckusick 	register char *p = ip;
67011240Smckusick 
67111240Smckusick 	while(c--)  {
67211240Smckusick 		if(!nleft)  {
67311240Smckusick again:
67411240Smckusick 			if(read(Input, Cbuf, Bufsize) != Bufsize)  {
67511240Smckusick 				Input = chgreel(0, Input);
67611240Smckusick 				goto again;
67711240Smckusick 			}
67811240Smckusick 			nleft = Bufsize;
67911240Smckusick 			p = Cbuf;
68011240Smckusick 			++Blocks;
68111240Smckusick 		}
68211240Smckusick 		*b++ = *p++;
68311240Smckusick 		--nleft;
68411240Smckusick 	}
68511240Smckusick 	ip = p;
68611240Smckusick }
68711240Smckusick 
bwrite(rp,c)68811240Smckusick bwrite(rp, c)
68911240Smckusick register short *rp;
69011240Smckusick register c;
69111240Smckusick {
69211240Smckusick 	register short *wp = Wp;
69311240Smckusick 
69411240Smckusick 	c = (c+1) >> 1;
69511240Smckusick 	while(c--) {
69611240Smckusick 		if(!Wct) {
69711240Smckusick again:
69811240Smckusick 			if(write(Output, Dbuf, Bufsize)<0) {
69911240Smckusick 				Output = chgreel(1, Output);
70011240Smckusick 				goto again;
70111240Smckusick 			}
70211240Smckusick 			Wct = Bufsize >> 1;
70311240Smckusick 			wp = Dbuf;
70411240Smckusick 			++Blocks;
70511240Smckusick 		}
70611240Smckusick 		*wp++ = *rp++;
70711240Smckusick 		--Wct;
70811240Smckusick 	}
70911240Smckusick 	Wp = wp;
71011240Smckusick }
writehdr(rp,c)71111240Smckusick writehdr(rp,c)
71211240Smckusick register char *rp;
71311240Smckusick register c;
71411240Smckusick {
71511240Smckusick          register char *cp = Cp;
71611240Smckusick 
71711240Smckusick          while(c--)  {
71811240Smckusick                  if(!Wc)  {
71911240Smckusick again:
72011240Smckusick                         if(write(Output,Cbuf,Bufsize)<0)  {
72111240Smckusick                                 Output = chgreel(1, Output);
72211240Smckusick                                 goto again;
72311240Smckusick                         }
72411240Smckusick                         Wc = Bufsize;
72511240Smckusick                         cp = Cbuf;
72611240Smckusick                         ++Blocks;
72711240Smckusick                  }
72811240Smckusick                  *cp++ = *rp++;
72911240Smckusick                  --Wc;
73011240Smckusick          }
73111240Smckusick          Cp = cp;
73211240Smckusick }
73311240Smckusick 
73411240Smckusick 
postml(namep,np)73511240Smckusick postml(namep, np)
73611240Smckusick register char *namep, *np;
73711240Smckusick {
73811240Smckusick 	register i;
73911240Smckusick 	static struct ml {
74011240Smckusick 		short	m_dev,
74111240Smckusick 			m_ino;
74211240Smckusick 		char	m_name[2];
74311240Smckusick 	} *ml[LINKS];
74411240Smckusick 	static	mlinks = 0;
74511240Smckusick 	char *mlp;
74611240Smckusick 
74711240Smckusick 	for(i = 0; i < mlinks; ++i) {
74811240Smckusick 		if(mlinks == LINKS) break;
74911240Smckusick 		if(ml[i]->m_ino==Hdr.h_ino &&
75011240Smckusick 			ml[i]->m_dev==Hdr.h_dev) {
75111240Smckusick 			if(Verbose)
75211240Smckusick 			  printf("%s linked to %s\n", ml[i]->m_name,
75311240Smckusick 				np);
75411240Smckusick 			unlink(namep);
75511240Smckusick 			if(Option == IN) {
75611240Smckusick 				Fullname[Pathend] = '\0';
75711240Smckusick 				strcat(Fullname, ml[i]->m_name);
75811240Smckusick 				mlp = Fullname;
75911240Smckusick 			} else
76011240Smckusick 				mlp = ml[i]->m_name;
76111240Smckusick l_again:
76211240Smckusick 			if(link(mlp, namep) < 0) {
76311240Smckusick 				if(missdir(np))
76411240Smckusick 					goto l_again;
76511240Smckusick 				err("Cannot link <%s>&<%s>.\n",
76611240Smckusick 					ml[i]->m_name, np);
76711240Smckusick 			}
76811240Smckusick 			set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
76911240Smckusick 			return 0;
77011240Smckusick 		}
77111240Smckusick 	}
77211240Smckusick 	if(mlinks == LINKS
77311240Smckusick 	|| !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) {
77411240Smckusick 		static int first=1;
77511240Smckusick 
77611240Smckusick 		if(first)
77711240Smckusick 			if(mlinks == LINKS)
77811240Smckusick 				err("Too many links\n");
77911240Smckusick 			else
78011240Smckusick 				err("No memory for links\n");
78111240Smckusick 		mlinks = LINKS;
78211240Smckusick 		first = 0;
78311240Smckusick 		return 1;
78411240Smckusick 	}
78511240Smckusick 	ml[mlinks]->m_dev = Hdr.h_dev;
78611240Smckusick 	ml[mlinks]->m_ino = Hdr.h_ino;
78711240Smckusick 	strcpy(ml[mlinks]->m_name, np);
78811240Smckusick 	++mlinks;
78911240Smckusick 	return 1;
79011240Smckusick }
79111240Smckusick 
pentry(namep)79211240Smckusick pentry(namep)
79311240Smckusick register char *namep;
79411240Smckusick {
79511240Smckusick 
79611240Smckusick 	register i;
79711240Smckusick 	static short lastid = -1;
79811240Smckusick #include <pwd.h>
79911240Smckusick 	static struct passwd *pw;
80011240Smckusick 	struct passwd *getpwuid();
80111240Smckusick 	static char tbuf[32];
80211240Smckusick 
80311240Smckusick 	printf("%-7o", Hdr.h_mode & 0177777);
80411240Smckusick 	if(lastid == Hdr.h_uid)
80511240Smckusick 		printf("%-6s", pw->pw_name);
80611240Smckusick 	else {
80711240Smckusick 		setpwent();
80811240Smckusick 		if(pw = getpwuid(Hdr.h_uid)) {
80911240Smckusick 			printf("%-6s", pw->pw_name);
81011240Smckusick 			lastid = Hdr.h_uid;
81111240Smckusick 		} else {
81211240Smckusick 			printf("%-6d", Hdr.h_uid);
81311240Smckusick 			lastid = -1;
81411240Smckusick 		}
81511240Smckusick 	}
81611240Smckusick 	printf("%7ld ", mklong(Hdr.h_filesize));
81711240Smckusick 	U.l = mklong(Hdr.h_mtime);
81811240Smckusick 	strcpy(tbuf, ctime(&U.l));
81911240Smckusick 	tbuf[24] = '\0';
82011240Smckusick 	printf(" %s  %s\n", &tbuf[4], namep);
82111240Smckusick }
82211240Smckusick 
nmatch(s,pat)82311240Smckusick nmatch(s, pat)
82411240Smckusick char *s, **pat;
82511240Smckusick {
82611240Smckusick 	if(EQ(*pat, "*"))
82711240Smckusick 		return 1;
82811240Smckusick 	while(*pat) {
82911240Smckusick 		if((**pat == '!' && !gmatch(s, *pat+1))
83011240Smckusick 		|| gmatch(s, *pat))
83111240Smckusick 			return 1;
83211240Smckusick 		++pat;
83311240Smckusick 	}
83411240Smckusick 	return 0;
83511240Smckusick }
gmatch(s,p)83611240Smckusick gmatch(s, p)
83711240Smckusick register char *s, *p;
83811240Smckusick {
83911240Smckusick 	register int c;
84011240Smckusick 	register cc, ok, lc, scc;
84111240Smckusick 
84211240Smckusick 	scc = *s;
84311240Smckusick 	lc = 077777;
84411240Smckusick 	switch (c = *p) {
84511240Smckusick 
84611240Smckusick 	case '[':
84711240Smckusick 		ok = 0;
84811240Smckusick 		while (cc = *++p) {
84911240Smckusick 			switch (cc) {
85011240Smckusick 
85111240Smckusick 			case ']':
85211240Smckusick 				if (ok)
85311240Smckusick 					return(gmatch(++s, ++p));
85411240Smckusick 				else
85511240Smckusick 					return(0);
85611240Smckusick 
85711240Smckusick 			case '-':
85811240Smckusick 				ok |= (lc <= scc & scc <= (cc=p[1]));
85911240Smckusick 			}
86011240Smckusick 			if (scc==(lc=cc)) ok++;
86111240Smckusick 		}
86211240Smckusick 		return(0);
86311240Smckusick 
86411240Smckusick 	case '?':
86511240Smckusick 	caseq:
86611240Smckusick 		if(scc) return(gmatch(++s, ++p));
86711240Smckusick 		return(0);
86811240Smckusick 	case '*':
86911240Smckusick 		return(umatch(s, ++p));
87011240Smckusick 	case 0:
87111240Smckusick 		return(!scc);
87211240Smckusick 	}
87311240Smckusick 	if (c==scc) goto caseq;
87411240Smckusick 	return(0);
87511240Smckusick }
87611240Smckusick 
umatch(s,p)87711240Smckusick umatch(s, p)
87811240Smckusick register char *s, *p;
87911240Smckusick {
88011240Smckusick 	if(*p==0) return(1);
88111240Smckusick 	while(*s)
88211240Smckusick 		if (gmatch(s++,p)) return(1);
88311240Smckusick 	return(0);
88411240Smckusick }
88511240Smckusick 
makdir(namep)88611240Smckusick makdir(namep)
88711240Smckusick register char *namep;
88811240Smckusick {
88911240Smckusick 	static status;
89011240Smckusick 	register pid;
89111240Smckusick 
89211240Smckusick 	if(pid = fork())
89311240Smckusick 		while(wait(&status) != pid);
89411240Smckusick 	else {
89511240Smckusick 		close(2);
89611240Smckusick 		execl("/bin/mkdir", "mkdir", namep, 0);
89711240Smckusick 		exit(2);
89811240Smckusick 	}
89911240Smckusick 	return ((status>>8) & 0377)? 0: 1;
90011240Smckusick }
90111240Smckusick 
swap(buf,ct)90211240Smckusick swap(buf, ct)
90311240Smckusick register ct;
90411240Smckusick register union swp { short	shortw; char	charv[2]; } *buf;
90511240Smckusick {
90611240Smckusick 	register char c;
90711240Smckusick 
90811240Smckusick 	ct = (ct + 1) >> 1;
90911240Smckusick 
91011240Smckusick 	while(ct--) {
91111240Smckusick 		c = buf->charv[0];
91211240Smckusick 		buf->charv[0] = buf->charv[1];
91311240Smckusick 		buf->charv[1] = c;
91411240Smckusick 		++buf;
91511240Smckusick 	}
91611240Smckusick }
set_time(namep,atime,mtime)91711240Smckusick set_time(namep, atime, mtime)
91811240Smckusick register *namep;
91911240Smckusick long atime, mtime;
92011240Smckusick {
92111240Smckusick 	static long timevec[2];
92211240Smckusick 
92311240Smckusick 	if(!Mod_time)
92411240Smckusick 		return;
92511240Smckusick 	timevec[0] = atime;
92611240Smckusick 	timevec[1] = mtime;
92711240Smckusick 	utime(namep, timevec);
92811240Smckusick }
chgreel(x,fl)92911240Smckusick chgreel(x, fl)
93011240Smckusick {
93111240Smckusick 	register f;
93211240Smckusick 	char str[22];
93311240Smckusick 	FILE *devtty;
93411240Smckusick 	struct stat statb;
93511240Smckusick 
93611240Smckusick 	err("errno: %d, ", errno);
93711240Smckusick 	err("Can't %s\n", x? "write output": "read input");
93811240Smckusick 	fstat(fl, &statb);
93911240Smckusick #ifdef RT
94011240Smckusick 	if(!MERT){
94111240Smckusick 		if((statb.st_mode&S_IFMT) != S_IFCHR)
94211240Smckusick 			exit(2);
94311240Smckusick 	}
94411240Smckusick 	else if((statb.st_mode & (S_IFBLK|S_IFREC))==0)
94511240Smckusick 		exit(2);
94611240Smckusick #endif
94711240Smckusick #ifndef RT
94811240Smckusick 	if((statb.st_mode&S_IFMT) != S_IFCHR)
94911240Smckusick 		exit(2);
95011240Smckusick #endif
95111240Smckusick again:
95211240Smckusick 	err("If you want to go on, type device/file name when ready\n");
95311240Smckusick 	devtty = fopen("/dev/tty", "r");
95411240Smckusick 	fgets(str, 20, devtty);
95511240Smckusick 	str[strlen(str) - 1] = '\0';
95611240Smckusick 	if(!*str)
95711240Smckusick 		exit(2);
95811240Smckusick 	close(fl);
95911240Smckusick 	if((f = open(str, x? 1: 0)) < 0) {
96011240Smckusick 		err("That didn't work");
96111240Smckusick 		fclose(devtty);
96211240Smckusick 		goto again;
96311240Smckusick 	}
96411240Smckusick 	return f;
96511240Smckusick }
missdir(namep)96611240Smckusick missdir(namep)
96711240Smckusick register char *namep;
96811240Smckusick {
96911240Smckusick 	register char *np;
97011240Smckusick 	register ct = 0;
97111240Smckusick 
97211240Smckusick 	if(!Dir)
97311240Smckusick 		return 0;
97411240Smckusick 	for(np = namep; *np; ++np)
97511240Smckusick 		if(*np == '/') {
97611240Smckusick 			*np = '\0';
97711240Smckusick 			if(stat(namep, &Xstatb) == -1)
97811240Smckusick 				makdir(namep), ++ct;
97911240Smckusick 			*np = '/';
98011240Smckusick 		}
98111240Smckusick 	return ct;
98211240Smckusick }
err(a,b,c)98311240Smckusick err(a, b, c)
98411240Smckusick {
98511240Smckusick 	fprintf(stderr, a, b, c);
98611240Smckusick }
pwd()98711240Smckusick pwd()
98811240Smckusick {
98911240Smckusick 	FILE *dir;
99011240Smckusick 
99111240Smckusick 	dir = popen("pwd", "r");
99211240Smckusick 	fgets(Fullname, 256, dir);
99311240Smckusick 	if(pclose(dir))
99411240Smckusick 		exit(2);
99511240Smckusick 	Pathend = strlen(Fullname);
99611240Smckusick 	Fullname[Pathend - 1] = '/';
99711240Smckusick }
cd(n)99811240Smckusick char * cd(n)
99911240Smckusick register char *n;
100011240Smckusick {
100111240Smckusick 	char *p_save = Name, *n_save = n, *p_end = 0;
100211240Smckusick 	register char *p = Name;
100311240Smckusick 	static char dotdot[]="../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../";
100411240Smckusick 	int slashes;
100511240Smckusick 
100611240Smckusick 	if(*n == '/') /* don't try to chdir on full pathnames */
100711240Smckusick 		return n;
100811240Smckusick 	for(; *p && *n == *p; ++p, ++n) { /* whatever part of strings == */
100911240Smckusick 		if(*p == '/')
101011240Smckusick 			p_save = p+1, n_save = n+1;
101111240Smckusick 	}
101211240Smckusick 
101311240Smckusick 	p = p_save;
101411240Smckusick 	*p++ = '\0';
101511240Smckusick 	for(slashes = 0; *p; ++p) { /* if prev is longer, chdir("..") */
101611240Smckusick 		if(*p == '/')
101711240Smckusick 			++slashes;
101811240Smckusick 	}
101911240Smckusick 	p = p_save;
102011240Smckusick 	if(slashes) {
102111240Smckusick 		slashes = slashes * 3 - 1;
102211240Smckusick 		dotdot[slashes] = '\0';
102311240Smckusick 		chdir(dotdot);
102411240Smckusick 		dotdot[slashes] = '/';
102511240Smckusick 	}
102611240Smckusick 
102711240Smckusick 	n = n_save;
102811240Smckusick 	for(; *n; ++n, ++p) {
102911240Smckusick 		*p = *n;
103011240Smckusick 		if(*n == '/')
103111240Smckusick 			p_end = p+1, n_save = n+1;
103211240Smckusick 	}
103311240Smckusick 	*p = '\0';
103411240Smckusick 
103511240Smckusick 	if(p_end) {
103611240Smckusick 		*p_end = '\0';
103711240Smckusick 		if(chdir(p_save) == -1) {
103811240Smckusick 			if(!missdir(p_save)) {
103911240Smckusick cd_err:
104011240Smckusick 				err("Cannot chdir (no `d' option)\n");
104111240Smckusick 				exit(2);
104211240Smckusick 			} else if(chdir(p_save) == -1)
104311240Smckusick 				goto cd_err;
104411240Smckusick 		}
104511240Smckusick 	} else
104611240Smckusick 		*p_save = '\0';
104711240Smckusick 	return n_save;
104811240Smckusick }
104911240Smckusick #ifdef RT
actsize()105011240Smckusick actsize()
105111240Smckusick {
105211240Smckusick }
105311240Smckusick #endif
1054