summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2013-03-05 07:16:29 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2013-03-05 07:16:29 (GMT)
commitf142ee94c2fa3d5f8ec3686b2ced2e1f0b807def (patch) (side-by-side diff)
tree6a150aea4679db77420db91c26e6a93865abbe65
parenta75760ff7d9bedcb1377fc3441f5e38178da1d6a (diff)
downloadalck-f142ee94c2fa3d5f8ec3686b2ced2e1f0b807def.tar.gz
alck-f142ee94c2fa3d5f8ec3686b2ced2e1f0b807def.tar.bz2
Revamp as a standalone project. Remove unneeded dependencies.
* Makefile.am: Remove * Makefile: Restore from bc518485 * ckaliases.c: Rename to alck.c * ckaliases.h: Rename to alck.h * gram.y (emalloc, error) (syserror, parserror): New functions. (main): Use traditional getopt. * lex.l: Use slist instead of obstack. * slist.c: New file.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile13
-rw-r--r--Makefile.am23
-rw-r--r--alck.c (renamed from ckaliases.c)278
-rw-r--r--alck.h (renamed from ckaliases.h)54
-rw-r--r--gram.y115
-rw-r--r--lex.l65
-rw-r--r--slist.c97
7 files changed, 416 insertions, 229 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..00f7ea0
--- a/dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+CFLAGS=-ggdb
+alck: lex.yy.o y.tab.o alck.o slist.o
+ cc -ggdb -o $@ $^
+
+y.tab.c y.tab.h: gram.y
+ yacc -vtd gram.y
+
+lex.yy.c: lex.l
+ lex -d lex.l
+
+lex.yy.o: lex.yy.c y.tab.h
+
+clean:; rm -rf *.o ckaliases \ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index 12f531c..0000000
--- a/Makefile.am
+++ b/dev/null
@@ -1,23 +0,0 @@
-# This file is part of GSC
-# Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
-#
-# GSC 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, or (at your option)
-# any later version.
-#
-# GSC 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 GSC. If not, see <http://www.gnu.org/licenses/>.
-
-AM_YFLAGS=-vtd
-AM_LFLAGS=-d
-sbin_PROGRAMS=ckaliases
-noinst_HEADERS=gram.h
-ckaliases_SOURCES=gram.y lex.l ckaliases.c ckaliases.h
-LDADD=../lib/libgsc.a ../gnu/libgnu.a
-INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/gnu -I../gnu
diff --git a/ckaliases.c b/alck.c
index da0a5c1..f8a3d11 100644
--- a/ckaliases.c
+++ b/alck.c
@@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include "ckaliases.h"
+#include "alck.h"
#ifndef CHAR_BIT
# define CHAR_BIT 8
@@ -77,115 +77,31 @@ TC(unsigned *R, int n)
}
}
-
-void
-slist_add(SLIST **plist, char *str)
-{
- struct string_list *p = xmalloc(sizeof(*p));
- p->str = str;
- p->next = NULL;
-
- if (!*plist) {
- *plist = xmalloc(sizeof(**plist));
- (*plist)->head = NULL;
- }
-
- if ((*plist)->head == NULL) {
- (*plist)->head = p;
- (*plist)->count = 0;
- } else {
- (*plist)->tail->next = p;
- (*plist)->count++;
- }
- (*plist)->tail = p;
-}
-
-void
-slist_append(SLIST **pdst, SLIST *src)
-{
- struct string_list *tail;
-
- if (!*pdst) {
- *pdst = xmalloc(sizeof(**pdst));
- (*pdst)->head = NULL;
- (*pdst)->count = 0;
- }
-
- if ((*pdst)->head = NULL)
- (*pdst)->head = src->head;
-
- for (tail = src->tail; tail->next; tail = tail->next)
- ;
-
- (*pdst)->tail = tail;
- (*pdst)->count += src->count;
-}
-
-char *
-slist_member(SLIST *plist, char *name)
-{
- struct string_list *p;
-
- if (plist)
- for (p = plist->head; p; p = p->next)
- if (p->str && strcmp(p->str, name) == 0)
- return p->str;
- return NULL;
-}
-
-void
-slist_destroy(SLIST **plist)
-{
- struct string_list *p;
- if (!plist || !*plist)
- return;
- p = (*plist)->head;
- while (p) {
- struct string_list *next = p->next;
- free(p);
- p = next;
- }
- free(*plist);
- *plist = NULL;
-}
-
-
-typedef struct {
+struct alias {
+ struct alias *prev, *next;
char *name;
+ int num;
SLIST *exp;
-} ALIAS;
+};
-struct obstack alias_stk;
-unsigned alias_count;
-ALIAS *aliases;
+struct ali_list {
+ struct alias *head, *tail;
+ size_t count;
+};
-void
-regalias(char *name, SLIST *exp)
-{
- ALIAS a;
- a.name = name;
- a.exp = exp;
- obstack_grow(&alias_stk, &a, sizeof a);
- alias_count++;
-}
-
-void
-begin_aliases()
-{
- obstack_init(&alias_stk);
-}
+struct ali_list aliases;
static int
-alias_cmp(const void *a, const void *b)
+ali_cmp(struct alias *a, struct alias *b)
{
- return strcmp(((ALIAS *) a)->name, ((ALIAS *) b)->name);
+ return strcmp(a->name, b->name);
}
static int
-alias_cmp2(const void *a, const void *b)
+ali_cmp2(struct alias *a, struct alias *b)
{
- char *aname = ((ALIAS *) a)->name;
- char *bname = ((ALIAS *) b)->name;
+ char *aname = a->name;
+ char *bname = b->name;
int rc;
int alen;
int blen;
@@ -208,29 +124,148 @@ alias_cmp2(const void *a, const void *b)
}
void
+ali_insert(struct ali_list *lp,
+ struct alias *anchor,
+ struct alias *ent, int before)
+{
+ struct alias *p;
+
+ if (!anchor) {
+ ent->prev = NULL;
+ ent->next = lp->head;
+ if (lp->head)
+ lp->head->prev = ent;
+ else
+ lp->tail = ent;
+ lp->head = ent;
+ lp->count++;
+ return;
+ }
+
+ if (before) {
+ ali_insert(lp, anchor->prev, ent, 0);
+ return;
+ }
+
+ ent->prev = anchor;
+ if (p = anchor->next)
+ p->prev = ent;
+ else
+ lp->tail = ent;
+ ent->next = p;
+ anchor->next = ent;
+ lp->count++;
+}
+
+void
+ali_join(struct ali_list *a, struct ali_list *b)
+{
+ if (!b->head)
+ return;
+ b->head->prev = a->tail;
+ if (a->tail)
+ a->tail->next = b->head;
+ else
+ a->head = b->head;
+ a->tail = b->tail;
+}
+
+void
+ali_sort(struct ali_list *list, int (*cmp)(struct alias *, struct alias *))
+{
+ struct alias *cur, *middle;
+ struct ali_list high_list, low_list;
+ int rc;
+
+ if (!list->head)
+ return;
+ cur = list->head;
+ do {
+ cur = cur->next;
+ if (!cur)
+ return;
+ } while ((rc = cmp(list->head, cur)) == 0);
+
+ /* Select the lower of the two as the middle value */
+ middle = (rc > 0) ? cur : list->head;
+
+ /* Split into two sublists */
+ low_list.head = low_list.tail = NULL;
+ high_list.head = high_list.tail = NULL;
+
+ for (cur = list->head; cur; ) {
+ struct alias *next = cur->next;
+ cur->next = NULL;
+ if (cmp(middle, cur) < 0)
+ ali_insert(&high_list, high_list.tail, cur, 0);
+ else
+ ali_insert(&low_list, low_list.tail, cur, 0);
+ cur = next;
+ }
+
+ /* Sort both sublists recursively */
+ ali_sort(&low_list, cmp);
+ ali_sort(&high_list, cmp);
+
+ /* Join both lists in order */
+ ali_join(&low_list, &high_list);
+
+ /* Return the resulting list */
+ list->head = low_list.head;
+ list->tail = low_list.tail;
+}
+
+struct alias *
+ali_locate(struct ali_list *lp, int (*cmp)(struct alias *, struct alias *),
+ struct alias *data)
+{
+ struct alias *ep;
+
+ for (ep = lp->head; ep; ep = ep->next) {
+ if (cmp(ep, data) == 0)
+ return ep;
+ }
+ return NULL;
+}
+
+void
end_aliases()
{
int i;
- aliases = obstack_finish(&alias_stk);
- qsort(aliases, alias_count, sizeof aliases[0], alias_cmp);
- for (i = 1; i < alias_count; i++)
- if (alias_cmp(aliases + i - 1, aliases + i) == 0) {
- error(0, 0, "alias `%s' multiply defined", aliases[i].name);
+ struct alias *ali;
+
+ ali_sort(&aliases, ali_cmp);
+ if (!aliases.head)
+ return;
+ for (i = 0, ali = aliases.head; ali->next; ali = ali->next, i++) {
+ if (ali_cmp(ali, ali->next) == 0) {
+ error("alias `%s' multiply defined", ali->name);
error_count++;
}
+ ali->num = i;
+ }
}
+void
+regalias(char *name, SLIST *exp)
+{
+ struct alias *a = emalloc(sizeof(*a));
+ a->name = name;
+ a->exp = exp;
+ a->next = NULL;
+ ali_insert(&aliases, NULL, a, 0);
+}
int
find_alias(char *name)
{
- ALIAS a, *p;
+ struct alias a, *p;
if (!name)
return -1;
a.name = name;
- p = bsearch(&a, aliases, alias_count, sizeof aliases[0], alias_cmp2);
- return p ? p - aliases : -1;
+ p = ali_locate(&aliases, ali_cmp2, &a);
+ return p ? p->num : -1;
}
@@ -246,19 +281,18 @@ alias_bitisset(unsigned *r, unsigned rowsize, unsigned row, unsigned col)
return BITISSET(r + rowsize * row, col);
}
-
void
mark_connected(unsigned *r, unsigned size)
{
- int i;
+ struct alias *ali;
- for (i = 0; i < alias_count; i++) {
- if (aliases[i].exp) {
+ for (ali = aliases.head; ali; ali = ali->next) {
+ if (ali->exp) {
struct string_list *p;
- for (p = aliases[i].exp->head; p; p = p->next) {
+ for (p = ali->exp->head; p; p = p->next) {
int n = find_alias(p->str);
if (n >= 0)
- alias_setbit(r, size, i, n);
+ alias_setbit(r, size, ali->num, n);
}
}
}
@@ -267,11 +301,11 @@ mark_connected(unsigned *r, unsigned size)
void
check_circular_deps(unsigned *r, unsigned size)
{
- int i;
+ struct alias *ali;
- for (i = 0; i < alias_count; i++) {
- if (alias_bitisset(r, size, i, i)) {
- error(0, 0, "%s: circular dependency", aliases[i].name);
+ for (ali = aliases.head; ali; ali = ali->next) {
+ if (alias_bitisset(r, size, ali->num, ali->num)) {
+ error("%s: circular dependency", ali->name);
error_count++;
}
}
@@ -284,19 +318,19 @@ check_aliases()
unsigned *r;
/* Allocate matrix */
- size = (alias_count + BITS_PER_WORD - 1) / BITS_PER_WORD;
- r = xmalloc(alias_count * size * sizeof(*r));
- memset(r, 0, alias_count * size * sizeof(*r));
+ size = (aliases.count + BITS_PER_WORD - 1) / BITS_PER_WORD;
+ r = emalloc(aliases.count * size * sizeof(*r));
+ memset(r, 0, aliases.count * size * sizeof(*r));
/* First pass: mark directly connected entries */
mark_connected(r, size);
/* Compute transitive closure of the matrix r */
- TC(r, alias_count);
+ TC(r, aliases.count);
/* Third pass: check for circular deps */
check_circular_deps(r, size);
if (verbose)
- printf("%lu aliases\n", alias_count);
+ printf("%lu aliases\n", aliases.count);
}
diff --git a/ckaliases.h b/alck.h
index d3e053c..9af8db6 100644
--- a/ckaliases.h
+++ b/alck.h
@@ -14,14 +14,8 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
#include <stdio.h>
#include <stdlib.h>
-#define obstack_chunk_alloc malloc
-#define obstack_chunk_free free
-#include <obstack.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -30,42 +24,42 @@
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
-#include "getopt.h"
-#include "progname.h"
-#include "error.h"
-#include "xalloc.h"
extern char *file_name;
extern int line_num;
extern int error_count;
-void init_lex ();
-void lex_debug (int n);
-void openaliases (char *name);
-void openaliases_prefix (char *prefix, char *name);
+void *emalloc(size_t size);
+void error(const char *fmt, ...);
+void syserror(int ec, const char *fmt, ...);
+void parserror(const char *file, int line, const char *fmt, ...);
-struct string_list
-{
- struct string_list *next;
- char *str;
+void init_lex();
+void lex_debug(int n);
+void openaliases(char *name);
+void openaliases_prefix(char *prefix, char *name);
+
+struct string_list {
+ struct string_list *next;
+ char *str;
+ size_t len;
};
-typedef struct slist
-{
- struct string_list *head, *tail;
- int count;
+typedef struct slist {
+ struct string_list *head, *tail;
+ int count;
} SLIST;
-void slist_add (SLIST ** plist, char *str);
-void slist_append (SLIST ** pdst, SLIST * src);
-char *slist_member (SLIST * plist, char *name);
-void slist_destroy (SLIST ** plist);
+char *slist_add(SLIST **plist, char *str);
+char *slist_add_n(SLIST **plist, char *str, size_t n);
+void slist_append(SLIST **pdst, SLIST * src);
+char *slist_member(SLIST *plist, char *name);
+void slist_destroy(SLIST **plist);
-void read_include (SLIST ** plist, char *name);
+void read_include(SLIST **plist, char *name);
-void regalias (char *name, SLIST * exp);
-void begin_aliases (void);
-void end_aliases (void);
+void regalias(char *name, SLIST *exp);
+void end_aliases(void);
extern SLIST *cw_list;
extern int verbose;
diff --git a/gram.y b/gram.y
index 34d46e2..4da7cb2 100644
--- a/gram.y
+++ b/gram.y
@@ -15,8 +15,10 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include "ckaliases.h"
-
+#include "alck.h"
+#include <stdarg.h>
+
+char *program_name;
SLIST *cw_list; /* List of domain names pertaining to Sendmail 'w' class */
static int restricted; /* prohibit use of `special' aliases (pipes,
file redirections and includes */
@@ -111,9 +113,53 @@ string: IDENT
int
yyerror (char *s)
{
- error_at_line(0, 0, file_name, line_num, "%s", s);
+ parserror(file_name, line_num, "%s", s);
error_count++;
}
+
+void *
+emalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (!p) {
+ error("not enough memory");
+ exit(1);
+ }
+ return p;
+}
+
+void
+error(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", program_name);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+}
+
+void
+syserror(int ec, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", program_name);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ": %s\n", strerror(ec));
+ va_end(ap);
+}
+
+void
+parserror(const char *file, int line, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: %s:%d: ", program_name, file, line);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+}
void
@@ -122,36 +168,40 @@ usage()
printf("usage: ckaliases [OPTIONS] [FILES...]\n");
printf("OPTIONS and FILES may be interspered.\n");
printf("Valid options are:\n");
- printf(" -d,--debug=SPEC Set debug level. SPEC consists of the following\n");
+ printf(" -d SPEC Set debug level. SPEC consists of the following\n");
printf(" letters:\n");
printf(" y enable parser debugging\n");
printf(" l enable lexical analizer debugging\n");
printf(" Upper-case variants are also accepted. Prepending\n");
printf(" a letter with '-' reverts its sense\n");
- printf(" -f, --files-from=FILE\n");
- printf(" Read names of alias files from FILE\n");
- printf(" -h, --help Display this help list\n");
- printf(" -r, --restrict Restrict alias file syntax to aliases only (i.e.\n");
+ printf(" -f FILE Read names of alias files from FILE\n");
+ printf(" -h Display this help list\n");
+ printf(" -r Restrict alias file syntax to aliases only (i.e.\n");
printf(" prohibit use of pipes and file redirections\n");
- printf(" -u, --unrestrict Revert the effect of the previous -r option\n");
- printf(" -v, --verbose Verbose mode\n");
- printf(" -V, --version print program version and exit\n");
+ printf(" -u Revert the effect of the previous -r option\n");
+ printf(" -v Verbose mode\n");
+ printf(" -V print program version and exit\n");
printf(" -w FILE Read contents of Sendmail `w' class from the given\n");
printf(" file.\n");
printf("\n");
- printf("Report bugs to <%s>\n", PACKAGE_BUGREPORT);
+ printf("Report bugs to <%s>\n", "gray@gnu.org");
}
-struct option options[] = {
- { "debug", required_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, 'V' },
- { "restrict", no_argument, NULL, 'r' },
- { "unrestrict", no_argument, NULL, 'u' },
- { "verbose", no_argument, NULL, 'v' },
- { "files-from", required_argument, NULL, 'f' },
- { NULL }
-};
+static char license[] = "\
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
+This is free software: you are free to change and redistribute it.\n\
+There is NO WARRANTY, to the extent permitted by law.\n";
+
+#define VERSION "2.0"
+
+void
+version()
+{
+ printf("alck %s\n", VERSION);
+ printf("Copyright (C) 2005, 2007, 2013 Sergey Poznyakoff\n");
+ printf("%s\n", license);
+ exit(0);
+}
int
main(int argc, char **argv)
@@ -164,11 +214,9 @@ main(int argc, char **argv)
SLIST *file_list; /* List of files to be read */
struct string_list *s;
- begin_aliases();
- init_lex ();
+ init_lex();
program_name = argv[0];
- while ((c = getopt_long(argc, argv, "-d:f:hp:ruvw:",
- options, NULL)) != EOF) {
+ while ((c = getopt(argc, argv, "-d:f:hp:ruVvw:")) != EOF) {
switch (c) {
case 1:
if (!cw_list)
@@ -198,7 +246,8 @@ main(int argc, char **argv)
break;
default:
- error(1, 0, "%s: unknown debug option %c", argv[0]);
+ error("%s: unknown debug option %c",
+ argv[0], c);
}
}
break;
@@ -235,12 +284,12 @@ main(int argc, char **argv)
break;
case 'V':
- gsc_version ("ckaliases");
+ version();
exit (0);
case 'w':
if (file_count)
- error(1, 0, "-w must be used before first non-option argument");
+ error("-w must be used before first non-option argument");
cwfile = optarg;
break;
@@ -260,9 +309,11 @@ main(int argc, char **argv)
file_count++;
}
- if (!file_count)
- error(1, 0, "no files specified");
-
+ if (!file_count) {
+ error("no files specified");
+ exit(1);
+ }
+
if (verbose)
printf("%d files\n", file_count);
end_aliases();
diff --git a/lex.l b/lex.l
index c71d4b9..85bd53f 100644
--- a/lex.l
+++ b/lex.l
@@ -15,15 +15,15 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include "ckaliases.h"
-#include "gram.h"
+#include "alck.h"
+#include "y.tab.h"
static void line_begin (void);
static void line_add (char *text, size_t len);
static void line_add_unescape (char *text, size_t len);
static void line_finish (void);
-struct obstack string_stk;
+static SLIST *slist;
char *file_name;
int line_num;
@@ -86,6 +86,8 @@ int
yywrap()
{
fclose(yyin);
+ free(file_name);
+ file_name = NULL;
return 1;
}
@@ -106,37 +108,52 @@ unescape_char(int c)
void
line_add(char *text, size_t len)
{
- obstack_grow(&string_stk, text, len);
+ slist_add_n(&slist, text, len);
}
void
line_add_unescape(char *text, size_t len)
{
char c;
- obstack_grow(&string_stk, text, len - 2);
- c = unescape_char(text[len - 1]);
- obstack_1grow(&string_stk, c);
+ char *p;
+
+ p = slist_add_n(&slist, text, len);
+ p[len - 1] = unescape_char(text[len - 1]);
}
void
line_begin()
{
+ slist_destroy(&slist);
}
void
-line_finish ()
+line_finish()
{
- obstack_1grow(&string_stk, 0);
- yylval.string = obstack_finish(&string_stk);
+ size_t len = 0;
+ struct string_list *sp;
+ char *p;
+
+ for (sp = slist->head; sp; sp = sp->next)
+ len += sp->len;
+ yylval.string = emalloc(len + 1);
+ p = yylval.string;
+ for (sp = slist->head; sp; sp = sp->next) {
+ memcpy(p, sp->str, sp->len);
+ p += sp->len;
+ }
+ *p = 0;
}
void
openaliases(char *name)
{
- yyin = fopen (name, "r");
- if (!yyin)
- error(1, errno, "cannot open file `%s'", name);
- file_name = name;
+ yyin = fopen(name, "r");
+ if (!yyin) {
+ syserror(errno, "cannot open file `%s'", name);
+ exit(1);
+ }
+ file_name = strdup(name);
line_num = 0;
}
@@ -146,8 +163,10 @@ openaliases_prefix(char *prefix, char *name)
char *fullname = NULL;
struct stat st;
- if (stat(prefix, &st))
- error(1, errno, "cannot stat `%s'", prefix);
+ if (stat(prefix, &st)) {
+ syserror(errno, "cannot stat `%s'", prefix);
+ exit(1);
+ }
if (!S_ISDIR(st.st_mode)) {
char *p = strrchr(prefix, '/');
@@ -156,7 +175,10 @@ openaliases_prefix(char *prefix, char *name)
else
prefix = ".";
}
- asprintf(&fullname, "%s/%s", prefix, name);
+ fullname = emalloc(strlen(prefix) + strlen(name) + 2);
+ strcpy(fullname, prefix);
+ strcat(fullname, "/");
+ strcat(fullname, name);
openaliases(fullname);
free(fullname);
}
@@ -164,7 +186,6 @@ openaliases_prefix(char *prefix, char *name)
void
init_lex()
{
- obstack_init(&string_stk);
yy_flex_debug = 0;
}
@@ -182,9 +203,9 @@ read_include(SLIST **plist, char *name)
FILE *fp = fopen(name, "r");
if (!fp) {
- error_at_line(0, 0, file_name, line_num,
- "cannot open include file `%s': %s",
- name, strerror(errno));
+ parserror(file_name, line_num,
+ "cannot open include file `%s': %s",
+ name, strerror(errno));
error_count++;
return;
}
@@ -200,7 +221,7 @@ read_include(SLIST **plist, char *name)
;
q[1] = 0;
if (*p)
- slist_add(plist, strdup(p));
+ slist_add(plist, p);
}
fclose(fp);
}
diff --git a/slist.c b/slist.c
new file mode 100644
index 0000000..3742aa5
--- a/dev/null
+++ b/slist.c
@@ -0,0 +1,97 @@
+/* ckaliases - verify syntax of sendmail-style alias files
+ Copyright (C) 2005, 2007, 2013 Sergey Poznyakoff
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#include "alck.h"
+
+char *
+slist_add_n(SLIST **plist, char *str, size_t n)
+{
+ struct string_list *p = emalloc(sizeof(*p));
+ p->str = emalloc(n);
+ memcpy(p->str, str, n);
+ p->len = n;
+ p->next = NULL;
+
+ if (!*plist) {
+ *plist = emalloc(sizeof(**plist));
+ (*plist)->head = NULL;
+ }
+
+ if ((*plist)->head == NULL) {
+ (*plist)->head = p;
+ (*plist)->count = 0;
+ } else {
+ (*plist)->tail->next = p;
+ (*plist)->count++;
+ }
+ (*plist)->tail = p;
+ return p->str;
+}
+
+char *
+slist_add(SLIST **plist, char *str)
+{
+ return slist_add_n(plist, str, strlen(str) + 1);
+}
+
+void
+slist_append(SLIST **pdst, SLIST *src)
+{
+ struct string_list *tail;
+
+ if (!*pdst) {
+ *pdst = emalloc(sizeof(**pdst));
+ (*pdst)->head = NULL;
+ (*pdst)->count = 0;
+ }
+
+ if ((*pdst)->head = NULL)
+ (*pdst)->head = src->head;
+
+ for (tail = src->tail; tail->next; tail = tail->next)
+ ;
+
+ (*pdst)->tail = tail;
+ (*pdst)->count += src->count;
+}
+
+char *
+slist_member(SLIST *plist, char *name)
+{
+ struct string_list *p;
+
+ if (plist)
+ for (p = plist->head; p; p = p->next)
+ if (p->str && strcmp(p->str, name) == 0)
+ return p->str;
+ return NULL;
+}
+
+void
+slist_destroy(SLIST **plist)
+{
+ struct string_list *p;
+ if (!plist || !*plist)
+ return;
+ p = (*plist)->head;
+ while (p) {
+ struct string_list *next = p->next;
+ free(p);
+ p = next;
+ }
+ free(*plist);
+ *plist = NULL;
+}

Return to:

Send suggestions and report system problems to the System administrator.