diff options
author | John Ankarström <john@ankarstrom.se> | 2021-07-10 17:24:18 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2021-07-10 17:24:18 +0200 |
commit | 0e73390efffbeb76ea3eb739767b1c04e1641051 (patch) | |
tree | 1fbc6c3cb7b2569cc61a9291bbdc86d6de5d8f8f | |
parent | 5a794bb1827d1bf603de08df25684a4d77096b20 (diff) | |
download | re-name-0e73390efffbeb76ea3eb739767b1c04e1641051.tar.gz |
name.c: Implement -x flag
-rw-r--r-- | name.c | 88 |
1 files changed, 78 insertions, 10 deletions
@@ -4,58 +4,126 @@ #include <unistd.h> #include <string.h> #include <sys/select.h> +#include <sys/wait.h> -#define MAXFILES 100 /* Maximum number of files. */ -#define MAXFILE 255 /* Maximum file name length. */ -#define MAXLINE MAXFILE+1 +#define MAXFILES 100 /* Maximum number of files. */ +#define MAXFILE 255 /* Maximum file name length. */ +#define MAXLINE MAXFILE+1 /* Extra room for newline. */ +extern char *optarg; +extern int optind; + +void escape(char *, char **); void waitstdin(void); int main(int argc, char *argv[]) { - char file[30]; - char from[MAXLINE], *froms[MAXFILES], to[MAXLINE], *tos[MAXFILES]; - FILE *fp; - int i, j; + char file[30], *name, from[MAXLINE], *froms[MAXFILES], + *tmp, to[MAXLINE], *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; fgets(from, MAXLINE, fp); i++) { from[strcspn(from, "\n")] = 0; strcpy(froms[i], from); - printf("from %s\n", from); } + /* Read new file names. */ for (j = 0; fgets(to, MAXLINE, stdin); j++) { to[strcspn(to, "\n")] = 0; strcpy(tos[j], to); - printf("to %s\n", to); } if (i != j) { fprintf(stderr, "%s: too %s lines\n", - argv[0], j > i ? "many" : "few"); + 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; |