Index: ossp-pkg/petidomo/acl.y RCS File: /v/ossp/cvs/ossp-pkg/petidomo/acl.y,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/petidomo/acl.y,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/acl.y' 2>/dev/null --- ossp-pkg/petidomo/acl.y +++ - 2024-05-17 04:18:01.912708059 +0200 @@ -0,0 +1,326 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1997 by CyberSolutions GmbH. + * All rights reserved. + */ + +%{ + /* Definitions we need in the parser. */ + +#include +#include +#include +#include +#include + +#include +#include + +static int yyerror(char *); +static int yylex(void); +static int domatch(int, int, char *); +static int dofilter(const char *); + +unsigned int lineno; +int operation, g_rc; +char * g_parameter = NULL; +struct Mail * g_MailStruct; + +#include "acl_scan.c" + +#define YYERROR_VERBOSE +%} +%token TOK_IF TOK_EQUAL TOK_EQUAL TOK_FROM TOK_SUBJECT +%token TOK_ENVELOPE TOK_HEADER TOK_BODY TOK_AND TOK_OR TOK_NOT +%token TOK_THEN TOK_MATCH TOK_STRING TOK_DROP TOK_PASS +%token TOK_REDIRECT TOK_FORWARD TOK_REJECT TOK_REJECTWITH +%token TOK_FILTER +%left TOK_AND +%left TOK_OR +%right TOK_NOT +%% + +input: /* empty */ + | input statmt +; + +statmt: ';' + | TOK_IF exp TOK_THEN action ';' { if ($2 == TRUE) { + operation = $4; + YYACCEPT; + } + } +; + +exp: qualifier TOK_EQUAL TOK_STRING { + g_rc = domatch($1, TOK_EQUAL, yytext); + if (g_rc == -1) + YYABORT; + $$ = g_rc; + } + | qualifier TOK_MATCH TOK_STRING { + g_rc = domatch($1, TOK_MATCH, yytext); + if (g_rc == -1) + YYABORT; + $$ = g_rc; + } + | TOK_STRING { + g_rc = dofilter(yytext); + if (g_rc == -1) + YYABORT; + $$ = g_rc; + } + | exp TOK_OR exp { $$ = $1 || $3; } + | exp TOK_AND exp { $$ = $1 && $3; } + | TOK_NOT exp { $$ = ! $2; } + | '(' exp ')' { $$ = $2; } +; + +qualifier: TOK_FROM { $$ = TOK_FROM; } + | TOK_SUBJECT { $$ = TOK_SUBJECT; } + | TOK_ENVELOPE { $$ = TOK_ENVELOPE; } + | TOK_HEADER { $$ = TOK_HEADER; } + | TOK_BODY { $$ = TOK_BODY; } +; + +action: TOK_PASS { $$ = ACL_PASS; } + | TOK_DROP { $$ = ACL_DROP; } + | TOK_REJECT { $$ = ACL_REJECT; } + | TOK_REJECTWITH TOK_STRING { + $$ = ACL_REJECTWITH; + if (g_parameter != NULL) + free(g_parameter); + g_parameter = strdup(yytext); + if (g_parameter == NULL) + YYABORT; + } + | TOK_REDIRECT TOK_STRING { + $$ = ACL_REDIRECT; + if (g_parameter != NULL) + free(g_parameter); + g_parameter = strdup(yytext); + if (g_parameter == NULL) + YYABORT; + } + | TOK_FORWARD TOK_STRING { + $$ = ACL_FORWARD; + if (g_parameter != NULL) + free(g_parameter); + g_parameter = strdup(yytext); + if (g_parameter == NULL) + YYABORT; + } + | TOK_FILTER TOK_STRING { + $$ = ACL_FILTER; + if (g_parameter != NULL) + free(g_parameter); + g_parameter = strdup(yytext); + if (g_parameter == NULL) + YYABORT; + } +; +%% +/***** internal routines *****/ + +int +yywrap(void) +{ + return 1; +} + +static int +yyerror(char * string) +{ + syslog(LOG_ERR, "Syntax error in line %u: %s\n", lineno, string); + return 0; +} + + +static int +dofilter(const char * filter) +{ + FILE * fh; + int rc; + + debug((DEBUG_ACL, 2, "Starting ACL-filter \"%s\".", filter)); + fh = popen(filter, "w"); + if (fh == NULL) { + syslog(LOG_ERR, "Failed to open ACL-filter \"%s\": %m", filter); + return -1; + } + fprintf(fh, "%s\n", g_MailStruct->Header); + fprintf(fh, "%s", g_MailStruct->Body); + rc = pclose(fh); + + if (!WIFEXITED(rc)) + return -1; + + rc = WEXITSTATUS(rc); + switch(rc) { + case 0: + debug((DEBUG_ACL, 2, "Filter returned %d (TRUE).", rc)); + return TRUE; + case 1: + debug((DEBUG_ACL, 2, "Filter returned %d (FALSE).", rc)); + return FALSE; + default: + syslog(LOG_ERR, "ACL-filter \"%s\" returned unexpected value %d.", filter, rc); + return -1; + } +} + + +static int +domatch(int qualifier, int oper, char * string) +{ + char * left; + + switch(qualifier) { + case TOK_FROM: + left = g_MailStruct->From; + break; + case TOK_SUBJECT: + left = g_MailStruct->Subject; + break; + case TOK_ENVELOPE: + left = g_MailStruct->Envelope; + break; + case TOK_HEADER: + left = g_MailStruct->Header; + break; + case TOK_BODY: + left = g_MailStruct->Body; + break; + default: + syslog(LOG_CRIT, "Internal error in the ACL parser. Unknown qualifier %d.", + qualifier); + return -1; + } + + switch(oper) { + case TOK_EQUAL: + if (left != NULL && strcasecmp(left, string) == 0) { + debug((DEBUG_ACL, 1, "ACL: \"%s\" == \"%s\" == TRUE", left, string)); + return TRUE; + } + else { + debug((DEBUG_ACL, 1, "ACL: \"%s\" == \"%s\" == FALSE", left, string)); + return FALSE; + } + case TOK_MATCH: + if (left != NULL && text_easy_pattern_match(left, string) == TRUE) { + debug((DEBUG_ACL, 1, "ACL: \"%s\" match \"%s\" == TRUE", left, string)); + return TRUE; + } + else { + debug((DEBUG_ACL, 1, "ACL: \"%s\" match \"%s\" == FALSE", left, string)); + return FALSE; + } + default: + syslog(LOG_CRIT, "Internal error in the ACL parser. Unknown operator %d.", oper); + return -1; + } +} + + +/****** public routines ******/ + +int checkACL(struct Mail * MailStruct, + const char * listname, + int * operation_ptr, + char ** parameter_ptr) +{ + char * filename; + int rc; + + assert(MailStruct != NULL); + assert(operation_ptr != NULL); + assert(parameter_ptr != NULL); + + g_MailStruct = MailStruct; + g_parameter = NULL; + + /* Set up the lex scanner. */ + + BEGIN(INITIAL); + lineno = 1; operation = ACL_NONE; + + /* First check the mail against the master acl file. */ + + debug((DEBUG_ACL, 2, "Testing mail against \"~petidomo/etc/acl\".")); + yyin = fopen("etc/acl", "r"); + if (yyin == NULL) { + switch(errno) { + case ENOENT: + /* no master acl file */ + debug((DEBUG_ACL, 1, "No master acl file found.")); + goto check_local_acl_file; + default: + syslog(LOG_ERR, "Couldn't open \"~petidomo/etc/acl\" acl file.: %m"); + return -1; + } + } + + /* Parse the acl file. */ + + rc = yyparse(); + if (yyin != NULL) { + fclose(yyin); + yyin = NULL; + } + if (rc != 0) { + syslog(LOG_ERR, "Parsing \"~petidomo/etc/acl\" file returned with an error."); + return -1; + } + + /* If we had a hit, return now. */ + + if (operation != ACL_NONE) + goto finished; + + + +check_local_acl_file: + + /* Set up the lex scanner. */ + + BEGIN(INITIAL); + lineno = 1; operation = ACL_NONE; + + /* Do we have a local acl file to test? */ + + if (listname == NULL) + goto finished; + + filename = text_easy_sprintf("lists/%s/acl", listname); + debug((DEBUG_ACL, 2, "Testing mail against \"~petidomo/%s\".", filename)); + yyin = fopen(filename, "r"); + if (yyin == NULL) { + switch(errno) { + case ENOENT: + /* no list acl file */ + debug((DEBUG_ACL, 1, "No acl file for list \"%s\".", listname)); + goto finished; + default: + syslog(LOG_ERR, "Couldn't open \"~petidomo/%s\" file: %m", filename); + return -1; + } + } + + rc = yyparse(); + fclose(yyin); + yyin = NULL; + if (rc != 0) { + syslog(LOG_ERR, "Parsing \"~petidomo/etc/acl\" file returned with an error."); + return -1; + } + + /* Return to the caller. */ +finished: + *operation_ptr = operation; + *parameter_ptr = g_parameter; + return 0; +} Index: ossp-pkg/petidomo/acl_scan.l RCS File: /v/ossp/cvs/ossp-pkg/petidomo/Attic/acl_scan.l,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/petidomo/Attic/acl_scan.l,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/acl_scan.l' 2>/dev/null --- ossp-pkg/petidomo/acl_scan.l +++ - 2024-05-17 04:18:01.928888292 +0200 @@ -0,0 +1,47 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1997 by CyberSolutions GmbH. + * All rights reserved. + */ + +%{ +#include +#include "acl_scan.h" +%} +%% +^[ \t]*#.*$ /* ignore comments */ +[ \t] /* ignore whitespace */ +\n lineno++; + +if return TOK_IF; += return TOK_EQUAL; +== return TOK_EQUAL; +from return TOK_FROM; +subject return TOK_SUBJECT; +envelope return TOK_ENVELOPE; +header return TOK_HEADER; +body return TOK_BODY; +and return TOK_AND; +or return TOK_OR; +not return TOK_NOT; +then return TOK_THEN; +match(es)? return TOK_MATCH; +\"[^\"]*\" { + yytext[yyleng-1] = '\0'; + yytext++; + yyleng -= 2; + return TOK_STRING; + } +drop return TOK_DROP; +pass return TOK_PASS; +redirect return TOK_REDIRECT; +forward return TOK_FORWARD; +reject return TOK_REJECT; +rejectwith return TOK_REJECTWITH; +filter return TOK_FILTER; + +. { yylval = yytext[0]; return yylval; } /* literal */ +%% Index: ossp-pkg/petidomo/archive.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/archive.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/petidomo/archive.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/archive.c' 2>/dev/null --- ossp-pkg/petidomo/archive.c +++ - 2024-05-17 04:18:01.931448274 +0200 @@ -0,0 +1,152 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1996 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +int +ArchiveMail(const struct Mail * MailStruct, const char * listname) +{ + const struct List_Config * ListConfig; + struct stat sb; + FILE * fh; + char * filename; + char * path; + u_int counter; + int rc; + struct tm * timeptr; + char * date; + time_t clock; + + assert(MailStruct != NULL); + assert(listname != NULL); + + /* Initialize internals. */ + + ListConfig = getListConfig(listname); + clock = time(NULL); + timeptr = localtime(&clock); + date = asctime(timeptr); + rc = -1; + + /* Sanity checks. */ + + if (ListConfig->archivepath == NULL) + return 0; + + /* Construct the path to the log file or directory. */ + + if (*(ListConfig->archivepath) == '/') + path = xstrdup(ListConfig->archivepath); + else { + path = text_easy_sprintf("lists/%s/%s", listname, ListConfig->archivepath); + path = xstrdup(path); + } + debug((DEBUG_ARCHIVE, 2, "Our archive path is \"%s\".", path)); + + /* Check whether we have a file or a directory. */ + + if (stat(path, &sb) == 0 && (sb.st_mode & S_IFDIR) != 0) { + + /* Store the article to the current number into the directory. */ + + debug((DEBUG_ARCHIVE, 3, "\"%s\" is a directory.", path)); + + /* Read the "active"-file to see at what article number we + were. */ + + filename = text_easy_sprintf("%s/.active", path); + fh = fopen(filename, "r"); + if (fh != NULL) { + fscanf(fh, "%u", &counter); + debug((DEBUG_ARCHIVE, 5, ".active file contained '%u'.", counter)); + fclose(fh); + } + else { + if (errno != ENOENT) + syslog(LOG_ERR, "Failed to read file \"%s\": %m", filename); + else + debug((DEBUG_ARCHIVE, 1, "File \".active\" did not exist.")); + counter = 0; + } + + /* Store the article. */ + + do { + filename = text_easy_sprintf("%s/%u", path, counter); + debug((DEBUG_ARCHIVE, 4, "Testing whether file \"%s\" exists already.", + filename)); + if (stat(filename, &sb) == -1) { + debug((DEBUG_ARCHIVE, 7, "Nope, it doesn't.")); + if (errno == ENOENT) { + debug((DEBUG_ARCHIVE, 1, "Writing mail to file \"%s\".", filename)); + fh = fopen(filename, "a"); + if (fh != NULL) { + fprintf(fh, "From %s-owner@%s %s", listname, ListConfig->fqdn, date); + fprintf(fh, "%s\n", MailStruct->Header); + fprintf(fh, "%s\n", MailStruct->Body); + fclose(fh); + rc = 0; + } + else + syslog(LOG_ERR, "Failed opening file \"%s\" for writing: %m", filename); + break; + } + else { + syslog(LOG_ERR, "An error while trying to access the log " \ + "directory \"%s\": %m", path); + break; + } + } + else + debug((DEBUG_ARCHIVE, 7, "Yep, it does.")); + } while (++counter); /* until break */ + + /* Write the current "active" number back to the file. */ + + counter++; + filename = text_easy_sprintf("%s/.active", path); + fh = fopen(filename, "w"); + if (fh != NULL) { + fprintf(fh, "%u", counter); + debug((DEBUG_ARCHIVE, 5, "Wrote '%u' to .active file.", counter)); + fclose(fh); + } + else + syslog(LOG_ERR, "Failed to write to file \"%s\": %m", filename); + } + else { + + /* Simply append the article to this file. */ + + debug((DEBUG_ARCHIVE, 1, "Appending mail to logfile \"%s\".", path)); + fh = fopen(path, "a"); + if (fh != NULL) { + /* Write an envelope first. */ + + fprintf(fh, "From %s-owner@%s %s", listname, ListConfig->fqdn, date); + fprintf(fh, "%s\n", MailStruct->Header); + fprintf(fh, "%s\n", MailStruct->Body); + fclose(fh); + rc = 0; + } + else + syslog(LOG_ERR, "Failed opening file \"%s\" for writing: %m", path); + } + + free(path); + return rc; +} Index: ossp-pkg/petidomo/authen.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/authen.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/petidomo/authen.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/authen.c' 2>/dev/null --- ossp-pkg/petidomo/authen.c +++ - 2024-05-17 04:18:01.934059826 +0200 @@ -0,0 +1,102 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1996 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include +#include + +#include +#include + +int +FindBodyPassword(struct Mail * MailStruct) +{ + char * currLine; + + currLine = MailStruct->Body; + while(isspace((int)*currLine)) + currLine++; + if (!strncasecmp(currLine, "Approve", 7) || + !strncasecmp(currLine, "Approved", 8) || + !strncasecmp(currLine, "Passwd", 6) || + !strncasecmp(currLine, "Password", 8)) { + MailStruct->Body = text_find_next_line(currLine); + (text_find_next_line(currLine))[-1] = '\0'; + while(!isspace((int)*currLine)) + currLine++; + if (ParseApproveLine(currLine) != 0) { + syslog(LOG_ERR, "Failed to parse the approve statement in the mail body."); + return -1; + } + debug((DEBUG_HERMES, 3, "Found password \"%s\" in mail body.", currLine)); + MailStruct->Approve = currLine; + } + return 0; +} + +bool +isValidAdminPassword(const char * password, const char * listname) +{ + const struct PD_Config * MasterConfig; + const struct List_Config * ListConfig; + + if (password == NULL) + return FALSE; + + MasterConfig = getMasterConfig(); + + if (!strcasecmp(MasterConfig->master_password, password)) + return TRUE; + + if (listname != NULL) { + ListConfig = getListConfig(listname); + + if (ListConfig->admin_password == NULL) + return FALSE; + + debug((DEBUG_AUTHEN, 5, "Comparing provided password '%s' to correct one '%s'.", + ListConfig->admin_password, password)); + + if (!strcasecmp(ListConfig->admin_password, password)) + return TRUE; + } + return FALSE; +} + +bool +isValidPostingPassword(const char * password, const char * listname) +{ + const struct List_Config * ListConfig; + + if (password == NULL) + return FALSE; + + if (isValidAdminPassword(password, listname) == TRUE) + return TRUE; + + if (listname != NULL) { + ListConfig = getListConfig(listname); + + if (ListConfig->posting_password == NULL) + return FALSE; + + debug((DEBUG_AUTHEN, 5, "provided password '%s' to correct one '%s'.", + ListConfig->posting_password, password)); + + if (!strcasecmp(ListConfig->posting_password, password)) { + debug((DEBUG_AUTHEN, 2, "Provided password is correct!")); + return TRUE; + } + else { + debug((DEBUG_AUTHEN, 2, "Provided password is incorrect!")); + } + + } + + return FALSE; +} Index: ossp-pkg/petidomo/config.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/Attic/config.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/petidomo/Attic/config.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/config.c' 2>/dev/null --- ossp-pkg/petidomo/config.c +++ - 2024-05-17 04:18:01.936644657 +0200 @@ -0,0 +1,227 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1996 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include +#include +#include +#include + +#include +#include +#include + +static struct PD_Config * MasterConfig; +List ListConfigs; + +/* These variables need to be static/global, so that the addresses as + used in MasterCF are known at compile time. */ + +static char * fqdn = NULL; +static char * master_password = NULL; +static char * mta = "/usr/sbin/sendmail"; +static char * mta_options = "-f%s"; +static bool detach = FALSE; +static bool show_stats = TRUE; + +int +InitPetidomo(void) +{ + struct passwd * pwd; + char * basedir = "/usr/local/petidomo"; + int rc; + + /* Format description of our global config file. */ + + struct ConfigFile MasterCF[] = { + { "Hostname", CF_STRING, &fqdn }, + { "AdminPassword", CF_STRING, &master_password }, + { "MTA", CF_STRING, &mta }, + { "MTA_Options", CF_STRING, &mta_options }, + { "DetachImmediately", CF_YES_NO, &detach }, + { "ShowStatistics", CF_YES_NO, &show_stats }, + { NULL, 0, NULL} + }; + + /* Allocate memory for the global config structure. */ + + MasterConfig = calloc(sizeof(struct PD_Config), 1); + if (MasterConfig == NULL) { + syslog(LOG_ERR, "Failed to allocate %d byte of memory.", sizeof(struct PD_Config)); + return -1; + } + + /* Init the list of read list configs. */ + + ListConfigs = InitList(NULL); + + /* First of all, determine the home directory of the "petidomo" + user. This will be our base directory for all operations. */ + + debug((DEBUG_CONFIG, 9, "Looking for the home directory of user petidomo.")); + pwd = getpwnam("petidomo"); + if (pwd != NULL) { + debug((DEBUG_CONFIG, 8, "Home directory of petidomo is \"%s\".", pwd->pw_dir)); + if (strcmp(basedir, pwd->pw_dir) != 0) + basedir = xstrdup(pwd->pw_dir); /* Replace the default above. */ + endpwent(); + } + else + syslog(LOG_WARNING, "User \"petidomo\" not found."); + debug((DEBUG_CONFIG, 8, "Will use basedir \"%s\".", basedir)); + + /* chdir() into the base directory. */ + + rc = chdir(basedir); + if (rc != 0) { + syslog(LOG_ERR, "Failed to change current directory to \"%s\": %m", basedir); + return -1; + } + + /* Parse the config file. */ + + rc = ReadConfig("etc/petidomo.conf", MasterCF); + if (rc != 0) { + syslog(LOG_ERR, "Failed to parse the master config file \"petidomo.conf\""); + return -1; + } + + /* Do consistency checks. */ + + if (fqdn == NULL) { + syslog(LOG_ERR, "The master config file \"petidomo.conf\" doesn't set the host name."); + return -1; + } + if (master_password == NULL) { + syslog(LOG_ERR, "The master config file \"petidomo.conf\" doesn't set the admin password."); + return -1; + } + if (strstr(mta_options, "%s") == NULL) { + syslog(LOG_ERR, "The argument to MTA_Options in the master config file is invalid."); + return -1; + } + + /* Copy the results to the structure. */ + + MasterConfig->basedir = basedir; + MasterConfig->fqdn = fqdn; + MasterConfig->master_password = master_password; + MasterConfig->mta = mta; + MasterConfig->mta_options = mta_options; + MasterConfig->detach = detach; + MasterConfig->show_stats = show_stats; + + return 0; +} + +const struct PD_Config * +getMasterConfig(void) +{ + return MasterConfig; +} + +static char * list_fqdn = NULL; +static char * admin_password = NULL; +static char * posting_password = NULL; +static char * listtype = NULL; +static char * reply_to = NULL; +static char * postingfilter = NULL; +static char * archivepath = NULL; +static bool allowpubsub = TRUE; +static bool allowaliensub = TRUE; +static bool allowmembers = FALSE; +static bool showonindex = TRUE; + +const struct List_Config * +getListConfig(const char * listname) +{ + const struct PD_Config * MasterConfig; + struct List_Config * ListConfig; + Node node; + int rc; + char buffer[4096]; + + /* Format description of our global config file. */ + + struct ConfigFile ListCF[] = { + { "ListType", CF_STRING, &listtype }, + { "AllowPublicSubscription", CF_YES_NO, &allowpubsub }, + { "AllowAlienSubscription", CF_YES_NO, &allowaliensub }, + { "AllowMembersCommand", CF_YES_NO, &allowmembers }, + { "ShowOnIndex", CF_YES_NO, &showonindex }, + { "ReplyTo", CF_STRING, &reply_to }, + { "Hostname", CF_STRING, &list_fqdn }, + { "AdminPassword", CF_STRING, &admin_password }, + { "PostingPassword", CF_STRING, &posting_password }, + { "PostingFilter", CF_STRING, &postingfilter }, + { "Archive", CF_STRING, &archivepath }, + { NULL, 0, NULL} + }; + + /* Get the master configuration. */ + + MasterConfig = getMasterConfig(); + + /* Did we read this config file already? */ + + node = FindNodeByKey(ListConfigs, listname); + if (node != NULL) + return getNodeData(node); + + /* No? Then read the config file. */ + + sprintf(buffer, "lists/%s/config", listname); + debug((DEBUG_CONFIG, 6, "getListConfig(): Loading config file \"%s\".", buffer)); + rc = ReadConfig(buffer, ListCF); + if (rc != 0) { + syslog(LOG_ERR, "Failed to parse the list \"%s\"'s config file.", listname); + exit(1); + } + + /* Do consistency checks. */ + + if (listtype == NULL) { + syslog(LOG_ERR, "List \"%s\" doesn't have a valid type in config file.", listname); + exit(1); + } + + /* Set up the list config structure. */ + + ListConfig = calloc(sizeof(struct List_Config), 1); + if (ListConfig == NULL) { + syslog(LOG_ERR, "Failed to allocate %d byte of memory.", sizeof(struct List_Config)); + exit(1); + } + debug((DEBUG_CONFIG, 6, "Loaded config file successfully.")); + debug((DEBUG_CONFIG, 4, "Read listtype is \"%s\".", listtype)); + if (!strcasecmp(listtype, "open")) + ListConfig->listtype = LIST_OPEN; + else if (!strcasecmp(listtype, "closed")) + ListConfig->listtype = LIST_CLOSED; + else if (!strcasecmp(listtype, "moderated")) + ListConfig->listtype = LIST_MODERATED; + else { + syslog(LOG_ERR, "List \"%s\" doesn't have a valid type in config file.", listname); + exit(1); + } + ListConfig->allowpubsub = allowpubsub; + ListConfig->allowaliensub = allowaliensub; + ListConfig->allowmembers = allowmembers; + ListConfig->showonindex = showonindex; + ListConfig->fqdn = (list_fqdn) ? list_fqdn : MasterConfig->fqdn; + ListConfig->reply_to = reply_to; + if (reply_to != NULL && strcasecmp(reply_to, "none")) + CanonizeAddress(&(ListConfig->reply_to), ListConfig->fqdn); + ListConfig->admin_password = admin_password; + ListConfig->posting_password = posting_password; + ListConfig->postingfilter = postingfilter; + ListConfig->archivepath = archivepath; + AppendNode(ListConfigs, xstrdup(listname), ListConfig); + + return ListConfig; +}