home *** CD-ROM | disk | FTP | other *** search
- /*
- * DIGEST
- *
- * Sample program that makes digest message format messages for GIGO mailing
- * lists. This source code is provided so that others may may improvements
- * on it, or so that you may use it as a base for other projects.
- *
- * This program will take all *.MLS (mailing list SENT files), and turn them
- * into *.MLD files (mailing list DONE files). A new *.DLQ file will be
- * created; you will want to move it to a new directory specifically for
- * digest list members, and rename it to *.MLQ at the same time. The
- * resulting file will be ready for GIGO to "EXPLODE" as a normal MLQ file.
- *
- * Jason Fesler March, 1995 jfesler@wmeonlin.sacbbx.com
- */
-
-
- /*
- * For simplicity sake, I include everything, so that I don't have any
- * problems with the compiler knowing what I am talking about.
- */
- #include <time.h>
- #include <io.h>
- #include <fcntl.h>
- #include <sys\stat.h>
- #include <process.h>
- #include <share.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <conio.h>
- #include <ctype.h>
- #include <direct.h>
- #include <dos.h>
- #include <stdarg.h>
-
-
- /*
- * Global variables are usually a bad programming practice. However, I don't
- * give a damn.. :-)
- *
- */
-
-
- struct headers {
- char From[256];
- char Subject[256];
- char Date[256];
- } header;
- struct configs {
- char listname[256];
- char from[256];
- char receivedline[256];
- char dateline[256];
- char fromline[256];
- char replyto[256];
- char to[256];
- } config;
-
- FILE *infile;
- FILE *topfile = NULL, *tempfile = NULL, *cfgfile = NULL;
-
-
- /*
- * cmpcopy looks to see if string at <source> compares to the string at
- * <token>. If it does, the parameters after <token> are going to be copied
- * to <dest>.
- */
-
-
- void
- cmpcopy(char *token, char *source, char *dest)
- {
- if (!strncmp(source, token, strlen(token))) {
- source += strlen(token);
- //get past the token itself
- while (*source == ' ')
- source++;
- //get past the spaces
- strcpy(dest, source);
- }
- }
-
- /*
- * stristr is a case insensitive strstr function.
- *
- */
- char *
- stristr(char *master, char *sub)
- {
- int l;
- l = strlen(sub);
- while (*master) {
- if (!strnicmp(master, sub, l))
- return master;
- master++;
- }
- return NULL;
- }
-
- char *
- currentunixdate(void)
- {
- static char buf[150];
- struct tm *time_now;
- time_t secs_now;
- char tzone[256];
-
- long temp;
- strcpy(tzone, "TZ=PST8");
- putenv(tzone);
- tzset();
- time(&secs_now);
- time_now = localtime(&secs_now);
- strftime(buf, sizeof(buf) - 1, "%d %b %y %H:%M:%S ", time_now);
- temp = atol(tzone + 6);
- if (temp > 0)
- strcat(buf, "-");
- else {
- strcat(buf, "+");
- temp /= -1;
- }
- sprintf(buf + strlen(buf), "%02li00", temp);
- return buf;
- }
-
- char *
- datestring(char *s)
- {
- static char buf[150];
- struct tm *time_now;
- time_t secs_now;
- char tzone[256];
-
- long temp;
- strcpy(tzone, "TZ=PST8");
- putenv(tzone);
- tzset();
- time(&secs_now);
- time_now = localtime(&secs_now);
- strftime(buf, sizeof(buf) - 1, s, time_now);
- return buf;
- }
-
- unsigned long filenumber(void)
- {
- static char buf[150];
- struct tm *time_now;
- time_t secs_now;
- char tzone[256];
- static unsigned long returnme;
-
- long temp;
- strcpy(tzone, "TZ=PST8");
- putenv(tzone);
- tzset();
- time(&secs_now);
- time_now = localtime(&secs_now);
- strftime(buf, sizeof(buf) - 1, "%y%m%d00", time_now);
- returnme=atol(buf);
- return returnme;
- }
-
-
-
- /*
- * readheaders reads in the top part of the file until it reaches a newline
- * character.
- *
- */
-
-
- void
- readheaders(void)
- {
- char line[1024] = " ";
- memset(&header, 0, sizeof(headers));
- while ((*line) && (!feof(infile))) {
-
- /* remember, GIGO stands for garbage in, garbage out. */
- memset(line, 0, sizeof(line));
- fgets(line, sizeof(line) - 1, infile);
-
- /* fgets includes the line terminator; we need to remove it. */
- if (*line)
- if (line[strlen(line) - 1] == '\n')
- line[strlen(line) - 1] = 0;
- if (*line)
- if (line[strlen(line) - 1] == '\r')
- line[strlen(line) - 1] = 0;
- if (!*line)
- continue; /* We got a blank line, or an eof */
- cmpcopy("From:", line, header.From);
- cmpcopy("Subject:", line, header.Subject);
- cmpcopy("Date:", line, header.Date);
- }
- }
-
- void
- readconfig(void)
- {
- char line[1024] = " ";
- int stage = 0;
-
- cfgfile = fopen("digest.cfg", "rt");
- if (!cfgfile) {
- fprintf(stderr, "DIGEST.CFG not available.\n");
- exit(1);
- } /* endif */
- memset(&config, 0, sizeof(config));
- while ((*line) && (!feof(cfgfile))) {
- stage++;
- if (stage > 7)
- break;
- /* remember, GIGO stands for garbage in, garbage out. */
- memset(line, 0, sizeof(line));
- fgets(line, sizeof(line) - 1, cfgfile);
-
- /* fgets includes the line terminator; we need to remove it. */
- if (*line)
- if (line[strlen(line) - 1] == '\n')
- line[strlen(line) - 1] = 0;
- if (*line)
- if (line[strlen(line) - 1] == '\r')
- line[strlen(line) - 1] = 0;
- if (!*line)
- continue; /* We got a blank line, or an eof */
- //linename
- // char from[256];
- //char receivedline[256];
- //char dateline[256];
- //char fromline[256];
- //char replyto[256];
- switch (stage) {
- case 1:
- sprintf(config.listname, line, currentunixdate());
- printf("List name: %s\n", config.listname);
- break;
- case 2:
- sprintf(config.from, line, currentunixdate());
- printf("\"from\".. %s\n", config.from);
- break;
- case 3:
- sprintf(config.receivedline, line, currentunixdate());
- printf("\"Received:\".. %s\n", config.receivedline);
- break;
- case 4:
- sprintf(config.dateline, line, currentunixdate());
- printf("\"Date:\".. %s\n", config.dateline);
- break;
- case 5:
- sprintf(config.fromline, line, currentunixdate());
- printf("\"From:\".. %s\n", config.fromline);
- break;
- case 6:
- sprintf(config.replyto, line, currentunixdate());
- printf("\"Reply-To:\".. %s\n", config.replyto);
- break;
- case 7:
- sprintf(config.to, line, currentunixdate());
- printf("\"To:\".. %s\n", config.to);
- break;
- } /* endswitch */
- }
- }
-
- void
- maketopfile(void)
- {
- topfile = fopen("digest.top", "wt");
- if (!topfile)
- return;
- fprintf(topfile,
- "%s\n" // dateline
- "%s\n" // fromline
- "%s\n" // replyto
- "Subject: %s Digest\n" // listname
- "%s\n" // to
- "\n"
- "%s Digest %s\n" // Volume yy:Issue nn \ n
- "\n"
- "Today's Topics:\n:"
- "\n", config.dateline, config.fromline, config.replyto, config.listname, config.to,
- config.listname, currentunixdate());
- }
- void
- maketempfile(void)
- {
- tempfile = fopen("digest.tmp", "wt");
-
- }
-
-
-
- /*
- * All of the answer_*() functions are used with the check_multiple(function
- * pointer) command. check_multiple scans the directory for all .MLS files,
- * and runs the routine specified passing the parameter of the list name in
- * question.
- *
- */
-
- void
- answer_mls(char *filename)
- {
- char buf[256];
- int c;
- sprintf(buf, "%s", filename);
- infile = fopen(buf, "rt");
- if (!infile)
- return;
- readheaders();
- if (!topfile)
- maketopfile();
- if (!topfile) {
- fclose(infile);
- return;
- }
- if (!tempfile)
- maketempfile();
- if (!tempfile) {
- fclose(infile);
- fclose(topfile);
- return;
- }
- fprintf(topfile, " %s\n", header.Subject);
-
- fprintf(tempfile, "Date: %s\n", header.Date);
- fprintf(tempfile, "From: %s\n", header.From);
- fprintf(tempfile, "Subject: %s\n", header.Subject);
- fprintf(tempfile, "\n");
- while (!feof(infile)) {
- c = fgetc(infile);
- if (c != EOF)
- fputc(c, tempfile);
- }
- fprintf(tempfile, "\n\n------------------------------\n\n");
-
-
- fclose(infile);
- sprintf(buf, filename);
- if (strchr(buf, '.'))
- *strchr(buf, '.') = 0;
- strcat(buf, ".mld");
- rename(filename, buf);
- }
- /*
- * check_multiple is a special function..
- *
- * It takes as it's parameter the address to another function(char*).
- *
- * All answer_*(char*) functions use this procedure.
- *
- * check_multiple will run that function once for every mailing list in the
- * current directory. It has multiple uses; it can make an index of the
- * lists, globally desubscribe, and check to see which lists a user is in.
- * This method of handling it means that I don't have to have 3-4 (maybe more
- * in the future) copies of the directory-reading code.
- *
- */
-
- void
- check_multiple(void func(char *))
- {
- DIR *dir;
- struct dirent *ent;
- char buf[256];
- errno = 0;
- if ((dir = opendir("*.*")) == NULL) {
- fprintf(stdout, "Unable to open directory\n");
- return;
- }
- while ((ent = readdir(dir)) != NULL) {
- strcpy(buf, ent->d_name);
- if (stristr(buf, ".MLS"))
- func(buf);
- }
- }
-
- void
- complete_file(void)
- {
- FILE *file;
- int c;
- char *tcpip;
- unsigned long tryme;
- char buf[256];
- tryme=filenumber();
-
- loop:
- sprintf(buf,"%lu.dlq",tryme);
- file=fopen(buf,"rt");
- if (file) {
- fclose(file); tryme++; goto loop;
- } /* endif */
- printf("Creating %s\n",buf);
- file=fopen(buf,"wt");
- if (!file) {
- fprintf(stderr, "oh oh - can't open %s for output!\n",buf);
- exit(1);
- } /* endif */
- fprintf(file, "Digest.Dlq\n");
- tcpip=getenv("MAILSERVER");
- if ((tcpip==NULL) || (tcpip[0]==0))
- {
- fprintf(file, "%s\n", config.from);
- fprintf(file, "%s\n", config.receivedline);
- }
- infile = fopen("digest.top", "rt");
- if (infile) {
- while (!feof(infile)) {
- c = fgetc(infile);
- if (c != EOF)
- fputc(c, file);
- }
- fclose(infile);
-
- } else {
- fprintf(stderr, "oh oh - can't open DIGEST.TOP for read!\n");
- exit(1);
- } /* endif */
- infile = cfgfile;
- if (infile) {
- while (!feof(infile)) {
- c = fgetc(infile);
- if (c != EOF)
- fputc(c, file);
- }
- fclose(infile);
-
- }
- fprintf(file, "\n\n----------------------------------------------------------------------\n\n");
-
- infile = fopen("digest.tmp", "rt");
- if (infile) {
- while (!feof(infile)) {
- c = fgetc(infile);
- if (c != EOF)
- fputc(c, file);
- }
- fclose(infile);
-
- } else {
- fprintf(stderr, "oh oh - can't open DIGEST.TMP for read!\n");
- exit(1);
- } /* endif */
-
- fprintf(file, "\nEnd of %s Digest\n**********************************************\n", config.listname);
- fclose(file);
- }
- void
- main(int _argc, char *_argv[])
- {
- int i;
- fprintf(stderr, "DIGEST processor for GIGO compile " __DATE__ ".\n");
- readconfig();
- check_multiple(answer_mls);
-
- if (topfile)
- fclose(topfile);
- if (tempfile) {
- fclose(tempfile);
-
- complete_file();
- }
- }
-