[comp.sources.unix] v22i103: CRITICAL patch to MMV

rsalz@uunet.uu.net (Rich Salz) (06/08/90)

Submitted-by: Vladimir Lanin <lanin@csd4.cs.nyu.edu>
Posting-number: Volume 22, Issue 103
Archive-name: mmv.pch
Patch-To: volume21/mmv

The following patch fixes a number of bugs in mmv 1.0 (as distributed on
comp.sources.unix) and provides V7 compatibility.  The new version is
known as mmv 1.01b.

Since one of the bugs can result in the unintended DELETION of the source
file(s), it is imperative that the old version be replaced with the new
one.

The two major bugs fixed are:
1) in its BSD reincarnation, whenever a file had to be moved between devices
(by copying, then deleting), mmv 1.0 made a symbolic link to "/" instead
of copying the file. It still deleted the original, though. Oops!
2) the uppercase/lowercase conversion feature did not work.

Vladimir Lanin

---cut here---
***************
*** 1,5 ****
  /*
! 	mmv 1.0
  	Copyright (c) 1990 Vladimir Lanin.
  	This program may be freely used and copied on a non-commercial basis.
  	The author assumes no responsibility for any damage or data loss that may
--- 1,5 ----
  /*
! 	mmv 1.01b
  	Copyright (c) 1990 Vladimir Lanin.
  	This program may be freely used and copied on a non-commercial basis.
  	The author assumes no responsibility for any damage or data loss that may
***************
*** 7,21 ****
  
  	Author may be reached at:
  
! 	lanin@csd4.nyu.edu
  
  	Vladimir Lanin
  	330 Wadsworth Ave, Apt 6F,
  	New York, NY 10040
  */
  
  /*
  	Define SYSV to compile under System V.
  	If your System V has a rename() call, define RENAME.
  	Otherwise, mmv will only be able to rename directories (via option -r)
  	when running as the super-user.
--- 7,36 ----
  
  	Author may be reached at:
  
! 	lanin@csd4.cs.nyu.edu
  
  	Vladimir Lanin
  	330 Wadsworth Ave, Apt 6F,
  	New York, NY 10040
+ 
+ 	Many thanks to those who have to contributed to the design
+ 	and/or coding of this program:
+ 
+ 	Tom Albrecht:	initial Sys V adaptation, consultation, and testing
+ 	Carl Mascott:	V7 adaptation
+ 	Mark Lewis:	-n flag idea, consultation.
+ 	Dave Bernhold:	upper/lowercase conversion idea.
+ 	Paul Stodghill:	copy option, argv[0] checking.
+ 	Frank Fiamingo:	consultation and testing.
+ 	Tom Jordahl:	bug reports and testing.
+ 	John Lukas, Hugh Redelmeyer, Barry Nelson, John Sauter,
+ 	Phil Dench, John Nelson:
+ 			bug reports.
  */
  
  /*
  	Define SYSV to compile under System V.
+ 	Define both SYSV and V7 to compile under V7.
  	If your System V has a rename() call, define RENAME.
  	Otherwise, mmv will only be able to rename directories (via option -r)
  	when running as the super-user.
***************
*** 74,84 ****
  
  #include <stdio.h>
  #include <ctype.h>
- #include <string.h>
  
  #ifdef MSDOS
  /* for MS-DOS (under Turbo C 1.5)*/
  
  #include <stdlib.h>
  #include <sys/stat.h>
  #include <dos.h>
--- 89,99 ----
  
  #include <stdio.h>
  #include <ctype.h>
  
  #ifdef MSDOS
  /* for MS-DOS (under Turbo C 1.5)*/
  
+ #include <string.h>
  #include <stdlib.h>
  #include <sys/stat.h>
  #include <dos.h>
***************
*** 109,116 ****
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/file.h>
! #include <sys/signal.h>
! #include <fcntl.h>
  extern char *getenv();
  extern long lseek();
  extern char *malloc();
--- 124,130 ----
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/file.h>
! 
  extern char *getenv();
  extern long lseek();
  extern char *malloc();
***************
*** 149,176 ****
  
  static char TTY[] = "/dev/tty";
  
! #ifdef SYSV
! /* for System V */
  
  struct utimbuf {
  	time_t actime;
  	time_t modtime;
  };
! #define utimes(f, t) utime((f), (t))
  
- 
  #else
  /* for BSD */
- 
  #define RENAME
- 
  #include <sys/time.h>
  
  #endif
- 
  #endif
  
- 
  #define mylower(c) (isupper(c) ? (c)-'A'+'a' : (c))
  #define myupper(c) (islower(c) ? (c)-'a'+'A' : (c))
  #define STRLEN(s) (sizeof(s) - 1)
--- 163,202 ----
  
  static char TTY[] = "/dev/tty";
  
! #ifdef V7
! /* for Version 7 */
! #include <errno.h>
! extern int errno;
! #define strchr index
! extern char *strcpy(), *strchr();
! #include <signal.h>
! #define O_RDONLY 0
! #define O_WRONLY 1
! #define O_RDWR   2
  
+ #else
+ /* for System V and BSD */
+ #include <string.h>
+ #include <sys/signal.h>
+ #include <fcntl.h>
+ #endif
+ 
+ #ifdef SYSV
+ /* for System V and Version 7*/
  struct utimbuf {
  	time_t actime;
  	time_t modtime;
  };
! #define utimes(f, t) utime((f), &(t))
  
  #else
  /* for BSD */
  #define RENAME
  #include <sys/time.h>
  
  #endif
  #endif
  
  #define mylower(c) (isupper(c) ? (c)-'A'+'a' : (c))
  #define myupper(c) (islower(c) ? (c)-'a'+'A' : (c))
  #define STRLEN(s) (sizeof(s) - 1)
***************
*** 298,304 ****
  static void init(/* */);
  static void procargs(/* int argc, char **argv,
  	char **pfrompat, char **ptopat */);
! static void matchpats(/* char *cfrom, char *cto */);
  static int getpat(/* */);
  static int getword(/* char *buf */);
  static void matchpat(/*  */);
--- 324,330 ----
  static void init(/* */);
  static void procargs(/* int argc, char **argv,
  	char **pfrompat, char **ptopat */);
! static void domatch(/* char *cfrom, char *cto */);
  static int getpat(/* */);
  static int getword(/* char *buf */);
  static void matchpat(/*  */);
***************
*** 355,360 ****
--- 381,387 ----
  static void *challoc(/* int k, int which */);
  static void chgive(/* void *p, unsigned k */);
  static int mygetc(/* */);
+ static char *mygets(/* char *s, int l */);
  #ifdef MSDOS
  static int leave(/*  */);
  static void cleanup(/*  */);
***************
*** 394,406 ****
  
  static char PATLONG[] = "%.40s... : pattern too long.\n";
  
! static char from[MAXPATLEN], to[MAXPATLEN];
  static int fromlen, tolen;
  static char *(stagel[MAXWILD]), *(firstwild[MAXWILD]), *(stager[MAXWILD]);
  static int nwilds[MAXWILD];
  static int nstages;
! static char pathbuf[MAXPATH];
! static char fullrep[MAXPATH + 1];
  static char *(start[MAXWILD]);
  static int len[MAXWILD];
  static char hasdot[MAXWILD];
--- 421,433 ----
  
  static char PATLONG[] = "%.40s... : pattern too long.\n";
  
! char from[MAXPATLEN], to[MAXPATLEN];
  static int fromlen, tolen;
  static char *(stagel[MAXWILD]), *(firstwild[MAXWILD]), *(stager[MAXWILD]);
  static int nwilds[MAXWILD];
  static int nstages;
! char pathbuf[MAXPATH];
! char fullrep[MAXPATH + 1];
  static char *(start[MAXWILD]);
  static int len[MAXWILD];
  static char hasdot[MAXWILD];
***************
*** 446,452 ****
  
  	init();
  	procargs(argc, argv, &frompat, &topat);
! 	matchpats(frompat, topat);
  	if (!(op & APPEND))
  		checkcollisions();
  	findorder();
--- 473,479 ----
  
  	init();
  	procargs(argc, argv, &frompat, &topat);
! 	domatch(frompat, topat);
  	if (!(op & APPEND))
  		checkcollisions();
  	findorder();
***************
*** 616,622 ****
  }
  
  
! static void matchpats(cfrom, cto)
  	char *cfrom, *cto;
  {
  	if (cfrom == NULL)
--- 643,649 ----
  }
  
  
! static void domatch(cfrom, cto)
  	char *cfrom, *cto;
  {
  	if (cfrom == NULL)
***************
*** 1381,1392 ****
  	flags |= FI_STTAKEN;
  #ifdef SYSV
  	if (stat(ffull, &fstat)) {
! 		fprintf("Strange, couldn't stat %s.\n", ffull);
  		quit();
  	}
  #else
  	if (lstat(ffull, &fstat)) {
! 		fprintf("Strange, couldn't lstat %s.\n", ffull);
  		quit();
  	}
  	if ((flags & FI_INSTICKY) && fstat.st_uid != uid && uid != 0)
--- 1408,1419 ----
  	flags |= FI_STTAKEN;
  #ifdef SYSV
  	if (stat(ffull, &fstat)) {
! 		fprintf(stderr, "Strange, couldn't stat %s.\n", ffull);
  		quit();
  	}
  #else
  	if (lstat(ffull, &fstat)) {
! 		fprintf(stderr, "Strange, couldn't lstat %s.\n", ffull);
  		quit();
  	}
  	if ((flags & FI_INSTICKY) && fstat.st_uid != uid && uid != 0)
***************
*** 1967,1973 ****
  				cnv = LOWER;
  				c = *(++pat);
  			}
! 			if (c == 'u') {
  				cnv = UPPER;
  				c = *(++pat);
  			}
--- 1994,2000 ----
  				cnv = LOWER;
  				c = *(++pat);
  			}
! 			else if (c == 'u') {
  				cnv = UPPER;
  				c = *(++pat);
  			}
***************
*** 2358,2364 ****
  				if (
  					(op & (COPY | APPEND)) ?
  						copy(p->r_ffrom,
! 							p->r_flags & R_ISALIASED ? aliaslen : -1) :
  #ifndef MSDOS
  					(op & HARDLINK) ?
  						link(pathbuf, fullrep) :
--- 2385,2391 ----
  				if (
  					(op & (COPY | APPEND)) ?
  						copy(p->r_ffrom,
! 							p->r_flags & R_ISALIASED ? aliaslen : -1L) :
  #ifndef MSDOS
  					(op & HARDLINK) ?
  						link(pathbuf, fullrep) :
***************
*** 2484,2490 ****
  #endif
  		while (
  			fprintf(stderr, "File name> "),
! 			(outfile = fopen(gets(fname), "w")) == NULL
  		)
  			fprintf(stderr, "Can't open %s.\n", fname);
  	}
--- 2511,2517 ----
  #endif
  		while (
  			fprintf(stderr, "File name> "),
! 			(outfile = fopen(mygets(fname, 80), "w")) == NULL
  		)
  			fprintf(stderr, "Can't open %s.\n", fname);
  	}
***************
*** 2552,2558 ****
  		int llen;
  		char linkbuf[MAXPATH];
  
! 		if ((llen = readlink(pathbuf, linkbuf, MAXPATH - 1)) != 1) {
  			linkbuf[llen] = '\0';
  			return(symlink(linkbuf, fullrep) || myunlink(pathbuf, p->r_ffrom));
  		}
--- 2579,2585 ----
  		int llen;
  		char linkbuf[MAXPATH];
  
! 		if ((llen = readlink(pathbuf, linkbuf, MAXPATH - 1)) >= 0) {
  			linkbuf[llen] = '\0';
  			return(symlink(linkbuf, fullrep) || myunlink(pathbuf, p->r_ffrom));
  		}
***************
*** 2559,2565 ****
  	}
  #endif
  #endif
! 	return(copy(p->r_ffrom, -1) || myunlink(pathbuf, p->r_ffrom));
  }
  
  
--- 2586,2592 ----
  	}
  #endif
  #endif
! 	return(copy(p->r_ffrom, -1L) || myunlink(pathbuf, p->r_ffrom));
  }
  
  
***************
*** 2595,2601 ****
  			ff->fi_mode
  #endif
  		;
! 	mode = O_CREAT |
  #ifdef MSDOS
  		O_BINARY | (op & ZAPPEND ? O_RDWR : O_WRONLY)
  #else
--- 2622,2636 ----
  			ff->fi_mode
  #endif
  		;
! 
! #ifdef V7
! 	if (
! 		!(op & APPEND) ||
! 		(((t = open(fullrep, O_RDWR)) < 0 && errno == ENOENT)
! 	)
! 		t = creat(fullrep, perm);
! #else
! 	mode = O_CREAT | (op & APPEND ? 0 : O_TRUNC) |
  #ifdef MSDOS
  		O_BINARY | (op & ZAPPEND ? O_RDWR : O_WRONLY)
  #else
***************
*** 2602,2624 ****
  		O_WRONLY
  #endif
  		;
! 	if (!(op & APPEND))
! 		mode |= O_TRUNC;
! 	if ((t = open(fullrep, mode, perm)) < 0) {
  		close(f);
  		return(-1);
  	}
  	if (op & APPEND)
! 		lseek(t, 0, 2);
  #ifdef MSDOS
  	if (op & ZAPPEND && filelength(t) != 0) {
! 		if (lseek(t, -1, 1) == -1L || read(t, &c, 1) != 1) {
  			close(f);
  			close(t);
  			return(-1);
  		}
  		if (c == 26)
! 			lseek(t, -1, 1);
  	}
  #endif
  	if ((op & APPEND) && len != -1L) {
--- 2637,2659 ----
  		O_WRONLY
  #endif
  		;
! 	t = open(fullrep, mode, perm);
! #endif
! 	if (t < 0) {
  		close(f);
  		return(-1);
  	}
  	if (op & APPEND)
! 		lseek(t, 0L, 2);
  #ifdef MSDOS
  	if (op & ZAPPEND && filelength(t) != 0) {
! 		if (lseek(t, -1L, 1) == -1L || read(t, &c, 1) != 1) {
  			close(f);
  			close(t);
  			return(-1);
  		}
  		if (c == 26)
! 			lseek(t, -1L, 1);
  	}
  #endif
  	if ((op & APPEND) && len != -1L) {
***************
*** 2822,2827 ****
--- 2857,2880 ----
  	if (lastc == EOF)
  		return(EOF);
  	return(lastc = getchar());
+ }
+ 
+ 
+ static char *mygets(s, l)
+ 	char *s;
+ 	int l;
+ {
+ 	char *nl;
+ 
+ 	for (;;) {
+ 		if (fgets(s, l, stdin) == NULL)
+ 			return(NULL);
+ 		if ((nl = strchr(s, '\n')) != NULL)
+ 			break;
+ 		fprintf(stderr, "Input string too long. Try again> ");
+ 	}
+ 	*nl = '\0';
+ 	return(s);
  }
  
  

exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.