vidir-c/main.c
2025-06-14 03:14:44 +05:00

146 lines
2.5 KiB
C

#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/wait.h>
struct file {
struct file *next;
char *name;
char *newname;
};
int main(int argc, char *argv[]) {
char *dirname = ".";
if (argc > 1) {
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
printf("Usage: %s [-h] [directory]\n", argv[0]);
exit(0);
}
dirname = argv[1];
}
DIR *dir = opendir(dirname);
if (!dir) {
perror("opendir");
exit(1);
}
int fd = dirfd(dir);
fchdir(fd);
struct file *begin = NULL;
struct file **cur = &begin;
while (1) {
errno = 0;
struct dirent *entry = readdir(dir);
if (!entry) {
if (errno != 0) {
perror("readdir");
exit(1);
}
break;
}
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
*cur = malloc(sizeof(struct file));
if (!*cur) {
perror("malloc");
exit(1);
}
(*cur)->name = strdup(entry->d_name);
(*cur)->newname = NULL;
cur = &(*cur)->next;
}
if (!begin) {
exit(0);
}
char template[] = "/tmp/vidir-c.XXXXXX";
if (!mkstemp(template)) {
perror("mkstemp");
exit(1);
}
FILE *tempfile = fopen(template, "w+");
if (!tempfile) {
perror("fopen");
exit(1);
}
int i = 1;
for (struct file *file = begin; file; file = file->next) {
fprintf(tempfile, "%d %s\n", i, file->name);
i ++;
}
fflush(tempfile);
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) {
char *editor = getenv("EDITOR");
if (!editor)
editor = "nano";
execlp(editor, editor, template, (char *) NULL);
perror("execlp");
exit(1);
}
wait(NULL);
fseek(tempfile, 0, SEEK_SET);
ssize_t nread;
char *line = NULL;
size_t n;
while ((nread = getline(&line, &n, tempfile)) != -1) {
line[nread - 1] = '\0';
char *endptr = NULL;
long num = strtol(line, &endptr, 10);
if (line == endptr)
continue;
if (*endptr != ' ')
continue;
char *filename = endptr + 1;
struct file *file = begin;
int i = 1;
while (file && i ++ < num)
file = file->next;
if (!file)
continue;
file->newname = strdup(filename);
}
for (struct file *file = begin; file; file = file->next) {
if (!file->newname) {
printf("Delete: %s\n", file->name);
remove(file->name);
continue;
}
if (strcmp(file->name, file->newname) != 0) {
printf("Rename: %s to %s\n", file->name, file->newname);
rename(file->name, file->newname);
continue;
}
}
unlink(template);
exit(0);
}