/******************************************************** * File: crashwrite.c * Created at Sun Jan 28 22:10:33 MSK 2001 by raorn // raorn@binec.ru * CrashWrite - text-to-pkt utility * $Id: crashwrite.c,v 1.18 2002/02/04 22:13:30 raorn Exp $ *******************************************************/ #include #include #include #include #include #include #if TIME_WITH_SYS_TIME # include # include #elif HAVE_SYS_TIME # include #else # include #endif #ifdef HAVE_GETOPT_H # include #else # include #endif #ifdef HAVE_UNISTD_H # include #endif #include #include #include #include #include #include uchar verstr[] = "CrashWrite/" PLATFORM_NAME " " VERSION; #define PKTFROMADDR 128 #define PKTTOADDR 129 #define FROMNAME 130 #define FROMADDR 131 #define TONAME 132 #define TOADDR 133 #define NOMSGID 134 #define NOTEAR 135 #define SHOWVER 136 uchar PktMsgHeader[SIZE_PKTMSGHEADER]; uchar PktHeader[SIZE_PKTHEADER]; bool nomem, diskfull; ushort getuword(uchar * buf, ulong offset) { return (ushort) (buf[offset] + 256 * buf[offset + 1]); } void putuword(uchar * buf, ulong offset, ushort num) { buf[offset] = num % 256; buf[offset + 1] = num / 256; } void MakeFidoDate(time_t tim, uchar * dest) { struct tm *tp; time_t t; static uchar *monthnames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" }; t = tim; tp = localtime(&t); snprintf(dest, 20, "%02d %s %02d %02d:%02d:%02d", tp->tm_mday, monthnames[tp->tm_mon], tp->tm_year % 100, tp->tm_hour, tp->tm_min, tp->tm_sec); } void WriteNull(FILE *ofh, uchar * str) { fwrite(str, (ulong) (strlen(str) + 1), 1, ofh); } int main(int argc, char **argv) { static struct Node4D from4d = {0, 0, 0, 0}, to4d = {0, 0, 0, 0}, pktfrom4d = {0, 0, 0, 0}, pktto4d = {0, 0, 0, 0}; FILE *ifh, *ofh; time_t t; struct tm *tp; ulong pktnum, c, serial; ushort attr; static uchar fromname[36] = "CrashWrite", toname[36] = "All", subject[72] = "Information", origin[80] = "Another user of CrashEcho", datetime[20], password[8]; uchar *area = NULL, *file = NULL; int fileattach = 0, nomsgid = 0, notear = 0; uchar pktname[30], fullname[200], *readbuf, *outdir = NULL; int got_pf = 0, got_pt = 0, got_tearline = 0; static struct option lopts[] = { {"help", 0, NULL, 'h'}, {"out-dir", required_argument, NULL, 'd'}, {"pkt-from", required_argument, NULL, PKTFROMADDR}, {"pkt-to", required_argument, NULL, PKTTOADDR}, {"password", required_argument, NULL, 'p'}, {"from-name", required_argument, NULL, FROMNAME}, {"from-addr", required_argument, NULL, FROMADDR}, {"to-name", required_argument, NULL, TONAME}, {"to-addr", required_argument, NULL, TOADDR}, {"subject", required_argument, NULL, 'S'}, {"area", required_argument, NULL, 'A'}, {"origin", required_argument, NULL, 'O'}, {"file-attach", 0, NULL, 'a'}, {"no-msgid", 0, NULL, NOMSGID}, {"no-tearline", 0, NULL, NOTEAR}, {"file", required_argument, NULL, 'f'}, {"version", 0, NULL, SHOWVER}, {0, 0, 0, 0} }; static uchar optstr[] = "+hd:p:S:A:O:af:"; static uchar helpstr[] = "Usage: crashwrite [OPTION]... [FILE]...\n" "Write FILEs to Type-2+ FTN packet.\n" "\n" " -h, --help display this help and exit\n" " -d, --out-dir=PATH output directory\n" " this argument is mandatory!\n" " --pkt-from=ADDR packet's originating address\n" " --pkt-to=ADDR packet's destination address\n" " -p, --password=TEXT packet's password\n" " --from-name=NAME from name of the message\n" " --from-addr=ADDR from address of the message\n" " --to-name=NAME to name of the message\n" " --to-addr=ADDR to address of the message\n" " -S, --subject=TEXT the subject of the message (or file if file-attach)\n" " -A, --area=TAG the area the message should be posted in; if you skip\n" " this option, the message will be sent as netmail.\n" " -O, --origin=TEXT the origin line for echomail message\n" " -a, --file-attach sets the file-attach flag for netmails; the filename\n" " should be put in the subject\n" " --no-msgid prevents CrashWrite from adding a ^aMSGID kludge\n" " --no-tearline prevents CrashWrite from adding tearline\n" " -f, --file=FILE the name of a text file that should be included as\n" " message's text\n" " --version print version number and exit\n\n"; int ch, lopt_index; while((ch=getopt_long(argc, argv, optstr, lopts, &lopt_index)) != -1){ switch(ch){ case 'h': case '?': default: fprintf(stderr, helpstr); exit(EXIT_OK); /* Not reached */ case SHOWVER: fprintf(stderr, "%s\n", verstr); exit(EXIT_OK); /* Not reached */ case 'd': outdir = optarg; break; case PKTFROMADDR: if (!(Parse4D((uchar *) optarg, &pktfrom4d))) { fprintf(stderr, "Invalid address \"%s\"\n", (uchar *) optarg); exit(EXIT_ERROR); } got_pf = 1; break; case PKTTOADDR: if (!(Parse4D((uchar *) optarg, &pktto4d))) { fprintf(stderr, "Invalid address \"%s\"\n", (uchar *) optarg); exit(EXIT_ERROR); } got_pt = 1; break; case 'p': strncpy(password, (uchar *) optarg, 8); break; case FROMNAME: mystrncpy(fromname, (uchar *) optarg, 36); break; case FROMADDR: if (!(Parse4D((uchar *) optarg, &from4d))) { fprintf(stderr, "Invalid address \"%s\"\n", (uchar *) optarg); exit(EXIT_ERROR); } break; case TONAME: mystrncpy(toname, (uchar *) optarg, 36); break; case TOADDR: if (!(Parse4D((uchar *) optarg, &to4d))) { fprintf(stderr, "Invalid address \"%s\"\n", (uchar *) optarg); exit(EXIT_ERROR); } break; case 'S': mystrncpy(subject, (uchar *) optarg, 72); break; case 'A': if (optarg[0]) area = optarg; break; case 'O': mystrncpy(origin, (uchar *) optarg, 80); break; case 'a': fileattach = 1; break; case NOMSGID: nomsgid = 1; break; case NOTEAR: notear = 1; break; case 'f': file = optarg; break; } } argc -= optind; argv += optind; if(argc) file = argv[0]; if(!outdir){ fprintf(stderr, helpstr); exit(EXIT_ERROR); } if(!got_pf) Copy4D(&pktfrom4d, &from4d); if(!got_pt) Copy4D(&pktto4d, &to4d); if(!(readbuf = malloc(4096))){ fprintf(stderr, "Out of memory\n"); exit(EXIT_ERROR); } do { time(&t); tp = localtime(&t); /* Create pkt file */ serial = 0; do { t = time(NULL); pktnum = (t << 8) + serial; serial++; snprintf(pktname, 30, "%08lx.pkt", pktnum); MakeFullPath(outdir, pktname, fullname, 200); } while (Exists(fullname)); if (!(ofh = fopen(fullname, "wb"))) { fprintf(stderr, "Unable to create packet %s\n", fullname); fprintf(stderr, "Error: %s\n", strerror(errno)); continue; } if (file && strcmp(file, "-")) { printf("Appending %s...\n", (uchar *) file); if (!(ifh = fopen(file, "rt"))) { fprintf(stderr, "Unable to open \"%s\" for reading\n", file); fprintf(stderr, "Error: %s\n", strerror(errno)); fclose(ofh); unlink(fullname); continue; } } else ifh = stdin; /* Create packet header */ putuword(PktHeader, PKTHEADER_ORIGNODE, pktfrom4d.Node); putuword(PktHeader, PKTHEADER_DESTNODE, pktto4d.Node); putuword(PktHeader, PKTHEADER_DAY, tp->tm_mday); putuword(PktHeader, PKTHEADER_MONTH, tp->tm_mon); putuword(PktHeader, PKTHEADER_YEAR, tp->tm_year + 1900); putuword(PktHeader, PKTHEADER_HOUR, tp->tm_hour); putuword(PktHeader, PKTHEADER_MINUTE, tp->tm_min); putuword(PktHeader, PKTHEADER_SECOND, tp->tm_sec); putuword(PktHeader, PKTHEADER_BAUD, 0); putuword(PktHeader, PKTHEADER_PKTTYPE, 2); putuword(PktHeader, PKTHEADER_ORIGNET, pktfrom4d.Net); putuword(PktHeader, PKTHEADER_DESTNET, pktto4d.Net); PktHeader[PKTHEADER_PRODCODELOW] = 0xfe; PktHeader[PKTHEADER_REVMAJOR] = VERSION_MAJOR; putuword(PktHeader, PKTHEADER_QORIGZONE, pktfrom4d.Zone); putuword(PktHeader, PKTHEADER_QDESTZONE, pktto4d.Zone); putuword(PktHeader, PKTHEADER_AUXNET, 0); putuword(PktHeader, PKTHEADER_CWVALIDCOPY, 0x0100); PktHeader[PKTHEADER_PRODCODEHIGH] = 0; PktHeader[PKTHEADER_REVMINOR] = VERSION_MINOR; putuword(PktHeader, PKTHEADER_CAPABILWORD, 0x0001); putuword(PktHeader, PKTHEADER_ORIGZONE, pktfrom4d.Zone); putuword(PktHeader, PKTHEADER_DESTZONE, pktto4d.Zone); putuword(PktHeader, PKTHEADER_ORIGPOINT, pktfrom4d.Point); putuword(PktHeader, PKTHEADER_DESTPOINT, pktto4d.Point); PktHeader[PKTHEADER_PRODDATA] = 0; PktHeader[PKTHEADER_PRODDATA + 1] = 0; PktHeader[PKTHEADER_PRODDATA + 2] = 0; PktHeader[PKTHEADER_PRODDATA + 3] = 0; for (c = 0; c < 8; c++) PktHeader[PKTHEADER_PASSWORD + c] = 0; if (password[0]) strncpy(&PktHeader[PKTHEADER_PASSWORD], password, 8); /* Create message header */ attr = 0; if (!area) { attr |= FLAG_PVT; if (fileattach) attr |= FLAG_FILEATTACH; } putuword(PktMsgHeader, PKTMSGHEADER_PKTTYPE, 0x0002); putuword(PktMsgHeader, PKTMSGHEADER_ORIGNODE, from4d.Node); putuword(PktMsgHeader, PKTMSGHEADER_DESTNODE, to4d.Node); putuword(PktMsgHeader, PKTMSGHEADER_ORIGNET, from4d.Net); putuword(PktMsgHeader, PKTMSGHEADER_DESTNET, to4d.Net); putuword(PktMsgHeader, PKTMSGHEADER_ATTR, attr); putuword(PktMsgHeader, PKTMSGHEADER_COST, 0); MakeFidoDate(t, datetime); printf("Writing...\n"); printf(" From: %-36s (%u:%u/%u.%u)\n", fromname, from4d.Zone, from4d.Net, from4d.Node, from4d.Point); printf(" To: %-36s (%u:%u/%u.%u)\n", toname, to4d.Zone, to4d.Net, to4d.Node, to4d.Point); printf(" Subj: %s\n", subject); printf(" Date: %s\n", datetime); fwrite(PktHeader, SIZE_PKTHEADER, 1, ofh); fwrite(PktMsgHeader, SIZE_PKTMSGHEADER, 1, ofh); WriteNull(ofh, datetime); WriteNull(ofh, toname); WriteNull(ofh, fromname); WriteNull(ofh, subject); if (area) { fprintf(ofh, "AREA:%s\015", area); } else { if (from4d.Point) fprintf(ofh, "\001FMPT %u\015", from4d.Point); if (to4d.Point) fprintf(ofh, "\001TOPT %u\015", to4d.Point); fprintf(ofh, "\001INTL %u:%u/%u %u:%u/%u\015", to4d.Zone, to4d.Net, to4d.Node, from4d.Zone, from4d.Net, from4d.Node); } if (!nomsgid) { fprintf(ofh, "\001MSGID: %u:%u/%u.%u %08lx\015", from4d.Zone, from4d.Net, from4d.Node, from4d.Point, pktnum); } fprintf(ofh, "\001PID: CrashWrite " VERSION "\015"); while (fgets(readbuf, 4096, ifh)) { if (readbuf[0] != 0) readbuf[strlen(readbuf) - 1] = 0; got_tearline = !strncmp(readbuf, "--- ", 4) || !strcmp(readbuf, "---") ? 1 : 0; fprintf(ofh, "%s\015", readbuf); } if(!notear && !got_tearline) fprintf(ofh, "--- %s\015", verstr); if (area) fprintf(ofh, " * Origin: %s (%u:%u/%u.%u)\015", origin, from4d.Zone, from4d.Net, from4d.Node, from4d.Point); fwrite("", 1, 1, ofh); fwrite("", 1, 1, ofh); fwrite("", 1, 1, ofh); fclose(ofh); if(ifh != stdin) fclose(ifh); argc--; argv++; if (argc > 0) file = argv[0]; } while(argc > 0); free(readbuf); exit(EXIT_OK); }