#include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #ifdef HAVE_DIRENT_H # include #else # define dirent direct # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif #endif #ifdef HAVE_LIMITS_H #include #endif #include #include #include #include #ifdef DMALLOC #include #endif #include "suck_config.h" #include "suck.h" #include "both.h" #include "suckutils.h" #include "phrases.h" /*------------------------------------------------------------------------*/ /* check if directory exists, if not, try to create it. */ /* return TRUE if made/exists and can write to it */ /* -----------------------------------------------------------------------*/ int checkdir(const char *dirname) { struct stat buf; int retval = TRUE; if(stat(dirname, &buf)== 0) { /* it exists */ if(!S_ISDIR(buf.st_mode)) { error_log(ERRLOG_REPORT, sucku_phrases[0], dirname, NULL); retval = FALSE; } else if(access(dirname, W_OK) != 0) { error_log(ERRLOG_REPORT, sucku_phrases[1], dirname, NULL); retval = FALSE; } } else if(errno == ENOENT) { /* doesn't exist, make it */ if(mkdir(dirname, (S_IRUSR | S_IWUSR | S_IXUSR)) != 0) { MyPerror(dirname); retval = FALSE; } } else { /* huh? */ MyPerror(dirname); retval = FALSE; } return retval; } /*--------------------------------------------------------------*/ /* if which = FP_SET, store directory in array */ /* = FP_GET, retrieve directory and add file name */ /* = FP_GET_NOPOSTFIX, get without appending postfix */ /* = FP_GET_POSTFIX, get ONLY the postfix */ /* retval FP_SET, if valid dir, the dir, else NULL */ /* FP_GET, full path */ /* FP_GET_POSTFIX, only the postfix */ /*--------------------------------------------------------------*/ const char *full_path(int which, int dir, const char *fname) { static char dirs[FP_NR_DIRS][PATH_MAX+1] = { N_TMPDIR, N_DATADIR, N_MSGDIR }; static char path[PATH_MAX+1]; /* static so area valid after return */ static char postfix[PATH_MAX+1] = { "\0" }; char *retptr; int ok, i; retptr = NULL; switch(which) { case FP_GET: case FP_GET_NOPOSTFIX: /* put the right directory as the first part of the path */ strcpy(path, dirs[dir]); /* if it contains a dit, then change to full path */ if(path[0] == '.') { path[0] = '\0'; if(getcwd(path, PATH_MAX) == NULL) { MyPerror(path); /* restore current path and pray */ /* it will work later */ strcpy(path, dirs[dir]); } else { /* tack on remainder of path */ /* the 1 so skip . */ strcat(path, &dirs[dir][1]); } } if(fname != NULL && fname[0] != '\0') { i = strlen(path); /* if nothing to put on don't do any of this */ /* put on trailing slant bar if needed */ if(path[i-1] != '/') { path[i++] = '/'; path[i] = '\0'; /* null terminate it */ } /* finally, put on filename */ strcpy(&path[i], fname); if(which != FP_GET_NOPOSTFIX && postfix[0] != '\0') { strcat(path, postfix); } } retptr = path; break; case FP_SET_POSTFIX: ok = TRUE; strncpy(postfix, fname, sizeof(postfix)); break; case FP_GET_POSTFIX: retptr = postfix; break; case FP_SET: ok = TRUE; switch(dir) { case FP_TMPDIR: if(access(fname, W_OK) == -1) { MyPerror(fname); ok = FALSE; } break; case FP_DATADIR: if(access(fname, R_OK) == -1) { MyPerror(fname); ok = FALSE; } break; case FP_MSGDIR: /* do_nothing, this is checked elsewhere */ break; } if(ok == FALSE) { retptr = NULL; } else { strncpy(dirs[dir], fname, sizeof(dirs[0])); retptr = dirs[dir]; } break; } return retptr; } #ifdef LOCKFILE /*--------------------------------------------------------------*/ int do_lockfile(PMaster master) { int retval; FILE *f_lock; const char *lockfile; pid_t pid; retval = RETVAL_OK; lockfile = full_path(FP_GET, FP_TMPDIR, N_LOCKFILE); if((f_lock = fopen(lockfile, "r")) != NULL) { /* okay, let's try and see if this sucker is truly alive */ fscanf(f_lock, "%ld", (long *) &pid); fclose(f_lock); if(pid <= 0) { error_log(ERRLOG_REPORT, sucku_phrases[2], lockfile, NULL); retval = RETVAL_ERROR; } /* this next technique borrowed from pppd, sys-linux.c (ppp2.2.0c) */ /* if the pid doesn't exist (can't send any signal to it), then try */ /* to remove the stale PID file so can recreate it. */ else if(kill(pid, 0) == -1 && errno == ESRCH) { /* no pid found */ if(unlink(lockfile) == 0) { /* this isn't error so don't put in error log */ print_phrases(master->msgs, sucku_phrases[3], lockfile, NULL); } else { error_log(ERRLOG_REPORT, sucku_phrases[4], lockfile, NULL); retval = RETVAL_ERROR; } } else { error_log(ERRLOG_REPORT, sucku_phrases[5], lockfile, NULL); retval = RETVAL_ERROR; } } if(retval == RETVAL_OK) { if((f_lock = fopen(lockfile, "w")) != NULL) { fprintf(f_lock, "%ld", (long) getpid()); fclose(f_lock); } else { error_log(ERRLOG_REPORT, sucku_phrases[6], lockfile, NULL); retval = RETVAL_ERROR; } } return retval; } #endif /*-------------------------------------------------------------------------*/ int qcmp_msgid(const char *nr1, const char *nr2) { /* return -1 if a < b, 0 if a == b, 1 if a > b */ int retval = 0; /* cmp two article id numbers */ /* which is */ /* use case sensitive compares up to the @ */ /* then use case insensitive compares on the organization */ /* this is to conform to rfc822 */ int retval = FALSE; if(nr1 != NULL && nr2 != NULL) { while ( *nr1 == *nr2 && *nr1 != '\0' && *nr1 != '@') { nr1++; nr2++; } if(*nr1 == '@') { while( tolower(*nr1) == tolower(*nr2) && *nr1 != '\0') { nr1++; nr2++; } } if(*nr1 == *nr2 && *nr1 == '\0') { retval = TRUE; } } return retval; } /*-----------------------------------------------------------------------------*/ /* move a file from one location to another */ /*-----------------------------------------------------------------------------*/ int move_file(const char *src, const char *dest) { char block[MAXLINLEN]; FILE *fpi, *fpo; int retval = RETVAL_OK; size_t nrread; /* first try the easy way */ if(src == NULL || dest == NULL) { error_log(ERRLOG_REPORT, sucku_phrases[9], NULL); retval = RETVAL_ERROR; } else if(rename(src, dest) != 0) { #ifdef EMX if(errno != EACCES) { MyPerror(src); retval = RETVAL_ERROR; } #else if(errno != EXDEV) { MyPerror(src); retval = RETVAL_ERROR; } #endif else { /* can't rename, try to copy file */ if((fpi = fopen(src, "r")) == NULL) { MyPerror(src); retval = RETVAL_ERROR; } else if(( fpo = fopen(dest, "w")) == NULL) { fclose(fpi); MyPerror(dest); retval = RETVAL_ERROR; } else { while(retval == RETVAL_OK && (nrread = fread(block, sizeof(char), MAXLINLEN, fpi)) > 0) { if(fwrite(block, sizeof(char), nrread, fpo) != nrread) { error_log(ERRLOG_REPORT, sucku_phrases[7], dest, NULL); retval = RETVAL_ERROR; } } if(ferror(fpi) != 0) { error_log(ERRLOG_REPORT, sucku_phrases[8], src, NULL) ; } fclose(fpi); fclose(fpo); } /* now that copy is successful, nuke it */ if(retval == RETVAL_OK) { unlink(src); } } } return retval; }