diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2006-09-24 16:16:59 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gnu.org> | 2008-01-09 16:12:13 +0100 |
commit | ac9a20b3fb800e002fea2a16ce4679777fddcbff (patch) | |
tree | bd3397ae23902506df02f260300e5ae8777c8d1e /sed | |
parent | 0177318fa612307ce2e7eb7557e54d335ffd08f3 (diff) | |
download | sed-ac9a20b3fb800e002fea2a16ce4679777fddcbff.tar.gz |
gnulibify and add ACL support
2006-09-24 Paolo Bonzini <bonzini@gnu.org>
* sed/execute.c: Support ACLs.
* lib/utils.c: Move...
* sed/utils.c: ... here, and remove xmalloc.
git-archimport-id: bonzini@gnu.org--2004b/sed--stable--4.1--patch-74
Diffstat (limited to 'sed')
-rw-r--r-- | sed/Makefile.am | 2 | ||||
-rw-r--r-- | sed/execute.c | 12 | ||||
-rw-r--r-- | sed/sed.c | 3 | ||||
-rw-r--r-- | sed/sed.h | 1 | ||||
-rw-r--r-- | sed/utils.c | 539 | ||||
-rw-r--r-- | sed/utils.h | 49 |
6 files changed, 600 insertions, 6 deletions
diff --git a/sed/Makefile.am b/sed/Makefile.am index e2b5b9d..2bad1bd 100644 --- a/sed/Makefile.am +++ b/sed/Makefile.am @@ -3,7 +3,7 @@ bin_PROGRAMS = sed localedir = $(datadir)/locale -sed_SOURCES = sed.c compile.c execute.c regexp.c fmt.c mbcs.c +sed_SOURCES = sed.c compile.c execute.c regexp.c fmt.c mbcs.c utils.c noinst_HEADERS = sed.h AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/intl \ diff --git a/sed/execute.c b/sed/execute.c index 582ceb0..0ca2ca5 100644 --- a/sed/execute.c +++ b/sed/execute.c @@ -70,6 +70,7 @@ extern int errno; #endif #include <sys/stat.h> +#include "stat-macros.h" /* Sed operates a line at a time. */ @@ -706,7 +707,7 @@ open_next_file(name, input) if (in_place_extension) { - int output_fd; + int input_fd, output_fd; char *tmpdir = ck_strdup(name), *p; struct stat st; @@ -721,7 +722,8 @@ open_next_file(name, input) if (isatty (fileno (input->fp))) panic(_("couldn't edit %s: is a terminal"), input->in_file_name); - fstat (fileno (input->fp), &st); + input_fd = fileno (input->fp); + fstat (input_fd, &st); if (!S_ISREG (st.st_mode)) panic(_("couldn't edit %s: not a regular file"), input->in_file_name); @@ -733,13 +735,13 @@ open_next_file(name, input) panic(_("couldn't open temporary file %s: %s"), input->out_file_name, strerror(errno)); output_fd = fileno (output_file.fp); -#ifdef HAVE_FCHMOD - fchmod (output_fd, st.st_mode); -#endif #ifdef HAVE_FCHOWN if (fchown (output_fd, st.st_uid, st.st_gid) == -1) fchown (output_fd, -1, st.st_gid); #endif + copy_acl (input->in_file_name, input_fd, + input->out_file_name, output_fd, + st.st_mode); } else output_file.fp = stdout; @@ -59,6 +59,8 @@ # define ATOI(x) strtoul(x, NULL, 0) #endif +char *program_name; + int extended_regexp_flags = 0; /* If set, fflush(stdout) on every line output. */ @@ -178,6 +180,7 @@ main(argc, argv) int return_code; const char *cols = getenv("COLS"); + program_name = argv[0]; initialize_main (&argc, &argv); #if HAVE_SETLOCALE /* Set locale according to user's wishes. */ @@ -25,6 +25,7 @@ #ifndef BOOTSTRAP #include <stdio.h> +#include "unlocked-io.h" #endif #include "utils.h" diff --git a/sed/utils.c b/sed/utils.c new file mode 100644 index 0000000..b4f0164 --- /dev/null +++ b/sed/utils.c @@ -0,0 +1,539 @@ +/* Functions from hack's utils library. + Copyright (C) 1989, 1990, 1991, 1998, 1999, 2003 + Free Software Foundation, Inc. + + 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 2, 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, write to the Free Software + Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include "config.h" + +#include <stdio.h> + +#include <errno.h> +#ifndef errno + extern int errno; +#endif + +#ifdef HAVE_STRINGS_H +# include <strings.h> +#else +# include <string.h> +#endif /* HAVE_STRINGS_H */ + +#ifdef HAVE_STDLIB_H +# include <stdlib.h> +#endif /* HAVE_STDLIB_H */ + +#include "utils.h" + +const char *myname; + +/* Store information about files opened with ck_fopen + so that error messages from ck_fread, ck_fwrite, etc. can print the + name of the file that had the error */ + +struct open_file + { + FILE *fp; + char *name; + struct open_file *link; + unsigned temp : 1; + }; + +static struct open_file *open_files = NULL; +static void do_ck_fclose P_((FILE *fp)); + +/* Print an error message and exit */ +#if !defined __STDC__ || !(__STDC__-0) +# include <varargs.h> +# define VSTART(l,a) va_start(l) +void +panic(str, va_alist) + char *str; + va_dcl +#else /*__STDC__*/ +# include <stdarg.h> +# define VSTART(l,a) va_start(l, a) +void +panic(const char *str, ...) +#endif /* __STDC__ */ +{ + va_list iggy; + + fprintf(stderr, "%s: ", myname); + VSTART(iggy, str); +#ifndef HAVE_VPRINTF +# ifndef HAVE_DOPRNT + fputs(str, stderr); /* not great, but perhaps better than nothing... */ +# else /* HAVE_DOPRNT */ + _doprnt(str, &iggy, stderr); +# endif /* HAVE_DOPRNT */ +#else /* HAVE_VFPRINTF */ + vfprintf(stderr, str, iggy); +#endif /* HAVE_VFPRINTF */ + va_end(iggy); + putc('\n', stderr); + + /* Unlink the temporary files. */ + while (open_files) + { + if (open_files->temp) + { + int fd = fileno (open_files->fp); + fclose (open_files->fp); + errno = 0; + unlink (open_files->name); + if (errno != 0) + fprintf (stderr, _("cannot remove %s: %s"), open_files->name, strerror (errno)); + } + + open_files = open_files->link; + } + + exit(4); +} + + +/* Internal routine to get a filename from open_files */ +static const char *utils_fp_name P_((FILE *fp)); +static const char * +utils_fp_name(fp) + FILE *fp; +{ + struct open_file *p; + + for (p=open_files; p; p=p->link) + if (p->fp == fp) + return p->name; + if (fp == stdin) + return "stdin"; + else if (fp == stdout) + return "stdout"; + else if (fp == stderr) + return "stderr"; + + return "<unknown>"; +} + +static void +register_open_file (fp, name, temp) + FILE *fp; + const char *name; + bool temp; +{ + struct open_file *p; + for (p=open_files; p; p=p->link) + { + if (fp == p->fp) + { + FREE(p->name); + break; + } + } + if (!p) + { + p = MALLOC(1, struct open_file); + p->link = open_files; + open_files = p; + } + p->name = ck_strdup(name); + p->fp = fp; + p->temp = false; +} + +/* Panic on failing fopen */ +FILE * +ck_fopen(name, mode, fail) + const char *name; + const char *mode; + bool fail; +{ + FILE *fp; + + fp = fopen (name, mode); + if (!fp) + { + if (fail) + panic(_("couldn't open file %s: %s"), name, strerror(errno)); + + return NULL; + } + + register_open_file (fp, name, false); + return fp; +} + +/* Panic on failing fdopen */ +FILE * +ck_fdopen(fd, name, mode, fail) + int fd; + const char *name; + const char *mode; + bool fail; +{ + FILE *fp; + struct open_file *p; + + fp = fdopen (fd, mode); + if (!fp) + { + if (fail) + panic(_("couldn't attach to %s: %s"), name, strerror(errno)); + + return NULL; + } + + register_open_file (fp, name, false); + return fp; +} + +FILE * +ck_mkstemp (p_filename, tmpdir, base) + char **p_filename; + char *base, *tmpdir; +{ + char *template; + FILE *fp; + int fd; + struct open_file *p; + + if (tmpdir == NULL) + tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + { + tmpdir = getenv("TMP"); + if (tmpdir == NULL) +#ifdef P_tmpdir + tmpdir = P_tmpdir; +#else + tmpdir = "/tmp"; +#endif + } + + template = xmalloc (strlen (tmpdir) + strlen (base) + 8); + sprintf (template, "%s/%sXXXXXX", tmpdir, base); + + fd = mkstemp (template); + if (fd == -1) + panic(_("couldn't open temporary file %s: %s"), template, strerror(errno)); + + *p_filename = template; + fp = fdopen (fd, "w"); + register_open_file (fp, template, true); + return fp; +} + +/* Panic on failing fwrite */ +void +ck_fwrite(ptr, size, nmemb, stream) + const VOID *ptr; + size_t size; + size_t nmemb; + FILE *stream; +{ + clearerr(stream); + if (size && fwrite(ptr, size, nmemb, stream) != nmemb) + panic(ngettext("couldn't write %d item to %s: %s", + "couldn't write %d items to %s: %s", nmemb), + nmemb, utils_fp_name(stream), strerror(errno)); +} + +/* Panic on failing fread */ +size_t +ck_fread(ptr, size, nmemb, stream) + VOID *ptr; + size_t size; + size_t nmemb; + FILE *stream; +{ + clearerr(stream); + if (size && (nmemb=fread(ptr, size, nmemb, stream)) <= 0 && ferror(stream)) + panic(_("read error on %s: %s"), utils_fp_name(stream), strerror(errno)); + + return nmemb; +} + +size_t +ck_getline(text, buflen, stream) + char **text; + size_t *buflen; + FILE *stream; +{ + int result; + if (!ferror (stream)) + result = getline (text, buflen, stream); + + if (ferror (stream)) + panic (_("read error on %s: %s"), utils_fp_name(stream), strerror(errno)); + + return result; +} + +/* Panic on failing fflush */ +void +ck_fflush(stream) + FILE *stream; +{ + clearerr(stream); + if (fflush(stream) == EOF && errno != EBADF) + panic("couldn't flush %s: %s", utils_fp_name(stream), strerror(errno)); +} + +/* Panic on failing fclose */ +void +ck_fclose(stream) + FILE *stream; +{ + struct open_file r; + struct open_file *prev; + struct open_file *cur; + + /* a NULL stream means to close all files */ + r.link = open_files; + prev = &r; + while ( (cur = prev->link) ) + { + if (!stream || stream == cur->fp) + { + do_ck_fclose (cur->fp); + prev->link = cur->link; + FREE(cur->name); + FREE(cur); + } + else + prev = cur; + } + + open_files = r.link; + + /* Also care about stdout, because if it is redirected the + last output operations might fail and it is important + to signal this as an error (perhaps to make). */ + if (!stream) + { + do_ck_fclose (stdout); + do_ck_fclose (stderr); + } +} + +/* Close a single file. */ +void +do_ck_fclose(fp) + FILE *fp; +{ + int fd; + ck_fflush(fp); + clearerr(fp); + + /* We want to execute both arms, so use | not ||. */ + if (fclose(fp) == EOF) + panic("couldn't close %s: %s", utils_fp_name(fp), strerror(errno)); +} + + +/* Panic on failing rename */ +void +ck_rename (from, to, unlink_if_fail) + const char *from, *to; + const char *unlink_if_fail; +{ + int rd = rename (from, to); + if (rd != -1) + return; + + if (unlink_if_fail) + { + int save_errno = errno; + errno = 0; + unlink (unlink_if_fail); + + /* Failure to remove the temporary file is more severe, so trigger it first. */ + if (errno != 0) + panic (_("cannot remove %s: %s"), unlink_if_fail, strerror (errno)); + + errno = save_errno; + } + + panic (_("cannot rename %s: %s"), from, strerror (errno)); +} + + + + +/* Panic on failing malloc */ +VOID * +ck_malloc(size) + size_t size; +{ + VOID *ret = calloc(1, size ? size : 1); + if (!ret) + panic("couldn't allocate memory"); + return ret; +} + +/* Panic on failing realloc */ +VOID * +ck_realloc(ptr, size) + VOID *ptr; + size_t size; +{ + VOID *ret; + + if (size == 0) + { + FREE(ptr); + return NULL; + } + if (!ptr) + return ck_malloc(size); + ret = realloc(ptr, size); + if (!ret) + panic("couldn't re-allocate memory"); + return ret; +} + +/* Return a malloc()'d copy of a string */ +char * +ck_strdup(str) + const char *str; +{ + char *ret = MALLOC(strlen(str)+1, char); + return strcpy(ret, str); +} + +/* Return a malloc()'d copy of a block of memory */ +VOID * +ck_memdup(buf, len) + const VOID *buf; + size_t len; +{ + VOID *ret = ck_malloc(len); + return memcpy(ret, buf, len); +} + +/* Release a malloc'd block of memory */ +void +ck_free(ptr) + VOID *ptr; +{ + if (ptr) + free(ptr); +} + + +/* Implement a variable sized buffer of `stuff'. We don't know what it is, +nor do we care, as long as it doesn't mind being aligned by malloc. */ + +struct buffer + { + size_t allocated; + size_t length; + char *b; + }; + +#define MIN_ALLOCATE 50 + +struct buffer * +init_buffer() +{ + struct buffer *b = MALLOC(1, struct buffer); + b->b = MALLOC(MIN_ALLOCATE, char); + b->allocated = MIN_ALLOCATE; + b->length = 0; + return b; +} + +char * +get_buffer(b) + struct buffer *b; +{ + return b->b; +} + +size_t +size_buffer(b) + struct buffer *b; +{ + return b->length; +} + +static void resize_buffer P_((struct buffer *b, size_t newlen)); +static void +resize_buffer(b, newlen) + struct buffer *b; + size_t newlen; +{ + char *try = NULL; + size_t alen = b->allocated; + + if (newlen <= alen) + return; + alen *= 2; + if (newlen < alen) + try = realloc(b->b, alen); /* Note: *not* the REALLOC() macro! */ + if (!try) + { + alen = newlen; + try = REALLOC(b->b, alen, char); + } + b->allocated = alen; + b->b = try; +} + +char * +add_buffer(b, p, n) + struct buffer *b; + const char *p; + size_t n; +{ + char *result; + if (b->allocated - b->length < n) + resize_buffer(b, b->length+n); + result = memcpy(b->b + b->length, p, n); + b->length += n; + return result; +} + +char * +add1_buffer(b, c) + struct buffer *b; + int c; +{ + /* This special case should be kept cheap; + * don't make it just a mere convenience + * wrapper for add_buffer() -- even "builtin" + * versions of memcpy(a, b, 1) can become + * expensive when called too often. + */ + if (c != EOF) + { + char *result; + if (b->allocated - b->length < 1) + resize_buffer(b, b->length+1); + result = b->b + b->length++; + *result = c; + return result; + } + + return NULL; +} + +void +free_buffer(b) + struct buffer *b; +{ + if (b) + FREE(b->b); + FREE(b); +} diff --git a/sed/utils.h b/sed/utils.h new file mode 100644 index 0000000..cef0f6d --- /dev/null +++ b/sed/utils.h @@ -0,0 +1,49 @@ +/* Functions from hack's utils library. + Copyright (C) 1989, 1990, 1991, 1998, 1999, 2003 + Free Software Foundation, Inc. + + 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 2, 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, write to the Free Software + Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include <stdio.h> + +#include "basicdefs.h" + +void panic P_((const char *str, ...)); + +FILE *ck_fopen P_((const char *name, const char *mode, bool fail)); +FILE *ck_fdopen P_((int fd, const char *name, const char *mode, bool fail)); +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)); +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)); + +VOID *ck_malloc P_((size_t size)); +VOID *xmalloc P_((size_t size)); +VOID *ck_realloc P_((VOID *ptr, size_t size)); +char *ck_strdup P_((const char *str)); +VOID *ck_memdup P_((const VOID *buf, size_t len)); +void ck_free P_((VOID *ptr)); + +struct buffer *init_buffer P_((void)); +char *get_buffer P_((struct buffer *b)); +size_t size_buffer P_((struct buffer *b)); +char *add_buffer P_((struct buffer *b, const char *p, size_t n)); +char *add1_buffer P_((struct buffer *b, int ch)); +void free_buffer P_((struct buffer *b)); + +extern const char *myname; |