X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=innduct.git;a=blobdiff_plain;f=innfeed%2Fmisc.c;fp=innfeed%2Fmisc.c;h=0000000000000000000000000000000000000000;hp=0da269dfde58444f070966515b9c691d14028b6d;hb=b7a32e2d73e3ab1add8208d3e157f7269a31ef4d;hpb=ac902a8299ff4469b356836f431ead31c3377377 diff --git a/innfeed/misc.c b/innfeed/misc.c deleted file mode 100644 index 0da269d..0000000 --- a/innfeed/misc.c +++ /dev/null @@ -1,782 +0,0 @@ -/* $Id: misc.c 7420 2005-10-09 04:40:13Z eagle $ -** -** Helper routines for the innfeed program. -** -** Written by James Brister -*/ - -#include "innfeed.h" -#include "config.h" -#include "clibrary.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* FIXME: Default to a max length of 256 characters for path names if the - host headers doesn't give better information. Should be replaced by the - code from Stevens. */ -#ifndef PATH_MAX -# define PATH_MAX 256 -#endif - -#include "inn/messages.h" -#include "libinn.h" - -#include "endpoint.h" -#include "misc.h" -#include "tape.h" - -unsigned int openfds ; -int debuggingOutput ; -unsigned int loggingLevel ; -char **PointersFreedOnExit ; - -bool debuggingDump = true ; -extern void (*gPrintInfo) (void) ; -void (*gCleanUp) (void) = 0 ; - - -/* Log a message to stderr, called from warn or die. Mostly the same as the - standard message_log_stderr, but prepends the date to each line. */ -void -error_log_stderr_date(int len UNUSED, const char *fmt, va_list args, int err) -{ - char timebuff[30]; - time_t now; - struct tm *tm; - - now = time(NULL); - tm = localtime(&now); - strftime(timebuff, sizeof(timebuff), "%Y-%m-%d %H:%M:%S", tm); - fprintf(stderr, "%s %s: ", timebuff, - (message_program_name ? message_program_name : "UNKNOWN")); - vfprintf(stderr, fmt, args); - if (err) fprintf(stderr, ": %s", strerror(err)); - fprintf(stderr, "\n"); -} - -/* If desired, print out the state of innfeed, call a cleanup function, and - then dump core. Used as an exit handler for die. */ -int -dump_core(void) -{ -#if SNAPSHOT_ON_DIE - if (debuggingDump && gPrintInfo != NULL) - (*gPrintInfo)(); -#endif - - if (gCleanUp != NULL) - (*gCleanUp)(); - - if (CORE_DIRECTORY != NULL) - chdir(CORE_DIRECTORY); - else - chdir(getTapeDirectory()); - - sleep(5); - abort(); - - /* Not reached. */ - return 1; -} - -/* An alternate version of die, used when we don't want to dump core. This - should somehow eventually be phased out to simplify things; it's - basically a copy of die() from lib/error.c that ignores the cleanup - handler and has innfeed's handlers hard-coded (ugh). */ -void -logAndExit(int status, const char *format, ...) -{ - va_list args; - int length; - - va_start(args, format); - length = vsnprintf(NULL, 0, format, args); - va_end(args); - va_start(args, format); - error_log_stderr_date(length, format, args, 0); - va_end(args); - va_start(args, format); - message_log_syslog_err(length, format, args, 0); - va_end(args); - exit(status); -} - - - -void d_printf (unsigned int level, const char *fmt, ...) -{ - static pid_t myPid ; - char timeString [30] ; - time_t now ; - va_list ap ; - - if (myPid == 0) - myPid = getpid () ; - - if (loggingLevel < level) - return ; - - now = theTime() ; - /* strip off leading day name */ - strlcpy (timeString, ctime (&now) + 4, sizeof (timeString)) ; - timeString [15] = '\0' ; /* strip off trailing year and newline */ - - va_start (ap, fmt) ; - fprintf (stderr, "%s %s[%ld]: ",timeString, - (message_program_name ? message_program_name : "UNKNOWN"), - (long) myPid) ; - vfprintf (stderr, fmt, ap) ; - va_end (ap) ; -} - -void logOrPrint (int level, FILE *fp, const char *fmt, ...) -{ - va_list ap ; - - va_start (ap,fmt) ; - if (fp != NULL) - { - vfprintf (fp,fmt,ap) ; - fputc ('\n',fp) ; - } - else - { - char buffer [512] ; /* gag me */ - - vsnprintf (buffer,sizeof (buffer),fmt,ap) ; - syslog (level,"%s",buffer) ; - } - va_end (ap) ; -} - - - -/* return true if the file exists and is a regular file. */ -bool fileExistsP (const char *filename) -{ - struct stat buf ; - - if (stat (filename,&buf) < 0) - return false ; - - return (S_ISREG (buf.st_mode) ? true : false) ; -} - - -bool isDirectory (const char *filename) -{ - struct stat buf ; - - if (stat (filename,&buf) < 0) - return false ; - - return (S_ISDIR (buf.st_mode) ? true : false) ; -} - - - -bool getNntpResponse (char *p, int *code, char **rest) -{ - bool rval = true ; - int cd = 0 ; - int digits = 0 ; - - if (rest) - *rest = 0 ; - *code = 0 ; - - if (p == NULL) - return false ; - - while (*p && CTYPE (isspace, *p)) - p++ ; - - while (*p && CTYPE (isdigit, *p)) - { - digits++ ; - cd = (cd * 10) + (*p - '0') ; - p++ ; - } - - if (digits != 3) - return false ; - - if (*p == '-') - p++ ; - - while (*p && CTYPE (isspace, *p)) - p++ ; - - if (rest) - *rest = p ; - - *code = cd ; - - return rval ; -} - - - -/* Pull out a message id from a response on to a streaming command */ -char *getMsgId (const char *p) -{ - const char *q ; - char *rval ; - - while (*p && CTYPE (isspace, *p)) p++ ; - while (*p && !CTYPE (isspace, *p)) p++ ; /* skip response code */ - while (*p && CTYPE (isspace, *p)) p++ ; - - if ( *p == '\0' ) - return NULL ; - - q = p ; - while ( *q && !CTYPE (isspace, *q) ) - q++ ; - - rval = xstrndup (p, q - p) ; - - return rval ; -} - - - - -char *findNonBlankString (char *ptr, char **tail) -{ - char *p, *q ; - - for (p = ptr ; *p && CTYPE (isspace, *p) ; p++) - /* nada */ ; - if ( ! *p ) - return NULL ; - - for (q = p ; *q && !CTYPE (isspace, *q) ; q++) - /* nada */ ; - - *tail = q ; - - return p ; -} - - -/* strtok can't handle zero length tokens. */ -char *mystrtok (char *line, const char *sep) -{ - static char *newPoint ; - char *oldline ; - - if (line == NULL && newPoint == NULL) - return NULL ; - - if (line != NULL) - { - oldline = line ; - while (*line != '\0' && strchr (sep,*line) == NULL) - line++ ; - - if (*line == '\0') - newPoint = NULL ; - else - { - newPoint = line + 1 ; - *line = '\0' ; - } - } - else - { - if (newPoint == NULL) - return NULL ; - - oldline = newPoint ; - line = oldline ; - - while (*line != '\0' && strchr (sep,*line) == NULL) - line++ ; - - if (*line == '\0') - newPoint = NULL ; - else - { - newPoint = line + 1 ; - *line = '\0' ; - } - } - - return oldline ; -} - - - -void trim_ws (char *string) -{ - char *p ; - unsigned int len ; - - assert (string != NULL) ; - - len = strlen (string) ; - if (len == 0) - return ; - - for (p = string + len - 1 ; p >= string && CTYPE (isspace, *p) ; p--) - /* nada */ ; - *++p = '\0' ; -} - - -#if 0 -/* Scribble on top of memory we're about to free. */ -void deadBeef (void *base, size_t byteCount) -{ - unsigned char *b = (unsigned char *) base ; - int i ; - -#if 0 - - memset (base, 0, byteCount) ; - -#else - - assert (b != NULL) ; - - for (i = 0 ; i < ((int) byteCount) - 4 ; i += 4) - { -#if 0 - *((int *) (b + i)) = 0xdeadbeef ; -#else - b [i + 0] = (unsigned char) 0xde ; - b [i + 1] = (unsigned char) 0xad ; - b [i + 2] = (unsigned char) 0xbe ; - b [i + 3] = (unsigned char) 0xef ; -#endif - } - - switch (byteCount % 4) - { - case 0: - *(b + i + 3) = (unsigned char) 0xef ; - - case 3: - *(b + i + 2) = (unsigned char) 0xbe ; - - case 2: - *(b + i + 1) = (unsigned char) 0xad ; - - case 1: - *b = (unsigned char) 0xde ; - } - -#endif -} -#endif - -/* Not using plain flock or lockf 'cause I don't want to waste file - descriptors. This routine is based on the file shlock.c from INN. */ -bool lockFile (const char *fileName) -{ - char buff [20] ; - char tmpName [PATH_MAX], realName [PATH_MAX] ; - char *p ; - int fd, i ; - pid_t pid = getpid () ; - - strlcpy (realName,fileName,sizeof (realName)) ; - if ((p = strrchr (realName, '/')) != NULL) - { - *p = '\0' ; - snprintf (tmpName, sizeof(tmpName), "%s/lockf%ld", realName, - (long) pid) ; - *p = '/' ; - } - else - snprintf (tmpName, sizeof(tmpName), "lockf%ld", (long) pid) ; - - /* Create the temporary name for the lock file. */ - while ((fd = open (tmpName, O_RDWR | O_CREAT | O_EXCL, 0644)) < 0) - { - switch (errno) - { - default: - unlink (tmpName) ; - syswarn ("ME lock file open: %s", tmpName) ; - return false ; - - case EEXIST: - if (unlink (tmpName) < 0) - { - syswarn ("ME lock file unlink: %s", tmpName) ; - return false ; - } - break; - } - } - - /* stick our pid in the temp file. */ - snprintf (buff,sizeof(buff),"%ld\n",(long) pid) ; - if (write (fd,buff,(size_t) strlen (buff)) != (int) strlen (buff)) - { - syswarn ("ME lock file pid-write") ; - close (fd) ; - unlink (tmpName) ; - return false ; - } - close (fd) ; - - /* now link the real name to the temp file. */ - while (link (tmpName,realName) < 0) - { - switch (errno) - { - default: /* opps. bailing out. */ - syswarn ("ME lock file link: %s", realName) ; - unlink (tmpName) ; - return false ; - - case EEXIST: - /* the real lock file exists. So pull out the pid in there and - see if that process is still alive. */ - if ((fd = open (realName,O_RDONLY)) < 0) - { - syswarn ("ME lock file open: %s", realName) ; - unlink (tmpName) ; - return false ; - } - - if ((i = read (fd,buff,sizeof (buff) - 1)) <= 0) - { - close (fd) ; - unlink (tmpName) ; - return false ; - } - close (fd) ; - - buff [i] = '\0' ; - pid = (pid_t) atol (buff) ; - if (pid <= 0) - { - warn ("ME lock bad-pid info in %s: %s", realName, buff) ; - unlink (tmpName) ; - return false ; - } - - /* now send a null signal to the process named inside to see if - it's still alive. */ - if (kill (pid,0) == 0) - { - warn ("ME lock in-use already: %s by pid %ld", realName, - (unsigned long) pid); - unlink (tmpName) ; - return false ; /* process is still alive */ - } - - /* process that took out the lock is gone */ - if (unlink (realName) < 0) - { - syswarn ("ME lock file unlink: %s", realName) ; - unlink (tmpName) ; - return false ; - } - } - } - - unlink (tmpName) ; - - return true ; -} - - -void unlockFile (const char *lockfile) -{ - unlink (lockfile) ; -} - - -bool endsIn (const char *string, const char *tail) -{ - size_t len = strlen (tail) ; - size_t slen = strlen (string) ; - - if (slen < len) - return false ; - else if (strcmp (string + slen - len, tail) == 0) - return true ; - else - return false ; -} - - -/* append the contents of src to dest. src is removed if append if - successful */ -bool appendFile (const char *dest, const char *src) -{ - FILE *inTmp, *outTmp ; - char buff [BUFSIZ] ; - size_t rval ; - - /* append the outputFilename file to the inputFilename file */ - if ((outTmp = fopen (dest, "a")) == NULL) - die ("fopen (%s): %s",dest, strerror (errno)) ; - if ((inTmp = fopen (src, "r")) == NULL) - die ("fopen (%s): %s",src, strerror (errno)) ; - - while ((rval = fread (buff,sizeof (char),BUFSIZ,inTmp)) > 0) - { - if (fwrite (buff,sizeof (char), rval, outTmp) != rval) - die ("fwrite: %s", strerror (errno)) ; - } - - if (ferror (inTmp)) - die ("Error on inTmp in newTape") ; - if (ferror (outTmp)) - die ("Error on outTmp in newTape") ; - - if (fclose (inTmp) != 0) - die ("fclose (inTmp): appendFile (%s,%s): %s",dest,src,strerror (errno)) ; - - if (fclose (outTmp) != 0) - die ("fclose (outTmp): appendFile (%s,%s): %s",dest,src,strerror (errno)) ; - - if (unlink (src) != 0) - die ("unlink (%s): %s", src, strerror (errno)) ; - - return true ; -} - - -/* return true if file1 is older than file2 */ -bool isOlder (const char *file1, const char *file2) -{ - struct stat buf1 ; - struct stat buf2 ; - - if (stat (file1,&buf1) < 0) - return false ; - - if (stat (file2,&buf2) < 0) - return false ; - - return ((buf1.st_mtime < buf2.st_mtime) ? true : false) ; -} - - -void freeCharP (char *charp) -{ - free (charp) ; -} - - -/* return the length of the file reference by the given file descriptor */ -long fileLength (int fd) -{ - struct stat buf ; - - if (fstat (fd,&buf) < 0) - return false ; - - return ((long) buf.st_size) ; -} - - - -const char *boolToString (bool val) -{ - return val ? "true" : "false" ; -} - -void addPointerFreedOnExit (char *pointerToFree) -{ - static int totalPointers = 0 ; - static int nextPointer = 0 ; - - if (nextPointer == 0 || nextPointer == totalPointers - 1) - { - int i; - - totalPointers += 16 ; - if (PointersFreedOnExit == NULL) - PointersFreedOnExit = xmalloc (sizeof(char *) * totalPointers) ; - else - PointersFreedOnExit = - xrealloc (PointersFreedOnExit, sizeof(char *) * totalPointers) ; - - for (i = nextPointer; i < totalPointers; i++) - PointersFreedOnExit [i] = NULL; - } - PointersFreedOnExit [nextPointer++] = pointerToFree ; -} - -/* malloc a buffer and build the filename in it. */ -char *buildFilename (const char *directory, const char *fname) -{ - int len = 0 ; - char *p = NULL ; - - if (fname == NULL) - return NULL ; - - if (directory == NULL) - directory = "." ; - - len = strlen (directory) + strlen (fname) + 2 + 1 ; - - if (len < pathMax(directory) - 2) - { - p = xmalloc (len) ; - p [0] = '\0' ; - if (fname [0] != '/') - { - strlcat (p,directory,len) ; - if (p [strlen(p) - 1] != '/') - strlcat (p,"/",len) ; - } - strlcat (p,fname,len) ; - } - - return p ; -} - - - -/* borrows heavily from the shrinkfile program by chongo. */ -bool shrinkfile (FILE *fp, long size, char *name, const char *mode) -{ - long currlen = ftello (fp) ; - char *tmpname ; - char buffer [BUFSIZ] ; - FILE *tmpFp ; - int c ; - int i ; - int fd ; - - if (currlen <= size) - { - d_printf (1,"No need to shrink file (%s %ld vs %ld\n", - name,size,currlen) ; - return true ; - } - - /* create a temp file. */ - tmpname = concat (name,".XXXXXX",(char *)0) ; - fd = mkstemp (tmpname) ; - - if (fd < 0) - { - syswarn ("ME error creating temp shrink file for %s", name) ; - free (tmpname) ; - return false ; - } - - if ((tmpFp = fdopen (fd,"w")) == NULL) - { - syswarn ("ME error opening temp shrink file %s", tmpname) ; - free (tmpname) ; - return false ; - } - - if (fseeko (fp,currlen - size,SEEK_SET) != 0) - { - fclose (tmpFp) ; - warn ("ME error seeking to point %ld in %s", currlen - size, name) ; - free (tmpname) ; - return false ; - } - - /* find the end of the next line in the shrinking file. */ - while ((c = fgetc (fp)) != '\n') - if (c == EOF) - { - warn ("ME no newline in shrinking file %s", name) ; - fclose (tmpFp) ; - fseeko (fp,currlen,SEEK_SET) ; - free (tmpname) ; - return false ; - } - - /* copy the tail of the shrinking file to the temp file. */ - while ((i = fread (buffer,1,sizeof (buffer),fp)) > 0) - { - if (fwrite (buffer,1,i,tmpFp) != (size_t) i) - { - fclose (tmpFp) ; - syswarn ("ME fwrite failed to temp shrink file %s", tmpname) ; - fseeko (fp,currlen, SEEK_SET) ; - free (tmpname) ; - return false ; - } - } - - if (i < 0) - logAndExit (1,"ME fread failed on file %s: %s",name, strerror (errno)) ; - - fclose (tmpFp) ; - - if (unlink (name) != 0) - logAndExit (1,"ME oserr unlink %s: %s",name, strerror (errno)) ; - - /* we're in the same directory so this is ok. */ - if (rename (tmpname,name) != 0) - logAndExit (1,"ME oserr rename %s, %s: %s", tmpname, name, - strerror (errno)) ; - - if (freopen (name,mode,fp) != fp) - logAndExit (1,"ME freopen on shrink file failed %s: %s", name, - strerror (errno)) ; - - fseeko (fp,0,SEEK_END) ; - size = ftello (fp) ; - - notice ("ME file %s shrunk from %ld to %ld", name, currlen, size) ; - - free (tmpname) ; - - return true ; -} - - - -long pathMax (const char *pathname UNUSED) -{ - static long rval = 0 ; - - if (rval > 0) - return rval ; - -#if defined (PATH_MAX) - - rval = PATH_MAX ; - -#elif defined (_POSIX_PATH_MAX) - - rval = _POSIX_PATH_MAX ; - -#elif defined (DO_HAVE_PATHCONF) && defined (_PC_PATH_MAX) - - if (pathname == NULL) - pathname = "/tmp" ; - - rval = pathconf (pathname,_PC_PATH_MAX) ; - -#else - - rval = 255 ; - if (!logged) - { - syslog (LOG_ERR,NO_PATH_MAX,rval) ; - logged = true ; - } - -#endif - - return rval ; -}