xref: /csrg-svn/local/local.cmd/dl.c (revision 33063)
1*33063Sbostic static char *sccsid = "@(#)dl.c	4.2\t12/20/87";
216067Sralph 
316067Sralph #include <stdio.h>
416067Sralph #include <sys/param.h>
516067Sralph #include <sys/stat.h>
616067Sralph #include <sys/dir.h>
716067Sralph #include <errno.h>
816067Sralph #include <signal.h>
916067Sralph 
1016067Sralph #define	DELIM	'/'
1116067Sralph #define MODEBITS 07777
1216067Sralph #define	ISDIR(st)	(((st).st_mode&S_IFMT) == S_IFDIR)
1316067Sralph #define	ISLNK(st)	(((st).st_mode&S_IFMT) == S_IFLNK)
1416067Sralph #define	ISREG(st)	(((st).st_mode&S_IFMT) == S_IFREG)
1516067Sralph #define	ISDEV(st) \
1616067Sralph 	(((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK)
1716067Sralph 
1816067Sralph struct	stat s1, s2, buf;
1916067Sralph extern	unsigned errno;
2016067Sralph int	errcode;
2116067Sralph char    *path;
2216067Sralph char    *path2;
2316067Sralph char    line[1024];
2416067Sralph int     cflag = 0;   /* "copy" - same as cp  */
2516067Sralph int     dflag = 0;   /* "debug" - enable trace printf statements */
2616067Sralph int     fflag = 0;   /* "force" option: override protection, no messages */
2716067Sralph int     mflag = 0;   /* "move" - same as mv  */
2816067Sralph int     cs = 0;      /* flag used with cflag to prevent endless recursion */
2916067Sralph int     ms = 0;      /* flag used with mflag to prevent endless recursion */
3016067Sralph int     tflag = 0;   /* restore original time stamp */
3116067Sralph 
main(argc,argv)3216067Sralph main(argc, argv)     /* dl.c - delete, undelete, move, copy */
3316067Sralph char *argv[];
3416067Sralph {
3516067Sralph 	register char *arg;
3616067Sralph 	char *s;
3716067Sralph 	int mode;
3816067Sralph 	int aflg = 0;   /* "all" option: undelete all deleted files */
3916067Sralph 	int iflg = 0;	/* "interactive" option: send messages to user */
4016067Sralph 	int rflg = 0;   /* "recursive" opt., used only with n */
4116067Sralph 	int sflg = 0;   /* do not delete previous dlsave file */
4216067Sralph 	int uflg = 0;   /* undelete named files and/or directories */
4316067Sralph 	int nflg = 0;   /* do not provide back-up files */
4416067Sralph 
4516067Sralph 	if (isatty(0) == 0)	/* if standard i/o is not a terminal, */
4616067Sralph 		fflag++;		/*  turn on the f flag                */
4716067Sralph 
4816067Sralph 	if (strcmp(*argv,"ud") == 0)
4916067Sralph 		uflg++;
5016067Sralph 
5116067Sralph 	if (strcmp(*argv,"copy") == 0)
5216067Sralph 		cflag++;
5316067Sralph 
5416067Sralph 	if (strcmp(*argv,"move") == 0)
5516067Sralph 		mflag++;
5616067Sralph 
5716067Sralph 	while(argc>1 && argv[1][0]=='-') {
5816067Sralph 		arg = *++argv;
5916067Sralph 		argc--;
6016067Sralph 
6116067Sralph 		/*
6216067Sralph 		 *  all arguments following a null option (- ) are
6316067Sralph 		 *   treated as file names, so that file names may
6416067Sralph 		 *   begin with a minus sign (-).
6516067Sralph 		 */
6616067Sralph 		if (*(arg+1) == '\0') break;
6716067Sralph 
6816067Sralph 		while(*++arg != '\0')
6916067Sralph 			switch(*arg) {
7016067Sralph 			case 'a':	/* "all" */
7116067Sralph 				aflg++;
7216067Sralph 				break;
7316067Sralph 			case 'c':	/* "copy" */
7416067Sralph 				cflag++;
7516067Sralph 				break;
7616067Sralph 			case 'd':	/* "debug" */
7716067Sralph 				dflag++;
7816067Sralph 				break;
7916067Sralph 			case 'f':	/* "force" */
8016067Sralph 				fflag++;
8116067Sralph 				break;
8216067Sralph 			case 'i':	/* "interactive" */
8316067Sralph 				iflg++;
8416067Sralph 				break;
8516067Sralph 			case 'r':	/* "recursive" */
8616067Sralph 				rflg++;
8716067Sralph 				break;
8816067Sralph 			case 's':	/* "save" */
8916067Sralph 				sflg++;
9016067Sralph 				break;
9116067Sralph 			case 't':	/* "time" stamp */
9216067Sralph 				tflag++;
9316067Sralph 				break;
9416067Sralph 			case 'u':	/* "undelete" */
9516067Sralph 				uflg++;
9616067Sralph 				break;
9716067Sralph 			case 'm':	/* "move" */
9816067Sralph 				mflag++;
9916067Sralph 				break;
10016067Sralph 			case 'n':	/* "not save" */
10116067Sralph 				nflg++;
10216067Sralph 				break;
10316067Sralph 			default:
10416067Sralph 				printf("dl: unknown option %s\n", *argv);
10516067Sralph 				exit(1);
10616067Sralph 			}
10716067Sralph 	}
10816067Sralph 	if (cflag || mflag || nflg)  sflg++;
10916067Sralph 	/*
11016067Sralph 	 * set up home directory pathname
11116067Sralph 	 */
11216067Sralph 	setpath();
11316067Sralph 	/*
11416067Sralph 	 * process "undelete all" request
11516067Sralph 	 */
11616067Sralph 	if(aflg) {
11716067Sralph 		undelete_all(iflg);
11816067Sralph 		exit;
11916067Sralph 	}
12016067Sralph 	/*
12116067Sralph 	 * remove previously saved files unless "save" option,
12216067Sralph 	 *  or ud or rm mode
12316067Sralph 	 */
12416067Sralph 	if(!sflg && !uflg)
12516067Sralph 		dldir(path,0);
12616067Sralph 	if(!nflg && lstat(path,&buf) != 0) {
12716067Sralph 		/*
12816067Sralph 		 * set up .dlsave directory
12916067Sralph 	 	 */
13016067Sralph 		mode = 0777;
13116067Sralph           	if (mkdir(path,mode) != 0) {
13216067Sralph 		       	   fprintf(stderr,"dl: cannot mkdir ~/.dlsave\n");
13316067Sralph 			   perror(s);
13416067Sralph 			   exit(1);
13516067Sralph 		}
13616067Sralph 	}
13716067Sralph      	while(--argc > 0) {
13816067Sralph 		if(!strcmp(*++argv, "..")) {
13916067Sralph 		    	if(!fflag)
14016067Sralph 				fprintf(stderr, "dl: cannot remove `..'\n");
14116067Sralph 			continue;
14216067Sralph 		}
14316067Sralph 	       /*
14416067Sralph 	 	* process "undelete" request(s)
14516067Sralph 	 	*/
14616067Sralph 		if(uflg) {
14716067Sralph 			undelete(*argv,iflg);
14816067Sralph 			exit;
14916067Sralph 		}
15016067Sralph 		else {
15116067Sralph 		/*
15216067Sralph 		 * process delete request(s)
15316067Sralph 		 */
15416067Sralph 			if (cflag) {
15516067Sralph 				copy(*argv,argv[argc-1],iflg,rflg);
15616067Sralph 				exit(errcode);
15716067Sralph 			}
15816067Sralph 			if (mflag) {
15916067Sralph 				move(*argv,argv[argc-1],iflg);
16016067Sralph 				exit(errcode);
16116067Sralph 			}
16216067Sralph 			if (nflg)
16316067Sralph 				rm(*argv, iflg, rflg);
16416067Sralph 			else
16516067Sralph 				dl(*argv, iflg);
16616067Sralph 		}
16716067Sralph 	}
16816067Sralph 	exit(errcode);
16916067Sralph }
17016067Sralph 
setpath()17116067Sralph setpath()
17216067Sralph {
17316067Sralph 	char *home;
17416067Sralph 	char *suffix;
17516067Sralph 	char *getenv();
17616067Sralph 
17716067Sralph 	home = "HOME";
17816067Sralph 	if ((path=getenv(home)) == NULL) {
17916067Sralph 		fprintf(stderr,"dl: getenv failed\n");
18016067Sralph 		exit(1);
18116067Sralph 	}
18216067Sralph 	suffix = "/.dlsave";
18316067Sralph 	strcat(path,suffix);
18416067Sralph 	return;
18516067Sralph }
18616067Sralph 
package(argu)18716067Sralph package(argu)
18816067Sralph char argu[];
18916067Sralph {
19016067Sralph 	register int i, j, k;
19116067Sralph 	char  *slash, *slashdot;
19216067Sralph 	char  *place;
19316067Sralph 	char  line2[512];
19416067Sralph 
19516067Sralph 	place = line2;
19616067Sralph 	strcpy(place,argu);
19716067Sralph 	path2 = line;
19816067Sralph 	strcpy(path2,path);
19916067Sralph 	slashdot = "/.#";
20016067Sralph 	strcat(path2,slashdot);
20116067Sralph 	i = strlen(argu);
20216067Sralph 	slash = "/";
20316067Sralph 	k = 0;
20416067Sralph 	for (j=0;j<i;j++) {
20516067Sralph 		if (place[j] == *slash) {
20616067Sralph 			k = j + 1;
20716067Sralph 		}
20816067Sralph 	}
20916067Sralph 	strcat(path2,argu+k);
21016067Sralph 	return;
21116067Sralph }
21216067Sralph 
undelete_all(iflg)21316067Sralph undelete_all(iflg)
21416067Sralph {
21516067Sralph 	struct direct *dp;
21616067Sralph 	DIR *dirp;
21716067Sralph 	char *filename;
21816067Sralph 	int x;
21916067Sralph 
22016067Sralph 	/*
22116067Sralph 	 * undelete all saved files (a option)
22216067Sralph 	 */
22316067Sralph 	if((dirp = opendir(path)) == NULL) {
22416067Sralph 		if(!fflag)
22516067Sralph 			printf("uda: cannot read %s?\n", path);
22616067Sralph 		exit(1);
22716067Sralph 	}
22816067Sralph 	while((dp = readdir(dirp)) != NULL) {
22916067Sralph              	if(dp->d_ino != 0 && !dotname(dp->d_name)) {
23016067Sralph 			filename = (dp->d_name)+2;
23116067Sralph 			package(filename);
23216067Sralph 			if(iflg) {
23316067Sralph 				printf("uda: undelete %s?", filename);
23416067Sralph 				if (!yes())
23516067Sralph 					goto no;
23616067Sralph 			}
23716067Sralph 			if(lstat(filename, &buf) == 0) {
23816067Sralph 				printf("uda: %s exists. Override?", filename);
23916067Sralph 				if(!yes())
24016067Sralph 					goto no;
24116067Sralph 			}
24216067Sralph 			x = move(path2,filename,0);
24316067Sralph 			if(iflg) {
24416067Sralph 			        if (x >= 0)
24516067Sralph 				       printf("uda: %s undeleted.\n", filename);
24616067Sralph 				else
24716067Sralph 				       printf("uda: unable to undelete %s\n", filename);
24816067Sralph 			}
24916067Sralph no:		continue;
25016067Sralph 	        }
25116067Sralph 	}
25216067Sralph 	closedir(dirp);
25316067Sralph 	return;
25416067Sralph }
25516067Sralph 
undelete(arg,iflg)25616067Sralph undelete(arg,iflg)
25716067Sralph char arg[];
25816067Sralph {
25916067Sralph 	struct stat buf1, buf2;
26016067Sralph 	int x;
26116067Sralph 
26216067Sralph 	/*
26316067Sralph 	 * undelete a saved file (u option)
26416067Sralph 	 */
26516067Sralph 	package(arg);
26616067Sralph 	if(lstat(path2, &buf1)) {
26716067Sralph 		if (!fflag)
26816067Sralph 			printf("ud: %s nonexistent\n", path2);
26916067Sralph 		++errcode;
27016067Sralph 	    	return;
27116067Sralph 	}
27216067Sralph 	if(iflg) {
27316067Sralph 		printf("ud: undelete %s?", arg);
27416067Sralph 		if(!yes())
27516067Sralph 			return;
27616067Sralph 	}
27716067Sralph 	if(lstat(arg, &buf2) == 0) {
27816067Sralph 			printf("ud: %s exists: overwrite?", arg);
27916067Sralph 			if(!yes())
28016067Sralph 				return;
28116067Sralph 	}
28216067Sralph         x = move(path2,arg,0);
28316067Sralph 	if(iflg) {
28416067Sralph 		if (x >= 0)
28516067Sralph       	      		printf("ud: %s undeleted.\n", arg);
28616067Sralph         	else
28716067Sralph        	      		printf("ud: unable to undelete %s\n", arg);
28816067Sralph 	}
28916067Sralph 	return;
29016067Sralph }
29116067Sralph 
rm(arg,iflg,rflg)29216067Sralph rm(arg, iflg, rflg)
29316067Sralph char arg[];
29416067Sralph {
29516067Sralph 	if (dflag) printf("rm entered: arg=%s fflag=%d iflg=%d rflg=%d\n",arg,fflag,iflg,rflg);
29616067Sralph 	if(lstat(arg, &buf)) {
29716067Sralph 		if (!fflag)
29816067Sralph 			printf("rm: %s nonexistent\n", arg);
29916067Sralph 		++errcode;
30016067Sralph 	    	return;
30116067Sralph 	}
30216067Sralph 	/*
30316067Sralph 	 * unlink file named by arg
30416067Sralph 	 */
30516067Sralph 	if ((buf.st_mode&S_IFMT) == S_IFDIR || rflg) {
30616067Sralph 		if(iflg) {
30716067Sralph 			printf("rm: remove directory %s?", arg);
30816067Sralph 			if(!yes())
30916067Sralph 				return;
31016067Sralph 		}
31116067Sralph 		dldir(arg, iflg);
31216067Sralph 		return;
31316067Sralph 	}
31416067Sralph 	if (!fflag && iflg) {
31516067Sralph 		printf("rm: remove %s?", arg);
31616067Sralph 		if (!yes())
31716067Sralph 			return;
31816067Sralph 	}
31916067Sralph 	else if (!fflag) {
32016067Sralph 		if ((buf.st_mode&S_IFMT) != S_IFLNK && access(arg, 02) < 0) {
32116067Sralph 			printf("rm: override protection %o for %s?\n",buf.st_mode&0777,arg);
32216067Sralph 			if (!yes())
32316067Sralph 				return;
32416067Sralph 		}
32516067Sralph 	}
32616067Sralph 	if (unlink(arg) && !fflag) {
32716067Sralph 		printf ("rm: %s not removed.\n",arg);
32816067Sralph 		++errcode;
32916067Sralph 	}
33016067Sralph 	else {
33116067Sralph 		if (!fflag && iflg)
33216067Sralph 			printf ("rm: %s removed.\n",arg);
33316067Sralph 	}
33416067Sralph 	return;
33516067Sralph }
33616067Sralph 
dl(arg,iflg)33716067Sralph dl(arg, iflg)
33816067Sralph char arg[];
33916067Sralph {
34016067Sralph 	/*
34116067Sralph 	 * move the argument (file or directory) to
34216067Sralph 	 *  .dlsave directory in user's home directory
34316067Sralph 	 */
34416067Sralph 	if (dflag) printf("dl entered: arg=%s fflag=%d iflg=%d\n",arg,fflag,iflg);
34516067Sralph 	package(arg);
34616067Sralph 	move(arg,path2,iflg);
34716067Sralph 	return;
34816067Sralph }
34916067Sralph 
dldir(arg,iflg)35016067Sralph dldir(arg, iflg)
35116067Sralph char arg[];
35216067Sralph {
35316067Sralph 	struct  stat  buf1, buf2;
35416067Sralph 	struct direct *dp;
35516067Sralph 	DIR *dirp;
35616067Sralph 	char name[BUFSIZ];
35716067Sralph 
35816067Sralph 	if (dflag) printf("dldir entered: arg=%s fflag=%d iflg=%d\n",arg,fflag,iflg);
35916067Sralph 	if(lstat(arg, &buf1)) {
36016067Sralph 		if (!fflag && iflg)
36116067Sralph 			printf("dldir: %s nonexistent\n", arg);
36216067Sralph 		++errcode;
36316067Sralph 	    	return;
36416067Sralph 	}
36516067Sralph 	/*
36616067Sralph 	 * if the argument is a directory,
36716067Sralph 	 * recursively remove the directory's contents
36816067Sralph 	 * and then the directory.
36916067Sralph 	 */
37016067Sralph 	if ((buf1.st_mode&S_IFMT) == S_IFDIR) {
37116067Sralph 		if (access(arg, 02) < 0) {
37216067Sralph 			if(!fflag) {
37316067Sralph 			 	printf("dldir: %s not accessable\n",arg);
37416067Sralph 			}
37516067Sralph 			errcode++;
37616067Sralph 			return;
37716067Sralph 		}
37816067Sralph 		if((dirp = opendir(arg)) == NULL)
37916067Sralph 			exit(1);
38016067Sralph 		while((dp = readdir(dirp)) != NULL) {
38116067Sralph 			if(dp->d_ino != 0 && !dotname(dp->d_name)) {
382*33063Sbostic 				(void) sprintf(name, "%s/%s", arg, dp->d_name);
38316067Sralph 				if (dflag) printf("dldir: name= %s\n",name);
38416067Sralph 				if(lstat(name, &buf2)) {
38516067Sralph 					if (!fflag)
38616067Sralph 					   printf("dldir: %s nonexistent\n", name);
38716067Sralph 					++errcode;
38816067Sralph 	    				return;
38916067Sralph 				}
39016067Sralph 				if ((buf2.st_mode&S_IFMT) == S_IFDIR) {
39116067Sralph     				if(!fflag && iflg) {
39216067Sralph 					printf("dldir: delete directory %s?", name);
39316067Sralph 					if(!yes())
39416067Sralph 						return;
39516067Sralph    				}
39616067Sralph   				dldir(name, iflg);
39716067Sralph 				}
39816067Sralph 				else {
39916067Sralph     					if(!fflag && iflg) {
40016067Sralph 					   printf("dldir: delete file %s?", name);
40116067Sralph 						if(!yes())
40216067Sralph 							return;
40316067Sralph    					}
40416067Sralph 			       		/*
40516067Sralph 	 				 * permanently remove the file
40616067Sralph 	 				 */
40716067Sralph 					if (unlink(name)) {
40816067Sralph 					  if (!fflag)
40916067Sralph 					   printf("dldir: %s not removed\n", name);
41016067Sralph 					   ++errcode;
41116067Sralph 					}
41216067Sralph 					else {
41316067Sralph 					   if (!fflag && iflg)
41416067Sralph 					     printf("dldir: %s removed.\n", name);
41516067Sralph 					}
41616067Sralph 				}
41716067Sralph 			}
41816067Sralph 		}
41916067Sralph 		closedir(dirp);
42016067Sralph 		if (dotname(arg))
42116067Sralph 			return;
42216067Sralph 		if (rmdir(arg) < 0) {
42316067Sralph 			if(!fflag && iflg) {
42416067Sralph 				fprintf(stderr, "dldir: rmdir:");
42516067Sralph 				perror(arg);
42616067Sralph 			}
42716067Sralph 			errcode++;
42816067Sralph 		}
42916067Sralph 		else {
43016067Sralph 			if(!fflag && iflg)
43116067Sralph 				printf("dldir: directory %s removed.\n",arg);
43216067Sralph 		}
43316067Sralph 	return;
43416067Sralph 	}
43516067Sralph }
43616067Sralph 
dotname(s)43716067Sralph dotname(s)
43816067Sralph char *s;
43916067Sralph {
44016067Sralph 	if(s[0] == '.')
44116067Sralph 		if(s[1] == '.')
44216067Sralph 			if(s[2] == '\0')
44316067Sralph 				return(1);
44416067Sralph 			else
44516067Sralph 				return(0);
44616067Sralph 		else if(s[1] == '\0')
44716067Sralph 			return(1);
44816067Sralph 	return(0);
44916067Sralph }
45016067Sralph 
yes()45116067Sralph yes()
45216067Sralph {
45316067Sralph 	int i, b;
45416067Sralph 
45516067Sralph 	i = b = getchar();
45616067Sralph 	while(b != '\n' && b != EOF)
45716067Sralph 		b = getchar();
45816067Sralph 	return(i == 'y');
45916067Sralph }
46016067Sralph 
move(source,target,iflag)46116067Sralph move(source, target, iflag)
46216067Sralph 	char *source, *target;
46316067Sralph {
46416067Sralph 	int targetexists;
46516067Sralph 	int sw = 0;
46616067Sralph 
46716067Sralph 	if (dflag) printf("move entered: source=%s target=%s fflag=%d iflag=%d\n",source,target,fflag,iflag);
46816067Sralph 	if (lstat(source, &s1) < 0) {
46916067Sralph 		if (!fflag)
47016067Sralph 			error("cannot access %s", source);
47116067Sralph 		return (1);
47216067Sralph 	}
47316067Sralph 	if (dflag) printf("move: lstat(%s) successful\n",source);
47416067Sralph 	/*
47516067Sralph 	 * First, try to rename source to target.
47616067Sralph 	 */
47716067Sralph 	targetexists = lstat(target, &s2) >= 0;
47816067Sralph 	if (targetexists) {
47916067Sralph 		if (dflag) printf("move: lstat(%s) successful\n",target);
48016067Sralph 		if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino) {
48116067Sralph 			if (!fflag)
48216067Sralph 			      error("%s and %s are identical", source, target);
48316067Sralph 			return (1);
48416067Sralph 		}
48516067Sralph 		if (access(target, 2) < 0 && !fflag && isatty(fileno(stdin))) {
48616067Sralph 			if (query("override protection %o for %s? ",
48716067Sralph 			  s2.st_mode & MODEBITS, target) == 0)
48816067Sralph 				return (1);
48916067Sralph 			sw++;
49016067Sralph 		}
49116067Sralph 		if (mflag && ms == 0) {
49216067Sralph 			if (ISREG(s2)) {
49316067Sralph 				if (!fflag && sw == 0) {
49416067Sralph 		   		printf("overwrite file %s?", target);
49516067Sralph 				if(!yes())
49616067Sralph 					return;
49716067Sralph 				}
49816067Sralph 			ms = 1;
49916067Sralph 			dl (target, 0);
50016067Sralph 			}
50116067Sralph 			else
50216067Sralph 			if (s1.st_dev != s2.st_dev && ISDIR(s2))
50316067Sralph 				goto copyit;
50416067Sralph 		}
50516067Sralph 	}
50616067Sralph 	if (!fflag && iflag && !mflag) {
50716067Sralph 		if (ISDIR(s1))
50816067Sralph 			printf("dl: delete directory %s?", source);
50916067Sralph 		else
51016067Sralph 			printf("dl: delete file %s?", source);
51116067Sralph 		if(!yes())
51216067Sralph 			return;
51316067Sralph 	}
51416067Sralph 	if(dflag) printf("move(1)rename: source=%s, target=%s\n",source, target);
51516067Sralph 	if (rename(source, target) >= 0) {
51616067Sralph 		if (!fflag && iflag && !mflag)
51716067Sralph 			printf("dl: %s deleted. \n",source);
51816067Sralph 		if (dflag) printf("move: %s renamed %s.\n",source,target);
51916067Sralph 		return (0);
52016067Sralph 	}
52116067Sralph 	if (dflag) printf("move/rename: errno=%d\n",errno);
52216067Sralph 	if (errno != EXDEV) {
52316067Sralph 		if (!fflag && iflag) {
52416067Sralph 			Perror2(source, "rename");
52516067Sralph 		}
52616067Sralph 		goto copyit;
52716067Sralph 	}
52816067Sralph 	if (targetexists && unlink(target) < 0) {
52916067Sralph 		if(!fflag)
53016067Sralph 			error("cannot unlink %s", target);
53116067Sralph 		return (1);
53216067Sralph 	}
53316067Sralph 	if (dflag) printf("move: target unlinked\n");
53416067Sralph 
53516067Sralph 	/*
53616067Sralph 	 * If file or directory cannot be renamed:
53716067Sralph 	 *  If directory, copy it with r option
53816067Sralph 	 *   and delete the source
53916067Sralph 	 */
54016067Sralph copyit:	if (ISDIR(s1)) {
54116067Sralph 	     if (dflag) printf("move: directory copy %s to %s\n",source,target);
54216067Sralph 		copy (source, target, iflag, 1);
54316067Sralph 		dldir (source, iflag);
54416067Sralph 		return(0);
54516067Sralph 	}
54616067Sralph 
54716067Sralph 	/*
54816067Sralph 	 *  If link, recreate symbolic link
54916067Sralph 	 */
55016067Sralph 	if (ISLNK(s1)) {
55116067Sralph 		register m;
55216067Sralph 		char symln[MAXPATHLEN];
55316067Sralph 
55416067Sralph 		if (readlink(source, symln, sizeof (symln)) < 0) {
55516067Sralph 			if (!fflag)
55616067Sralph 				Perror(source);
55716067Sralph 				return (1);
55816067Sralph 		}
55916067Sralph 		m = umask(~(s1.st_mode & MODEBITS));
56016067Sralph 		if (symlink(symln, target) < 0) {
56116067Sralph 			if (!fflag)
56216067Sralph 				Perror(target);
56316067Sralph 				return (1);
56416067Sralph 		}
56516067Sralph 		if (dflag) printf("move: symlink to target successful\n");
56616067Sralph 		(void) umask(m);
56716067Sralph 		goto cleanup;
56816067Sralph 	}
56916067Sralph 
57016067Sralph 	/*
57116067Sralph 	 *  If device
57216067Sralph 	 */
57316067Sralph 	if (ISDEV(s1)) {
57416067Sralph 		if (mknod(target, s1.st_mode, s1.st_rdev) < 0) {
57516067Sralph 			if (!fflag)
57616067Sralph 				Perror(target);
57716067Sralph 			return (1);
57816067Sralph 		}
57916067Sralph 		if (dflag) printf("move: mknod for target successful\n");
58016067Sralph 		goto cleanup;
58116067Sralph 	}
58216067Sralph 
58316067Sralph 	/*
58416067Sralph 	 *  If regular file, copy it
58516067Sralph 	 */
58616067Sralph 	if (ISREG(s1)) {
58716067Sralph 	     	if(dflag) printf("move: file copy %s to %s\n",source,target);
58816067Sralph 		copy(source, target, iflag, 0);
58916067Sralph 		goto cleanup;
59016067Sralph  	}
59116067Sralph 
59216067Sralph 	if (!fflag)
59316067Sralph 		error("%s: unknown file type %o", source, s1.st_mode);
59416067Sralph 	return (1);
59516067Sralph 
59616067Sralph 	/*
59716067Sralph 	 *  If a move has been successful, erase the source
59816067Sralph 	 */
59916067Sralph cleanup:
60016067Sralph 	if (dflag) printf("move: cleanup\n");
60116067Sralph 	if (unlink(source) < 0) {
60216067Sralph 		if (!fflag)
60316067Sralph 			error("cannot unlink %s", source);
60416067Sralph 		return (1);
60516067Sralph 	}
60616067Sralph 	if (dflag) printf("move: %s unlinked.\n",source);
60716067Sralph 	if (!fflag && iflag && !mflag)
60816067Sralph 		printf("dl: %s deleted.\n",source);
60916067Sralph 	return (0);
61016067Sralph }
61116067Sralph 
61216067Sralph /*VARARGS*/
query(prompt,a1,a2)61316067Sralph query(prompt, a1, a2)
61416067Sralph 	char *a1;
61516067Sralph {
61616067Sralph 	register char i, c;
61716067Sralph 
61816067Sralph 	fprintf(stderr, prompt, a1, a2);
61916067Sralph 	i = c = getchar();
62016067Sralph 	while (c != '\n' && c != EOF)
62116067Sralph 		c = getchar();
62216067Sralph 	return (i == 'y');
62316067Sralph }
62416067Sralph 
error(fmt,a1,a2)62516067Sralph error(fmt, a1, a2)
62616067Sralph 	char *fmt;
62716067Sralph {
62816067Sralph 	fprintf(stderr, "dl: ");
62916067Sralph 	fprintf(stderr, fmt, a1, a2);
63016067Sralph 	fprintf(stderr, "\n");
63116067Sralph }
63216067Sralph 
Perror(s)63316067Sralph Perror(s)
63416067Sralph 	char *s;
63516067Sralph {
63616067Sralph 	char buf[MAXPATHLEN + 10];
637*33063Sbostic 
638*33063Sbostic 	(void) sprintf(buf, "move: %s", s);
63916067Sralph 	perror(buf);
64016067Sralph }
64116067Sralph 
Perror2(s1,s2)64216067Sralph Perror2(s1, s2)
64316067Sralph 	char *s1, *s2;
64416067Sralph {
64516067Sralph 	char buf[MAXPATHLEN + 20];
64616067Sralph 
647*33063Sbostic 	(void) sprintf(buf, "dl: %s: %s", s1, s2);
64816067Sralph 	perror(buf);
64916067Sralph }
65016067Sralph 
65116067Sralph #define	BSIZE	8192
65216067Sralph 
65316067Sralph char	*rindex();
65416067Sralph 
copy(from,to,iflag,rflag)65516067Sralph copy(from, to, iflag, rflag)
65616067Sralph 	char *from, *to;
65716067Sralph {
65816067Sralph 	int fold, fnew, n;
65916067Sralph 	char *last, destname[BSIZE], buf[BSIZE];
66016067Sralph 	struct stat stfrom, stto;
66116067Sralph 	time_t tv[2];
66216067Sralph 
66316067Sralph 	if (dflag) printf("copy entered: from=%s to=%s iflag=%d rflag=%d\n",from,to,iflag,rflag);
66416067Sralph 	fold = open(from, 0);
66516067Sralph 	if (fold < 0) {
66616067Sralph 		Cerror(from,fflag);
66716067Sralph 		return (1);
66816067Sralph 	}
66916067Sralph 	if (fstat(fold, &stfrom) < 0) {
67016067Sralph 		Cerror(from,fflag);
67116067Sralph 		(void) close(fold);
67216067Sralph 		return (1);
67316067Sralph 	}
67416067Sralph 	if (dflag) printf("copy: fstat(%s) OK.\n",from);
67516067Sralph 	if (stat(to, &stto) >= 0 &&
67616067Sralph 	   (stto.st_mode&S_IFMT) == S_IFDIR) {
67716067Sralph 		last = rindex(from, '/');
67816067Sralph 		if (last) last++; else last = from;
67916067Sralph 		if (strlen(to) + strlen(last) >= BSIZE - 1) {
68016067Sralph 			fprintf(stderr, "cp: %s/%s: Name too long", to, last);
68116067Sralph 			(void) close(fold);
68216067Sralph 			return(1);
68316067Sralph 		}
68416067Sralph 		(void) sprintf(destname, "%s/%s", to, last);
68516067Sralph 		if (dflag) printf("copy: stat %s & %s is dir., to=%s.\n",to,to,destname);
68616067Sralph 		to = destname;
68716067Sralph 	}
68816067Sralph 	if (!rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) {
68916067Sralph 		fprintf(stderr, "cp: %s is a directory, and option -r not chosen.  Job aborted.\n", from);
69016067Sralph 		return(1);
69116067Sralph 	}
69216067Sralph 	if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) {
69316067Sralph 		(void) close(fold);
69416067Sralph 		if (dflag) printf("copy: rflag & from is dir., %s closed.\n",from);
69516067Sralph 		if (stat(to, &stto) < 0) {
69616067Sralph 			if (mkdir(to, (int)stfrom.st_mode) < 0) {
69716067Sralph 				Cerror(to,fflag);
69816067Sralph 				return (1);
69916067Sralph 			}
70016067Sralph 			if (dflag) printf("copy: stat(%s) failed & mkdir % successful.\n",to,to);
70116067Sralph 		}
70216067Sralph 		else {
70316067Sralph 			if (!fflag) {
70416067Sralph 				if ((stto.st_mode&S_IFMT) == S_IFDIR) {
70516067Sralph 				dl(to, iflag);
70616067Sralph 				}
70716067Sralph 				else {
70816067Sralph 			      		fprintf(stderr, "cp: %s: Not a directory.\n", to);
70916067Sralph 			      		return (1);
71016067Sralph 				}
71116067Sralph 			}
71216067Sralph 		}
71316067Sralph 		if (dflag) printf("copy: return with rcopy(%s,%s,%d,%d)\n",from,to,iflag,rflag);
71416067Sralph 		return (rcopy(from, to, iflag, rflag));
71516067Sralph 	}
71616067Sralph 	if (stat(to, &stto) >= 0) {
71716067Sralph 		if (dflag) printf("cp:stat(%s) o.k.\n",to);
71816067Sralph 		if (stfrom.st_dev == stto.st_dev &&
71916067Sralph 		   stfrom.st_ino == stto.st_ino) {
72016067Sralph 			fprintf(stderr, "cp: Cannot copy file to itself.\n");
72116067Sralph 			(void) close(fold);
72216067Sralph 			return (1);
72316067Sralph 		}
72416067Sralph 		if (cflag && cs == 0) {
72516067Sralph 			if (!fflag)
72616067Sralph 			     fprintf (stderr, "cp: %s exists: overwrite? ", to);
72716067Sralph 			     if (!yes()) {
72816067Sralph 			        	(void) close(fold);
72916067Sralph 					return(1);
73016067Sralph 			}
73116067Sralph 			dl(to, 0);
73216067Sralph 			cs = 1;
73316067Sralph 		}
73416067Sralph 	}
73516067Sralph 	fnew = creat(to, (int)stfrom.st_mode);
73616067Sralph 	if (fnew < 0) {
73716067Sralph 		Cerror(to,fflag);
73816067Sralph 		(void) close(fold); return(1);
73916067Sralph 	}
74016067Sralph 	if (dflag) printf("copy: creat(%s,%d) successful.\n",to,stfrom.st_mode);
74116067Sralph 	for (;;) {
74216067Sralph 		n = read(fold, buf, BSIZE);
74316067Sralph 		if (n == 0)
74416067Sralph 			break;
74516067Sralph 		if (n < 0) {
74616067Sralph 			Cerror(from,fflag);
74716067Sralph 			(void) close(fold); (void) close(fnew); return (1);
74816067Sralph 		}
74916067Sralph 		if (write(fnew, buf, n) != n) {
75016067Sralph 			Cerror(to,fflag);
75116067Sralph 			(void) close(fold); (void) close(fnew); return (1);
75216067Sralph 		}
75316067Sralph 	}
75416067Sralph 	if (dflag) printf("copy: %s copied to %s.\n",from,to);
75516067Sralph 	if (!tflag) {
75616067Sralph 		/* restore original time-stamp */
75716067Sralph 		tv[0] = stfrom.st_atime;
75816067Sralph 		tv[1] = stfrom.st_mtime;
75916067Sralph 		(void) utime(to, tv);
76016067Sralph 		if (dflag) printf("copy: tflag on, tv[0]=%d, tv[1]=%d.\n",tv[0], tv[1]);
76116067Sralph 	}
76216067Sralph 	if (dflag) printf("copy: returning from copy, from=%s, to=%s.\n",from,to);
76316067Sralph 	(void) close(fold); (void) close(fnew); return (0);
76416067Sralph }
76516067Sralph 
rcopy(from,to,iflag,rflag)76616067Sralph rcopy(from, to, iflag, rflag)
76716067Sralph 	char *from, *to;
76816067Sralph {
76916067Sralph 	DIR *fold = opendir(from);
77016067Sralph 	struct direct *dp;
77116067Sralph 	int errs = 0;
77216067Sralph 	char fromname[BUFSIZ];
77316067Sralph 
77416067Sralph 	if (dflag) printf("rcopy: entered: from=%s, to=%s.\n",from,to);
77516067Sralph 	if (fold == 0) {
77616067Sralph 		Cerror(from,fflag);
77716067Sralph 		return (1);
77816067Sralph 	}
77916067Sralph 	for (;;) {
78016067Sralph 		dp = readdir(fold);
78116067Sralph 		if (dp == 0) {
78216067Sralph 			closedir(fold);
78316067Sralph 			return (errs);
78416067Sralph 		}
78516067Sralph 		if (dp->d_ino == 0)
78616067Sralph 			continue;
78716067Sralph 		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
78816067Sralph 			continue;
78916067Sralph 		if (strlen(from) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
79016067Sralph 			if (!fflag) {
79116067Sralph 				fprintf(stderr, "cp: %s/%s: Name too long.\n",
79216067Sralph 			    		from, dp->d_name);
79316067Sralph 			}
79416067Sralph 			errs++;
79516067Sralph 			continue;
79616067Sralph 		}
79716067Sralph 		(void) sprintf(fromname, "%s/%s", from, dp->d_name);
79816067Sralph 		if (dflag) printf("rcopy: copy(%s,%s,%d,%d)\n",fromname,to,iflag,rflag);
79916067Sralph 		errs += copy(fromname, to, iflag, rflag);
80016067Sralph 	}
80116067Sralph }
80216067Sralph 
Cerror(s)80316067Sralph Cerror(s)
80416067Sralph 	char *s;
80516067Sralph {
80616067Sralph 	if (!fflag) {
80716067Sralph 	 	fprintf(stderr, "cp: ");
80816067Sralph 		perror(s);
80916067Sralph 	}
81016067Sralph }
811