#include #include #include #include #include #include #include #define MAXFILES 100 /* Maximum number of files. */ #define MAXFILE 255 /* Maximum file name length. */ #define MAXLINE MAXFILE+1 /* MAXFILE plus newline. */ extern char *optarg; extern int optind; void escape(char *, char **); void waitstdin(void); int main(int argc, char *argv[]) { char file[30], *name, *froms[MAXFILES], *tmp, *tos[MAXFILES]; FILE *fp; int c, i, j, s, xflag; /* Allocate memory. */ for(i = 0; i < MAXFILES; i++) if(!(froms[i] = malloc(MAXFILE)) || !(tos[i] = malloc(MAXFILE))) err(1, "malloc"); if(!(tmp = malloc(MAXLINE*4))) err(1, "malloc"); sprintf(file, "/var/tmp/re.%d", getppid()); /* * The existence of the temporary file is only checked when there * is input to be read on standard in, as re(1) doesn't create * the file until it starts writing on standard out. */ if(waitstdin(), access(file, F_OK)){ fprintf(stderr, "%s: %s does not exist\n", argv[0], file); return 1; } /* Read command-line options. */ name = argv[0]; xflag = 0; while((c = getopt(argc, argv, "x")) != -1) switch(c){ case 'x': xflag = 1; break; default: goto usage; } argc -= optind; argv += optind; if(argc > 0){ usage: fprintf(stderr, "usage: %s [-x]\n", name); return 1; } if(!(fp = fopen(file, "r"))) err(1, "fopen"); /* Read original file names. */ for(i = 0; i < MAXFILES && fgets(tmp, MAXLINE, fp); i++){ tmp[strcspn(tmp, "\n")] = 0; strcpy(froms[i], tmp); } /* Read new file names. */ for(j = 0; j < MAXFILES && fgets(tmp, MAXLINE, stdin); j++){ tmp[strcspn(tmp, "\n")] = 0; strcpy(tos[j], tmp); } if(i != j){ fprintf(stderr, "%s: too %s lines\n", name, j > i ? "many" : "few"); return 1; } /* * The corresponding mv invocations are printed on standard out. * If the -x flag is given, they are executed too. */ for(i = 0; i < j; i++){ escape(froms[i], &tmp); printf("mv '%s'", tmp); escape(tos[i], &tmp); printf(" '%s'\n", tmp); if(xflag){ if(!fork()){ execl("/bin/mv", "mv", froms[i], tos[i], NULL); err(1, "execl"); } if(wait(&s), s){ fprintf(stderr, "/bin/mv exited with %d\n", WEXITSTATUS(s)); return 1; } } } unlink(file); fclose(fp); } void escape(char *str, char **res) { int i, j, offset; for(i = j = 0; str[i]; i++){ if(str[i] == '\''){ strcat(*res, "'\\''"); j += 4; } else (*res)[j++] = str[i]; } (*res)[j] = 0; } void waitstdin() { fd_set readfds; FD_ZERO(&readfds); FD_SET(0, &readfds); if(select(1, &readfds, NULL, NULL, NULL) == -1) err(1, "select"); }