home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Filename: LharcUUCP.c $
- * $Revision: 0.25 $
- * $Date: 1993/12/18 21:43:11 $
- *
- * Copyright (C) 1993 by Peter Simons <simons@peti.GUN.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: LharcUUCP.c,v 0.25 1993/12/18 21:43:11 simons Exp simons $
- *
- * ------------------------------ log history ----------------------------
- * $Log: LharcUUCP.c,v $
- * Revision 0.25 1993/12/18 21:43:11 simons
- * Added the myGetConfigEntry() routine to make accessing configuration
- * easier.
- * Added config-keywords allowing to specify a batchonlygrade per system.
- * The name of the keyword is "BatchOnlyGrade_<systemname>". If this
- * entry can't be found or is invalid, the global default is used.
- *
- * Revision 0.24 1993/12/14 22:04:24 simons
- * Added check, wether the specified grade is a valid alpha-numeric
- * character or not.
- *
- * Revision 0.23 1993/12/14 21:52:37 simons
- * Added a comment describing IsPath().
- *
- * Revision 0.22 1993/12/14 21:25:45 simons
- * Changed the main loop in LharcJob() to free the C.* file as soon as
- * possible, right after the renames, so that an eventually waiting uucico
- * doesn't get blocked.
- *
- * Revision 0.21 1993/12/14 17:59:16 simons
- * Remved the tests in the routines handling with grades. Now we just need
- * one central test in LharcUUCPJob(), right after the configfile is read.
- * Changed the arraysize for the filenames in jobs to 256 byte.
- * Changed GoNextLine() to work with a following feof().
- * Added IsPath() to determine the validity of the requests.
- * Changed the way, IsValidJob() recognizes 'unbatchable' UUCP requests. The
- * last version just counted the number of lines (If that's no hack, what
- * else? :->), while this version recognizes the paths.
- * Added a missing comment in the history (for 0.18).
- * Added a few comments.
- *
- * Revision 0.20 1993/12/14 16:42:41 simons
- * Adedd a DOS version string using C='s bumprev tool.
- * Changes usage-output.
- *
- * Revision 0.19 1993/12/14 15:21:36 simons
- * Added a variable 'LharcBatchGrade' determining the batch-grade of our
- * own job. This defaults to 'A'. Currently, this is only global for the
- * whole system.
- *
- * Revision 0.18 1993/12/14 15:05:36 simons
- * Added a grade-check into IsValidJob(). This required two more parameters:
- * systemname and grade. Currently, the grade is only global, but I'll add
- * some local way.
- * Changed the order of checks in IsValidJob(). Now, the check requiring
- * fileaccess is the last one.
- *
- * Revision 0.17 1993/12/11 14:31:46 simons
- * LharcUUCP is now able to parse the UUCP main config file and determine
- * the sitename from the appropiate entry there. However, HOSTNAME is tested
- * before parsing the file and still has priority. Local vars aren't
- * supported.
- *
- * Revision 0.16 1993/12/10 22:26:14 simons
- * Added the command ("m") in the LHARC-define.
- * LharcUUCP() now terminates, when the current C.* file is already locked,
- * because this usually means, that uucico is currently working on this job
- * and our batch would fail anyway, so we better process the next job.
- * Then LharcUUCP() used to unlock the C.* file before deleting it. This
- * has been fixed.
- * Now, we're locking the full archive name (<system>.LHARCPOSTFIX), to
- * avoid problems with uucico, trying to transfer our archive while we're
- * working on it.
- *
- * Revision 0.15 1993/12/08 17:11:03 simons
- * Changed the call to InitDirScan() to match the new routines.
- *
- * Revision 0.14 1993/12/07 02:22:48 simons
- * Changed the spool directory finding routine again.
- *
- * Revision 0.13 1993/12/07 02:15:50 simons
- * Now checking for a spooldirectory with a truncated systemname, too.
- *
- * Revision 0.12 1993/12/05 16:11:39 simons
- * IsValidJob() didn't free the locked files.
- *
- * Revision 0.11 1993/12/05 15:46:13 simons
- * Added IsValidJob() which determines if we should process this job.
- * Currently, only mail and news are processed--UUCP commands and our
- * own archive-copy is skipped. Since this check is now in a seperate
- * routine, LharcJob() has become a little bit easier and more straight.
- *
- * Revision 0.10 1993/12/05 13:32:37 simons
- * PostArchive() is now called only, when actually a job has been processed.
- * Additionally, it's called after the process is finished, not every time
- * the archive changed. I'm not completely sure if this is the better
- * way--will need some thought.
- *
- * Revision 0.9 1993/12/05 13:19:28 simons
- * HOMESYSTEM is not determined at startup from the related enviroment
- * variable, maybe I'll add configfile parsing some day.
- * Change the order of the tests in main(): Now the commandline is checked
- * first.
- * Added TruncName(), which makes the handling of the 7-char-maximum
- * systemnames easier.
- * Changed commentblock style.
- *
- * Revision 0.8 1993/12/05 00:35:28 simons
- * The history in the sourcefile was broken.
- * Also I didn't mention the seq-routines, I took from Dillon UUCP.
- * Known bug: LharcUUCP packs it's self-generated Archive job. :-) It
- * doesn't really matter, but I'll find a way around this.
- *
- * Revision 0.7 1993/12/05 00:29:29 simons
- * Added PostArchive(), a small and neat routine to create the X.* and
- * the C.* file for the archive.
- *
- * Revision 0.6 1993/12/04 22:34:33 simons
- * The outgoing-archive is now locked while the archiver runs. Actually,
- * only the systemname is used to lock the archive, not the complete name,
- * like "peti.lha" or something similar. So, the mechanism will work with
- * different archivers than LhA on the Amiga platform.
- *
- * Revision 0.5 1993/12/04 22:30:44 simons
- * Now actually starting the archiver, creating a file names <system>.lha,
- * located in the appropiate outgoing directory.
- *
- * Revision 0.4 1993/12/04 20:44:35 simons
- * Moved the directory scanning routine into an extra module, since this
- * is the only routine that is really system-dependant.
- *
- * Revision 0.3 1993/12/04 18:05:00 simons
- * LharcJob() now reads the C.* files and renames the D.* and X.* file to
- * the names they shall have on the remote system, so they can be easily
- * packed.
- * Non-send-jobs are recognized.
- * UUCP jobs (which are send-jobs in fact) are merely recognized, although
- * the current method (UUCP-jobs have only one line!) is a hack. I'll
- * change that soon.
- * Also some problems with the directory scanning routine occur. I will
- * have to re-write GetFileName() soon, too.
- *
- * Revision 0.2 1993/12/04 17:13:04 simons
- * Added commandline parsing, calling PackSpoolJobs() for every provided
- * system.
- * Added GetFileName() which is able to scan a directory for files,
- * matching a certain pattern.
- * Added a basic LharcJob() call, which just locks and opens the file
- * until now.
- *
- * Revision 0.1 1993/12/04 13:45:54 simons
- * This program is released under the GNU General Public License.
- */
-
-
- /************************************* includes ***********/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <dos.h>
- #include <proto/dos.h>
-
- #include "LharcUUCP_rev.h"
-
- /************************************* defines ************/
- #define BUFFERSIZE 128
- #define UUSPOOL "UUSpool:"
- #define SEQ "UULib:Seq"
- #define LHARC "LhA m" /* archiver command, moving enabled */
- #define LHARCPOSTFIX ".lha"
-
- #define USAGE VERS " -- written by Peter Simons <simons@peti.GUN.de>\n" \
- "Usage: LharcUUCP system [[system] [...]]\n"
-
- /************************************* prototypes *********/
- void PackSpoolJobs(char *systemname);
- char *GetFileName(char *pattern, int reset);
- void LharcJob(char *systemname, char *cfile, char grade);
- void PostArchive(char *systemname, char *postfix, char grade);
- char *TruncName(char *string);
- int IsValidJob(char *cfilename, char *systemname, char grade);
- int GoNextLine(FILE *fh);
- unsigned int GetSequence(unsigned int);
- char *SeqToName(unsigned int);
- int IsPath(char *filename);
- char *myGetConfigEntry(char *keyword, char *def);
-
- void LockFile(char *);
- int FileIsLocked(char *);
- void UnLockFile(char *);
- void UnLockFiles(void);
-
- int InitDirScan(char *);
- char *ScanNextFile(void);
- void EndDirScan(void);
-
- char *GetConfigEntry(char *, char *, char *);
-
- /************************************* global variables ***/
- static const char __RCSId[] = "$Id: LharcUUCP.c,v 0.25 1993/12/18 21:43:11 simons Exp simons $";
- static const char __DOSVer[] = VERSTAG;
- char *homesystem;
- int processed_flag;
-
- /************************************* program ************/
-
- int main(int argc, char **argv)
- {
- char currentdir[512];
-
- if (argc < 2) {
- fprintf(stderr, USAGE);
- return 10;
- }
-
- if (!(homesystem = getenv("HOSTNAME")))
- if (!(homesystem = GetConfigEntry(NULL, "NodeName", NULL))) {
- fprintf(stderr, "LharcUUCP: Can't determine the name of this machine!\n");
- return 10;
- }
-
- if (getcd(0, currentdir))
- return 10;
-
- while (--argc)
- PackSpoolJobs(argv[argc]);
-
- chdir(currentdir);
-
- return 0;
- }
-
-
- /************************************* subroutines ********/
- void PostArchive(char *systemname, char *postfix, char grade)
- {
- FILE *cfh, *xfh;
- char cfilename[64], xfilename[64], *trunc_sysname;
- char dremote[64];
-
- trunc_sysname = TruncName(systemname);
-
- sprintf(cfilename, "C.%s%c0000", trunc_sysname, grade);
- LockFile(cfilename);
- if (!(cfh = fopen(cfilename, "r"))) {
- fclose(cfh);
-
- /*
- * When the fopen() call succedes, does the file already
- * exist and we're finished.
- */
-
- sprintf(xfilename, "D.%sX%s", trunc_sysname, SeqToName(GetSequence(1)));
- sprintf(dremote, "%s%s", TruncName(homesystem), SeqToName(GetSequence(1)));
-
- if (cfh = fopen(cfilename, "w")) {
- fprintf(cfh, "S %s%s D.%s lharc-uucp-daemon - %s%s 0666\n",
- systemname, postfix, dremote, systemname, postfix);
- fprintf(cfh, "S %s X.%s%s lharc-uucp-daemon - %s 0666\n",
- xfilename, TruncName(homesystem), SeqToName(GetSequence(1)), xfilename);
- fclose(cfh);
- }
-
- LockFile(xfilename);
- if (xfh = fopen(xfilename, "w")) {
- fprintf(xfh, "U lharc-uucp-daemon %s\nF D.%s\nC rlharc\n", homesystem, dremote);
- fclose(xfh);
- }
- else
- remove(cfilename);
- UnLockFile(xfilename);
- }
- else
- fclose(cfh);
-
- UnLockFile(cfilename);
- }
-
-
- void PackSpoolJobs(char *systemname)
- {
- char currentdir[BUFFERSIZE], *cfile;
- int success;
- char owngrade, grade;
-
- processed_flag = 0;
-
- if (strlen(systemname)+strlen(UUSPOOL)+1 > BUFFERSIZE) {
- fprintf(stderr, "LharcUUCP: Directoryname is too long for internal buffer.\n");
- return; /* Buffer overflow! */
- }
-
- printf("Processing queued jobs for >%s<.\n", systemname);
-
-
- /*
- * Change into the appropiate directory, holding the spool jobs
- * for the specified system.
- */
-
- sprintf(currentdir, "%s%s", UUSPOOL, systemname);
- if (chdir(currentdir)) {
- sprintf(currentdir, "%s%s", UUSPOOL, TruncName(systemname));
- if (chdir(currentdir)) {
- fprintf(stderr, "LharcUUCP: System >%s< has no spool directory?\n", systemname);
- strcpy(currentdir, UUSPOOL);
- if (chdir(currentdir)) {
- fprintf(stderr, "LharcUUCP: Cd to >%s< failed.\n", UUSPOOL);
- return;
- }
- }
- }
-
-
- /*
- * Determine the configured grades for our process.
- */
-
- {
- char *string, buf[80];
-
- string = myGetConfigEntry("BatchOnlyGrade", NULL);
- grade = (string && isalnum(string[0])) ? string[0] : 'z';
-
- sprintf(buf, "%s_%s", "BatchOnlyGrade", systemname);
- string = myGetConfigEntry(buf, NULL);
- grade = (string && isalnum(string[0])) ? string[0] : grade;
-
- string = myGetConfigEntry("LharcBatchGrade", NULL);
- owngrade = (string && isalnum(string[0])) ? string[0] : 'A';
- }
-
-
- /*
- * Build a pattern matching 'C.system*', with the systemname
- * truncated to 7 characters and scan the spooldirectory for
- * queued jobs we can pack.
- */
-
- {
- char pattern[64];
- sprintf(pattern, "C.%s#?", TruncName(systemname));
- success = InitDirScan(pattern);
- }
-
- if (success)
- while (cfile = ScanNextFile())
- LharcJob(systemname, cfile, grade);
- else
- fprintf(stderr, "LharcUUCP: Directory scan for >%s< failed!\n", currentdir);
-
- EndDirScan();
-
- if (processed_flag)
- PostArchive(systemname, LHARCPOSTFIX, owngrade);
- }
-
-
- void LharcJob(char *systemname, char *cfilename, char grade)
- {
- FILE *cfilehandle;
- char command[2], from[256], to[256], from2[256], to2[256];
- char cmdbuf[256], archivename[64];
- int success = 0;
-
- printf("LharcUUCP: processing <%s>\n", cfilename);
-
- if (FileIsLocked(cfilename))
- return; /* uucico is processing this job right now,
- * so we better leave it alone.
- */
- LockFile(cfilename);
-
- if(!IsValidJob(cfilename, systemname, grade)) {
- UnLockFile(cfilename);
- return;
- }
-
- if (cfilehandle = fopen(cfilename, "r")) {
- fscanf(cfilehandle, "%s%s%s", command, from, to);
- if (GoNextLine(cfilehandle) != EOF) {
- fscanf(cfilehandle, "%s%s%s", command, from2, to2);
-
- LockFile(from);
- LockFile(to);
- LockFile(from2);
- LockFile(to2);
- if (!(rename(from, to)))
- if (!(rename(from2, to2))) {
- success = 1;
- processed_flag = 1;
-
-
- /* Free unused files a soon as
- * possible.
- */
-
- fclose(cfilehandle);
- remove(cfilename);
- UnLockFile(from);
- UnLockFile(from2);
- UnLockFile(cfilename);
-
-
- /* Batch the processed files.
- */
-
- sprintf(cmdbuf, "%s %s %s %s", LHARC, systemname, to, to2);
- printf("%s\n", cmdbuf);
- sprintf(archivename, "%s%s", systemname, LHARCPOSTFIX);
- LockFile(archivename);
- system(cmdbuf);
- UnLockFile(archivename);
- }
- else
- rename(to, from);
-
-
- /* When one of the 'renames' failed, we still
- * have to close and unlock the files.
- */
-
- if (!success) {
- UnLockFile(from);
- UnLockFile(from2);
- fclose(cfilehandle);
- UnLockFile(cfilename);
- }
-
- UnLockFile(to); /* These must be freed */
- UnLockFile(to2); /* in any case. */
- }
- }
- }
-
-
- /*
- * IsValidJob() checks the provided C.* file and tests if this job may
- * may be processed by LharcUUCP. Currently, we only process mail and
- * news. UUCP- and lharc-jobs are left alone.
- */
-
- int IsValidJob(char *cfilename, char *systemname, char grade)
- {
-
- /*
- * Test if the grade of the commandfile is lower or the same as
- * our max. grade.
- */
-
- if (cfilename[strlen(TruncName(systemname)) + 2] > grade)
- return 0;
-
-
- /*
- * Check the number part of the filename. C.*0000 are the C.*
- * files for the processed archives and won't be touched.
- */
-
- if (!strncmp(&cfilename[strlen(cfilename) - 4], "0000", 4))
- return 0;
-
-
- /*
- * Check the contents of the file. Neither target nor source file
- * may contain paths and we can't batch read-requests of course.
- */
-
- {
- FILE *fh;
- int success = 0;
- char from[256], to[256];
-
- if (fh = fopen(cfilename, "r")) {
- while (1) {
- if (fgetc(fh) == 'S') {
- fscanf(fh, "%s%s", from, to);
- if (IsPath(from) || IsPath(to))
- break;
- GoNextLine(fh);
- if (feof(fh)) {
- success = 1;
- break;
- }
- }
- else
- break;
- }
- fclose(fh);
- }
- if (!success)
- return 0;
- }
-
- return 1;
- }
-
-
-
- unsigned int GetSequence(unsigned int bump)
- {
- FILE *fh;
- unsigned int seq = 0;
-
- LockFile(SEQ);
- if (fh = fopen(SEQ, "r")) {
- fscanf(fh, "%u", &seq);
- fclose(fh);
- }
- else {
- fprintf(stderr, "LharcUUCP: Can't open seq file!\n");
- }
-
- if (bump && seq >= 0) {
- if (bump + seq > 0xFFFFF)
- seq = 1;
-
- endlessloop:
- if (fh = fopen(SEQ, "w")) {
- fprintf(fh, "%u", seq + bump);
- fclose(fh);
- }
- else {
- fprintf(stderr, "LharcUUCP: Can't update seq file!\n");
- Delay(5*50);
- goto endlessloop;
- }
- }
- UnLockFile(SEQ);
- return seq;
- }
-
-
- /*
- * Convert a sequence number into a numeric/character combination. Names
- * are unique and case-insensitive. The sequence number 0-0xFFFFF will be
- * converted to a 4 character string each position containing 0-9 a-z,
- * or base 36 (total of 1.6 million combinations)
- */
-
- char *SeqToName(unsigned int seqNo)
- {
- static char Buf[5];
- short i;
-
- seqNo &= 0xFFFFF;
-
- for (i = 3; i >= 0; --i) {
- short n = seqNo % 36;
-
- if (n < 10)
- Buf[i] = n + '0';
- else
- Buf[i] = n - 10 + 'a';
- seqNo /= 36;
- }
- Buf[4] = '\0';
- return (Buf);
- }
-
-
- /*
- * TruncName() duplicates the given string and truncates it to 7
- * characters, which is required by a number of tasks in the UUCP
- * enviroment.
- */
-
- char *TruncName(char *string)
- {
- static char buffer[8];
-
- strncpy(buffer, string, 7);
- buffer[7] = '\0';
-
- return buffer;
- }
-
-
- /*
- * GoNextLine() reads from the provided filehandle until either end-
- * of-file or an end-of-line ('\n') occurs.
- */
-
- int GoNextLine(FILE *fh)
- {
- int c;
-
- while ((c = fgetc(fh)) != EOF && c != '\n')
- ;
-
- if ((c = fgetc(fh)) != EOF) /* Read next character to make */
- ungetc(c, fh); /* feof() work. */
-
- return c;
- }
-
-
- /*
- * This small routine returns a flag indicating wether the provided
- * string was a filepath or just a filename! This is important, because
- * filerequests containing paths can't be processed with LharcUUCP.
- * This routine has to be customized for other systems.
- */
-
- int IsPath(char *filename)
- {
- if (strchr(filename, '/') || strchr(filename, ':'))
- return 1;
- else
- return 0;
- }
-
-
- char *myGetConfigEntry(char *keyword, char *def)
- {
- char *string;
-
- if (string = getenv(keyword))
- return string;
-
- return GetConfigEntry(NULL, keyword, def);
- }
-
-