#include <sys_defs.h>
#include <string.h>
#include <ctype.h>
#include <msg.h>
#include <mymalloc.h>
#include <htable.h>
#include <vstring.h>
#include <vstring_vstream.h>
#include <edit_file.h>
#include <readlline.h>
#include <stringops.h>
#include <mail_params.h>
#include <postconf.h>
#define STR(x) vstring_str(x)
void edit_parameters(int mode, int argc, char **argv)
{
char *path;
EDIT_FILE *ep;
VSTREAM *src;
VSTREAM *dst;
VSTRING *buf = vstring_alloc(100);
VSTRING *key = vstring_alloc(10);
char *cp;
char *edit_key;
char *edit_val;
HTABLE *table;
struct cvalue {
char *value;
int found;
};
struct cvalue *cvalue;
HTABLE_INFO **ht_info;
HTABLE_INFO **ht;
int interesting;
const char *err;
table = htable_create(argc);
while ((cp = *argv++) != 0) {
if (strchr(cp, '\n') != 0)
msg_fatal("-e or -# accepts no multi-line input");
while (ISSPACE(*cp))
cp++;
if (*cp == '#')
msg_fatal("-e or -# accepts no comment input");
if (mode & EDIT_MAIN) {
if ((err = split_nameval(cp, &edit_key, &edit_val)) != 0)
msg_fatal("%s: \"%s\"", err, cp);
} else if (mode & COMMENT_OUT) {
if (*cp == 0)
msg_fatal("-# requires non-blank parameter names");
if (strchr(cp, '=') != 0)
msg_fatal("-# requires parameter names only");
edit_key = mystrdup(cp);
trimblanks(edit_key, 0);
edit_val = 0;
} else {
msg_panic("edit_parameters: unknown mode %d", mode);
}
cvalue = (struct cvalue *) mymalloc(sizeof(*cvalue));
cvalue->value = edit_val;
cvalue->found = 0;
htable_enter(table, edit_key, (char *) cvalue);
}
set_config_dir();
path = concatenate(var_config_dir, "/", MAIN_CONF_FILE, (char *) 0);
if ((ep = edit_file_open(path, O_CREAT | O_WRONLY, 0644)) == 0)
msg_fatal("open %s%s: %m", path, EDIT_FILE_SUFFIX);
dst = ep->tmp_fp;
if ((src = vstream_fopen(path, O_RDONLY, 0)) == 0) {
(void) unlink(ep->tmp_path);
msg_fatal("open %s for reading: %m", path);
}
#define STR(x) vstring_str(x)
interesting = 0;
while (vstring_get(buf, src) != VSTREAM_EOF) {
for (cp = STR(buf); ISSPACE(*cp) ; cp++)
;
if (*cp == '#' || *cp == 0) {
vstream_fputs(STR(buf), dst);
}
else if (cp > STR(buf)) {
if (interesting == 0)
vstream_fputs(STR(buf), dst);
else if (mode & COMMENT_OUT)
vstream_fprintf(dst, "#%s", STR(buf));
}
else {
vstring_strncpy(key, cp, strcspn(cp, " \t\r\n="));
cvalue = (struct cvalue *) htable_find(table, STR(key));
if ((interesting = !!cvalue) != 0) {
if (cvalue->found++ == 1)
msg_warn("%s: multiple entries for \"%s\"", path, STR(key));
if (mode & EDIT_MAIN)
vstream_fprintf(dst, "%s = %s\n", STR(key), cvalue->value);
else if (mode & COMMENT_OUT)
vstream_fprintf(dst, "#%s", cp);
else
msg_panic("edit_parameters: unknown mode %d", mode);
} else {
vstream_fputs(STR(buf), dst);
}
}
}
if (mode & EDIT_MAIN) {
for (ht_info = ht = htable_list(table); *ht; ht++) {
cvalue = (struct cvalue *) ht[0]->value;
if (cvalue->found == 0)
vstream_fprintf(dst, "%s = %s\n", ht[0]->key, cvalue->value);
}
myfree((char *) ht_info);
}
if (vstream_fclose(src))
msg_fatal("read %s: %m", path);
if (edit_file_close(ep) != 0)
msg_fatal("close %s%s: %m", path, EDIT_FILE_SUFFIX);
myfree(path);
vstring_free(buf);
vstring_free(key);
htable_free(table, myfree);
}