#include #include #include #include #include #include #include #include #include #include "qwk.h" #include "../../deps/jamlib/jam.h" #include "../../src/inih/ini.h" char *outbound_path; char *message_base_path; char *temp_dir; char *pack_cmd; char *config_file; char *hostid; int bases_exists = 0; struct msg_bases { int baseno; char *path; }; struct msg_bases **msgbases; int msgbasecount = 0; int recursive_delete(const char *dir) { int ret = 0; FTS *ftsp = NULL; FTSENT *curr; char *files[] = { (char *) dir, NULL }; ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL); if (!ftsp) { fprintf(stderr, "%s: fts_open failed: %s\n", dir, strerror(errno)); ret = -1; goto finish; } while ((curr = fts_read(ftsp))) { switch (curr->fts_info) { case FTS_NS: case FTS_DNR: case FTS_ERR: fprintf(stderr, "%s: fts_read error: %s\n", curr->fts_accpath, strerror(curr->fts_errno)); break; case FTS_DC: case FTS_DOT: case FTS_NSOK: break; case FTS_D: break; case FTS_DP: case FTS_F: case FTS_SL: case FTS_SLNONE: case FTS_DEFAULT: if (remove(curr->fts_accpath) < 0) { fprintf(stderr, "%s: Failed to remove: %s", curr->fts_path, strerror(errno)); ret = -1; } break; } } finish: if (ftsp) { fts_close(ftsp); } return ret; } 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; } } else { free(jb); return NULL; } } return jb; } static int handler(void* user, const char* section, const char* name, const char* value) { if (strcasecmp(section, "main") == 0) { if (strcasecmp(name, "message path") == 0) { message_base_path = strdup(value); } else if (strcasecmp(name, "outbound") == 0) { outbound_path = strdup(value); } else if (strcasecmp(name, "temp dir") == 0) { temp_dir = strdup(value); } else if (strcasecmp(name, "pack command") == 0) { pack_cmd = strdup(value); } else if (strcasecmp(name, "host") == 0) { hostid = strdup(value); } } else if (strcasecmp(section, "bases") == 0) { bases_exists = 1; if (msgbasecount == 0) { msgbases = (struct msg_bases **)malloc(sizeof(struct msg_bases *)); } else { msgbases = (struct msg_bases **)realloc(msgbases, sizeof(struct msg_bases *) * (msgbasecount + 1)); } msgbases[msgbasecount] = (struct msg_bases *)malloc(sizeof(struct msg_bases)); msgbases[msgbasecount]->baseno = atoi(name); msgbases[msgbasecount]->path = strdup(value); msgbasecount++; } return 1; } int export_messages(int baseno, char *basefilename, int qwkidx) { int msgcount = 0; s_JamBase *jb; s_JamBaseHeader jbh; s_JamMsgHeader jmh; s_JamSubPacket* jsp; s_JamSubfield jsf; int i; int z; int len; int lenbytes; char buffer[PATH_MAX]; struct QwkHeader qh; struct tm msgtm; FILE *fptr; char text[128]; char *msgbuf; char *msgptr; snprintf(buffer, PATH_MAX, "%s/%s", message_base_path, basefilename); jb = open_jam_base(buffer); if (jb) { JAM_ReadMBHeader(jb, &jbh); if (jbh.ActiveMsgs > 0) { for (i=0;iNumFields;z++) { if (jsp->Fields[z]->LoID == JAMSFLD_SUBJECT) { if (jsp->Fields[z]->DatLen > 24) { len = 24; } else { len = jsp->Fields[z]->DatLen; } memset(qh.MsgSubj, ' ', 25); memcpy(qh.MsgSubj, jsp->Fields[z]->Buffer, len); } if (jsp->Fields[z]->LoID == JAMSFLD_SENDERNAME) { if (jsp->Fields[z]->DatLen > 24) { len = 24; } else { len = jsp->Fields[z]->DatLen; } memset(qh.MsgFrom, ' ', 25); memcpy(qh.MsgFrom, jsp->Fields[z]->Buffer, len); } if (jsp->Fields[z]->LoID == JAMSFLD_RECVRNAME) { if (jsp->Fields[z]->DatLen > 24) { len = 24; } else { len = jsp->Fields[z]->DatLen; } memset(qh.MsgTo, ' ', 25); memcpy(qh.MsgTo, jsp->Fields[z]->Buffer, len); } } qh.Msgstat = ' '; snprintf(buffer, 7, "%d", baseno); memset(qh.Msgnum, ' ', 7); memcpy(qh.Msgnum, buffer, strlen(buffer)); localtime_r(&jmh.DateWritten, &msgtm); snprintf(buffer, PATH_MAX, "%02d-%02d-%02d", msgtm.tm_mon + 1, msgtm.tm_mday, msgtm.tm_year - 100); memcpy(qh.Msgdate, buffer, 8); snprintf(buffer, PATH_MAX, "%02d:%02d", msgtm.tm_hour, msgtm.tm_min); memcpy(qh.Msgtime, buffer, 5); memset(qh.Msgpass, ' ', 12); memset(qh.Msgrply, ' ', 8); len = jmh.TxtLen / 128 + 2; lenbytes = len * 128; msgbuf = (char *)malloc(lenbytes); memset(msgbuf, ' ', lenbytes); JAM_ReadMsgText(jb, jmh.TxtOffset, jmh.TxtLen, msgbuf); msgptr = msgbuf; while (*msgptr != '\0') { if (*msgptr == '\r') { *msgptr = '\xe3'; } msgptr++; } for (z=0;z> 8) & 0xff; qh.Msgoffhi = ((qwkidx + msgcount + 1) >> 8) & 0xff; qh.Msgofflo = (qwkidx + msgcount + 1) & 0xff; qh.Msgtagp = '*'; snprintf(buffer, PATH_MAX, "%s/%s.MSG", temp_dir, hostid); fptr = fopen(buffer, "r+"); if (!fptr) { fptr = fopen(buffer, "w"); if (fptr) { memset(text, ' ', 128); memcpy(text, hostid, strlen(hostid)); fwrite(text, 128, 1, fptr); } else { fprintf(stderr, "UNABLE TO OPEN %s!!\n", buffer); JAM_CloseMB(jb); free(jb); exit(-1); } } else { fseek(fptr, 0, SEEK_END); } fwrite(&qh, 128, 1, fptr); fwrite(msgbuf, lenbytes - 128, 1, fptr); fclose(fptr); jmh.Attribute |= JAM_MSG_SENT; while (1) { z = JAM_LockMB(jb, 100); if (z == 0) { break; } else if (z == JAM_LOCK_FAILED) { sleep(1); } else { JAM_DelSubPacket(jsp); JAM_CloseMB(jb); free(jb); fprintf(stderr, "Error locking JAM base!\n"); exit(-1); } } z =JAM_ChangeMsgHeader(jb, i, &jmh); JAM_UnlockMB(jb); JAM_DelSubPacket(jsp); free(msgbuf); msgcount++; } } } JAM_CloseMB(jb); free(jb); } return msgcount; } int main(int argc, char **argv) { int i; message_base_path = NULL; outbound_path = NULL; temp_dir = NULL; int qwkidx = 0; int msgcount = 0; char buffer[PATH_MAX]; char archive[PATH_MAX]; int ret; if (argc < 2) { fprintf(stderr, "Usage:\n ./qwkscan config.ini\n"); return -1; } config_file = argv[1]; if (ini_parse(config_file, handler, NULL) <0) { fprintf(stderr, "Unable to load configuration ini (%s)!\n", config_file); exit(-1); } if (temp_dir == NULL || message_base_path == NULL || outbound_path == NULL) { fprintf(stderr, "Outbound Path & Temp dir must both be set\n"); exit(-1); } mkdir(temp_dir, 0755); for (i=0;ibaseno, msgbases[i]->path, qwkidx); qwkidx += msgcount; fprintf(stderr, "Exporting from base %d... %d exported\n", msgbases[i]->baseno, msgcount); } if (qwkidx > 0) { snprintf(archive, PATH_MAX, "%s/%s.REP", outbound_path, hostid); char *b = buffer; size_t blen = sizeof buffer; for (const char *p = pack_cmd; *p != '\0' && blen >= 1; ++p) { if (*p != '*') { *b++ = *p; --blen; continue; } p++; size_t alen = 0; if (*p == 'a') { strncpy(b, archive, blen); alen = strlen(archive); } else if (*p == 'f') { snprintf(b, blen, "%s/%s.MSG", temp_dir, hostid); alen = strlen(b); } else if (*p == '*') { *b++ = '*'; alen = 1; } b += alen; blen -= alen; } *b = '\0'; ret = system(buffer); if (ret == -1 || ret >> 8 == 127) { fprintf(stderr, "Failed to run archiver!\n"); return -1; } } recursive_delete(temp_dir); }