Rewrote Petidomo so that virtually any file's path can be configured
at run-time now.
This commit is contained in:
parent
81d982c82b
commit
88ffd53ded
8
acl.y
8
acl.y
@ -236,6 +236,7 @@ int checkACL(struct Mail * MailStruct,
|
||||
int * operation_ptr,
|
||||
char ** parameter_ptr)
|
||||
{
|
||||
const struct PD_Config * MasterConfig;
|
||||
char * filename;
|
||||
int rc;
|
||||
|
||||
@ -243,6 +244,7 @@ int checkACL(struct Mail * MailStruct,
|
||||
assert(operation_ptr != NULL);
|
||||
assert(parameter_ptr != NULL);
|
||||
|
||||
MasterConfig = getMasterConfig();
|
||||
g_MailStruct = MailStruct;
|
||||
g_parameter = NULL;
|
||||
|
||||
@ -253,14 +255,14 @@ int checkACL(struct Mail * MailStruct,
|
||||
|
||||
/* First check the mail against the master acl file. */
|
||||
|
||||
yyin = fopen("etc/acl", "r");
|
||||
yyin = fopen(MasterConfig->acl_file, "r");
|
||||
if (yyin == NULL) {
|
||||
switch(errno) {
|
||||
case ENOENT:
|
||||
/* no master acl file */
|
||||
goto check_local_acl_file;
|
||||
default:
|
||||
syslog(LOG_ERR, "Couldn't open \"~petidomo/etc/acl\" acl file.: %m");
|
||||
syslog(LOG_ERR, "Couldn't open \"%s\" acl file.: %m", MasterConfig->acl_file);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -273,7 +275,7 @@ int checkACL(struct Mail * MailStruct,
|
||||
yyin = NULL;
|
||||
}
|
||||
if (rc != 0) {
|
||||
syslog(LOG_ERR, "Parsing \"~petidomo/etc/acl\" file returned with an error.");
|
||||
syslog(LOG_ERR, "Parsing \"%s\" file returned with an error.", MasterConfig->acl_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
75
archive.c
75
archive.c
@ -29,12 +29,11 @@
|
||||
|
||||
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;
|
||||
@ -55,25 +54,17 @@ ArchiveMail(const struct Mail * MailStruct, const char * listname)
|
||||
/* 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);
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* Check whether we have a file or a directory. */
|
||||
|
||||
if (stat(path, &sb) == 0 && (sb.st_mode & S_IFDIR) != 0) {
|
||||
if (stat(ListConfig->archivepath, &sb) == 0 && (sb.st_mode & S_IFDIR) != 0)
|
||||
{
|
||||
|
||||
/* Read the "active"-file to see at what article number we
|
||||
were. */
|
||||
|
||||
filename = text_easy_sprintf("%s/.active", path);
|
||||
filename = text_easy_sprintf("%s/.active", ListConfig->archivepath);
|
||||
fh = fopen(filename, "r");
|
||||
if (fh != NULL)
|
||||
{
|
||||
@ -90,48 +81,57 @@ ArchiveMail(const struct Mail * MailStruct, const char * listname)
|
||||
|
||||
/* Store the article. */
|
||||
|
||||
do {
|
||||
filename = text_easy_sprintf("%s/%u", path, counter);
|
||||
if (stat(filename, &sb) == -1) {
|
||||
if (errno == ENOENT) {
|
||||
do
|
||||
{
|
||||
filename = text_easy_sprintf("%s/%u", ListConfig->archivepath, counter);
|
||||
if (stat(filename, &sb) == -1)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
fh = fopen(filename, "a");
|
||||
if (fh != NULL) {
|
||||
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);
|
||||
syslog(LOG_ERR, "Failed opening file \"%s\" for writing: %m", filename);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_ERR, "An error while trying to access the log " \
|
||||
"directory \"%s\": %m", path);
|
||||
"directory \"%s\": %m", ListConfig->archivepath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (++counter); /* until break */
|
||||
while (++counter); /* until break */
|
||||
|
||||
/* Write the current "active" number back to the file. */
|
||||
|
||||
counter++;
|
||||
filename = text_easy_sprintf("%s/.active", path);
|
||||
filename = text_easy_sprintf("%s/.active", ListConfig->archivepath);
|
||||
fh = fopen(filename, "w");
|
||||
if (fh != NULL) {
|
||||
if (fh != NULL)
|
||||
{
|
||||
fprintf(fh, "%u", counter);
|
||||
fclose(fh);
|
||||
}
|
||||
}
|
||||
else
|
||||
syslog(LOG_ERR, "Failed to write to file \"%s\": %m", filename);
|
||||
}
|
||||
else {
|
||||
syslog(LOG_ERR, "Failed to write to file \"%s\": %m", filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Simply append the article to this file. */
|
||||
|
||||
fh = fopen(path, "a");
|
||||
if (fh != NULL) {
|
||||
fh = fopen(ListConfig->archivepath, "a");
|
||||
if (fh != NULL)
|
||||
{
|
||||
/* Write an envelope first. */
|
||||
|
||||
fprintf(fh, "From %s-owner@%s %s", listname, ListConfig->fqdn, date);
|
||||
@ -139,11 +139,10 @@ ArchiveMail(const struct Mail * MailStruct, const char * listname)
|
||||
fprintf(fh, "%s\n", MailStruct->Body);
|
||||
fclose(fh);
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
syslog(LOG_ERR, "Failed opening file \"%s\" for writing: %m", path);
|
||||
}
|
||||
syslog(LOG_ERR, "Failed opening file \"%s\" for writing: %m", ListConfig->archivepath);
|
||||
}
|
||||
|
||||
free(path);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
120
config.c
120
config.c
@ -20,7 +20,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "libtext/text.h"
|
||||
#include "liblists/lists.h"
|
||||
#include "libconfigfile/configfile.h"
|
||||
#include "petidomo.h"
|
||||
@ -33,8 +35,12 @@ List ListConfigs;
|
||||
|
||||
static char* fqdn = NULL;
|
||||
static char* master_password = NULL;
|
||||
static char* mta = "/usr/sbin/sendmail";
|
||||
static char* mta = NULL;
|
||||
static char* mta_options = "-i -f%s";
|
||||
static char* help_file = DATADIR "/petidomo.conf";
|
||||
static char* acl_file = SYSCONFDIR "/petidomo.acl";
|
||||
static char* index_file = LOCALSTATEDIR "/index";
|
||||
static char* list_dir = LOCALSTATEDIR;
|
||||
|
||||
int InitPetidomo(const char* masterconfig_path)
|
||||
{
|
||||
@ -48,6 +54,10 @@ int InitPetidomo(const char* masterconfig_path)
|
||||
{ "AdminPassword", CF_STRING, &master_password },
|
||||
{ "MTA", CF_STRING, &mta },
|
||||
{ "MTA_Options", CF_STRING, &mta_options },
|
||||
{ "Help_File", CF_STRING, &help_file },
|
||||
{ "Acl_File", CF_STRING, &acl_file },
|
||||
{ "Index_File", CF_STRING, &index_file },
|
||||
{ "List_Directory", CF_STRING, &list_dir },
|
||||
{ NULL, 0, NULL}
|
||||
};
|
||||
|
||||
@ -80,6 +90,11 @@ int InitPetidomo(const char* masterconfig_path)
|
||||
syslog(LOG_ERR, "The master config file \"%s\" doesn't set the host name.", masterconfig_path);
|
||||
return -1;
|
||||
}
|
||||
if (mta == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, "The master config file \"%s\" doesn't set the MTA.", masterconfig_path);
|
||||
return -1;
|
||||
}
|
||||
if (master_password == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, "The master config file \"%s\" doesn't set the admin password.", masterconfig_path);
|
||||
@ -97,6 +112,10 @@ int InitPetidomo(const char* masterconfig_path)
|
||||
MasterConfig->master_password = master_password;
|
||||
MasterConfig->mta = mta;
|
||||
MasterConfig->mta_options = mta_options;
|
||||
MasterConfig->help_file = help_file;
|
||||
MasterConfig->acl_file = acl_file;
|
||||
MasterConfig->index_file = index_file;
|
||||
MasterConfig->list_dir = list_dir;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -107,17 +126,22 @@ const struct PD_Config* getMasterConfig(void)
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
static char* list_fqdn;
|
||||
static char* admin_password;
|
||||
static char* posting_password;
|
||||
static char* listtype;
|
||||
static char* reply_to;
|
||||
static char* postingfilter;
|
||||
static char* archivepath;
|
||||
static bool allowpubsub;
|
||||
static bool allowaliensub;
|
||||
static bool allowmembers;
|
||||
static char* intro_file;
|
||||
static char* sig_file;
|
||||
static char* desc_file;
|
||||
static char* header_file;
|
||||
static char* list_acl_file;
|
||||
static char* address_file;
|
||||
|
||||
const struct List_Config* getListConfig(const char * listname)
|
||||
{
|
||||
@ -125,7 +149,9 @@ const struct List_Config* getListConfig(const char * listname)
|
||||
struct List_Config * ListConfig;
|
||||
Node node;
|
||||
int rc;
|
||||
char buffer[4096];
|
||||
char * buffer;
|
||||
struct stat sb;
|
||||
char* list_dir;
|
||||
|
||||
/* Format description of our global config file. */
|
||||
|
||||
@ -135,16 +161,40 @@ const struct List_Config* getListConfig(const char * listname)
|
||||
{ "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 },
|
||||
{ "IntroductionFile", CF_STRING, &intro_file },
|
||||
{ "SignatureFile", CF_STRING, &sig_file },
|
||||
{ "DescriptionFile", CF_STRING, &desc_file },
|
||||
{ "HeaderFile", CF_STRING, &header_file },
|
||||
{ "ListACLFile", CF_STRING, &list_acl_file },
|
||||
{ "AddressFile", CF_STRING, &address_file },
|
||||
{ NULL, 0, NULL}
|
||||
};
|
||||
|
||||
/* Set the defaults. */
|
||||
|
||||
list_fqdn = NULL;
|
||||
admin_password = NULL;
|
||||
posting_password = NULL;
|
||||
listtype = NULL;
|
||||
reply_to = NULL;
|
||||
postingfilter = NULL;
|
||||
archivepath = NULL;
|
||||
allowpubsub = TRUE;
|
||||
allowaliensub = TRUE;
|
||||
allowmembers = FALSE;
|
||||
intro_file = "introduction";
|
||||
sig_file = "signature";
|
||||
desc_file = "description";
|
||||
header_file = "header";
|
||||
list_acl_file = "acl";
|
||||
address_file = "list";
|
||||
|
||||
/* Get the master configuration. */
|
||||
|
||||
MasterConfig = getMasterConfig();
|
||||
@ -157,7 +207,19 @@ const struct List_Config* getListConfig(const char * listname)
|
||||
|
||||
/* No? Then read the config file. */
|
||||
|
||||
sprintf(buffer, "lists/%s/config", listname);
|
||||
buffer = text_easy_sprintf("%s/%s/config", MasterConfig->list_dir, listname);
|
||||
list_dir = text_easy_sprintf("%s/%s", MasterConfig->list_dir, listname);
|
||||
if (stat(buffer, &sb) != 0)
|
||||
{
|
||||
free(buffer);
|
||||
buffer = text_easy_sprintf("%s/%s.config", MasterConfig->list_dir, listname);
|
||||
list_dir = MasterConfig->list_dir;
|
||||
if (stat(buffer, &sb) != 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Can't find a config file for list \"%s\".", listname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
rc = ReadConfig(buffer, ListCF);
|
||||
if (rc != 0)
|
||||
{
|
||||
@ -195,7 +257,6 @@ const struct List_Config* getListConfig(const char * listname)
|
||||
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"))
|
||||
@ -203,7 +264,32 @@ const struct List_Config* getListConfig(const char * listname)
|
||||
ListConfig->admin_password = admin_password;
|
||||
ListConfig->posting_password = posting_password;
|
||||
ListConfig->postingfilter = postingfilter;
|
||||
ListConfig->archivepath = archivepath;
|
||||
|
||||
ListConfig->list_dir = list_dir;
|
||||
|
||||
#define EXPAND(dst, src) \
|
||||
if (src == NULL || src[0] == '/') \
|
||||
ListConfig->dst = src; \
|
||||
else \
|
||||
ListConfig->dst = text_easy_sprintf("%s/%s", ListConfig->list_dir, src);
|
||||
|
||||
EXPAND(archivepath, archivepath);
|
||||
EXPAND(intro_file, intro_file);
|
||||
EXPAND(desc_file, desc_file);
|
||||
EXPAND(sig_file, sig_file);
|
||||
EXPAND(header_file, header_file);
|
||||
EXPAND(acl_file, list_acl_file);
|
||||
EXPAND(address_file, address_file);
|
||||
|
||||
printf("archivepath: %s\n", ListConfig->archivepath);
|
||||
printf("intro_file: %s\n", ListConfig->intro_file);
|
||||
printf("desc_file: %s\n", ListConfig->desc_file);
|
||||
printf("sig_file: %s\n", ListConfig->sig_file);
|
||||
printf("header_file: %s\n", ListConfig->header_file);
|
||||
printf("acl_file: %s\n", ListConfig->acl_file);
|
||||
printf("address_file: %s\n", ListConfig->address_file);
|
||||
|
||||
|
||||
AppendNode(ListConfigs, xstrdup(listname), ListConfig);
|
||||
|
||||
return ListConfig;
|
||||
|
||||
7
help.c
7
help.c
@ -67,8 +67,7 @@ SendHelp(struct Mail * MailStruct,
|
||||
fprintf(fh, "Sender: %s\n", envelope);
|
||||
fprintf(fh, "\n");
|
||||
fprintf(fh, "Description of list \"%s\":\n\n", param1);
|
||||
buffer = text_easy_sprintf("lists/%s/description", param1);
|
||||
p = loadfile(buffer);
|
||||
p = loadfile(ListConfig->desc_file);
|
||||
if (p != NULL) {
|
||||
fprintf(fh, "%s\n", p);
|
||||
free(p);
|
||||
@ -136,7 +135,7 @@ SendHelp(struct Mail * MailStruct,
|
||||
fprintf(fh, "Precedence: junk\n");
|
||||
fprintf(fh, "Sender: %s\n", envelope);
|
||||
fprintf(fh, "\n");
|
||||
p = loadfile("etc/help");
|
||||
p = loadfile(MasterConfig->help_file);
|
||||
if (p != NULL) {
|
||||
fprintf(fh, "%s\n", p);
|
||||
free(p);
|
||||
@ -192,7 +191,7 @@ Indecipherable(struct Mail * MailStruct, const char * defaultlist)
|
||||
fprintf(fh, "Precedence: junk\n");
|
||||
fprintf(fh, "Sender: %s\n", envelope);
|
||||
fprintf(fh, "\n");
|
||||
p = loadfile("etc/help");
|
||||
p = loadfile(MasterConfig->help_file);
|
||||
if (p != NULL) {
|
||||
fprintf(fh, "%s\n", p);
|
||||
free(p);
|
||||
|
||||
13
hermes.c
13
hermes.c
@ -235,12 +235,11 @@ hermes_main(char * incoming_mail, const char * listname)
|
||||
dst += len;
|
||||
*dst = '\0';
|
||||
|
||||
/* Add custom headers if there are some. */
|
||||
/* Add custom headers if there are any. */
|
||||
|
||||
buffer = text_easy_sprintf("lists/%s/header", listname);
|
||||
if (stat(buffer, &sb) == 0)
|
||||
if (stat(ListConfig->header_file, &sb) == 0)
|
||||
{
|
||||
char* p = loadfile(buffer);
|
||||
char* p = loadfile(ListConfig->header_file);
|
||||
if (p == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed reading the header file for list \"%s\".", listname);
|
||||
@ -249,14 +248,12 @@ hermes_main(char * incoming_mail, const char * listname)
|
||||
strcpy(dst, p);
|
||||
dst += strlen(p);
|
||||
free(p);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/* Add the signature if there is one. */
|
||||
|
||||
buffer = text_easy_sprintf("lists/%s/signature", listname);
|
||||
if (stat(buffer, &sb) == 0) {
|
||||
buffer = loadfile(buffer);
|
||||
if (stat(ListConfig->sig_file, &sb) == 0) {
|
||||
buffer = loadfile(ListConfig->sig_file);
|
||||
if (buffer == NULL) {
|
||||
syslog(LOG_ERR, "Failed reading the signature file for list \"%s\".", listname);
|
||||
exit(1);
|
||||
|
||||
92
index.c
92
index.c
@ -32,18 +32,11 @@ GenIndex(struct Mail * MailStruct,
|
||||
const char * defaultlist)
|
||||
{
|
||||
const struct PD_Config * MasterConfig = getMasterConfig();
|
||||
const struct List_Config * ListConfig;
|
||||
FILE * fh;
|
||||
const char * address = NULL;
|
||||
char from[4096];
|
||||
char envelope[4096];
|
||||
char * description;
|
||||
char * currLine;
|
||||
char * nextLine;
|
||||
char * buffer;
|
||||
DIR * dirp;
|
||||
struct dirent * entry;
|
||||
unsigned int entry_num;
|
||||
char * p;
|
||||
|
||||
address = (MailStruct->Reply_To) ? MailStruct->Reply_To : MailStruct->From;
|
||||
|
||||
@ -71,84 +64,17 @@ GenIndex(struct Mail * MailStruct,
|
||||
fprintf(fh, "Precedence: junk\n");
|
||||
fprintf(fh, "Sender: %s\n", envelope);
|
||||
fprintf(fh, "\n");
|
||||
fprintf(fh, "Index of available lists:\n");
|
||||
fprintf(fh, "=========================\n\n");
|
||||
|
||||
/* Scan the directory. */
|
||||
|
||||
entry_num = 0;
|
||||
dirp = opendir("lists");
|
||||
if (dirp == NULL) {
|
||||
fprintf(fh, \
|
||||
"An internal error has occured while processing your request. The\n" \
|
||||
"server administrator has been notified. You don't need to re-submit\n" \
|
||||
"your request, it will be processed as soon as the problem has been\n" \
|
||||
"remedied.\n");
|
||||
CloseMailer(fh);
|
||||
syslog(LOG_ERR, "Failed to read directory \"lists\": %m");
|
||||
return -1;
|
||||
}
|
||||
while((entry = readdir(dirp)) != NULL) {
|
||||
if (!strcasecmp(entry->d_name, ".") || !strcasecmp(entry->d_name, ".."))
|
||||
continue;
|
||||
if (isValidListName(entry->d_name) == FALSE)
|
||||
continue;
|
||||
|
||||
ListConfig = getListConfig(entry->d_name);
|
||||
if (ListConfig->showonindex == FALSE)
|
||||
continue;
|
||||
entry_num++;
|
||||
|
||||
/* Print stuff to the mail. */
|
||||
|
||||
fprintf(fh, "%s", entry->d_name);
|
||||
p = loadfile(MasterConfig->index_file);
|
||||
if (p != NULL)
|
||||
{
|
||||
int i;
|
||||
i = 40 - strlen(entry->d_name);
|
||||
if (i < 1)
|
||||
i = 1;
|
||||
while(i-- > 0)
|
||||
fputc(' ', fh);
|
||||
fprintf(fh, "%s\n", p);
|
||||
free(p);
|
||||
}
|
||||
if (ListConfig->allowpubsub == TRUE) {
|
||||
if (ListConfig->listtype == LIST_MODERATED)
|
||||
fprintf(fh, "(moderated mailing list)\n");
|
||||
else
|
||||
fprintf(fh, "(public mailing list)\n");
|
||||
else
|
||||
{
|
||||
syslog(LOG_ERR, "There is no index file for Petidomo!");
|
||||
fprintf(fh, "No index available.\n");
|
||||
}
|
||||
else
|
||||
fprintf(fh, "(closed mailing list)\n");
|
||||
|
||||
buffer = text_easy_sprintf("lists/%s/description", entry->d_name);
|
||||
description = loadfile(buffer);
|
||||
if (description == NULL) {
|
||||
fprintf(fh, " no description available\n\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (currLine = description; *currLine != '\0'; currLine = nextLine) {
|
||||
nextLine = text_find_next_line(currLine);
|
||||
if (nextLine[-1] == '\n')
|
||||
nextLine[-1] = '\0';
|
||||
fprintf(fh, " %s\n", currLine);
|
||||
}
|
||||
fprintf(fh, "\n");
|
||||
free(description);
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
switch (entry_num) {
|
||||
case 0:
|
||||
fprintf(fh, "No mailing lists found.\n");
|
||||
break;
|
||||
case 1:
|
||||
fprintf(fh, "Found %d mailing list.\n", entry_num);
|
||||
break;
|
||||
default:
|
||||
fprintf(fh, "Found %d mailing lists.\n", entry_num);
|
||||
}
|
||||
|
||||
CloseMailer(fh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
4
mailer.c
4
mailer.c
@ -141,6 +141,7 @@ int
|
||||
ListMail(const char * envelope, const char * listname, const struct Mail * MailStruct)
|
||||
{
|
||||
const struct PD_Config * MasterConfig = getMasterConfig();
|
||||
const struct List_Config * ListConfig = getListConfig(listname);
|
||||
char ** arguments;
|
||||
u_int arguments_num = 256;
|
||||
char buffer[256];
|
||||
@ -164,8 +165,7 @@ ListMail(const char * envelope, const char * listname, const struct Mail * MailS
|
||||
|
||||
/* Load the list of recipients. */
|
||||
|
||||
sprintf(buffer, "lists/%s/list", listname);
|
||||
listfile = loadfile(buffer);
|
||||
listfile = loadfile(ListConfig->address_file);
|
||||
if (listfile == NULL)
|
||||
return 1;
|
||||
|
||||
|
||||
4
main.c
4
main.c
@ -42,8 +42,8 @@ main(int argc, char * argv[])
|
||||
argv_t args[] =
|
||||
{
|
||||
{ARGV_MAND, "mode", ARGV_CHAR_P, &mode, "mode", "listserv, deliver, or approve."},
|
||||
{ARGV_MAYBE, "listname", ARGV_CHAR_P, &listname, "listname", "Default mailing list."},
|
||||
{ARGV_MAYBE, "masterconf", ARGV_CHAR_P, &masterconfig_path, "masterconf", "Path to petidomo.conf."},
|
||||
{ARGV_MAYBE, 0L, ARGV_CHAR_P, &listname, "listname", "Default mailing list."},
|
||||
{ARGV_LAST}
|
||||
};
|
||||
|
||||
@ -66,8 +66,6 @@ main(int argc, char * argv[])
|
||||
}
|
||||
MasterConfig = getMasterConfig();
|
||||
|
||||
return 0;
|
||||
|
||||
/* Load the file from standard input and save it, so that it isn't
|
||||
lost in case of an error. */
|
||||
|
||||
|
||||
10
members.c
10
members.c
@ -99,12 +99,12 @@ SendSubscriberList(struct Mail * MailStruct,
|
||||
|
||||
/* Okay, send the address list back. */
|
||||
|
||||
buffer = text_easy_sprintf("lists/%s/list", listname);
|
||||
buffer = loadfile(buffer);
|
||||
if (buffer == NULL) {
|
||||
syslog(LOG_ERR, "Failed to open file \"~petidomo/lists/%s/list\"", listname);
|
||||
buffer = loadfile(ListConfig->address_file);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to open file \"%s\"", ListConfig->address_file);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fh = vOpenMailer(envelope, address, NULL);
|
||||
if (fh != NULL) {
|
||||
|
||||
43
petidomo.h
43
petidomo.h
@ -50,32 +50,45 @@
|
||||
|
||||
/********** config.c **********/
|
||||
|
||||
struct PD_Config {
|
||||
struct PD_Config
|
||||
{
|
||||
char * fqdn;
|
||||
char * master_password;
|
||||
char * mta;
|
||||
char * mta_options;
|
||||
};
|
||||
char * list_dir;
|
||||
char * help_file;
|
||||
char * acl_file;
|
||||
char * index_file;
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
LIST_OPEN,
|
||||
LIST_CLOSED,
|
||||
LIST_MODERATED
|
||||
};
|
||||
};
|
||||
|
||||
struct List_Config {
|
||||
struct List_Config
|
||||
{
|
||||
unsigned int listtype;
|
||||
int allowpubsub;
|
||||
int allowaliensub;
|
||||
int allowmembers;
|
||||
int showonindex;
|
||||
char * fqdn;
|
||||
char * admin_password;
|
||||
char * posting_password;
|
||||
char * postingfilter;
|
||||
char * archivepath;
|
||||
char * reply_to;
|
||||
};
|
||||
char * intro_file;
|
||||
char * desc_file;
|
||||
char * sig_file;
|
||||
char * header_file;
|
||||
char * acl_file;
|
||||
char * list_dir;
|
||||
char * address_file;
|
||||
};
|
||||
|
||||
int InitPetidomo(const char* masterconfig_path);
|
||||
const struct PD_Config *getMasterConfig(void);
|
||||
@ -83,7 +96,8 @@ const struct List_Config *getListConfig(const char* listname);
|
||||
|
||||
/********** rfcparse.c **********/
|
||||
|
||||
struct Mail {
|
||||
struct Mail
|
||||
{
|
||||
char * Header;
|
||||
char * Body;
|
||||
char * Envelope;
|
||||
@ -93,7 +107,7 @@ struct Mail {
|
||||
char * Message_Id;
|
||||
char * Approve;
|
||||
char * ListSignature;
|
||||
};
|
||||
};
|
||||
|
||||
void RemoveCarrigeReturns(char *buffer);
|
||||
int isRFC822Address(const char *buffer);
|
||||
@ -128,8 +142,8 @@ int MailFilter(struct Mail *MailStruct, const char *filter);
|
||||
/********** acl.c **********/
|
||||
|
||||
int checkACL(struct Mail *, const char *, int *, char **);
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ACL_DROP,
|
||||
ACL_PASS,
|
||||
ACL_REDIRECT,
|
||||
@ -138,7 +152,7 @@ enum {
|
||||
ACL_REJECTWITH,
|
||||
ACL_FILTER,
|
||||
ACL_NONE
|
||||
};
|
||||
};
|
||||
|
||||
/********** handleacl.c **********/
|
||||
|
||||
@ -199,10 +213,11 @@ int AddAddress(struct Mail *MailStruct, const char *param1, const char *param2,
|
||||
|
||||
/********** parsearray.c **********/
|
||||
|
||||
struct Parse {
|
||||
struct Parse
|
||||
{
|
||||
const char * keyword;
|
||||
int (*handleCommand)(struct Mail *, const char *, const char *, const char *);
|
||||
};
|
||||
};
|
||||
extern struct Parse ParseArray[];
|
||||
|
||||
#endif /* !defined(__PETIDOMO_H__) */
|
||||
|
||||
@ -231,10 +231,9 @@ AddAddress(struct Mail * MailStruct,
|
||||
|
||||
/* Okay, add the address to the list. */
|
||||
|
||||
buffer = text_easy_sprintf("lists/%s/list", listname);
|
||||
fh = fopen(buffer, "a");
|
||||
fh = fopen(ListConfig->address_file, "a");
|
||||
if (fh == NULL) {
|
||||
syslog(LOG_ERR, "Failed to open file \"%s\" for writing: %m", buffer);
|
||||
syslog(LOG_ERR, "Failed to open file \"%s\" for writing: %m", ListConfig->address_file);
|
||||
return -1;
|
||||
}
|
||||
fprintf(fh, "%s\n", address);
|
||||
@ -289,8 +288,7 @@ AddAddress(struct Mail * MailStruct,
|
||||
|
||||
/* Send introduction text to the new member. */
|
||||
|
||||
buffer = text_easy_sprintf("lists/%s/introduction", listname);
|
||||
p = loadfile(buffer);
|
||||
p = loadfile(ListConfig->intro_file);
|
||||
if (p != NULL) {
|
||||
fh = vOpenMailer(envelope, address, NULL);
|
||||
if (fh != NULL) {
|
||||
|
||||
76
tool.c
76
tool.c
@ -28,40 +28,50 @@
|
||||
bool
|
||||
isSubscribed(const char * listname, const char * address,
|
||||
char ** listfile, char ** subscriber, bool dofuzzy)
|
||||
{
|
||||
{
|
||||
const struct List_Config * ListConfig;
|
||||
struct stat sb;
|
||||
char * buffer;
|
||||
char * list;
|
||||
char * p;
|
||||
unsigned int len;
|
||||
bool rc;
|
||||
bool rc;
|
||||
|
||||
buffer = text_easy_sprintf("lists/%s/list", listname);
|
||||
if (stat(buffer, &sb) != 0)
|
||||
return FALSE;
|
||||
list = loadfile(buffer);
|
||||
if (isValidListName(listname))
|
||||
ListConfig = getListConfig(listname);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
if (stat(ListConfig->address_file, &sb) != 0)
|
||||
return FALSE;
|
||||
list = loadfile(ListConfig->address_file);
|
||||
if (list == NULL)
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
|
||||
for (len = strlen(address), p = list; *p != '\0'; p = text_find_next_line(p)) {
|
||||
for (len = strlen(address), p = list; *p != '\0'; p = text_find_next_line(p))
|
||||
{
|
||||
if (strncasecmp(p, address, len) == 0 &&
|
||||
(p == list || p[-1] == '\n') &&
|
||||
(isspace((int)p[len]) || p[len] == '\0')) {
|
||||
(isspace((int)p[len]) || p[len] == '\0'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*p == '\0' && dofuzzy == TRUE) {
|
||||
if (*p == '\0' && dofuzzy == TRUE)
|
||||
{
|
||||
address = buildFuzzyMatchAddress(address);
|
||||
if (address != NULL) {
|
||||
for (len = strlen(address), p = list; *p != '\0'; p = text_find_next_line(p)) {
|
||||
if (address != NULL)
|
||||
{
|
||||
for (len = strlen(address), p = list; *p != '\0'; p = text_find_next_line(p))
|
||||
{
|
||||
if (text_easy_pattern_match(p, address) == TRUE &&
|
||||
(p == list || p[-1] == '\n')) {
|
||||
(p == list || p[-1] == '\n'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Save the returncode now, because p may be invalid in a few
|
||||
@ -71,18 +81,19 @@ isSubscribed(const char * listname, const char * address,
|
||||
|
||||
/* Did the caller want results back? Then give them to him. */
|
||||
|
||||
if (listfile != NULL) {
|
||||
if (listfile != NULL)
|
||||
{
|
||||
*listfile = list;
|
||||
if (subscriber != NULL)
|
||||
*subscriber = (*p != '\0') ? p : NULL;
|
||||
}
|
||||
*subscriber = (*p != '\0') ? p : NULL;
|
||||
}
|
||||
else
|
||||
free(list);
|
||||
free(list);
|
||||
|
||||
/* Return the result. */
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
buildFuzzyMatchAddress(const char * address)
|
||||
@ -118,24 +129,27 @@ buildFuzzyMatchAddress(const char * address)
|
||||
|
||||
bool
|
||||
isValidListName(const char * listname)
|
||||
{
|
||||
{
|
||||
struct stat sb;
|
||||
char * buffer;
|
||||
const struct PD_Config * MasterConfig = getMasterConfig();
|
||||
|
||||
assert(listname != NULL);
|
||||
|
||||
if ((strchr(listname, '/') != NULL) || (strchr(listname, ':') != NULL))
|
||||
return FALSE;
|
||||
|
||||
buffer = text_easy_sprintf("lists/%s", listname);
|
||||
buffer = text_easy_sprintf("%s/%s/config", MasterConfig->list_dir, listname);
|
||||
if (stat(buffer, &sb) != 0)
|
||||
return FALSE; /* Doesn't exist at all. */
|
||||
else if ((sb.st_mode & S_IFDIR) == 0)
|
||||
return FALSE; /* Entry isn't a directory. */
|
||||
else {
|
||||
buffer = text_easy_sprintf("lists/%s/config", listname);
|
||||
{
|
||||
free(buffer);
|
||||
buffer = text_easy_sprintf("%s/%s.config", MasterConfig->list_dir, listname);
|
||||
if (stat(buffer, &sb) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
{
|
||||
free(buffer);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
free(buffer);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,10 +230,9 @@ DeleteAddress(struct Mail * MailStruct,
|
||||
}
|
||||
}
|
||||
else {
|
||||
buffer = text_easy_sprintf("lists/%s/list", listname);
|
||||
fh = fopen(buffer, "w");
|
||||
fh = fopen(ListConfig->address_file, "w");
|
||||
if (fh == NULL) {
|
||||
syslog(LOG_ERR, "Failed to open file \"%s\" for writing: %m", buffer);
|
||||
syslog(LOG_ERR, "Failed to open file \"%s\" for writing: %m", ListConfig->address_file);
|
||||
return -1;
|
||||
}
|
||||
*p++ = '\0';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user