#include <sys_defs.h>
#include <string.h>
#include <msg.h>
#include <mymalloc.h>
#include <vstring.h>
#include <argv.h>
#include <vstream.h>
#include <readlline.h>
#include <stringops.h>
#include <mail_params.h>
#include <match_service.h>
#include <postconf.h>
#define STR(x) vstring_str(x)
static void normalize_options(ARGV *argv)
{
int field;
char *arg;
for (field = PC_MASTER_MIN_FIELDS; argv->argv[field] != 0; field++) {
arg = argv->argv[field];
if (arg[0] != '-' || strcmp(arg, "--") == 0)
break;
if (strncmp(arg, "-o", 2) == 0) {
if (arg[2] != 0) {
argv_insert_one(argv, field + 1, arg + 2);
argv_replace_one(argv, field, "-o");
field += 1;
} else if (argv->argv[field + 1] != 0) {
field += 1;
}
}
}
}
void read_master(int fail_on_open_error)
{
const char *myname = "read_master";
char *path;
VSTRING *buf;
ARGV *argv;
VSTREAM *fp;
int entry_count = 0;
int line_count = 0;
if (master_table != 0)
msg_panic("%s: master table is already initialized", myname);
if (var_config_dir == 0)
set_config_dir();
path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
#define MASTER_BLANKS " \t\r\n"
master_table = (PC_MASTER_ENT *) mymalloc(sizeof(*master_table));
if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0) {
if (fail_on_open_error)
msg_fatal("open %s: %m", path);
msg_warn("open %s: %m", path);
} else {
buf = vstring_alloc(100);
while (readlline(buf, fp, &line_count) != 0) {
master_table = (PC_MASTER_ENT *) myrealloc((char *) master_table,
(entry_count + 2) * sizeof(*master_table));
argv = argv_split(STR(buf), MASTER_BLANKS);
if (argv->argc < PC_MASTER_MIN_FIELDS)
msg_fatal("file %s: line %d: bad field count",
path, line_count);
normalize_options(argv);
master_table[entry_count].name_space =
concatenate(argv->argv[0], ".", argv->argv[1], (char *) 0);
master_table[entry_count].argv = argv;
master_table[entry_count].valid_names = 0;
master_table[entry_count].all_params = 0;
entry_count += 1;
}
vstream_fclose(fp);
vstring_free(buf);
}
master_table[entry_count].argv = 0;
myfree(path);
}
static void print_master_line(int mode, ARGV *argv)
{
char *arg;
char *aval;
int line_len;
int field;
int in_daemon_options;
static int column_goal[] = {
0,
11,
17,
25,
33,
41,
49,
57,
};
#define ADD_TEXT(text, len) do { \
vstream_fputs(text, VSTREAM_OUT); line_len += len; } \
while (0)
#define ADD_SPACE ADD_TEXT(" ", 1)
for (line_len = 0, field = 0; field < PC_MASTER_MIN_FIELDS; field++) {
arg = argv->argv[field];
if (line_len > 0) {
do {
ADD_SPACE;
} while (line_len < column_goal[field]);
}
ADD_TEXT(arg, strlen(arg));
}
in_daemon_options = 1;
for ( ; argv->argv[field] != 0; field++) {
arg = argv->argv[field];
if (in_daemon_options) {
if (arg[0] != '-' || strcmp(arg, "--") == 0) {
in_daemon_options = 0;
if ((mode & FOLD_LINE)
&& line_len > column_goal[PC_MASTER_MIN_FIELDS - 1]) {
vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT);
line_len = INDENT_LEN;
}
}
else if ((mode & FOLD_LINE)
&& line_len > INDENT_LEN && strcmp(arg, "-o") == 0
&& (aval = argv->argv[field + 1]) != 0
&& INDENT_LEN + 3 + strlen(aval) < LINE_LIMIT) {
vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT);
line_len = INDENT_LEN;
ADD_TEXT(arg, strlen(arg));
arg = aval;
field += 1;
}
}
if (line_len > INDENT_LEN) {
if ((mode & FOLD_LINE) == 0
|| line_len + 1 + strlen(arg) < LINE_LIMIT) {
ADD_SPACE;
} else {
vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT);
line_len = INDENT_LEN;
}
}
ADD_TEXT(arg, strlen(arg));
}
vstream_fputs("\n", VSTREAM_OUT);
}
void show_master(int mode, char **filters)
{
PC_MASTER_ENT *masterp;
ARGV *argv;
ARGV *service_filter = 0;
if (filters[0])
service_filter = match_service_init_argv(filters);
for (masterp = master_table; (argv = masterp->argv) != 0; masterp++)
if (service_filter == 0
|| match_service_match(service_filter, masterp->name_space) != 0)
print_master_line(mode, argv);
if (service_filter != 0)
argv_free(service_filter);
}