This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/utils/mgpost/mgpost.c
2018-08-01 11:13:00 +10:00

365 lines
7.7 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <sys/file.h>
#include "../../deps/jamlib/jam.h"
#include "../../src/inih/ini.h"
#include "../../deps/libuuid/uuid.h"
s_JamBase *open_jam_base(char *path) {
int ret;
s_JamBase *jb;
ret = JAM_OpenMB((char *)path, &jb);
if (ret != 0) {
if (ret == JAM_IO_ERROR) {
free(jb);
ret = JAM_CreateMB((char *)path, 1, &jb);
if (ret != 0) {
free(jb);
return NULL;
}
}
}
return jb;
}
struct fido_addr {
unsigned short zone;
unsigned short net;
unsigned short node;
unsigned short point;
};
struct fido_addr *parse_fido_addr(const char *str) {
struct fido_addr *ret = (struct fido_addr *)malloc(sizeof(struct fido_addr));
int c;
int state = 0;
ret->zone = 0;
ret->net = 0;
ret->node = 0;
ret->point = 0;
for (c=0;c<strlen(str);c++) {
switch(str[c]) {
case ':':
state = 1;
break;
case '/':
state = 2;
break;
case '.':
state = 3;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
switch (state) {
case 0:
ret->zone = ret->zone * 10 + (str[c] - '0');
break;
case 1:
ret->net = ret->net * 10 + (str[c] - '0');
break;
case 2:
ret->node = ret->node * 10 + (str[c] - '0');
break;
case 3:
ret->point = ret->point * 10 + (str[c] - '0');
break;
}
}
break;
default:
free(ret);
return NULL;
}
}
return ret;
}
struct msg_t {
int echo;
char *bbs_path;
char *filename;
char *jambase;
char *from;
char *subject;
char *origin;
struct fido_addr *localAddress;
int maginode;
};
static int handler(void* user, const char* section, const char* name,
const char* value)
{
struct msg_t *msg = (struct msg_t *)user;
if (strcasecmp(section, "main") == 0) {
if (strcasecmp(name, "echomail") == 0) {
if (strcasecmp(value, "true") == 0) {
msg->echo = 1;
} else if (strcasecmp(value, "magi") == 0) {
msg->echo = 2;
} else {
msg->echo = 0;
}
} else if (strcasecmp(name, "BBS Path") == 0) {
msg->bbs_path = strdup(value);
} else if (strcasecmp(name, "Message File") == 0) {
msg->filename = strdup(value);
} else if (strcasecmp(name, "JAM Base") == 0) {
msg->jambase = strdup(value);
} else if (strcasecmp(name, "From") == 0) {
msg->from = strdup(value);
} else if (strcasecmp(name, "Subject") == 0) {
msg->subject = strdup(value);
} else if (strcasecmp(name, "Local AKA") == 0) {
msg->localAddress = parse_fido_addr(value);
} else if (strcasecmp(name, "Origin Line") == 0) {
msg->origin = strdup(value);
} else if (strcasecmp(name, "Magi Node") == 0) {
msg->maginode = atoi(value);
}
}
return 1;
}
unsigned long generate_msgid(char *bbs_path) {
char buffer[1024];
unsigned long lastid;
FILE *fptr;
time_t unixtime;
snprintf(buffer, 1024, "%s/msgserial", bbs_path);
unixtime = time(NULL);
fptr = fopen(buffer, "r+");
if (fptr) {
flock(fileno(fptr), LOCK_EX);
fread(&lastid, sizeof(unsigned long), 1, fptr);
if (unixtime > lastid) {
lastid = unixtime;
} else {
lastid++;
}
rewind(fptr);
fwrite(&lastid, sizeof(unsigned long), 1, fptr);
flock(fileno(fptr), LOCK_UN);
fclose(fptr);
} else {
fptr = fopen(buffer, "w");
if (fptr) {
lastid = unixtime;
flock(fileno(fptr), LOCK_EX);
fwrite(&lastid, sizeof(unsigned long), 1, fptr);
flock(fileno(fptr), LOCK_UN);
fclose(fptr);
} else {
printf("Unable to open message id log\n");
return 0;
}
}
return lastid;
}
int main(int argc, char **argv) {
char buffer[1024];
char *body;
char *subject;
char *from;
FILE *fptr;
int len;
int totlen;
time_t thetime;
int z;
int i;
uuid_t myuuid;
struct msg_t msg;
if (argc < 2) {
printf("Usage: %s inifile\n", argv[0]);
exit(1);
}
if (ini_parse(argv[1], handler, &msg) <0) {
fprintf(stderr, "Unable to load configuration ini (%s)!\n", argv[1]);
exit(-1);
}
s_JamBase *jb;
s_JamMsgHeader jmh;
s_JamSubPacket* jsp;
s_JamSubfield jsf;
fptr = fopen(msg.filename, "r");
if (!fptr) {
printf("Unable to open %s\n", msg.filename);
exit(1);
}
body = NULL;
totlen = 0;
len = fread(buffer, 1, 1024, fptr);
while (len > 0) {
totlen += len;
if (body == NULL) {
body = (char *)malloc(totlen + 1);
} else {
body = (char *)realloc(body, totlen + 1);
}
memcpy(&body[totlen - len], buffer, len);
body[totlen] = '\0';
len = fread(buffer, 1, 1024, fptr);
}
fclose(fptr);
for (i=0;i<totlen;i++) {
if (body[i] == '\n') {
body[i] = '\r';
}
}
if (msg.echo == 1) {
if (msg.localAddress->point == 0) {
snprintf(buffer, 1024, "\r--- mgpost\r * Origin: %s (%d:%d/%d)\r", msg.origin, msg.localAddress->zone, msg.localAddress->net, msg.localAddress->node);
} else {
snprintf(buffer, 1024, "\r--- mgpost\r * Origin: %s (%d:%d/%d.%d)\r", msg.origin, msg.localAddress->zone, msg.localAddress->net, msg.localAddress->node, msg.localAddress->point);
}
} else if (msg.echo == 2) {
snprintf(buffer, 1024, "\r--- mgpost\r * Origin: %s (@%d)\r", msg.maginode);
}
totlen += strlen(buffer);
body = (char *)realloc(body, totlen + 1);
memcpy(&body[totlen - strlen(buffer)], buffer, strlen(buffer));
body[totlen] = '\0';
jb = open_jam_base(msg.jambase);
if (!jb) {
printf("Unable to open JAM base %s\n", msg.jambase);
exit(1);
}
thetime = time(NULL);
JAM_ClearMsgHeader( &jmh );
jmh.DateWritten = thetime;
jmh.Attribute |= JAM_MSG_LOCAL;
if (!msg.echo) {
jmh.Attribute |= JAM_MSG_TYPELOCAL;
} else {
jmh.Attribute |= JAM_MSG_TYPEECHO;
}
jsp = JAM_NewSubPacket();
jsf.LoID = JAMSFLD_SENDERNAME;
jsf.HiID = 0;
jsf.DatLen = strlen(msg.from);
jsf.Buffer = (char *)msg.from;
JAM_PutSubfield(jsp, &jsf);
jsf.LoID = JAMSFLD_RECVRNAME;
jsf.HiID = 0;
jsf.DatLen = 3;
jsf.Buffer = "ALL";
JAM_PutSubfield(jsp, &jsf);
jsf.LoID = JAMSFLD_SUBJECT;
jsf.HiID = 0;
jsf.DatLen = strlen(msg.subject);
jsf.Buffer = (char *)msg.subject;
JAM_PutSubfield(jsp, &jsf);
if (msg.echo == 1) {
if (msg.localAddress->point == 0) {
sprintf(buffer, "%d:%d/%d", msg.localAddress->zone, msg.localAddress->net, msg.localAddress->node);
} else {
sprintf(buffer, "%d:%d/%d.%d", msg.localAddress->zone, msg.localAddress->net, msg.localAddress->node, msg.localAddress->point);
}
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
sprintf(buffer, "%d:%d/%d.%d %08lx", msg.localAddress->zone,
msg.localAddress->net,
msg.localAddress->node,
msg.localAddress->point,
generate_msgid(msg.bbs_path));
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
} else if (msg.echo == 2) {
sprintf(buffer, "%d", msg.maginode);
jsf.LoID = JAMSFLD_OADDRESS;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
memset(buffer, 0, 1024);
uuid_generate(myuuid);
uuid_unparse_lower(myuuid, buffer);
jsf.LoID = JAMSFLD_MSGID;
jsf.HiID = 0;
jsf.DatLen = strlen(buffer);
jsf.Buffer = (char *)buffer;
JAM_PutSubfield(jsp, &jsf);
}
while (1) {
z = JAM_LockMB(jb, 100);
if (z == 0) {
break;
} else if (z == JAM_LOCK_FAILED) {
sleep(1);
} else {
printf("Failed to lock msg base!\n");
break;
}
}
if (z == 0) {
if (JAM_AddMessage(jb, &jmh, jsp, (char *)body, strlen(body))) {
printf("Failed to add message\n");
}
JAM_UnlockMB(jb);
JAM_DelSubPacket(jsp);
}
JAM_CloseMB(jb);
return 0;
}