aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2021-07-10 17:24:18 +0200
committerJohn Ankarström <john@ankarstrom.se>2021-07-10 17:24:18 +0200
commit0e73390efffbeb76ea3eb739767b1c04e1641051 (patch)
tree1fbc6c3cb7b2569cc61a9291bbdc86d6de5d8f8f
parent5a794bb1827d1bf603de08df25684a4d77096b20 (diff)
downloadre-name-0e73390efffbeb76ea3eb739767b1c04e1641051.tar.gz
name.c: Implement -x flag
-rw-r--r--name.c88
1 files changed, 78 insertions, 10 deletions
diff --git a/name.c b/name.c
index a53d7e0..26f6c8c 100644
--- a/name.c
+++ b/name.c
@@ -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;