summaryrefslogtreecommitdiffstats
path: root/src/pacman.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacman.c')
-rw-r--r--src/pacman.c336
1 files changed, 263 insertions, 73 deletions
diff --git a/src/pacman.c b/src/pacman.c
index 53c9d85c..11c8ef34 100644
--- a/src/pacman.c
+++ b/src/pacman.c
@@ -1,7 +1,7 @@
/*
* pacman.c
*
- * Copyright (c) 2002-2005 by Judd Vinet <jvinet@zeroflux.org>
+ * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* 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
@@ -53,51 +53,53 @@
*/
/* command line options */
-char *pmo_root = NULL;
-unsigned short pmo_op = PM_MAIN;
-unsigned short pmo_verbose = 0;
-unsigned short pmo_version = 0;
-unsigned short pmo_help = 0;
-unsigned short pmo_force = 0;
-unsigned short pmo_nodeps = 0;
-unsigned short pmo_upgrade = 0;
-unsigned short pmo_freshen = 0;
-unsigned short pmo_nosave = 0;
-unsigned short pmo_noconfirm = 0;
-unsigned short pmo_d_vertest = 0;
-unsigned short pmo_d_resolve = 0;
-unsigned short pmo_q_isfile = 0;
-unsigned short pmo_q_info = 0;
-unsigned short pmo_q_list = 0;
-unsigned short pmo_q_orphans = 0;
-unsigned short pmo_q_owns = 0;
-unsigned short pmo_q_search = 0;
-unsigned short pmo_r_cascade = 0;
-unsigned short pmo_r_dbonly = 0;
-unsigned short pmo_r_recurse = 0;
-unsigned short pmo_s_clean = 0;
+char *pmo_root = NULL;
+unsigned short pmo_op = PM_MAIN;
+unsigned short pmo_verbose = 0;
+unsigned short pmo_version = 0;
+unsigned short pmo_help = 0;
+unsigned short pmo_force = 0;
+unsigned short pmo_nodeps = 0;
+unsigned short pmo_upgrade = 0;
+unsigned short pmo_freshen = 0;
+unsigned short pmo_nosave = 0;
+unsigned short pmo_noconfirm = 0;
+unsigned short pmo_noprogressbar = 0;
+unsigned short pmo_d_vertest = 0;
+unsigned short pmo_d_resolve = 0;
+unsigned short pmo_q_isfile = 0;
+unsigned short pmo_q_info = 0;
+unsigned short pmo_q_list = 0;
+unsigned short pmo_q_foreign = 0;
+unsigned short pmo_q_orphans = 0;
+unsigned short pmo_q_owns = 0;
+unsigned short pmo_q_search = 0;
+unsigned short pmo_r_cascade = 0;
+unsigned short pmo_r_dbonly = 0;
+unsigned short pmo_r_recurse = 0;
+unsigned short pmo_s_clean = 0;
unsigned short pmo_s_downloadonly = 0;
-PMList *pmo_s_ignore = NULL;
-unsigned short pmo_s_info = 0;
-unsigned short pmo_s_printuris = 0;
-unsigned short pmo_s_search = 0;
-unsigned short pmo_s_sync = 0;
-unsigned short pmo_s_upgrade = 0;
-unsigned short pmo_group = 0;
+PMList *pmo_s_ignore = NULL;
+unsigned short pmo_s_info = 0;
+unsigned short pmo_s_printuris = 0;
+unsigned short pmo_s_search = 0;
+unsigned short pmo_s_sync = 0;
+unsigned short pmo_s_upgrade = 0;
+unsigned short pmo_group = 0;
/* configuration file options */
-char *pmo_dbpath = NULL;
-char *pmo_configfile = NULL;
-char *pmo_logfile = NULL;
-char *pmo_proxyhost = NULL;
-unsigned short pmo_proxyport = 0;
-char *pmo_xfercommand = NULL;
-PMList *pmo_noupgrade = NULL;
-PMList *pmo_noextract = NULL;
-PMList *pmo_ignorepkg = NULL;
-PMList *pmo_holdpkg = NULL;
-unsigned short pmo_chomp = 0;
-unsigned short pmo_usesyslog = 0;
-unsigned short pmo_nopassiveftp = 0;
+char *pmo_dbpath = NULL;
+char *pmo_configfile = NULL;
+char *pmo_logfile = NULL;
+char *pmo_proxyhost = NULL;
+unsigned short pmo_proxyport = 0;
+char *pmo_xfercommand = NULL;
+PMList *pmo_noupgrade = NULL;
+PMList *pmo_noextract = NULL;
+PMList *pmo_ignorepkg = NULL;
+PMList *pmo_holdpkg = NULL;
+unsigned short pmo_chomp = 0;
+unsigned short pmo_usesyslog = 0;
+unsigned short pmo_nopassiveftp = 0;
/* list of sync_t structs for sync locations */
@@ -256,8 +258,10 @@ int main(int argc, char *argv[])
pm_packages = db_loadpkgs(db_local);
/* the operation requires at least one target */
- if (list_count(pm_targets) == 0 && !(pmo_op == PM_QUERY || (pmo_op == PM_SYNC && (pmo_s_sync || pmo_s_upgrade || pmo_s_clean || pmo_group || pmo_q_list))))
+ if(list_count(pm_targets) == 0 && !(pmo_op == PM_QUERY || (pmo_op == PM_SYNC && (pmo_s_sync || pmo_s_upgrade || pmo_s_clean || pmo_group || pmo_q_list)))) {
+ fprintf(stderr, "error: no targets specified\n");
usage(pmo_op, (char*)basename(argv[0]));
+ }
/* start the requested operation */
switch(pmo_op) {
@@ -267,9 +271,15 @@ int main(int argc, char *argv[])
case PM_QUERY: ret = pacman_query(db_local, pm_targets); break;
case PM_SYNC: ret = pacman_sync(db_local, pm_targets); break;
case PM_DEPTEST: ret = pacman_deptest(db_local, pm_targets); break;
- case PM_MAIN: ret = 0; break;
- default: fprintf(stderr, "error: no operation specified (use -h for help)\n\n");
- ret = 1;
+ case PM_MAIN: /* fallthrough */
+ default:
+ ret = 0;
+ if(list_count(pm_targets) > 0) {
+ fprintf(stderr, "error: no operation specified\n");
+ usage(pmo_op, (char*)basename(argv[0]));
+ ret = 1;
+ }
+ break;
}
db_close(db_local);
cleanup(ret);
@@ -828,6 +838,36 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
}
if(!found) {
+ /* target was not found: check provides */
+ for(j = databases; !found && j; j = j->next) {
+ dbsync_t *dbs = (dbsync_t*)j->data;
+ PMList *p = whatprovides(dbs->db, targ);
+ if(p) {
+ /* we only take the first one in the list */
+ pkginfo_t *pkg = (pkginfo_t*)p->data;
+ if(treename == NULL ||
+ (treename && !strcmp(treename, dbs->sync->treename))) {
+ found = 1;
+ sync->dbs = dbs;
+ /* re-fetch the package record with dependency info */
+ sync->pkg = db_scan(sync->dbs->db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
+ if(sync->pkg == NULL) {
+ found = 0;
+ }
+ if(pmo_d_resolve) {
+ /* looks like we're being called from 'makepkg -s' so these are all deps */
+ sync->pkg->reason = REASON_DEPEND;
+ } else {
+ /* this package was explicitly requested */
+ sync->pkg->reason = REASON_EXPLICIT;
+ }
+ }
+ p->data = NULL;
+ FREELIST(p);
+ }
+ }
+ }
+ if(!found) {
if(treename == NULL) {
/* target not found: check if it's a group */
k = NULL;
@@ -1338,11 +1378,50 @@ int pacman_sync(pacdb_t *db, PMList *targets)
depmissing_t* miss = (depmissing_t*)j->data;
syncpkg_t *s = find_pkginsync(miss->depend.name, final);
if(s == NULL) {
- if(allgood) {
- fprintf(stderr, "error: this will break the following dependencies:\n");
+ int pfound = 0;
+ /* If miss->depend.name depends on something that miss->target and a
+ * package in final both provide, then it's okay... */
+ pkginfo_t *leavingp = db_scan(db, miss->target, INFRQ_DESC | INFRQ_DEPENDS);
+ pkginfo_t *conflictp = db_scan(db, miss->depend.name, INFRQ_DESC | INFRQ_DEPENDS);
+ if(!leavingp || !conflictp) {
+ fprintf(stderr, "error: something has gone horribly wrong\n");
allgood = 0;
+ goto sync_cleanup;
+ }
+ /* Look through the upset package's dependencies and try to match one up
+ * to a provisio from the package we want to remove */
+ for(k = conflictp->depends; k && !pfound; k = k->next) {
+ PMList *m;
+ for(m = leavingp->provides; m && !pfound; m = m->next) {
+ if(!strcmp(k->data, m->data)) {
+ /* Found a match -- now look through final for a package that
+ * provides the same thing. If none are found, then it truly
+ * is an unresolvable conflict. */
+ PMList *n, *o;
+ for(n = final; n && !pfound; n = n->next) {
+ syncpkg_t *sp = (syncpkg_t*)n->data;
+ for(o = sp->pkg->provides; o && !pfound; o = o->next) {
+ if(!strcmp(m->data, o->data)) {
+ /* found matching provisio -- we're good to go */
+ vprint("Found a matching provides (%s) in %s, conflict aborted\n",
+ (char*)o->data, sp->pkg->name);
+ pfound = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ FREEPKG(conflictp);
+ FREEPKG(leavingp);
+
+ if(!pfound) {
+ if(allgood) {
+ fprintf(stderr, "error: this will break the following dependencies:\n");
+ allgood = 0;
+ }
+ printf(" %s: is required by %s\n", miss->target, miss->depend.name);
}
- printf(" %s: is required by %s\n", miss->target, miss->depend.name);
}
}
FREELIST(i);
@@ -1401,7 +1480,6 @@ int pacman_sync(pacdb_t *db, PMList *targets)
allgood = !pacman_upgrade(db, files, dependonly);
}
/* propagate replaced packages' requiredby fields to their new owners */
- /* XXX: segfault */
if(allgood) {
for(i = final; i; i = i->next) {
syncpkg_t *sync = (syncpkg_t*)i->data;
@@ -1420,6 +1498,13 @@ int pacman_sync(pacdb_t *db, PMList *targets)
/* replace old's name with new's name in the requiredby's dependency list */
PMList *m;
pkginfo_t *depender = db_scan(db, k->data, INFRQ_DEPENDS);
+ if(depender == NULL) {
+ /* If the depending package no longer exists in the local db,
+ * then it must have ALSO conflicted with sync->pkg. If
+ * that's the case, then we don't have anything to propagate
+ * here. */
+ continue;
+ }
for(m = depender->depends; m; m = m->next) {
if(!strcmp(m->data, old->name)) {
FREE(m->data);
@@ -1866,17 +1951,21 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
if(nb) {
char *temp;
+ int fd;
char *md5_local, *md5_pkg;
- md5_local = MDFile(expath);
/* extract the package's version to a temporary file and md5 it */
temp = strdup("/tmp/pacman_XXXXXX");
- mkstemp(temp);
+ fd = mkstemp(temp);
if(tar_extract_file(tar, temp)) {
logaction(stderr, "could not extract %s: %s", pathname, strerror(errno));
errors++;
+ unlink(temp);
+ FREE(temp);
+ close(fd);
continue;
}
+ md5_local = MDFile(expath);
md5_pkg = MDFile(temp);
/* append the new md5 hash to it's respective entry in info->backup
* (it will be the new orginal)
@@ -1938,15 +2027,10 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
vprint(" action: installing new file\n");
installnew = 1;
} else {
- char newpath[PATH_MAX];
- vprint(" action: saving current file and installing new one\n");
+ vprint(" action: leaving file in place, installing new one as .pacnew\n");
+ strncat(expath, ".pacnew", PATH_MAX);
+ logaction(stderr, "warning: extracting %s%s as %s", pmo_root, pathname, expath);
installnew = 1;
- snprintf(newpath, PATH_MAX, "%s.pacsave", expath);
- if(rename(expath, newpath)) {
- logaction(stderr, "error: could not rename %s: %s", expath, strerror(errno));
- } else {
- logaction(stderr, "warning: %s saved as %s", expath, newpath);
- }
}
if(installnew) {
@@ -1963,6 +2047,7 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
FREE(md5_orig);
unlink(temp);
FREE(temp);
+ close(fd);
} else {
if(!notouch) {
/*vprint(" %s\n", expath);*/
@@ -2254,12 +2339,13 @@ int pacman_remove(pacdb_t *db, PMList *targets, PMList *skiplist)
info = (pkginfo_t*)targ->data;
if(!pmo_upgrade) {
- printf("removing %s... ", info->name);
- neednl = 1;
- fflush(stdout);
/* run the pre-remove scriptlet if it exists */
snprintf(pm_install, PATH_MAX, "%s%s/%s/%s-%s/install", pmo_root, pmo_dbpath, db->treename, info->name, info->version);
runscriptlet(pm_install, "pre_remove", info->version, NULL);
+
+ printf("removing %s... ", info->name);
+ neednl = 1;
+ fflush(stdout);
}
if(!pmo_r_dbonly) {
@@ -2404,8 +2490,33 @@ int pacman_query(pacdb_t *db, PMList *targets)
char *package = NULL;
char path[PATH_MAX+1];
pkginfo_t *info = NULL;
- PMList *targ, *lp, *q;
+ PMList *targ, *lp, *q, *databases = NULL;
int done = 0;
+ PMList *i, *j;
+
+ if(pmo_q_foreign)
+ {
+ /* open sync db(s) */
+ PMList *dbp;
+ for(dbp = pmc_syncs; dbp; dbp = dbp->next) {
+ pacdb_t *db_sync = NULL;
+ dbsync_t *dbs = NULL;
+ sync_t *sync = (sync_t*)dbp->data;
+
+ db_sync = db_open(pmo_root, pmo_dbpath, sync->treename);
+ if(db_sync == NULL) {
+ fprintf(stderr, "error: could not open sync database: %s\n", sync->treename);
+ fprintf(stderr, " have you used --refresh yet?\n");
+ return(1);
+ }
+ MALLOC(dbs, sizeof(dbsync_t));
+ dbs->sync = sync;
+ dbs->db = db_sync;
+ /* cache packages */
+ dbs->pkgcache = db_loadpkgs(db_sync);
+ databases = list_add(databases, dbs);
+ }
+ }
if(pmo_q_search) {
db_search(db, pm_packages, "local", targets);
@@ -2512,7 +2623,7 @@ int pacman_query(pacdb_t *db, PMList *targets)
/* no target */
for(lp = pm_packages; lp; lp = lp->next) {
pkginfo_t *tmpp = (pkginfo_t*)lp->data;
- if(pmo_q_list || pmo_q_orphans) {
+ if(pmo_q_list || pmo_q_orphans || pmo_q_foreign) {
info = db_scan(db, tmpp->name, INFRQ_ALL);
if(info == NULL) {
/* something weird happened */
@@ -2528,6 +2639,29 @@ int pacman_query(pacdb_t *db, PMList *targets)
printf("%s %s\n", tmpp->name, tmpp->version);
}
}
+ if(pmo_q_foreign) {
+ int match = 0;
+ for(i = databases; i; i = i->next) {
+ dbsync_t *dbs = (dbsync_t*)i->data;
+ for(j = dbs->pkgcache; j; j = j->next) {
+ pkginfo_t *pkg = (pkginfo_t*)j->data;
+ char *haystack;
+ char *needle;
+ haystack = strdup(pkg->name);
+ strtoupper(haystack);
+ needle = strdup(info->name);
+ strtoupper(needle);
+ if(strstr(haystack, needle)) {
+ match = 1;
+ }
+ FREE(haystack);
+ FREE(needle);
+ }
+ }
+ if(match==0) {
+ printf("%s %s\n", tmpp->name, tmpp->version);
+ }
+ }
FREEPKG(info);
} else {
printf("%s %s\n", tmpp->name, tmpp->version);
@@ -2592,6 +2726,33 @@ int pacman_query(pacdb_t *db, PMList *targets)
if(info->requiredby == NULL) {
printf("%s %s\n", info->name, info->version);
}
+ } else if(pmo_q_foreign) {
+ int match = 0;
+ info = db_scan(db, package, INFRQ_DESC | INFRQ_DEPENDS);
+ if(info == NULL) {
+ fprintf(stderr, "Package \"%s\" was not found.\n", package);
+ return(2);
+ }
+ for(i = databases; i; i = i->next) {
+ dbsync_t *dbs = (dbsync_t*)i->data;
+ for(j = dbs->pkgcache; j; j = j->next) {
+ pkginfo_t *pkg = (pkginfo_t*)j->data;
+ char *haystack;
+ char *needle;
+ haystack = strdup(pkg->name);
+ strtoupper(haystack);
+ needle = strdup(info->name);
+ strtoupper(needle);
+ if(strstr(haystack, needle)) {
+ match = 1;
+ }
+ FREE(haystack);
+ FREE(needle);
+ }
+ }
+ if(match==0) {
+ printf("%s %s\n", info->name, info->version);
+ }
} else {
info = db_scan(db, package, INFRQ_DESC);
if(info == NULL) {
@@ -2802,10 +2963,28 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l
return(1);
} else*/
if(miss->type == DEPEND) {
+ int provisio_match = 0;
syncpkg_t *sync = NULL;
MALLOC(sync, sizeof(syncpkg_t));
sync->replaces = NULL;
+ /* check if one of the packages in *list already provides this dependency */
+ for(j = list; j; j = j->next) {
+ syncpkg_t *sp = (syncpkg_t*)j->data;
+ if(sp == NULL) {
+ continue;
+ }
+ for(k = sp->pkg->provides; k; k = k->next) {
+ if(!strcmp(miss->depend.name, k->data)) {
+ vprint("resolvedeps: %s provides dependency %s\n", sp->pkg->name, miss->depend.name);
+ provisio_match = 1;
+ }
+ }
+ }
+ if(provisio_match) {
+ continue;
+ }
+
/* find the package in one of the repositories */
for(j = databases; !found && j; j = j->next) {
dbsync_t *dbs = (dbsync_t*)j->data;
@@ -2853,7 +3032,7 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l
FREE(sync);
continue;
}
- vprint("resolving %s\n", sync->pkg->name);
+ vprint("resolvedeps: resolving %s\n", sync->pkg->name);
found = 0;
for(j = trail; j; j = j->next) {
syncpkg_t *tmp = (syncpkg_t*)j->data;
@@ -2886,7 +3065,7 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l
if(resolvedeps(local, databases, sync, list, trail)) {
return(1);
}
- vprint("adding %s-%s\n", sync->pkg->name, sync->pkg->version);
+ vprint("resolvedeps: adding %s-%s\n", sync->pkg->name, sync->pkg->version);
list = list_add(list, sync);
} else {
fprintf(stderr, "error: cannot resolve dependencies for \"%s\"\n", miss->target);
@@ -2894,7 +3073,7 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l
}
} else {
/* cycle detected -- skip it */
- vprint("dependency cycle detected: %s\n", sync->pkg->name);
+ vprint("resolvedeps: dependency cycle detected: %s\n", sync->pkg->name);
FREEPKG(sync->pkg);
FREE(sync);
}
@@ -3014,11 +3193,15 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
/* CONFLICTS */
for(j = tp->conflicts; j; j = j->next) {
+ if(!strcmp(tp->name, j->data)) {
+ /* a package cannot conflict with itself -- that's just not nice */
+ continue;
+ }
/* check targets against database */
for(k = pm_packages; k; k = k->next) {
int conflict = 0;
pkginfo_t *dp = (pkginfo_t*)k->data;
- if(!strcmp(dp->name, tp->name)) {
+ if(!strcmp(tp->name, dp->name)) {
/* a package cannot conflict with itself -- that's just not nice */
continue;
}
@@ -3468,6 +3651,7 @@ int parseargs(int op, int argc, char **argv)
{"dbonly", no_argument, 0, 'k'},
{"list", no_argument, 0, 'l'},
{"nosave", no_argument, 0, 'n'},
+ {"foreign", no_argument, 0, 'm'},
{"owns", no_argument, 0, 'o'},
{"file", no_argument, 0, 'p'},
{"print-uris", no_argument, 0, 'p'},
@@ -3479,12 +3663,13 @@ int parseargs(int op, int argc, char **argv)
{"downloadonly", no_argument, 0, 'w'},
{"refresh", no_argument, 0, 'y'},
{"noconfirm", no_argument, 0, 1000},
+ {"noprogressbar", no_argument, 0, 1003},
{"config", required_argument, 0, 1001},
{"ignore", required_argument, 0, 1002},
{0, 0, 0, 0}
};
- while((opt = getopt_long(argc, argv, "ARUFQSTDYr:b:vkhscVfnoldepiuwyg", opts, &option_index))) {
+ while((opt = getopt_long(argc, argv, "ARUFQSTDYr:b:vkhscVfmnoldepiuwyg", opts, &option_index))) {
if(opt < 0) {
break;
}
@@ -3493,6 +3678,7 @@ int parseargs(int op, int argc, char **argv)
case 1000: pmo_noconfirm = 1; break;
case 1001: strcpy(pmo_configfile, optarg); break;
case 1002: pmo_s_ignore = list_add(pmo_s_ignore, strdup(optarg)); break;
+ case 1003: pmo_noprogressbar = 1; break;
case 'A': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_ADD); break;
case 'R': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_REMOVE); break;
case 'U': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_UPGRADE); break;
@@ -3514,6 +3700,7 @@ int parseargs(int op, int argc, char **argv)
case 'k': pmo_r_dbonly = 1; break;
case 'l': pmo_q_list = 1; break;
case 'n': pmo_nosave = 1; break;
+ case 'm': pmo_q_foreign = 1; break;
case 'p': pmo_q_isfile = 1; pmo_s_printuris = 1; break;
case 'o': pmo_q_owns = 1; break;
case 'r': if(realpath(optarg, pmo_root) == NULL) {
@@ -3853,6 +4040,7 @@ void usage(int op, char *myname)
printf(" -g, --groups view all members of a package group\n");
printf(" -i, --info view package information (use -ii for more)\n");
printf(" -l, --list list the contents of the queried package\n");
+ printf(" -m, --foreign list all packages that were not found in the sync db(s)\n");
printf(" -o, --owns <file> query the package that owns <file>\n");
printf(" -p, --file pacman will query the package file [package] instead of\n");
printf(" looking in the database\n");
@@ -3875,6 +4063,7 @@ void usage(int op, char *myname)
}
printf(" --config <path> set an alternate configuration file\n");
printf(" --noconfirm do not ask for any confirmation\n");
+ printf(" --noprogressbar do not show a progress bar when downloading files\n");
printf(" -v, --verbose be verbose\n");
printf(" -r, --root <path> set an alternate installation root\n");
printf(" -b, --dbpath <path> set an alternate database location\n");
@@ -3887,7 +4076,7 @@ void version(void)
{
printf("\n");
printf(" .--. Pacman v%s\n", PACVER);
- printf("/ _.-' .-. .-. .-. Copyright (C) 2002-2005 Judd Vinet <jvinet@zeroflux.org>\n");
+ printf("/ _.-' .-. .-. .-. Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>\n");
printf("\\ '-. '-' '-' '-' \n");
printf(" '--' This program may be freely redistributed under\n");
printf(" the terms of the GNU General Public License\n\n");
@@ -4029,6 +4218,7 @@ void cleanup(int signum)
FREE(pmo_logfile);
FREE(pmo_proxyhost);
FREE(pmo_xfercommand);
+ FREE(pmo_configfile);
FREELIST(pm_targets);