diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2006-12-15 12:30:25 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gnu.org> | 2008-01-09 16:12:20 +0100 |
commit | ba68fb42b8db505a89da4987df5936997a3c226a (patch) | |
tree | 28c41aecc082a91b95312909851db53cb1bda464 /sed | |
parent | 2128ec657b3d6bb3378424d0ddda923cdf8e2713 (diff) | |
download | sed-ba68fb42b8db505a89da4987df5936997a3c226a.tar.gz |
--posix disables all extensions to regular expressions
2006-12-15 Paolo Bonzini <bonzini@gnu.org>
* sed/regexp.c: Disable all extensions on --posix.
git-archimport-id: bonzini@gnu.org--2004b/sed--stable--4.1--patch-84
Diffstat (limited to 'sed')
-rw-r--r-- | sed/execute.c | 13 | ||||
-rw-r--r-- | sed/regexp.c | 23 | ||||
-rw-r--r-- | sed/sed.c | 14 | ||||
-rw-r--r-- | sed/sed.h | 3 | ||||
-rw-r--r-- | sed/utils.c | 83 | ||||
-rw-r--r-- | sed/utils.h | 1 |
6 files changed, 127 insertions, 10 deletions
diff --git a/sed/execute.c b/sed/execute.c index 0ca2ca5..6b6632c 100644 --- a/sed/execute.c +++ b/sed/execute.c @@ -762,15 +762,22 @@ closedown(input) if (in_place_extension && output_file.fp != NULL) { + const char *target_name; ck_fclose (output_file.fp); + + if (follow_symlinks) + target_name = follow_symlink (input->in_file_name); + else + target_name = input->in_file_name; + if (strcmp(in_place_extension, "*") != 0) { - char *backup_file_name = get_backup_file_name(input->in_file_name); - ck_rename (input->in_file_name, backup_file_name, input->out_file_name); + char *backup_file_name = get_backup_file_name(target_name); + ck_rename (target_name, backup_file_name, input->out_file_name); free (backup_file_name); } - ck_rename (input->out_file_name, input->in_file_name, input->out_file_name); + ck_rename (input->out_file_name, target_name, input->out_file_name); free (input->out_file_name); } diff --git a/sed/regexp.c b/sed/regexp.c index 1297c5e..4daefe2 100644 --- a/sed/regexp.c +++ b/sed/regexp.c @@ -64,15 +64,24 @@ compile_regex_1 (new_regex, needed_sub) const char *error; int syntax = ((extended_regexp_flags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED - : RE_SYNTAX_POSIX_BASIC) - & ~RE_DOT_NOT_NULL; - - if (posixicity == POSIXLY_EXTENDED) - syntax &= ~RE_UNMATCHED_RIGHT_PAREN_ORD; - else - syntax |= RE_UNMATCHED_RIGHT_PAREN_ORD; + : RE_SYNTAX_POSIX_BASIC); + syntax &= ~RE_DOT_NOT_NULL; syntax |= RE_NO_POSIX_BACKTRACKING; + + switch (posixicity) + { + case POSIXLY_EXTENDED: + syntax &= ~RE_UNMATCHED_RIGHT_PAREN_ORD; + break; + case POSIXLY_CORRECT: + syntax |= RE_UNMATCHED_RIGHT_PAREN_ORD; + break; + case POSIXLY_BASIC: + syntax |= RE_UNMATCHED_RIGHT_PAREN_ORD | RE_LIMITED_OPS | RE_NO_GNU_OPS; + break; + } + #ifdef RE_ICASE syntax |= (new_regex->flags & REG_ICASE) ? RE_ICASE : 0; #endif @@ -72,6 +72,9 @@ bool no_default_output = false; /* If set, reset line counts on every new file. */ bool separate_files = false; +/* If set, follow symlinks when processing in place */ +bool follow_symlinks = false; + /* How do we edit files in-place? (we don't if NULL) */ char *in_place_extension = NULL; @@ -110,6 +113,10 @@ Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n\ add the script to the commands to be executed\n")); fprintf(out, _(" -f script-file, --file=script-file\n\ add the contents of script-file to the commands to be executed\n")); +#ifdef ENABLE_FOLLOW_SYMLINKS + fprintf(out, _(" --follow-symlinks\n\ + follow symlinks when processing in place\n")); +#endif fprintf(out, _(" -i[SUFFIX], --in-place[=SUFFIX]\n\ edit files in place (makes backup if extension supplied)\n")); #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS) || defined(__EMX__) @@ -173,6 +180,9 @@ main(argc, argv) {"unbuffered", 0, NULL, 'u'}, {"version", 0, NULL, 'v'}, {"help", 0, NULL, 'h'}, +#ifdef ENABLE_FOLLOW_SYMLINKS + {"follow-symlinks", 0, NULL, 'F'}, +#endif {NULL, 0, NULL, 0} }; @@ -226,6 +236,10 @@ main(argc, argv) the_program = compile_file(the_program, optarg); break; + case 'F': + follow_symlinks = true; + break; + case 'i': separate_files = true; if (optarg == NULL) @@ -220,6 +220,9 @@ extern bool no_default_output; /* If set, reset line counts on every new file. */ extern bool separate_files; +/* If set, follow symlinks when invoked with -i option */ +extern bool follow_symlinks; + /* Do we need to be pedantically POSIX compliant? */ extern enum posixicity_types posixicity; diff --git a/sed/utils.c b/sed/utils.c index b4f0164..78bb2ff 100644 --- a/sed/utils.c +++ b/sed/utils.c @@ -35,6 +35,10 @@ # include <stdlib.h> #endif /* HAVE_STDLIB_H */ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + #include "utils.h" const char *myname; @@ -342,6 +346,85 @@ do_ck_fclose(fp) } +/* Follow symlink and panic if something fails. Return the ultimate + symlink target, stored in a temporary buffer that the caller should + not free. */ +const char * +follow_symlink(const char *fname) +{ +#ifdef ENABLE_FOLLOW_SYMLINKS + static char *buf1, *buf2; + static int buf_size; + + struct stat statbuf; + const char *buf = fname, *c; + int rc; + + if (buf_size == 0) + { + buf1 = ck_malloc (PATH_MAX + 1); + buf2 = ck_malloc (PATH_MAX + 1); + buf_size = PATH_MAX + 1; + } + + while ((rc = lstat (buf, &statbuf)) == 0 + && (statbuf.st_mode & S_IFLNK) == S_IFLNK) + { + if (buf == buf2) + { + strcpy (buf1, buf2); + buf = buf1; + } + + while ((rc = readlink (buf, buf2, buf_size)) == buf_size) + { + buf_size *= 2; + buf1 = ck_realloc (buf1, buf_size); + buf2 = ck_realloc (buf2, buf_size); + } + if (rc < 0) + panic (_("couldn't follow symlink %s: %s"), buf, strerror(errno)); + else + buf2 [rc] = '\0'; + + if (buf2[0] != '/' && (c = strrchr (buf, '/')) != NULL) + { + /* Need to handle relative paths with care. Reallocate buf1 and + buf2 to be big enough. */ + int len = c - buf + 1; + if (len + rc + 1 > buf_size) + { + buf_size = len + rc + 1; + buf1 = ck_realloc (buf1, buf_size); + buf2 = ck_realloc (buf2, buf_size); + } + + /* Always store the new path in buf1. */ + if (buf != buf1) + memcpy (buf1, buf, len); + + /* Tack the relative symlink at the end of buf1. */ + memcpy (buf1 + len, buf2, rc + 1); + buf = buf1; + } + else + { + /* Use buf2 as the buffer, it saves a strcpy if it is not pointing to + another link. It works for absolute symlinks, and as long as + symlinks do not leave the current directory. */ + buf = buf2; + } + } + + if (rc < 0) + panic (_("cannot stat %s: %s"), buf, strerror(errno)); + + return buf; +#else + return fname; +#endif /* ENABLE_FOLLOW_SYMLINKS */ +} + /* Panic on failing rename */ void ck_rename (from, to, unlink_if_fail) diff --git a/sed/utils.h b/sed/utils.h index cef0f6d..a80202d 100644 --- a/sed/utils.h +++ b/sed/utils.h @@ -28,6 +28,7 @@ void ck_fwrite P_((const VOID *ptr, size_t size, size_t nmemb, FILE *stream)); size_t ck_fread P_((VOID *ptr, size_t size, size_t nmemb, FILE *stream)); void ck_fflush P_((FILE *stream)); void ck_fclose P_((FILE *stream)); +const char *follow_symlink P_((const char *path)); size_t ck_getline P_((char **text, size_t *buflen, FILE *stream)); FILE * ck_mkstemp P_((char **p_filename, char *tmpdir, char *base)); void ck_rename P_((const char *from, const char *to, const char *unlink_if_fail)); |