xref: /original-bsd/local/local.cmd/dl.c (revision aba77441)
1 static char *sccsid = "@(#)dl.c	4.1\t02/17/84";
2 
3 #include <stdio.h>
4 #include <sys/param.h>
5 #include <sys/stat.h>
6 #include <sys/dir.h>
7 #include <errno.h>
8 #include <signal.h>
9 
10 #define	DELIM	'/'
11 #define MODEBITS 07777
12 #define	ISDIR(st)	(((st).st_mode&S_IFMT) == S_IFDIR)
13 #define	ISLNK(st)	(((st).st_mode&S_IFMT) == S_IFLNK)
14 #define	ISREG(st)	(((st).st_mode&S_IFMT) == S_IFREG)
15 #define	ISDEV(st) \
16 	(((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK)
17 
18 struct	stat s1, s2, buf;
19 extern	unsigned errno;
20 int	errcode;
21 char	*sprintf();
22 char    *path;
23 char    *path2;
24 char    line[1024];
25 int     cflag = 0;   /* "copy" - same as cp  */
26 int     dflag = 0;   /* "debug" - enable trace printf statements */
27 int     fflag = 0;   /* "force" option: override protection, no messages */
28 int     mflag = 0;   /* "move" - same as mv  */
29 int     cs = 0;      /* flag used with cflag to prevent endless recursion */
30 int     ms = 0;      /* flag used with mflag to prevent endless recursion */
31 int     tflag = 0;   /* restore original time stamp */
32 
33 main(argc, argv)     /* dl.c - delete, undelete, move, copy */
34 char *argv[];
35 {
36 	register char *arg;
37 	char *s;
38 	int mode;
39 	int aflg = 0;   /* "all" option: undelete all deleted files */
40 	int iflg = 0;	/* "interactive" option: send messages to user */
41 	int rflg = 0;   /* "recursive" opt., used only with n */
42 	int sflg = 0;   /* do not delete previous dlsave file */
43 	int uflg = 0;   /* undelete named files and/or directories */
44 	int nflg = 0;   /* do not provide back-up files */
45 
46 	if (isatty(0) == 0)	/* if standard i/o is not a terminal, */
47 		fflag++;		/*  turn on the f flag                */
48 
49 	if (strcmp(*argv,"ud") == 0)
50 		uflg++;
51 
52 	if (strcmp(*argv,"copy") == 0)
53 		cflag++;
54 
55 	if (strcmp(*argv,"move") == 0)
56 		mflag++;
57 
58 	while(argc>1 && argv[1][0]=='-') {
59 		arg = *++argv;
60 		argc--;
61 
62 		/*
63 		 *  all arguments following a null option (- ) are
64 		 *   treated as file names, so that file names may
65 		 *   begin with a minus sign (-).
66 		 */
67 		if (*(arg+1) == '\0') break;
68 
69 		while(*++arg != '\0')
70 			switch(*arg) {
71 			case 'a':	/* "all" */
72 				aflg++;
73 				break;
74 			case 'c':	/* "copy" */
75 				cflag++;
76 				break;
77 			case 'd':	/* "debug" */
78 				dflag++;
79 				break;
80 			case 'f':	/* "force" */
81 				fflag++;
82 				break;
83 			case 'i':	/* "interactive" */
84 				iflg++;
85 				break;
86 			case 'r':	/* "recursive" */
87 				rflg++;
88 				break;
89 			case 's':	/* "save" */
90 				sflg++;
91 				break;
92 			case 't':	/* "time" stamp */
93 				tflag++;
94 				break;
95 			case 'u':	/* "undelete" */
96 				uflg++;
97 				break;
98 			case 'm':	/* "move" */
99 				mflag++;
100 				break;
101 			case 'n':	/* "not save" */
102 				nflg++;
103 				break;
104 			default:
105 				printf("dl: unknown option %s\n", *argv);
106 				exit(1);
107 			}
108 	}
109 	if (cflag || mflag || nflg)  sflg++;
110 	/*
111 	 * set up home directory pathname
112 	 */
113 	setpath();
114 	/*
115 	 * process "undelete all" request
116 	 */
117 	if(aflg) {
118 		undelete_all(iflg);
119 		exit;
120 	}
121 	/*
122 	 * remove previously saved files unless "save" option,
123 	 *  or ud or rm mode
124 	 */
125 	if(!sflg && !uflg)
126 		dldir(path,0);
127 	if(!nflg && lstat(path,&buf) != 0) {
128 		/*
129 		 * set up .dlsave directory
130 	 	 */
131 		mode = 0777;
132           	if (mkdir(path,mode) != 0) {
133 		       	   fprintf(stderr,"dl: cannot mkdir ~/.dlsave\n");
134 			   perror(s);
135 			   exit(1);
136 		}
137 	}
138      	while(--argc > 0) {
139 		if(!strcmp(*++argv, "..")) {
140 		    	if(!fflag)
141 				fprintf(stderr, "dl: cannot remove `..'\n");
142 			continue;
143 		}
144 	       /*
145 	 	* process "undelete" request(s)
146 	 	*/
147 		if(uflg) {
148 			undelete(*argv,iflg);
149 			exit;
150 		}
151 		else {
152 		/*
153 		 * process delete request(s)
154 		 */
155 			if (cflag) {
156 				copy(*argv,argv[argc-1],iflg,rflg);
157 				exit(errcode);
158 			}
159 			if (mflag) {
160 				move(*argv,argv[argc-1],iflg);
161 				exit(errcode);
162 			}
163 			if (nflg)
164 				rm(*argv, iflg, rflg);
165 			else
166 				dl(*argv, iflg);
167 		}
168 	}
169 	exit(errcode);
170 }
171 
172 setpath()
173 {
174 	char *home;
175 	char *suffix;
176 	char *getenv();
177 
178 	home = "HOME";
179 	if ((path=getenv(home)) == NULL) {
180 		fprintf(stderr,"dl: getenv failed\n");
181 		exit(1);
182 	}
183 	suffix = "/.dlsave";
184 	strcat(path,suffix);
185 	return;
186 }
187 
188 package(argu)
189 char argu[];
190 {
191 	register int i, j, k;
192 	char  *slash, *slashdot;
193 	char  *place;
194 	char  line2[512];
195 
196 	place = line2;
197 	strcpy(place,argu);
198 	path2 = line;
199 	strcpy(path2,path);
200 	slashdot = "/.#";
201 	strcat(path2,slashdot);
202 	i = strlen(argu);
203 	slash = "/";
204 	k = 0;
205 	for (j=0;j<i;j++) {
206 		if (place[j] == *slash) {
207 			k = j + 1;
208 		}
209 	}
210 	strcat(path2,argu+k);
211 	return;
212 }
213 
214 undelete_all(iflg)
215 {
216 	struct direct *dp;
217 	DIR *dirp;
218 	char *filename;
219 	int x;
220 
221 	/*
222 	 * undelete all saved files (a option)
223 	 */
224 	if((dirp = opendir(path)) == NULL) {
225 		if(!fflag)
226 			printf("uda: cannot read %s?\n", path);
227 		exit(1);
228 	}
229 	while((dp = readdir(dirp)) != NULL) {
230              	if(dp->d_ino != 0 && !dotname(dp->d_name)) {
231 			filename = (dp->d_name)+2;
232 			package(filename);
233 			if(iflg) {
234 				printf("uda: undelete %s?", filename);
235 				if (!yes())
236 					goto no;
237 			}
238 			if(lstat(filename, &buf) == 0) {
239 				printf("uda: %s exists. Override?", filename);
240 				if(!yes())
241 					goto no;
242 			}
243 			x = move(path2,filename,0);
244 			if(iflg) {
245 			        if (x >= 0)
246 				       printf("uda: %s undeleted.\n", filename);
247 				else
248 				       printf("uda: unable to undelete %s\n", filename);
249 			}
250 no:		continue;
251 	        }
252 	}
253 	closedir(dirp);
254 	return;
255 }
256 
257 undelete(arg,iflg)
258 char arg[];
259 {
260 	struct stat buf1, buf2;
261 	int x;
262 
263 	/*
264 	 * undelete a saved file (u option)
265 	 */
266 	package(arg);
267 	if(lstat(path2, &buf1)) {
268 		if (!fflag)
269 			printf("ud: %s nonexistent\n", path2);
270 		++errcode;
271 	    	return;
272 	}
273 	if(iflg) {
274 		printf("ud: undelete %s?", arg);
275 		if(!yes())
276 			return;
277 	}
278 	if(lstat(arg, &buf2) == 0) {
279 			printf("ud: %s exists: overwrite?", arg);
280 			if(!yes())
281 				return;
282 	}
283         x = move(path2,arg,0);
284 	if(iflg) {
285 		if (x >= 0)
286       	      		printf("ud: %s undeleted.\n", arg);
287         	else
288        	      		printf("ud: unable to undelete %s\n", arg);
289 	}
290 	return;
291 }
292 
293 rm(arg, iflg, rflg)
294 char arg[];
295 {
296 	if (dflag) printf("rm entered: arg=%s fflag=%d iflg=%d rflg=%d\n",arg,fflag,iflg,rflg);
297 	if(lstat(arg, &buf)) {
298 		if (!fflag)
299 			printf("rm: %s nonexistent\n", arg);
300 		++errcode;
301 	    	return;
302 	}
303 	/*
304 	 * unlink file named by arg
305 	 */
306 	if ((buf.st_mode&S_IFMT) == S_IFDIR || rflg) {
307 		if(iflg) {
308 			printf("rm: remove directory %s?", arg);
309 			if(!yes())
310 				return;
311 		}
312 		dldir(arg, iflg);
313 		return;
314 	}
315 	if (!fflag && iflg) {
316 		printf("rm: remove %s?", arg);
317 		if (!yes())
318 			return;
319 	}
320 	else if (!fflag) {
321 		if ((buf.st_mode&S_IFMT) != S_IFLNK && access(arg, 02) < 0) {
322 			printf("rm: override protection %o for %s?\n",buf.st_mode&0777,arg);
323 			if (!yes())
324 				return;
325 		}
326 	}
327 	if (unlink(arg) && !fflag) {
328 		printf ("rm: %s not removed.\n",arg);
329 		++errcode;
330 	}
331 	else {
332 		if (!fflag && iflg)
333 			printf ("rm: %s removed.\n",arg);
334 	}
335 	return;
336 }
337 
338 dl(arg, iflg)
339 char arg[];
340 {
341 	/*
342 	 * move the argument (file or directory) to
343 	 *  .dlsave directory in user's home directory
344 	 */
345 	if (dflag) printf("dl entered: arg=%s fflag=%d iflg=%d\n",arg,fflag,iflg);
346 	package(arg);
347 	move(arg,path2,iflg);
348 	return;
349 }
350 
351 dldir(arg, iflg)
352 char arg[];
353 {
354 	struct  stat  buf1, buf2;
355 	struct direct *dp;
356 	DIR *dirp;
357 	char name[BUFSIZ];
358 
359 	if (dflag) printf("dldir entered: arg=%s fflag=%d iflg=%d\n",arg,fflag,iflg);
360 	if(lstat(arg, &buf1)) {
361 		if (!fflag && iflg)
362 			printf("dldir: %s nonexistent\n", arg);
363 		++errcode;
364 	    	return;
365 	}
366 	/*
367 	 * if the argument is a directory,
368 	 * recursively remove the directory's contents
369 	 * and then the directory.
370 	 */
371 	if ((buf1.st_mode&S_IFMT) == S_IFDIR) {
372 		if (access(arg, 02) < 0) {
373 			if(!fflag) {
374 			 	printf("dldir: %s not accessable\n",arg);
375 			}
376 			errcode++;
377 			return;
378 		}
379 		if((dirp = opendir(arg)) == NULL)
380 			exit(1);
381 		while((dp = readdir(dirp)) != NULL) {
382 			if(dp->d_ino != 0 && !dotname(dp->d_name)) {
383 				sprintf(name, "%s/%s", arg, dp->d_name);
384 				if (dflag) printf("dldir: name= %s\n",name);
385 				if(lstat(name, &buf2)) {
386 					if (!fflag)
387 					   printf("dldir: %s nonexistent\n", name);
388 					++errcode;
389 	    				return;
390 				}
391 				if ((buf2.st_mode&S_IFMT) == S_IFDIR) {
392     				if(!fflag && iflg) {
393 					printf("dldir: delete directory %s?", name);
394 					if(!yes())
395 						return;
396    				}
397   				dldir(name, iflg);
398 				}
399 				else {
400     					if(!fflag && iflg) {
401 					   printf("dldir: delete file %s?", name);
402 						if(!yes())
403 							return;
404    					}
405 			       		/*
406 	 				 * permanently remove the file
407 	 				 */
408 					if (unlink(name)) {
409 					  if (!fflag)
410 					   printf("dldir: %s not removed\n", name);
411 					   ++errcode;
412 					}
413 					else {
414 					   if (!fflag && iflg)
415 					     printf("dldir: %s removed.\n", name);
416 					}
417 				}
418 			}
419 		}
420 		closedir(dirp);
421 		if (dotname(arg))
422 			return;
423 		if (rmdir(arg) < 0) {
424 			if(!fflag && iflg) {
425 				fprintf(stderr, "dldir: rmdir:");
426 				perror(arg);
427 			}
428 			errcode++;
429 		}
430 		else {
431 			if(!fflag && iflg)
432 				printf("dldir: directory %s removed.\n",arg);
433 		}
434 	return;
435 	}
436 }
437 
438 dotname(s)
439 char *s;
440 {
441 	if(s[0] == '.')
442 		if(s[1] == '.')
443 			if(s[2] == '\0')
444 				return(1);
445 			else
446 				return(0);
447 		else if(s[1] == '\0')
448 			return(1);
449 	return(0);
450 }
451 
452 yes()
453 {
454 	int i, b;
455 
456 	i = b = getchar();
457 	while(b != '\n' && b != EOF)
458 		b = getchar();
459 	return(i == 'y');
460 }
461 
462 move(source, target, iflag)
463 	char *source, *target;
464 {
465 	int targetexists;
466 	int sw = 0;
467 
468 	if (dflag) printf("move entered: source=%s target=%s fflag=%d iflag=%d\n",source,target,fflag,iflag);
469 	if (lstat(source, &s1) < 0) {
470 		if (!fflag)
471 			error("cannot access %s", source);
472 		return (1);
473 	}
474 	if (dflag) printf("move: lstat(%s) successful\n",source);
475 	/*
476 	 * First, try to rename source to target.
477 	 */
478 	targetexists = lstat(target, &s2) >= 0;
479 	if (targetexists) {
480 		if (dflag) printf("move: lstat(%s) successful\n",target);
481 		if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino) {
482 			if (!fflag)
483 			      error("%s and %s are identical", source, target);
484 			return (1);
485 		}
486 		if (access(target, 2) < 0 && !fflag && isatty(fileno(stdin))) {
487 			if (query("override protection %o for %s? ",
488 			  s2.st_mode & MODEBITS, target) == 0)
489 				return (1);
490 			sw++;
491 		}
492 		if (mflag && ms == 0) {
493 			if (ISREG(s2)) {
494 				if (!fflag && sw == 0) {
495 		   		printf("overwrite file %s?", target);
496 				if(!yes())
497 					return;
498 				}
499 			ms = 1;
500 			dl (target, 0);
501 			}
502 			else
503 			if (s1.st_dev != s2.st_dev && ISDIR(s2))
504 				goto copyit;
505 		}
506 	}
507 	if (!fflag && iflag && !mflag) {
508 		if (ISDIR(s1))
509 			printf("dl: delete directory %s?", source);
510 		else
511 			printf("dl: delete file %s?", source);
512 		if(!yes())
513 			return;
514 	}
515 	if(dflag) printf("move(1)rename: source=%s, target=%s\n",source, target);
516 	if (rename(source, target) >= 0) {
517 		if (!fflag && iflag && !mflag)
518 			printf("dl: %s deleted. \n",source);
519 		if (dflag) printf("move: %s renamed %s.\n",source,target);
520 		return (0);
521 	}
522 	if (dflag) printf("move/rename: errno=%d\n",errno);
523 	if (errno != EXDEV) {
524 		if (!fflag && iflag) {
525 			Perror2(source, "rename");
526 		}
527 		goto copyit;
528 	}
529 	if (targetexists && unlink(target) < 0) {
530 		if(!fflag)
531 			error("cannot unlink %s", target);
532 		return (1);
533 	}
534 	if (dflag) printf("move: target unlinked\n");
535 
536 	/*
537 	 * If file or directory cannot be renamed:
538 	 *  If directory, copy it with r option
539 	 *   and delete the source
540 	 */
541 copyit:	if (ISDIR(s1)) {
542 	     if (dflag) printf("move: directory copy %s to %s\n",source,target);
543 		copy (source, target, iflag, 1);
544 		dldir (source, iflag);
545 		return(0);
546 	}
547 
548 	/*
549 	 *  If link, recreate symbolic link
550 	 */
551 	if (ISLNK(s1)) {
552 		register m;
553 		char symln[MAXPATHLEN];
554 
555 		if (readlink(source, symln, sizeof (symln)) < 0) {
556 			if (!fflag)
557 				Perror(source);
558 				return (1);
559 		}
560 		m = umask(~(s1.st_mode & MODEBITS));
561 		if (symlink(symln, target) < 0) {
562 			if (!fflag)
563 				Perror(target);
564 				return (1);
565 		}
566 		if (dflag) printf("move: symlink to target successful\n");
567 		(void) umask(m);
568 		goto cleanup;
569 	}
570 
571 	/*
572 	 *  If device
573 	 */
574 	if (ISDEV(s1)) {
575 		if (mknod(target, s1.st_mode, s1.st_rdev) < 0) {
576 			if (!fflag)
577 				Perror(target);
578 			return (1);
579 		}
580 		if (dflag) printf("move: mknod for target successful\n");
581 		goto cleanup;
582 	}
583 
584 	/*
585 	 *  If regular file, copy it
586 	 */
587 	if (ISREG(s1)) {
588 	     	if(dflag) printf("move: file copy %s to %s\n",source,target);
589 		copy(source, target, iflag, 0);
590 		goto cleanup;
591  	}
592 
593 	if (!fflag)
594 		error("%s: unknown file type %o", source, s1.st_mode);
595 	return (1);
596 
597 	/*
598 	 *  If a move has been successful, erase the source
599 	 */
600 cleanup:
601 	if (dflag) printf("move: cleanup\n");
602 	if (unlink(source) < 0) {
603 		if (!fflag)
604 			error("cannot unlink %s", source);
605 		return (1);
606 	}
607 	if (dflag) printf("move: %s unlinked.\n",source);
608 	if (!fflag && iflag && !mflag)
609 		printf("dl: %s deleted.\n",source);
610 	return (0);
611 }
612 
613 /*VARARGS*/
614 query(prompt, a1, a2)
615 	char *a1;
616 {
617 	register char i, c;
618 
619 	fprintf(stderr, prompt, a1, a2);
620 	i = c = getchar();
621 	while (c != '\n' && c != EOF)
622 		c = getchar();
623 	return (i == 'y');
624 }
625 
626 error(fmt, a1, a2)
627 	char *fmt;
628 {
629 	fprintf(stderr, "dl: ");
630 	fprintf(stderr, fmt, a1, a2);
631 	fprintf(stderr, "\n");
632 }
633 
634 Perror(s)
635 	char *s;
636 {
637 	char buf[MAXPATHLEN + 10];
638 
639 	sprintf(buf, "move: %s", s);
640 	perror(buf);
641 }
642 
643 Perror2(s1, s2)
644 	char *s1, *s2;
645 {
646 	char buf[MAXPATHLEN + 20];
647 
648 	sprintf(buf, "dl: %s: %s", s1, s2);
649 	perror(buf);
650 }
651 
652 #define	BSIZE	8192
653 
654 char	*rindex();
655 
656 copy(from, to, iflag, rflag)
657 	char *from, *to;
658 {
659 	int fold, fnew, n;
660 	char *last, destname[BSIZE], buf[BSIZE];
661 	struct stat stfrom, stto;
662 	time_t tv[2];
663 
664 	if (dflag) printf("copy entered: from=%s to=%s iflag=%d rflag=%d\n",from,to,iflag,rflag);
665 	fold = open(from, 0);
666 	if (fold < 0) {
667 		Cerror(from,fflag);
668 		return (1);
669 	}
670 	if (fstat(fold, &stfrom) < 0) {
671 		Cerror(from,fflag);
672 		(void) close(fold);
673 		return (1);
674 	}
675 	if (dflag) printf("copy: fstat(%s) OK.\n",from);
676 	if (stat(to, &stto) >= 0 &&
677 	   (stto.st_mode&S_IFMT) == S_IFDIR) {
678 		last = rindex(from, '/');
679 		if (last) last++; else last = from;
680 		if (strlen(to) + strlen(last) >= BSIZE - 1) {
681 			fprintf(stderr, "cp: %s/%s: Name too long", to, last);
682 			(void) close(fold);
683 			return(1);
684 		}
685 		(void) sprintf(destname, "%s/%s", to, last);
686 		if (dflag) printf("copy: stat %s & %s is dir., to=%s.\n",to,to,destname);
687 		to = destname;
688 	}
689 	if (!rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) {
690 		fprintf(stderr, "cp: %s is a directory, and option -r not chosen.  Job aborted.\n", from);
691 		return(1);
692 	}
693 	if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) {
694 		(void) close(fold);
695 		if (dflag) printf("copy: rflag & from is dir., %s closed.\n",from);
696 		if (stat(to, &stto) < 0) {
697 			if (mkdir(to, (int)stfrom.st_mode) < 0) {
698 				Cerror(to,fflag);
699 				return (1);
700 			}
701 			if (dflag) printf("copy: stat(%s) failed & mkdir % successful.\n",to,to);
702 		}
703 		else {
704 			if (!fflag) {
705 				if ((stto.st_mode&S_IFMT) == S_IFDIR) {
706 				dl(to, iflag);
707 				}
708 				else {
709 			      		fprintf(stderr, "cp: %s: Not a directory.\n", to);
710 			      		return (1);
711 				}
712 			}
713 		}
714 		if (dflag) printf("copy: return with rcopy(%s,%s,%d,%d)\n",from,to,iflag,rflag);
715 		return (rcopy(from, to, iflag, rflag));
716 	}
717 	if (stat(to, &stto) >= 0) {
718 		if (dflag) printf("cp:stat(%s) o.k.\n",to);
719 		if (stfrom.st_dev == stto.st_dev &&
720 		   stfrom.st_ino == stto.st_ino) {
721 			fprintf(stderr, "cp: Cannot copy file to itself.\n");
722 			(void) close(fold);
723 			return (1);
724 		}
725 		if (cflag && cs == 0) {
726 			if (!fflag)
727 			     fprintf (stderr, "cp: %s exists: overwrite? ", to);
728 			     if (!yes()) {
729 			        	(void) close(fold);
730 					return(1);
731 			}
732 			dl(to, 0);
733 			cs = 1;
734 		}
735 	}
736 	fnew = creat(to, (int)stfrom.st_mode);
737 	if (fnew < 0) {
738 		Cerror(to,fflag);
739 		(void) close(fold); return(1);
740 	}
741 	if (dflag) printf("copy: creat(%s,%d) successful.\n",to,stfrom.st_mode);
742 	for (;;) {
743 		n = read(fold, buf, BSIZE);
744 		if (n == 0)
745 			break;
746 		if (n < 0) {
747 			Cerror(from,fflag);
748 			(void) close(fold); (void) close(fnew); return (1);
749 		}
750 		if (write(fnew, buf, n) != n) {
751 			Cerror(to,fflag);
752 			(void) close(fold); (void) close(fnew); return (1);
753 		}
754 	}
755 	if (dflag) printf("copy: %s copied to %s.\n",from,to);
756 	if (!tflag) {
757 		/* restore original time-stamp */
758 		tv[0] = stfrom.st_atime;
759 		tv[1] = stfrom.st_mtime;
760 		(void) utime(to, tv);
761 		if (dflag) printf("copy: tflag on, tv[0]=%d, tv[1]=%d.\n",tv[0], tv[1]);
762 	}
763 	if (dflag) printf("copy: returning from copy, from=%s, to=%s.\n",from,to);
764 	(void) close(fold); (void) close(fnew); return (0);
765 }
766 
767 rcopy(from, to, iflag, rflag)
768 	char *from, *to;
769 {
770 	DIR *fold = opendir(from);
771 	struct direct *dp;
772 	int errs = 0;
773 	char fromname[BUFSIZ];
774 
775 	if (dflag) printf("rcopy: entered: from=%s, to=%s.\n",from,to);
776 	if (fold == 0) {
777 		Cerror(from,fflag);
778 		return (1);
779 	}
780 	for (;;) {
781 		dp = readdir(fold);
782 		if (dp == 0) {
783 			closedir(fold);
784 			return (errs);
785 		}
786 		if (dp->d_ino == 0)
787 			continue;
788 		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
789 			continue;
790 		if (strlen(from) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
791 			if (!fflag) {
792 				fprintf(stderr, "cp: %s/%s: Name too long.\n",
793 			    		from, dp->d_name);
794 			}
795 			errs++;
796 			continue;
797 		}
798 		(void) sprintf(fromname, "%s/%s", from, dp->d_name);
799 		if (dflag) printf("rcopy: copy(%s,%s,%d,%d)\n",fromname,to,iflag,rflag);
800 		errs += copy(fromname, to, iflag, rflag);
801 	}
802 }
803 
804 Cerror(s)
805 	char *s;
806 {
807 	if (!fflag) {
808 	 	fprintf(stderr, "cp: ");
809 		perror(s);
810 	}
811 }
812