/********************************************************
* 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 <machine/defs.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#elif HAVE_SYS_TIME
# include <sys/time.h>
#else
# include <time.h>
#endif
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#else
# include <shared/getopt.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <shared/jbstrcpy.h>
#include <shared/path.h>
#include <shared/mystrncpy.h>
#include <shared/node4d.h>
#include <shared/file.h>
#include <shared/fidonet.h>
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);
}
syntax highlighted by Code2HTML, v. 0.9.1