Update of /cvsroot/galaxyng/NG_Stable/lib In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv9654/lib Added Files: Makefile globals.c list.c loadNGConfig.c lockFile.c logging.c mail.c strutl.c util.c Log Message: baseline version as used at sifar.xs4all.nl --- NEW FILE: loadNGConfig.c --- #include "galaxy.h" #include "galaxyng.h" #include "util.h" /****f* LoadGame/readDefaults * NAME * readDefaults -- read game defaults * FUNCTION * Read defaults from a configuration file : .galaxyngrc * NOTES * Has a memory leak. * SEE ALSO * game ****** */ void initServerOptions(game* aGame) { /* initialize values */ aGame->serverOptions.sendmail = NULL; aGame->serverOptions.encode = NULL; aGame->serverOptions.compress = NULL; aGame->serverOptions.GMemail = NULL; aGame->serverOptions.GMname = NULL; aGame->serverOptions.GMpassword = NULL; aGame->serverOptions.SERVERemail = NULL; aGame->serverOptions.SERVERname = NULL; aGame->serverOptions.ReplyTo = NULL; aGame->serverOptions.fontpath = NULL; aGame->serverOptions.due = NULL; aGame->serverOptions.tick_interval = NULL; } void readDefaults(game *aGame, FILE * f) { char* isRead; /* to check for EOF */ char* key; /* the key part of the name/value pair */ for (isRead = fgets(lineBuffer, LINE_BUFFER_SIZE, f); isRead; isRead = fgets(lineBuffer, LINE_BUFFER_SIZE, f)) { key = getstr(lineBuffer); if (key[0] != '\0') { if (noCaseStrcmp("GMemail", key) == 0) { if (aGame->serverOptions.GMemail) free(aGame->serverOptions.GMemail); aGame->serverOptions.GMemail = strdup(getstr(0)); } else if (noCaseStrcmp("GMname", key) == 0) { if (aGame->serverOptions.GMname) free(aGame->serverOptions.GMname); aGame->serverOptions.GMname = strdup(getstr(0)); } else if (noCaseStrcmp("GMpassword", key) == 0) { if (aGame->serverOptions.GMpassword) free(aGame->serverOptions.GMpassword); aGame->serverOptions.GMpassword = strdup(getstr(0)); } else if (noCaseStrcmp("SERVERemail", key) == 0) { if (aGame->serverOptions.SERVERemail) free(aGame->serverOptions.SERVERemail); aGame->serverOptions.SERVERemail = strdup(getstr(0)); } else if (noCaseStrcmp("SERVERname", key) == 0) { if (aGame->serverOptions.SERVERname) free(aGame->serverOptions.SERVERname); aGame->serverOptions.SERVERname = strdup(getstr(0)); } else if (noCaseStrcmp("ReplyTo", key) == 0) { if (aGame->serverOptions.ReplyTo) free(aGame->serverOptions.ReplyTo); aGame->serverOptions.ReplyTo = strdup(getstr(0)); } else if (noCaseStrcmp("compress", key) == 0) { if (aGame->serverOptions.compress) free(aGame->serverOptions.compress); aGame->serverOptions.compress = strdup(getstr(0)); } else if (noCaseStrcmp("encode", key) == 0) { if (aGame->serverOptions.encode) free(aGame->serverOptions.encode); aGame->serverOptions.encode = strdup(getstr(0)); } else if (noCaseStrcmp("sendmail", key) == 0) { if (aGame->serverOptions.sendmail) free(aGame->serverOptions.sendmail); aGame->serverOptions.sendmail = strdup(getstr(0)); } else if (noCaseStrcmp("starttime", key) == 0) { if (aGame->starttime) free(aGame->starttime); aGame->starttime = strdup(getstr(0)); } else if (noCaseStrcmp("fontpath", key) == 0) { if (aGame->serverOptions.fontpath) free(aGame->serverOptions.fontpath); aGame->serverOptions.fontpath = strdup(getstr(0)); } else if (noCaseStrcmp("due", key) == 0) { if (aGame->serverOptions.due) free(aGame->serverOptions.due); aGame->serverOptions.due = strdup(getstr(0)); } else if (noCaseStrcmp("tick", key) == 0) { if (aGame->serverOptions.tick_interval) free(aGame->serverOptions.tick_interval); aGame->serverOptions.tick_interval = strdup(getstr(0)); } else { printf("Unknown key \"%s\"\n", key); } } } if (aGame->serverOptions.due == NULL) aGame->serverOptions.due = strdup("soon"); if (aGame->serverOptions.tick_interval == NULL) aGame->serverOptions.tick_interval = strdup("48"); if (aGame->serverOptions.SERVERemail == NULL) { char* logfile = createString("%s/Games/log/%s", galaxynghome, aGame->name); FILE* logfp = fopen(logfile, "+w"); fprintf(stderr, "SERVERemail is a required entry in your .galaxyngrc\n"); fprintf(logfp, "SERVERemail is a required entry in your .galaxyngrc\n"); fclose(logfp); exit(EXIT_FAILURE); } if (aGame->serverOptions.SERVERname == NULL) aGame->serverOptions.SERVERname = strdup("GalaxyNG Server"); if (aGame->serverOptions.GMemail == NULL) aGame->serverOptions.GMemail = strdup(aGame->serverOptions.SERVERemail); if (aGame->serverOptions.GMname == NULL) aGame->serverOptions.GMname = strdup("GalaxyNG GM"); if (aGame->serverOptions.ReplyTo == NULL) aGame->serverOptions.ReplyTo = strdup(aGame->serverOptions.SERVERemail); if (aGame->serverOptions.GMpassword == NULL) aGame->serverOptions.GMpassword = strdup(""); } /****f* LoadGame/loadConfig * NAME * loadConfig -- read configuration files * FUNCTION * reads defaults from $GALAXYNGHOME/.galaxyngrc * and then from $GALAXYNGHOME/data/<gamename>/.galaxyngrc **** */ void loadNGConfig(game *aGame) { FILE *f; initServerOptions(aGame); sprintf(lineBuffer, "%s/.galaxyngrc", galaxynghome); if ((f = fopen(lineBuffer, "r"))) { readDefaults(aGame, f); fclose(f); } sprintf(lineBuffer, "%s/data/%s/.galaxyngrc", galaxynghome, aGame->name); if ((f = fopen(lineBuffer, "r"))) { readDefaults(aGame, f); fclose(f); } } --- NEW FILE: strutl.c --- #include "strutl.h" /****f* strutl/getstr * * NAME * getstr -- extract a word from a longer string * SYNOPSIS * char *getstr(char *s) * word = getstr(someString) * FUNCTION * Extract a word from a string of words. A word is any things that * is seperated by white spaces or a comma, any string that is * delimited by quotes ("), or or any string delimited by { }. * * The function is intended to parse a string word by word. It * should be first called as: * * firstword = getstr(myStringOfWords); * * This gets the first word from the string pointed to by * myStringOfWords. Then consecutive calls of * * nextword = getstr(NULL); * * you get the remaining words. * * White spaces inside a quote delimited word are turned into * underscores. * * In a string a ';' signifies the start of a comment. Any words * after a ';' are not parsed. * * In the non comment part ';' and '<' are removed before the words * are returned. * * RESULTS * word = a pointer to a nul terminated string. * * Program is aborted if the length of the word is longer than 256, * since then some is most likely trying to crack your system. * * When there are no more words"\0" is returned. * NOTES * This function can only work on one string at the time since it * works with a statically allocated buffer. This function is used * almost everywhere in the program. * SOURCE */ char * getstr( char *s ) { static char *s1; static char buf[256]; int i; int j; if ( s ) s1 = s; /* first invocation of this function, for an order line. Each next * times, for the same order line, s1 will "progress" by a word to * the right */ assert( s1 != NULL ); i = 0; for ( ; *s1 && isspace( *s1 ); s1++ ) /* skips spaces */ ; if ( *s1 == '"' ) { /* Players can enclose name (ie : including spaces) with double quotes */ for ( s1++; *s1 && *s1 != '"'; ) { buf[i] = isspace( *s1 ) ? '_' : *s1; s1++; i++; assert( i < 256 ); /* abort execution if s1 too long */ } } else if ( *s1 == '{' ) { for ( s1++; *s1 && *s1 != '}'; ) { buf[i] = *s1; s1++; i++; assert( i < 256 ); /* abort execution if s1 too long */ } } else { if ( *s1 != ';' ) { /* otherwise, it's a comment */ for ( ; *s1 && !isspace( *s1 ) && *s1 != ','; ) { /* space or ',' can be used as separators, */ buf[i] = *s1; s1++; i++; assert( i < 256 ); /* abort execution if s1 too long */ } } } buf[i] = '\0'; if ( *s1 ) s1++; /* Skip ',' or space */ /* CB, 19980922. Remove ";" and "<" from names (planets, ships...), * * * * * to * protect machine report from corruption. Don't break messages * * * * * and * comments. */ i = 0; j = 0; while ( buf[j] && j < 256 ) { if ( buf[j] != ';' && buf[j] != '<' ) { buf[i] = buf[j]; i++; } j++; } if ( i ) buf[i] = '\0'; return buf; } /***********/ /****f* strutl/makestrlist * NAME * makestrlist -- create an element for a string list * FUNCTION * * RESULT * Pointer to an initialized strlist structure. * BUGS * This function has a wrong name. * SOURCE */ strlist* makestrlist(char* ns) { strlist* s; strlist* cur; char* tmp; char* sPtr; char* ePtr; char* sep; cur = NULL; sPtr = tmp = strdup(ns); sep = ePtr = strpbrk(sPtr, "\n\r"); if (ePtr == NULL) { cur = (strlist*)allocStruct(strlist); cur->str = tmp; return cur; } do { if ( cur ) { cur->next = ( strlist * ) allocStruct( strlist ); cur = cur->next; } else s = cur = ( strlist * ) allocStruct( strlist ); *ePtr = '\0'; cur->str = strdup( sPtr ); if (*sep == '\n' && *(ePtr+1) == '\r') sPtr = ePtr + 2; else sPtr = ePtr + 1; } while ((sep = ePtr = strpbrk(sPtr, "\n\r")) != NULL); if (*sPtr != '\0') { cur->next = ( strlist * ) allocStruct( strlist ); cur = cur->next; cur->str = strdup(sPtr); } free( tmp ); return s; } /*********/ /****f* strutl/freestrlist * NAME * freestrlist -- free memory used by a string list. * SYNOPSIS * void freestrlist(strlist *s) * FUNCTION * Free all memory used by a string list. Before * trying to free the memory used by an element check * if the element is valid. * SOURCE */ void freestrlist( strlist *s ) { strlist *s2; pdebug( DFULL, "free strlist\n" ); while ( s ) { validateStruct( strlist, s ); s2 = s->next; free( s->str ); free( s ); s = s2; } } void dumpstrlist(strlist *aStrlist) { for (; aStrlist; aStrlist = aStrlist->next) { printf("%s\n", aStrlist->str); } } /****f* strutl/noCaseStrcmp * NAME * noCaseStrcmp -- * SYNOPSIS * int noCaseStrcmp(char *s, char *t) * FUNCTION * Compare two strings without paying no attention to the case of * the letters. * RESULT * 0 s == t * -1 s < t * 1 s > t * SOURCE */ int noCaseStrcmp(const char *s, const char *t) { for (; tolower(*s) == tolower(*t); s++, t++) if (*s == '\0') return 0; return (int) (tolower(*s) - tolower(*t)); } /*********/ /****f* strutl/noCaseStrncmp * NAME * noCaseStrncmp -- * SYNOPSIS * int noCaseStrncmp(char *, char *, int) * result = noCaseStrncmp(s, t, n) * FUNCTION * Compare two strings without paying no attention to the case of * the letters, but compare no more than n characters. * RESULT * 0 s == t * -1 s < t * 1 s > t * SOURCE */ int noCaseStrncmp(const char *s, const char *t, int n) { for (n--; (tolower(*s) == tolower(*t)) && (n > 0); s++, t++, n--) if (*s == '\0') return 0; return (int) (tolower(*s) - tolower(*t)); } /***********/ char* strlwr(char* str) { char* ptr = str; while (*ptr) { if (isupper(*ptr)) *ptr = tolower(*ptr); ptr++; } return str; } --- NEW FILE: list.c --- #include "list.h" #include <stdlib.h> #include <string.h> #include <assert.h> /****h* GalaxyNG/List * NAME * List -- a number of list manipulating functions. ***** */ /****i* List/numberOfElementsF * NAME * numberOfElementsF -- ******* */ int numberOfElementsF(list *aList) { list *el; int noEl; noEl = 0; if (aList) for (el = aList; el; el = el->next) noEl++; return noEl; } /****i* List/add2ListF * NAME * add2ListF -- ****** */ void add2ListF(list **aList, list *anElement) { anElement->next = *aList; *aList = anElement; } /****f* List/freelist * NAME * freelist -- free all members in a list ***** */ void freelist(void *base) { list *p, *p2; pdebug(DFULL2, "freelist"); p = base; while (p) { p2 = p->next; free(p->name); free(p); p = p2; pdebug(DFULL2, "."); } pdebug(DFULL2, "\n"); } /****i* List/addListF * NAME * addListF -- ****** */ void addListF(list **aList, list *anElement) { list *curElement; if (*aList == NULL) { *aList = anElement; } else { for (curElement = *aList; curElement->next; curElement = curElement->next); curElement->next = anElement; } } /****i* List/insertListF * NAME * insertListF -- ****** */ void insertListF(list **aList, list* where, list *anElement) { list *curElement; list *listEnd; if (*aList == NULL) { *aList = anElement; } else { for (curElement = *aList; curElement->next; curElement = curElement->next) { if (curElement == where) { break; } } for (listEnd = anElement; listEnd->next; listEnd = listEnd->next) ; listEnd->next = curElement->next; curElement->next = anElement; } } /****** List/findElementF * NAME * findElementF -- * SYNOPSIS * list *findElementF(list *aList, char *name) * FUNCTION * Find an element in a list based on the name * of the element. * INPUTS * aList -- pointer to the first element in the list. * name -- name of the element to find. * RESULT * Address of the element or NULL in case the * element was not found. ****** */ list* findElementF(list *aList, char *name) { list *anElement; for (anElement = aList; anElement; anElement = anElement->next) { if (!noCaseStrcmp(anElement->name, name)) break; } return anElement; } /****f* List/removeListF * NAME * removeListF - * FUNCTION * Remove an element from a list. * NOTE * Do not use this function directly, use the * macro remList() * SEE ALSO * remList() ****** */ void removeListF(list **aList, list *anElement) { list *prevElement; assert(anElement != NULL); if (*aList == anElement) *aList = anElement->next; else { for (prevElement = *aList; prevElement->next != anElement; prevElement = prevElement->next) { assert(prevElement != NULL); } prevElement->next = anElement->next; } free(anElement); } /****f* List/ptonum * NAME * ptonum -- convert pointer to index number * SYNOPSIS * void *ptonum(void *base, void *target) * FUNCTION * Gives the index number of an element in a list. * INPUTS * base - base address of the list * target - the element * RESULT * the index number of the element. * SEE ALSO * numtop() ******* */ int ptonum(void *base, void *target) { list *p; int i; for (p = base, i = 1; p; p = p->next, i++) if (p == target) return i; return 0; } /****f* List/numtop * NAME * numtop -- convert index number to pointer * SYNOPSIS * void *numtop(void *base, int n) * FUNCTION * Look up an element in a list using it's index number. * INPUTS * base - base address of the list * n - index number * RESULT * address of the element. ******* */ void * numtop(void *base, int n) { list *p; int i; i = 0; for (p = base; p; p = p->next) { i++; if (i == n) return p; } return 0; } /****f* List/setName * NAME * setNameF * FUNCTION * Set the name of an element in a list. * NOTE * Do not use this function directly, use the * macro setName() * SEE ALSO * setName() ****** */ void setNameF(list *anElement, const char *name) { free(anElement->name); anElement->name = strdup(name); } void dumpList(char* label, list* aList, void* callback(void*)) { list* curElement; fprintf(stderr, "*** %s ***\n", label); for (curElement = aList; curElement; curElement=curElement->next) { fprintf(stderr, "%lX: %s\n", curElement->cookie, curElement->name); callback((void*)curElement); } } void* allocStructF(unsigned int n, long cookie) { list *p; p = calloc(1, n); if (p == 0) { pdebug(DERR, "Out of memory, aborting program.\n"); exit(1); } p->cookie = cookie; p->name = NULL; p->next = NULL; return (void *) p; } --- NEW FILE: Makefile --- # # $Id: Makefile,v 1.1 2008/01/17 23:18:33 gumpu Exp $ # CFLAGS = -Wall -pedantic -I../include $(ADDTL_CFLAGS) CC = gcc SOURCES=strutl.c logging.c list.c globals.c mail.c util.c loadNGConfig.c \ lockFile.c OBJECTS=$(SOURCES:.c=.o) all : libgalaxyng.a libgalaxyng.a: $(OBJECTS) ar cr libgalaxyng.a $(OBJECTS) clean: rm -f libgalaxyng.a $(OBJECTS) *~ depend: makedepend -- $(CFLAGS) -- $(SOURCES) # DO NOT DELETE THIS LINE -- make depend depends on it. strutl.o: ../include/strutl.h ../include/cookies.h ../include/logging.h logging.o: ../include/logging.h list.o: ../include/list.h ../include/util.h ../include/galaxy.h list.o: ../include/strutl.h ../include/cookies.h ../include/logging.h globals.o: ../include/galaxy.h ../include/strutl.h ../include/cookies.h globals.o: ../include/logging.h mail.o: ../include/mail.h ../include/galaxy.h ../include/strutl.h mail.o: ../include/logging.h ../include/util.h ../include/list.h util.o: ../include/util.h ../include/galaxy.h ../include/strutl.h util.o: ../include/logging.h ../include/list.h util.o: ../include/create.h ../include/avl.h ../include/loadgame.h --- NEW FILE: lockFile.c --- #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <sys/stat.h> #include <errno.h> #include <limits.h> #include <signal.h> static int readData(int fd, void* buf, size_t nbrBytes) { size_t toRead; size_t nbrRead = 0; ssize_t result; do { if (nbrBytes - nbrRead > SSIZE_MAX) toRead = SSIZE_MAX; else toRead = nbrBytes - nbrRead; if ((result = read(fd, (char*)buf+nbrRead, toRead)) >= 0) nbrRead += result; else if (errno != EINTR) return 0; } while (nbrRead < nbrBytes); return 1; } static int writeData(int fd, const void* buf, size_t nbrBytes) { size_t toWrite; size_t written = 0; ssize_t result; do { if (nbrBytes - written > SSIZE_MAX) toWrite = SSIZE_MAX; else toWrite = nbrBytes - written; if ((result = write(fd, (const char*)buf + written, toWrite)) >= 0) written += result; else if (errno != EINTR) return 0; } while (written < nbrBytes); return 1; } int spcLockFile(const char* lfpath) { int attempt; int fd; int result; pid_t pid; /* try 3 times, if we fail, we lose */ for (attempt = 0; attempt < 3; attempt++) { if ((fd = open(lfpath, O_RDWR|O_CREAT|O_EXCL, S_IRWXU)) == -1) { if (errno != EEXIST) return -1; if ((fd = open(lfpath, O_RDONLY)) == -1) return -1; result = readData(fd, &pid, sizeof(pid)); close(fd); if (result) { if (pid == getpid()) return 1; if (kill(pid, 0) == -1) { if (errno != ESRCH) return -1; attempt--; unlink(lfpath); continue; } } sleep(1); continue; } pid = getpid(); if (!writeData(fd, &pid, sizeof(pid))) { close(fd); return -1; } close(fd); attempt--; } /* If we've made it to here, three attempts have been made and the * lock could not be obtained. Return an error code indicating * failure to obtain the requested lock. */ return 0; } --- NEW FILE: mail.c --- #include "mail.h" #include "util.h" #include <assert.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> /****h* GalaxyNG/Mail * FUNCTION * This module contains functions to create, * fill and send email messages. ***** */ void createMailToAllHeader(game *aGame) { player* aPlayer; int state; if (aGame->serverOptions.SERVERemail) { if (aGame->serverOptions.SERVERname) { printf("From: %s <%s>\n", aGame->serverOptions.SERVERname, aGame->serverOptions.SERVERemail); } else { printf("From: %s\n", aGame->serverOptions.SERVERemail); } } printf("To: %s\nBCC: ", aGame->serverOptions.GMemail); for (aPlayer = aGame->players, state = 0; aPlayer; aPlayer = aPlayer->next) { if (!(aPlayer->flags & F_DEAD)) { if (state == 0) { printf(" %s", aPlayer->addr); state = 1; } else { printf(",\n %s", aPlayer->addr); } } } printf("\nSubject:\n"); } /****f* Mail/createEnvelope * NAME * createEnvelope -- create an envelope. * FUNCTION * Creates and initializes an envelope. ****** */ envelope* createEnvelope() { envelope *e; e = malloc(sizeof(envelope)); assert(e != NULL); e->to = NULL; e->from = NULL; e->replyto = NULL; e->subject = NULL; e->from_address = NULL; e->from_name = NULL; e->bcc = NULL; e->cc = NULL; e->compress = FALSE; e->contentType = NULL; e->contentEncoding = NULL; e->contentDescription = NULL; return e; } /****f* Mail/readEnvelope * NAME * readEnvelope -- create an envelope, filling in values from mail header. * FUNCTION * Creates and initializes an envelope from a file. ****** */ envelope* readEnvelope(FILE* fp) { envelope *e; char buffer[4096]; char* ptr; e = createEnvelope(); while (fgets(buffer, 4096, fp) != NULL) { *(strchr(buffer, '\n')) = '\0'; if (buffer[0] == '\0') break; /* end of headers */ if ((ptr = strchr(buffer, ':')) == NULL) continue; /* skip header, no : in it */ *ptr = '\0'; if (noCaseStrcmp(buffer, "from") == 0) { e->from = strdup(ptr+2); } else if (noCaseStrcmp(buffer, "to") == 0) { e->to = strdup(ptr+2); } else if (noCaseStrcmp(buffer, "subject") == 0) { e->subject = strdup(ptr+2); } else if (noCaseStrcmp(buffer, "cc") == 0) { e->cc = strdup(ptr+2); } else if (noCaseStrcmp(buffer, "content-type") == 0) { e->contentType = strdup(ptr+2); } else if (noCaseStrcmp(buffer, "content-transfer-encoding") == 0) { e->contentEncoding = strdup(ptr+2); } else if (noCaseStrcmp(buffer, "content-description") == 0) { e->contentDescription = strdup(ptr+2); } else continue; } return e; } /****f* Mail/setHeader * NAME * setHeader -- write something on the envelope. * SYNOPSIS * void setHeader(envelope *e, int headerType, char *format, ...) * FUNCTION * Dynamically create a mail header. ******* */ void setHeader(envelope *e, int headerType, char *format, ...) { int n; va_list ap; assert(e != NULL); va_start(ap, format); #ifdef WIN32 vsprintf(lineBuffer, format, ap); #else n = vsnprintf(lineBuffer, LINE_BUFFER_SIZE, format, ap); assert(n != -1); #endif va_end(ap); switch(headerType) { case MAILHEADER_TO: if (e->to) free(e->to); e->to = strdup(lineBuffer); break; case MAILHEADER_FROM: if (e->from) free(e->from); e->from = strdup(lineBuffer); break; case MAILHEADER_REPLYTO: if (e->replyto) free(e->replyto); e->replyto = strdup(lineBuffer); break; case MAILHEADER_SUBJECT: if (e->subject) free(e->subject); e->subject = strdup(lineBuffer); break; case MAILHEADER_BCC: if (e->bcc) free(e->bcc); e->bcc = strdup(lineBuffer); break; case MAILHEADER_CC: if (e->cc) free(e->cc); e->cc = strdup(lineBuffer); break; case MAILHEADER_CONTENTTYPE: if (e->contentType) free(e->contentType); e->contentType = strdup(lineBuffer); break; case MAILHEADER_CONTENTENCODING: if (e->contentEncoding) free(e->contentEncoding); e->contentEncoding = strdup(lineBuffer); break; case MAILHEADER_CONTENTDESCRIPTION: if (e->contentDescription) free(e->contentDescription); e->contentDescription = strdup(lineBuffer); default: assert(0); } } /****f* Mail/destroyEnvelope * NAME * destroyEnvelope -- free memory used by an envelope. * SYNOPSIS * destroyEnvelope(envelope *e) ******** */ void destroyEnvelope(envelope *e) { assert(e != NULL); if (e->to) free(e->to); if (e->from) free(e->from); if (e->from_address) free(e->from_address); if (e->from_name) free(e->from_name); if (e->replyto) free(e->replyto); if (e->subject) free(e->subject); if (e->bcc) free(e->bcc); if (e->cc) free(e->cc); if (e->contentType) free(e->contentType); if (e->contentEncoding) free(e->contentEncoding); if (e->contentDescription) free(e->contentDescription); free(e); } /****f* Mail/eMail_old * NAME * eMail_old -- mail the contents of a file to someone. * FUNCTION * Mail a file to someone. * INPUTS * e -- envelope * aGame -- game structure, contains settings for mailer etc. * fileName -- name of the file to send. * RESULT * status 0, all OK. * >0, something went wrong * BUGS * Does not write anything to the log file. ****** */ int eMail_old(game *aGame, envelope *e, char *fileName) { FILE* mailFile; char template[128]; int result; char command[4096]; pdebug(DFULL, "eMail\n"); sprintf(template, "%s/galaxyXXXXXX", tempdir); assert(fileName != NULL); assert(aGame != NULL); mailFile = fdopen(mkstemp(template), "w"); result = 1; assert(e->to); assert(e->subject); if (e->from_address && e->from_name) { fprintf(mailFile, "From: %s <%s>\n", e->from_name, e->from_address); } else if (e->from) { fprintf(mailFile, "From: %s\n", e->from); } fprintf(mailFile, "To: %s\n", e->to); fprintf(mailFile, "Subject: %s\n", e->subject); if (e->replyto) fprintf(mailFile, "Reply-To: %s\n", e->replyto); if (e->bcc) fprintf(mailFile, "BCC: %s\n", e->bcc); if (e->cc) fprintf(mailFile, "CC: %s\n", e->cc); if (e->contentType) fprintf(mailFile, "Content-Type: %s\n", e->contentType); if (e->contentEncoding) fprintf(mailFile, "Content-tranfer-encoding: %s\n", e->contentEncoding); if (e->contentDescription) fprintf(mailFile, "Content-description: %s\n", e->contentDescription); #ifndef WIN32 if (e->compress && aGame->serverOptions.compress && aGame->serverOptions.encode) { addMimeHeader(mailFile); } fprintf(mailFile, "\n\n"); if (e->compress && aGame->serverOptions.compress && aGame->serverOptions.encode) { char *relative_path; char *ptr; char zipped_name[4096]; char encoded_name[4096]; addMimeText(mailFile); fprintf(mailFile, "Turn report is attached as .zip file.\n\n"); relative_path = strstr(fileName, "reports"); if (relative_path == NULL) { fprintf(stderr, "Reports are not in their standards position\n"); relative_path = fileName; } strcpy(zipped_name, fileName); if ((ptr = strrchr(zipped_name, '.')) != NULL) *ptr = '_'; strcat(zipped_name, ".zip"); strcpy(encoded_name, fileName); if ((ptr = strrchr(encoded_name, '.')) != NULL) *ptr = '_'; result = ssystem("%s %s %s > /dev/null 2>&1", aGame->serverOptions.compress, zipped_name, relative_path); result |= ssystem("%s < %s > %s 2> /dev/null", aGame->serverOptions.encode, zipped_name, encoded_name); addMimeZip(mailFile); result |= appendToMail(encoded_name, mailFile); addMimeEnd(mailFile); result |= ssystem("rm %s %s", zipped_name, encoded_name); } else { result = appendToMail(fileName, mailFile); } #endif fclose(mailFile); #ifndef WIN32 sprintf(command, "%s", aGame->serverOptions.sendmail); if (e->from_address) { char tmpBuf[4096]; sprintf(tmpBuf, " -f \"%s\"", e->from_address); strcat(command, tmpBuf); } if (e->from_name) { char tmpBuf[4096]; sprintf(tmpBuf, " -F \"%s\"", e->from_name); strcat(command, tmpBuf); } result |= ssystem("%s < %s", command, template); result |= ssystem("rm %s", template); #endif return result; } /****f* Mail/eMail * NAME * eMail -- mail the contents of a file to someone. * FUNCTION * Mail a file to someone. * INPUTS * e -- envelope * aGame -- game structure, contains settings for mailer etc. * fileName -- name of the file to send. * RESULT * status 0, all OK. * >0, something went wrong * BUGS * Does not write anything to the log file. ****** */ int eMail(game *aGame, envelope *e, char *fileName) { FILE* mailFile; char template[128]; int result; char command[4096]; pdebug(DFULL, "eMail %s\n", fileName ); sprintf(template, "%s/galaxyXXXXXX", tempdir); assert(fileName != NULL); assert(aGame != NULL); mailFile = fdopen(mkstemp(template), "w"); result = 1; assert(e->to); assert(e->subject); if (e->from_address && e->from_name) { fprintf(mailFile, "From: %s <%s>\n", e->from_name, e->from_address); } else if (e->from) { fprintf(mailFile, "From: %s\n", e->from); } fprintf(mailFile, "To: %s\n", e->to); fprintf(mailFile, "Subject: %s\n", e->subject); if (e->replyto) fprintf(mailFile, "Reply-To: %s\n", e->replyto); if (e->bcc) fprintf(mailFile, "BCC: %s\n", e->bcc); if (e->cc) fprintf(mailFile, "CC: %s\n", e->cc); if (e->contentType) fprintf(mailFile, "Content-Type: %s\n", e->contentType); if (e->contentEncoding) fprintf(mailFile, "Content-tranfer-encoding: %s\n", e->contentEncoding); if (e->contentDescription) fprintf(mailFile, "Content-description: %s\n", e->contentDescription); #ifndef WIN32 addMimeHeader(mailFile); fprintf(mailFile, "\n\n"); if (e->compress && aGame->serverOptions.compress && aGame->serverOptions.encode) { char *relative_path; char *ptr; char zipped_name[4096]; char encoded_name[4096]; addMimeText(mailFile); fprintf(mailFile, "Turn report is attached as .zip file.\n\n"); relative_path = strstr(fileName, "reports"); if (relative_path == NULL) { relative_path = fileName; } strcpy(zipped_name, fileName); if ((ptr = strrchr(zipped_name, '.')) != NULL) *ptr = '_'; strcat(zipped_name, ".zip"); strcpy(encoded_name, fileName); strcat(encoded_name, "_enc"); if ((ptr = strrchr(encoded_name, '.')) != NULL) *ptr = '_'; result = ssystem("%s %s %s > /dev/null 2>&1", aGame->serverOptions.compress, zipped_name, relative_path); result |= ssystem("%s < %s > %s 2> /dev/null", aGame->serverOptions.encode, zipped_name, encoded_name); addMimeZip(mailFile); result |= appendToMail(encoded_name, mailFile); addMimeEnd(mailFile); result |= ssystem("rm %s %s", zipped_name, encoded_name); } else { char *relative_path; char *ptr; char dos_name[4096]; char encoded_name[4096]; addMimeText(mailFile); fprintf(mailFile, "Turn report is attached as text file.\n\n"); relative_path = strstr(fileName, "reports"); if (relative_path == NULL) { relative_path = fileName; } strcpy(encoded_name, fileName); strcat(encoded_name, "_enc"); strcpy(dos_name, fileName); strcat(dos_name, "_dos"); if ((ptr = strrchr(encoded_name, '.')) != NULL) *ptr = '_'; result = ssystem("/usr/bin/unix2dos -n %s %s 2> /dev/null", relative_path, dos_name); result |= ssystem("%s < %s > %s 2> /dev/null", aGame->serverOptions.encode, dos_name, encoded_name); addMimeTXT(mailFile, aGame->turn); result |= appendToMail(encoded_name, mailFile); addMimeEnd(mailFile); // result |= ssystem("rm %s %s" , encoded_name, dos_name); } #endif fclose(mailFile); #ifndef WIN32 sprintf(command, "%s", aGame->serverOptions.sendmail); if (e->from_address) { char tmpBuf[4096]; sprintf(tmpBuf, " -f \"%s\"", e->from_address); strcat(command, tmpBuf); } if (e->from_name) { char tmpBuf[4096]; sprintf(tmpBuf, " -F \"%s\"", e->from_name); strcat(command, tmpBuf); } result |= ssystem("%s < %s", command, template); result |= ssystem("rm %s", template); #endif return result; } void addMimeHeader(FILE *mailFile) { fprintf(mailFile, "Mime-Version: 1.0\n"); fprintf(mailFile, "Content-Type: multipart/mixed; boundary=\"9jxsPFA5p3P2qPhR\"\n"); fprintf(mailFile, "Content-Disposition: inline\n"); } void addMimeText(FILE *mailFile) { fprintf(mailFile, "--9jxsPFA5p3P2qPhR\n"); fprintf(mailFile, "Content-Type: text/plain; charset=us-ascii\n"); fprintf(mailFile, "Content-Disposition: inline\n"); fprintf(mailFile, "\n"); } void addMimeUUE(FILE *mailFile) { fprintf(mailFile, "--9jxsPFA5p3P2qPhR\n"); fprintf(mailFile, "Content-Type: application/zip\n"); fprintf(mailFile, "Content-Disposition: attachment; filename=\"turn.zip\"\n"); fprintf(mailFile, "Content-Transfer-Encoding: base64\n"); fprintf(mailFile, "\n"); } void addMimeZip(FILE *mailFile) { fprintf(mailFile, "--9jxsPFA5p3P2qPhR\n"); fprintf(mailFile, "Content-Type: application/zip\n"); fprintf(mailFile, "Content-Disposition: attachment; filename=\"turn.zip\"\n"); fprintf(mailFile, "Content-Transfer-Encoding: base64\n"); fprintf(mailFile, "\n"); } void addMimeTXT(FILE *mailFile, int turn) { fprintf(mailFile, "--9jxsPFA5p3P2qPhR\n"); fprintf(mailFile, "Content-Type: text/plain\n"); fprintf(mailFile, "Content-Disposition: attachment; filename=\"turn%02d.txt\"\n", turn); fprintf(mailFile, "Content-Transfer-Encoding: base64\n"); fprintf(mailFile, "\n"); } void addMimeEnd(FILE *mailFile) { fprintf(mailFile, "\n--9jxsPFA5p3P2qPhR--\n"); } int appendToMail(char *fileName, FILE *mailFile) { FILE *f; char *isRead; f = fopen(fileName, "r"); if (f) { for (isRead = fgets(lineBuffer, LINE_BUFFER_SIZE, f); isRead; isRead = fgets(lineBuffer, LINE_BUFFER_SIZE, f)) { fputs(lineBuffer, mailFile); } fclose(f); return FALSE; } else { return TRUE; } } /****f* Process/getReturnAddress * NAME * getReturnAddress * FUNCTION * Extract the return address from a players email. ****** */ char * getReturnAddress( FILE *orders ) { char *isRead; char *c; for ( isRead = fgets( lineBuffer, LINE_BUFFER_SIZE, orders ); isRead; isRead = fgets( lineBuffer, LINE_BUFFER_SIZE, orders ) ) { /* WIN32 */ if ( noCaseStrncmp( string_mail_to, lineBuffer, 3 ) == 0 ) break; } assert( isRead != NULL ); for ( c = lineBuffer; *c; c++ ) { if ( *c == '\n' ) *c = '\0'; } return strdup( lineBuffer + 3 ); } void gmNotify(char* subject, char* filename, game* aGame) { envelope* env; env = createEnvelope(); if (aGame == NULL) { char buffer[4096]; FILE* tmpFP; aGame = (game*)malloc(sizeof(game)); loadNGConfig(aGame); if (aGame->serverOptions.GMemail == NULL) { fprintf(stderr, "**ERROR** Could not load game or config in " "gmNotify!!!\n"); fprintf(stderr, "This is the message that was trying to be " "delivered:\n"); fprintf(stderr, "Subject: %s\n", subject); tmpFP = fopen(filename, "r"); while (fgets(buffer, 4096, tmpFP) != NULL) fprintf(stderr, "%s", buffer); fclose(tmpFP); return; } } env->to = strdup(aGame->serverOptions.GMemail); env->from = strdup(aGame->serverOptions.SERVERemail); env->replyto = strdup(aGame->serverOptions.ReplyTo); env->subject = strdup(subject); eMail(aGame, env, filename); destroyEnvelope(env); return; } --- NEW FILE: util.c --- #include "util.h" #include <stdlib.h> #include <limits.h> #include <math.h> #include <assert.h> #include <stdarg.h> #include <time.h> #include <ctype.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #ifndef WIN32 #include <unistd.h> #endif #ifdef WIN32 #include <direct.h> #endif #include "create.h" [...1721 lines suppressed...] rewind(inMail); /* read all the header stuff which only goes until the first blank line */ while (fgets(buffer, sizeof(char)*4096, inMail)) { if (buffer[0] == '\n') break; } /* now copy everything up to the (optional) #end */ while (fgets(buffer, sizeof(char)*4096, inMail)) { if (noCaseStrncmp(buffer, "#end", 4) == 0) { fprintf(outMail, "%s", buffer); break; } fprintf(outMail, "%s", buffer); } return; } --- NEW FILE: globals.c --- #include "galaxy.h" char map[MAPWIDTH][MAPHEIGHT]; char buf[LINE_BUFFER_SIZE]; /****v* GalaxyNG/lineBuffer * NAME * lineBuffer -- global line buffer. * NOTES * 2 is there to prevent buffer overflows. * SOURCE */ char lineBuffer[2 * LINE_BUFFER_SIZE]; /******/ /****v* GalaxyNG/productname * NAME * productname -- things a planet can produce. * SOURCE */ char *productname[] = { "CAP", "MAT", 0, "Drive", "Weapons", "Shields", "Cargo", }; /******/ int nbrProducts = sizeof(productname) / sizeof(char *); FILE *turnFile = NULL; /******/ /****v* GalaxyNG/galaxynghome * NAME * galaxynghome -- path to all data files * SOURCE */ char *galaxynghome = NULL; /*****/ /****v* GalaxyNG/tempdir * NAME * tempdir -- path to the directory used to store temporary files. * SOURCE */ char *tempdir = NULL; /*****/ /****v* GalaxyNG/options * NAME * options -- options available to players. * FUNCTION * Associative array to look-up option flag by option names. * SOURCE */ struct option options[] = { {"anonymous", F_ANONYMOUS}, {"autoUnload", F_AUTOUNLOAD}, {"prodTable", F_PRODTABLE}, {"sortGroups", F_SORTGROUPS}, {"groupForeCast", F_GROUPFORECAST}, {"planetForeCast", F_PLANETFORECAST}, {"shipTypeForecast", F_SHIPTYPEFORECAST}, {"routesForecast", F_ROUTESFORECAST}, {"compress", F_COMPRESS}, {"gplus", F_GPLUS}, {"machineReport", F_MACHINEREPORT}, /* CB 1998 - Experimental */ {"battleProtocol", F_BATTLEPROTOCOL}, {"xmlReport", F_XMLREPORT}, /* KDW 2003 */ {"txtReport", F_TXTREPORT}, {NULL, 0} }; char* string_mail_subject = "subject:"; /* Dutch: onderwerp: */ char* string_mail_to = "to:"; /* Dutch: aan: */ char* string_mail_from = "from:"; /* Dutch: van: */ /**********/ --- NEW FILE: logging.c --- #include "logging.h" static enum DebugLevels debugLevel = DNONE; static enum LogLevels logLevel = LNONE; static FILE* logFile = NULL; /****f* logging/pdebug * NAME * pdebug -- dump a message to stdout * SYNOPSIS * void pdebug(int level, char *format,...) * FUNCTION * Dump a debug message to stdout. Each message has a debug level. * Messages are only printed if they have a level below the debug * level (specified in the global debugLevel). * INPUTS * level -- debug level of the message * format -- format string for the messgage * ... -- other parameters * SOURCE */ void pdebug(enum DebugLevels level, char *format, ...) { va_list ap; if (level <= debugLevel) { va_start(ap, format); vprintf(format, ap); va_end(ap); } } /*******/ /****f* logging/plog * NAME * plog -- dump a messgage to the log file. * SYNOPSIS * void plog(int level, char *format,...) * FUNCTION * Dump a log message to the logfile. Each message has a log level. * Messages are only stored if they have a level below the * log level (specified in the global logLevel). * INPUTS * level -- log level of the message * format -- format string for the messgage * ... -- other parameters * SOURCE */ void plog(enum LogLevels level, char *format, ...) { va_list ap; if (level <= logLevel && logFile) { va_start(ap, format); vfprintf(logFile, format, ap); va_end(ap); } } /**********/ /****f* logging/plogtime * NAME * plogtime -- write current time and date to the log file. * SYNOPSIS * void plogtime(int level) * SOURCE */ void plogtime(enum LogLevels level) { if (level <= logLevel && logFile) { time_t ttp; char timeBuffer[255]; time(&ttp); strftime(timeBuffer, 255, "%H:%M:%S %a %b %d %Y\n", localtime(&ttp)); fprintf(logFile, "%s", timeBuffer); } } /***********/ /****f* logging/setDebugLevel * NAME * setDebugLevel -- set the system debugging level * SYNOPSIS * enum DebugLevels setDebugLevel(enum DebugLevels level) * FUNCTION * set the system debugging level * SOURCE */ enum DebugLevels setDebugLevel(enum DebugLevels level) { enum DebugLevels lastLevel = debugLevel; debugLevel = level; return lastLevel; } /****f* logging/setLogLevel * NAME * setLogLevel -- set the system logging level * SYNOPSIS * enum LogLevels setLogLevel(enum LogLevels level) * FUNCTION * set the system logging level * SOURCE */ enum LogLevels setLogLevel(enum LogLevels level) { enum LogLevels lastLevel = logLevel; logLevel = level; return lastLevel; } /****f* logging/openLog * NAME * openLog -- open a log file. * FUNCTION * Open a log file. Close the previous log file if open. * SOURCE */ int openLog(char *name, char* mode) { if (logFile) fclose(logFile); if ((logFile = fopen(name, mode)) == NULL) { fprintf(stderr, "Could not open log file %s\n", name); return 1; } setvbuf(logFile, NULL, _IONBF, 0); return 0; } /**********/ void closeLog() { if (logFile) { fclose(logFile); logFile = NULL; } } |