subst/000075500000000000000000000000001226300114000122015ustar00rootroot00000000000000subst/.gitignore000064400000000000000000000000211226300114000141620ustar00rootroot00000000000000*~ *.d *.o subst subst/Makefile000064400000000000000000000020551226300114000136430ustar00rootroot00000000000000# # Copyright (C) 2002, 2010 Dmitry V. Levin # # Makefile for subst, sed-based in-place files editor. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # CPPFLAGS = -D_GNU_SOURCE CFLAGS = $(RPM_OPT_FLAGS) INSTALL = install -p DESTDIR = $(RPM_BUILD_ROOT) BINDIR = /usr/bin SRC = subst.c TARGET = subst .PHONY: all install clean all: $(TARGET) install: all $(INSTALL) -D -m755 $(TARGET) $(DESTDIR)$(BINDIR)/$(TARGET) clean: $(RM) $(TARGET) *.d *.o *~ core subst/subst.c000064400000000000000000000073231226300114000135120ustar00rootroot00000000000000/* Copyright (C) 2002, 2010 Dmitry V. Levin The sed-based in-place files editor, a wrapper around sed -i --follow-symlinks. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include static struct option const longopts[] = { {"preserve", no_argument, 0, 'p'}, {"help", no_argument, 0, 'h'}, {0, no_argument, 0, 0} }; static void __attribute__ ((__noreturn__)) usage(FILE * stream, int status) { fprintf(stream, "\ %s - the sed-based in-place files editor.\n\ Usage: %s [-p | --preserve] files...\n\ %s [-h | --help]\n\ \nReport bugs to http://bugs.altlinux.ru/\n", program_invocation_short_name, program_invocation_short_name, program_invocation_short_name); exit(status); } static int sed(const char *pattern, const char *fname) { pid_t pid = fork(); if (pid < 0) { error(EXIT_SUCCESS, errno, "fork"); return EXIT_FAILURE; } if (!pid) { /* Child */ const char *const args[] = { "subst: sed", "-i", "--follow-symlinks", "-e", pattern, "--", fname, NULL }; execvp("sed", (char *const *) args); error(EXIT_FAILURE, errno, "execvp: sed"); } else { /* Parent */ int status; if (TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)) != pid) { error(EXIT_SUCCESS, errno, "waitpid: %d", pid); return EXIT_FAILURE; } if (!WIFEXITED(status) || WEXITSTATUS(status)) return EXIT_FAILURE; } return EXIT_SUCCESS; } static int subst(const char *pattern, const char *fname) { struct stat st; if (stat(fname, &st) < 0) { error(EXIT_SUCCESS, errno, "stat: %s", fname); return EXIT_FAILURE; } if (sed(pattern, fname) != EXIT_SUCCESS) return EXIT_FAILURE; struct utimbuf utm = { st.st_atime, st.st_mtime }; if (utime(fname, &utm) < 0) error(EXIT_SUCCESS, errno, "utime: %s", fname); /* ignore possible error */ return EXIT_SUCCESS; } int main(int ac, char *const av[]) { int c; int preserve = 0; const char *pattern; while ((c = getopt_long(ac, av, "ph", longopts, 0)) != -1) switch (c) { case 'p': preserve = 1; break; case 'h': usage(stdout, EXIT_SUCCESS); default: usage(stderr, EXIT_FAILURE); } if (optind >= ac) { error(EXIT_SUCCESS, 0, "no pattern specified."); usage(stderr, EXIT_FAILURE); } pattern = av[optind++]; if (optind >= ac) { error(EXIT_SUCCESS, 0, "no files specified."); usage(stderr, EXIT_FAILURE); } if (!preserve) { size_t nargs = ac - optind; size_t args_size = nargs + 7; const char **args = calloc(args_size, sizeof(*args)); if (!args) error(EXIT_FAILURE, errno, "calloc"); args[0] = "subst: sed"; args[1] = "-i"; args[2] = "--follow-symlinks"; args[3] = "-e"; args[4] = pattern; args[5] = "--"; memcpy(args + 6, av + optind, nargs * sizeof(*args)); args[args_size - 1] = NULL; execvp("sed", (char *const *) args); error(EXIT_FAILURE, errno, "execvp: sed"); } while (optind < ac) if (subst(pattern, av[optind++]) != EXIT_SUCCESS) return EXIT_FAILURE; return EXIT_SUCCESS; }