From bac8396cc90f34d617b583831e7a5902146b56b9 Mon Sep 17 00:00:00 2001 From: sobomax Date: Tue, 14 May 2002 21:42:37 +0000 Subject: - Make use of DEPOROGINs (if there are any) when installing package; - fix few bogosities here and there; - move some common routines into the library. MFC after: 2 weeks --- usr.sbin/pkg_install/add/perform.c | 102 ++++++++++++++++-------- usr.sbin/pkg_install/create/pl.c | 3 + usr.sbin/pkg_install/delete/perform.c | 56 +++++++++---- usr.sbin/pkg_install/info/perform.c | 80 +++++-------------- usr.sbin/pkg_install/lib/deps.c | 15 ++-- usr.sbin/pkg_install/lib/lib.h | 2 + usr.sbin/pkg_install/lib/match.c | 146 ++++++++++++++++++++++++++++++---- 7 files changed, 267 insertions(+), 137 deletions(-) (limited to 'usr.sbin') diff --git a/usr.sbin/pkg_install/add/perform.c b/usr.sbin/pkg_install/add/perform.c index 8b025d3..d707ec6 100644 --- a/usr.sbin/pkg_install/add/perform.c +++ b/usr.sbin/pkg_install/add/perform.c @@ -230,24 +230,39 @@ pkg_do(char *pkg) } setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1); - /* Protect against old packages with bogus @name fields */ - (const char *)PkgName = (p = find_plist(&Plist, PLIST_NAME)) ? p->name : "anonymous"; + /* Protect against old packages with bogus @name and origin fields */ + if (Plist.name == NULL) + Plist.name = "anonymous"; + if (Plist.origin == NULL) + Plist.origin = "anonymous/anonymous"; - /* See if we're already registered */ - sprintf(LogDir, "%s/%s", LOG_DIR, PkgName); - if (isdir(LogDir) && !Force) { - warnx("package '%s' already recorded as installed", PkgName); + /* + * See if we're already registered either with the same name (the same + * version) or some other version with the same origin. + */ + if ((isinstalledpkg(Plist.name) || + matchbyorigin(Plist.origin, NULL) != NULL) && !Force) { + warnx("package '%s' or its older version already installed", + Plist.name); code = 1; goto success; /* close enough for government work */ } /* Now check the packing list for dependencies */ for (p = Plist.head; p ; p = p->next) { + char *deporigin; + if (p->type != PLIST_PKGDEP) continue; - if (Verbose) - printf("Package '%s' depends on '%s'.\n", PkgName, p->name); - if (vsystem("pkg_info -e %s", p->name)) { + deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL; + if (Verbose) { + printf("Package '%s' depends on '%s'", Plist.name, p->name); + if (deporigin != NULL) + printf(" with '%s' origin", deporigin); + printf(".\n"); + } + if (!isinstalledpkg(p->name) && + !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) { char path[FILENAME_MAX], *cp = NULL; if (!Fake) { @@ -316,8 +331,8 @@ pkg_do(char *pkg) if (fexists(REQUIRE_FNAME)) { vsystem("chmod +x %s", REQUIRE_FNAME); /* be sure */ if (Verbose) - printf("Running requirements file first for %s..\n", PkgName); - if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, PkgName)) { + printf("Running requirements file first for %s..\n", Plist.name); + if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, Plist.name)) { warnx("package %s fails requirements %s", pkg_fullname, Force ? "installing anyway" : "- not installed"); if (!Force) { @@ -349,8 +364,8 @@ pkg_do(char *pkg) if (!NoInstall && fexists(pre_script)) { vsystem("chmod +x %s", pre_script); /* make sure */ if (Verbose) - printf("Running pre-install for %s..\n", PkgName); - if (!Fake && vsystem("./%s %s %s", pre_script, PkgName, pre_arg)) { + printf("Running pre-install for %s..\n", Plist.name); + if (!Fake && vsystem("./%s %s %s", pre_script, Plist.name, pre_arg)) { warnx("install script returned error status"); unlink(pre_script); code = 1; @@ -364,7 +379,7 @@ pkg_do(char *pkg) if (!Fake && fexists(MTREE_FNAME)) { if (Verbose) - printf("Running mtree for %s..\n", PkgName); + printf("Running mtree for %s..\n", Plist.name); p = find_plist(&Plist, PLIST_CWD); if (Verbose) printf("mtree -U -f %s -d -e -p %s >%s\n", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL); @@ -378,8 +393,8 @@ pkg_do(char *pkg) if (!NoInstall && fexists(post_script)) { vsystem("chmod +x %s", post_script); /* make sure */ if (Verbose) - printf("Running post-install for %s..\n", PkgName); - if (!Fake && vsystem("./%s %s %s", post_script, PkgName, post_arg)) { + printf("Running post-install for %s..\n", Plist.name); + if (!Fake && vsystem("./%s %s %s", post_script, Plist.name, post_arg)) { warnx("install script returned error status"); unlink(post_script); code = 1; @@ -394,12 +409,7 @@ pkg_do(char *pkg) if (getuid() != 0) warnx("not running as root - trying to record install anyway"); - if (!PkgName) { - warnx("no package name! can't record package, sorry"); - code = 1; - goto success; /* well, partial anyway */ - } - sprintf(LogDir, "%s/%s", LOG_DIR, PkgName); + sprintf(LogDir, "%s/%s", LOG_DIR, Plist.name); zapLogDir = 1; if (Verbose) printf("Attempting to record package into %s..\n", LogDir); @@ -438,24 +448,46 @@ pkg_do(char *pkg) write_plist(&Plist, contfile); fclose(contfile); for (p = Plist.head; p ; p = p->next) { + char *deporigin, **depnames; + int i; + if (p->type != PLIST_PKGDEP) continue; - if (Verbose) - printf("Attempting to record dependency on package '%s'\n", p->name); - sprintf(contents, "%s/%s/%s", LOG_DIR, basename(p->name), - REQUIRED_BY_FNAME); - contfile = fopen(contents, "a"); - if (!contfile) - warnx("can't open dependency file '%s'!\n" - "dependency registration is incomplete", contents); - else { - fprintf(contfile, "%s\n", PkgName); - if (fclose(contfile) == EOF) - warnx("cannot properly close file %s", contents); + deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : + NULL; + if (Verbose) { + printf("Trying to record dependency on package '%s'", p->name); + if (deporigin != NULL) + printf(" with '%s' origin", deporigin); + printf(".\n"); + } + + depnames = (deporigin != NULL) ? matchbyorigin(deporigin, NULL) : + NULL; + if (depnames == NULL) { + depnames = alloca(sizeof(*depnames) * 2); + depnames[0] = p->name; + depnames[1] = NULL; + } + for (i = 0; depnames[i] != NULL; i++) { + sprintf(contents, "%s/%s/%s", LOG_DIR, depnames[i], + REQUIRED_BY_FNAME); + if (strcmp(p->name, depnames[i]) != 0) + warnx("warning: package '%s' requires '%s', but '%s' " + "is installed", Plist.name, p->name, depnames[i]); + contfile = fopen(contents, "a"); + if (!contfile) + warnx("can't open dependency file '%s'!\n" + "dependency registration is incomplete", contents); + else { + fprintf(contfile, "%s\n", Plist.name); + if (fclose(contfile) == EOF) + warnx("cannot properly close file %s", contents); + } } } if (Verbose) - printf("Package %s registered in %s\n", PkgName, LogDir); + printf("Package %s registered in %s\n", Plist.name, LogDir); } if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) { diff --git a/usr.sbin/pkg_install/create/pl.c b/usr.sbin/pkg_install/create/pl.c index 9970249..d8b3d7e 100644 --- a/usr.sbin/pkg_install/create/pl.c +++ b/usr.sbin/pkg_install/create/pl.c @@ -41,12 +41,15 @@ check_list(const char *home, Package *pkg) case PLIST_CWD: where = p->name; break; + case PLIST_IGNORE: p = p->next; break; + case PLIST_SRC: there = p->name; break; + case PLIST_FILE: cp = NULL; sprintf(name, "%s/%s", there ? there : where, p->name); diff --git a/usr.sbin/pkg_install/delete/perform.c b/usr.sbin/pkg_install/delete/perform.c index a4f8370..1102165 100644 --- a/usr.sbin/pkg_install/delete/perform.c +++ b/usr.sbin/pkg_install/delete/perform.c @@ -27,7 +27,7 @@ __FBSDID("$FreeBSD$"); static int pkg_do(char *); static void sanity_check(char *); -static void undepend(PackingList, char *); +static void undepend(char *, char *); static char LogDir[FILENAME_MAX]; @@ -46,8 +46,18 @@ pkg_perform(char **pkgs) return 1; /* Not reached */ - if (matched != NULL) - pkgs = matched; + /* + * Copy matched[] into pkgs[], because we'll need to use + * matchinstalled() later on. + */ + if (matched != NULL) { + pkgs = NULL; + for (i = 0; matched[i] != NULL; i++) { + pkgs = realloc(pkgs, sizeof(*pkgs) * (i + 2)); + pkgs[i] = strdup(matched[i]); + } + pkgs[i] = NULL; + } else switch (MatchType) { case MATCH_GLOB: break; @@ -111,9 +121,9 @@ static int pkg_do(char *pkg) { FILE *cfile; - char home[FILENAME_MAX]; + char *deporigin, **depnames, home[FILENAME_MAX]; PackingList p; - int len; + int i, len; /* support for separate pre/post install scripts */ int new_m = 0; char pre_script[FILENAME_MAX] = DEINSTALL_FNAME; @@ -131,9 +141,7 @@ pkg_do(char *pkg) if (Plist.head) free_plist(&Plist); - sprintf(LogDir, "%s/%s", LOG_DIR, pkg); - - if (!fexists(LogDir)) { + if (!isinstalledpkg(pkg)) { warnx("no such package '%s' installed", pkg); return 1; } @@ -143,6 +151,8 @@ pkg_do(char *pkg) errx(2, "%s: unable to get current working directory!", __func__); } + sprintf(LogDir, "%s/%s", LOG_DIR, pkg); + if (chdir(LogDir) == FAIL) { warnx("unable to change directory to %s! deinstall failed", LogDir); return 1; @@ -288,10 +298,25 @@ pkg_do(char *pkg) for (p = Plist.head; p ; p = p->next) { if (p->type != PLIST_PKGDEP) continue; - if (Verbose) - printf("Attempting to remove dependency on package '%s'\n", p->name); - if (!Fake) - undepend(p, pkg); + deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : + NULL; + if (Verbose) { + printf("Trying to remove dependency on package '%s'", p->name); + if (deporigin != NULL) + printf(" with '%s' origin", deporigin); + printf(".\n"); + } + if (!Fake) { + depnames = (deporigin != NULL) ? matchbyorigin(deporigin, NULL) : + NULL; + if (depnames == NULL) { + depnames = alloca(sizeof(*depnames) * 2); + depnames[0] = p->name; + depnames[1] = NULL; + } + for (i = 0; depnames[i] != NULL; i++) + undepend(depnames[i], pkg); + } } return 0; } @@ -314,7 +339,7 @@ cleanup(int sig) } static void -undepend(PackingList p, char *pkgname) +undepend(char *p, char *pkgname) { char fname[FILENAME_MAX], ftmp[FILENAME_MAX]; FILE *fpwr; @@ -323,10 +348,9 @@ undepend(PackingList p, char *pkgname) struct reqr_by_head *rb_list; - if (requiredby(p->name, &rb_list, Verbose, FALSE) <= 0) + if (requiredby(p, &rb_list, Verbose, FALSE) <= 0) return; - snprintf(fname, sizeof(fname), "%s/%s/%s", LOG_DIR, p->name, - REQUIRED_BY_FNAME); + snprintf(fname, sizeof(fname), "%s/%s/%s", LOG_DIR, p, REQUIRED_BY_FNAME); snprintf(ftmp, sizeof(ftmp), "%s.XXXXXX", fname); s = mkstemp(ftmp); if (s == -1) { diff --git a/usr.sbin/pkg_install/info/perform.c b/usr.sbin/pkg_install/info/perform.c index 538d2ae..e9581f1 100644 --- a/usr.sbin/pkg_install/info/perform.c +++ b/usr.sbin/pkg_install/info/perform.c @@ -27,34 +27,28 @@ __FBSDID("$FreeBSD$"); #include static int pkg_do(char *); -static int find_pkg(const char *, struct which_head *); +static int find_pkg(struct which_head *); static int cmp_path(const char *, const char *, const char *); static char *abspath(const char *); -static int find_pkgs_by_origin(const char *, const char *); +static int find_pkgs_by_origin(const char *); int pkg_perform(char **pkgs) { char **matched; - const char *tmp; int err_cnt = 0; int i, errcode; signal(SIGINT, cleanup); - tmp = LOG_DIR; - /* Overriding action? */ if (CheckPkg) { - char buf[FILENAME_MAX]; - - snprintf(buf, FILENAME_MAX, "%s/%s", tmp, CheckPkg); - return abs(access(buf, R_OK)); + return isinstalledpkg(CheckPkg) == TRUE ? 0 : 1; /* Not reached */ } else if (!TAILQ_EMPTY(whead)) { - return find_pkg(tmp, whead); + return find_pkg(whead); } else if (LookUpOrigin != NULL) { - return find_pkgs_by_origin(tmp, LookUpOrigin); + return find_pkgs_by_origin(LookUpOrigin); } if (MatchType != MATCH_EXACT) { @@ -145,11 +139,11 @@ pkg_do(char *pkg) } /* It's not an ininstalled package, try and find it among the installed */ else { - sprintf(log_dir, "%s/%s", LOG_DIR, pkg); - if (!fexists(log_dir)) { + if (!isinstalledpkg(pkg)) { warnx("can't find package '%s' installed or in a file!", pkg); return 1; } + sprintf(log_dir, "%s/%s", LOG_DIR, pkg); if (chdir(log_dir) == FAIL) { warnx("can't change directory to '%s'!", log_dir); return 1; @@ -316,11 +310,11 @@ cmp_path(const char *target, const char *current, const char *cwd) } /* - * Look through package dbs in db_dir and find which + * Look through package dbs in LOG_DIR and find which * packages installed the files in which_list. */ static int -find_pkg(const char *db_dir, struct which_head *which_list) +find_pkg(struct which_head *which_list) { char **installed; int errcode, i; @@ -365,7 +359,7 @@ find_pkg(const char *db_dir, struct which_head *which_list) char *cwd = NULL; char tmp[PATH_MAX]; - snprintf(tmp, PATH_MAX, "%s/%s/%s", db_dir, installed[i], + snprintf(tmp, PATH_MAX, "%s/%s/%s", LOG_DIR, installed[i], CONTENTS_FNAME); fp = fopen(tmp, "r"); if (fp == NULL) { @@ -417,65 +411,27 @@ find_pkg(const char *db_dir, struct which_head *which_list) } /* - * Look through package dbs in db_dir and find which + * Look through package dbs in LOG_DIR and find which * packages have the given origin. Don't use read_plist() * because this increases time necessary for lookup by 40 * times, as we don't really have to parse all plist to * get origin. */ static int -find_pkgs_by_origin(const char *db_dir, const char *origin) +find_pkgs_by_origin(const char *origin) { - char **installed; + char **matched; int errcode, i; - installed = matchinstalled(MATCH_ALL, NULL, &errcode); - if (installed == NULL) - return errcode; - if (!Quiet) printf("The following installed package(s) has %s origin:\n", origin); - for (i = 0; installed[i] != NULL; i++) { - FILE *fp; - char *cp, tmp[PATH_MAX]; - int cmd; - snprintf(tmp, PATH_MAX, "%s/%s", db_dir, installed[i]); - /* - * SPECIAL CASE: ignore empty dirs, since we can can see them - * during port installation. - */ - if (isemptydir(tmp)) - continue; - snprintf(tmp, PATH_MAX, "%s/%s", tmp, CONTENTS_FNAME); - fp = fopen(tmp, "r"); - if (fp == NULL) { - warn("%s", tmp); - return 1; - } + matched = matchbyorigin(origin, &errcode); + if (matched == NULL) + return errcode; - cmd = -1; - while (fgets(tmp, sizeof(tmp), fp)) { - int len = strlen(tmp); - - while (len && isspace(tmp[len - 1])) - tmp[--len] = '\0'; - if (!len) - continue; - cp = tmp; - if (tmp[0] != CMD_CHAR) - continue; - cmd = plist_cmd(tmp + 1, &cp); - if (cmd == PLIST_ORIGIN) { - if (strcmp(origin, cp) == 0) - puts(installed[i]); - break; - } - } - if (cmd != PLIST_ORIGIN) - warnx("package %s has no origin recorded", installed[i]); - fclose(fp); - } + for (i = 0; matched[i] != NULL; i++) + puts(matched[i]); return 0; } diff --git a/usr.sbin/pkg_install/lib/deps.c b/usr.sbin/pkg_install/lib/deps.c index cf366f0..4ebb2cf 100644 --- a/usr.sbin/pkg_install/lib/deps.c +++ b/usr.sbin/pkg_install/lib/deps.c @@ -84,7 +84,6 @@ int chkifdepends(const char *pkgname1, const char *pkgname2) { char *cp1, *cp2; - char pkgdir[FILENAME_MAX]; int errcode; struct reqr_by_entry *rb_entry; struct reqr_by_head *rb_list; @@ -98,8 +97,7 @@ chkifdepends(const char *pkgname1, const char *pkgname2) errcode = 0; /* Check that pkgname2 is actually installed */ - snprintf(pkgdir, sizeof(pkgdir), "%s/%s", LOG_DIR, pkgname2); - if (!isdir(pkgdir)) + if (!isinstalledpkg(pkgname2)) goto exit; errcode = requiredby(pkgname2, &rb_list, FALSE, TRUE); @@ -142,7 +140,7 @@ int requiredby(const char *pkgname, struct reqr_by_head **list, Boolean strict, Boolean filter) { FILE *fp; - char fbuf[FILENAME_MAX], fname[FILENAME_MAX], pkgdir[FILENAME_MAX]; + char fbuf[FILENAME_MAX], fname[FILENAME_MAX]; int retval; struct reqr_by_entry *rb_entry; static struct reqr_by_head rb_list = STAILQ_HEAD_INITIALIZER(rb_list); @@ -155,14 +153,14 @@ requiredby(const char *pkgname, struct reqr_by_head **list, Boolean strict, Bool free(rb_entry); } - snprintf(fname, sizeof(fname), "%s/%s", LOG_DIR, pkgname); - if (!isdir(fname)) { + if (!isinstalledpkg(pkgname)) { if (strict == TRUE) warnx("no such package '%s' installed", pkgname); return -1; } - snprintf(fname, sizeof(fname), "%s/%s", fname, REQUIRED_BY_FNAME); + snprintf(fname, sizeof(fname), "%s/%s/%s", LOG_DIR, pkgname, + REQUIRED_BY_FNAME); fp = fopen(fname, "r"); if (fp == NULL) { /* Probably pkgname doesn't have any packages that depend on it */ @@ -175,8 +173,7 @@ requiredby(const char *pkgname, struct reqr_by_head **list, Boolean strict, Bool while (fgets(fbuf, sizeof(fbuf), fp) != NULL) { if (fbuf[strlen(fbuf) - 1] == '\n') fbuf[strlen(fbuf) - 1] = '\0'; - snprintf(pkgdir, sizeof(pkgdir), "%s/%s", LOG_DIR, fbuf); - if (filter == TRUE && !isdir(pkgdir)) { + if (filter == TRUE && !isinstalledpkg(fbuf)) { if (strict == TRUE) warnx("package '%s' is recorded in the '%s' but isn't " "actually installed", fbuf, fname); diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h index 181c3a2..5a11712 100644 --- a/usr.sbin/pkg_install/lib/lib.h +++ b/usr.sbin/pkg_install/lib/lib.h @@ -193,6 +193,8 @@ int pkg_perform(char **); /* Query installed packages */ char **matchinstalled(match_t, char **, int *); +char **matchbyorigin(const char *, int *); +int isinstalledpkg(const char *name); /* Dependencies */ int sortdeps(char **); diff --git a/usr.sbin/pkg_install/lib/match.c b/usr.sbin/pkg_install/lib/match.c index 5671406..fd96f3f 100644 --- a/usr.sbin/pkg_install/lib/match.c +++ b/usr.sbin/pkg_install/lib/match.c @@ -38,6 +38,7 @@ struct store { }; static int rex_match(const char *, const char *); +struct store *storecreate(struct store *); static int storeappend(struct store *, const char *); static int fname_cmp(const FTSENT **, const FTSENT **); @@ -63,22 +64,12 @@ matchinstalled(match_t MatchType, char **patterns, int *retval) FTSENT *f; Boolean *lmatched; + store = storecreate(store); if (store == NULL) { - store = malloc(sizeof *store); - if (store == NULL) { - warnx("%s(): malloc() failed", __func__); - if (retval != NULL) - *retval = 1; - return NULL; - } - store->currlen = 0; - store->store = NULL; - } else - if (store->store != NULL) - /* Free previously allocated memory */ - for (i = 0; store->store[i] != NULL; i++) - free(store->store[i]); - store->used = 0; + if (retval != NULL) + *retval = 1; + return NULL; + } if (retval != NULL) *retval = 0; @@ -163,6 +154,101 @@ matchinstalled(match_t MatchType, char **patterns, int *retval) } /* + * Synopsis is similar to matchinstalled(), but use origin + * as a key for matching packages. + */ +char ** +matchbyorigin(const char *origin, int *retval) +{ + char **installed; + int i; + static struct store *store = NULL; + + store = storecreate(store); + if (store == NULL) { + if (retval != NULL) + *retval = 1; + return NULL; + } + + if (retval != NULL) + *retval = 0; + + installed = matchinstalled(MATCH_ALL, NULL, retval); + if (installed == NULL) + return NULL; + + for (i = 0; installed[i] != NULL; i++) { + FILE *fp; + char *cp, tmp[PATH_MAX]; + int cmd; + + snprintf(tmp, PATH_MAX, "%s/%s", LOG_DIR, installed[i]); + /* + * SPECIAL CASE: ignore empty dirs, since we can can see them + * during port installation. + */ + if (isemptydir(tmp)) + continue; + snprintf(tmp, PATH_MAX, "%s/%s", tmp, CONTENTS_FNAME); + fp = fopen(tmp, "r"); + if (fp == NULL) { + warn("%s", tmp); + if (retval != NULL) + *retval = 1; + return NULL; + } + + cmd = -1; + while (fgets(tmp, sizeof(tmp), fp)) { + int len = strlen(tmp); + + while (len && isspace(tmp[len - 1])) + tmp[--len] = '\0'; + if (!len) + continue; + cp = tmp; + if (tmp[0] != CMD_CHAR) + continue; + cmd = plist_cmd(tmp + 1, &cp); + if (cmd == PLIST_ORIGIN) { + if (strcmp(origin, cp) == 0) + storeappend(store, installed[i]); + break; + } + } + if (cmd != PLIST_ORIGIN) + warnx("package %s has no origin recorded", installed[i]); + fclose(fp); + } + + if (store->used == 0) + return NULL; + else + return store->store; +} + +/* + * Return TRUE if the specified package is installed, + * or FALSE otherwise. + */ +int +isinstalledpkg(const char *name) +{ + char buf[FILENAME_MAX]; + + snprintf(buf, sizeof(buf), "%s/%s", LOG_DIR, name); + if (!isdir(buf) || access(buf, R_OK) == FAIL) + return FALSE; + + snprintf(buf, sizeof(buf), "%s/%s", buf, CONTENTS_FNAME); + if (!isfile(buf) || access(buf, R_OK) == FAIL) + return FALSE; + + return TRUE; +} + +/* * Returns 1 if specified pkgname matches RE pattern. * Otherwise returns 0 if doesn't match or -1 if RE * engine reported an error (usually invalid syntax). @@ -194,6 +280,36 @@ rex_match(const char *pattern, const char *pkgname) return retval; } +/* + * Create an empty store, optionally deallocating + * any previously allocated space if store != NULL. + */ +struct store * +storecreate(struct store *store) +{ + int i; + + if (store == NULL) { + store = malloc(sizeof *store); + if (store == NULL) { + warnx("%s(): malloc() failed", __func__); + return NULL; + } + store->currlen = 0; + store->store = NULL; + } else + if (store->store != NULL) + /* Free previously allocated memory */ + for (i = 0; store->store[i] != NULL; i++) + free(store->store[i]); + store->used = 0; + + return store; +} + +/* + * Append specified element to the provided store. + */ static int storeappend(struct store *store, const char *item) { -- cgit v1.1