int env_is_old( struct envelope *env, int dfile_fd ) { struct timeval tv_now; struct stat sb; if ( env->e_age == ENV_AGE_UNKNOWN ) { if ( fstat( dfile_fd, &sb ) != 0 ) { syslog( LOG_ERR, "Syserror: env_is_old fstat %s/D%s: %m", env->e_dir, env->e_id ); return( 0 ); } if ( simta_gettimeofday( &tv_now ) != 0 ) { return( 0 ); } if ( simta_bounce_seconds > 0 ) { if (( tv_now.tv_sec - sb.st_mtime ) > ( simta_bounce_seconds )) { env->e_age = ENV_AGE_OLD; } else { env->e_age = ENV_AGE_NOT_OLD; } } } if ( env->e_age == ENV_AGE_OLD ) { return( 1 ); } return( 0 ); }
int env_fsync( const char *path ) { int fd; int ret = 0; if (( fd = open( path, O_RDONLY )) < 0 ) { syslog( LOG_ERR, "Syserror: env_fsync open %s: %m", path ); return( 1 ); } /* fdatasync() "does not flush modified metadata unless that metadata is * needed in order to allow a subsequent data retrieval to be correctly * handled." We don't require that all metadata be synced to disk, so if * fdatasync() is available it's preferred. */ #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 if ( fdatasync( fd ) < 0 ) { #else if ( fsync( fd ) < 0 ) { #endif syslog( LOG_ERR, "Syserror: env_fsync fsync %s: %m", path ); ret = 1; } close( fd ); return( ret ); } /* calling this function updates the attempt time */ int env_touch( struct envelope *env ) { char fname[ MAXPATHLEN ]; struct timeval tv_now; sprintf( fname, "%s/E%s", env->e_dir, env->e_id ); if ( utime( fname, NULL ) != 0 ) { syslog( LOG_ERR, "Syserror: env_touch utime %s: %m", fname ); return( -1 ); } if ( simta_gettimeofday( &tv_now ) != 0 ) { return( -1 ); } env->e_etime.tv_sec = tv_now.tv_sec; return( 0 ); }
struct envelope * env_create( const char *dir, const char *id, const char *e_mail, const struct envelope *parent ) { struct envelope *env; struct timeval tv_now; int pid; /* way bigger than we should ever need */ char buf[ 1024 ]; env = calloc( 1, sizeof( struct envelope )); if (( id == NULL ) || ( *id == '\0' )) { if ( simta_gettimeofday( &tv_now ) != 0 ) { env_free( env ); return( NULL ); } if (( pid = getpid()) < 0 ) { syslog( LOG_ERR, "Syserror: env_set_id getpid: %m" ); env_free( env ); return( NULL ); } snprintf( buf, 1023, "%lX.%lX.%d", (unsigned long)tv_now.tv_sec, (unsigned long)tv_now.tv_usec, pid ); id = buf; } env->e_id = strdup( id ); if ( e_mail != NULL ) { if ( env_sender( env, e_mail ) != 0 ) { env_free( env ); return( NULL ); } } if ( parent ) { env->e_dinode = parent->e_dinode; env->e_n_exp_level = parent->e_n_exp_level + 1; env_jail_set( env, parent->e_jail ); } else if ( simta_rqueue_policy == RQUEUE_POLICY_JAIL ) { env_jail_set( env, ENV_JAIL_PRISONER ); } env->e_dir = dir; return( env ); }
int env_efile( struct envelope *e ) { char tf[ MAXPATHLEN + 1 ]; char ef[ MAXPATHLEN + 1 ]; char df[ MAXPATHLEN + 1 ]; struct timeval tv_now; struct dll_entry *e_dll; sprintf( tf, "%s/t%s", e->e_dir, e->e_id ); sprintf( ef, "%s/E%s", e->e_dir, e->e_id ); sprintf( df, "%s/D%s", e->e_dir, e->e_id ); if ( rename( tf, ef ) < 0 ) { syslog( LOG_ERR, "Syserror: env_efile rename %s %s: %m", tf, ef ); unlink( tf ); return( -1 ); } if ( e->e_dir == simta_dir_fast ) { simta_fast_files++; simta_debuglog( 2, "Envelope env <%s> fast_files increment %d", e->e_id, simta_fast_files ); } simta_debuglog( 3, "env_efile %s %s %s", e->e_dir, e->e_id, e->e_hostname ? e->e_hostname : "" ); e->e_flags = ( e->e_flags & ( ~ENV_FLAG_TFILE )); e->e_flags |= ENV_FLAG_EFILE; if ( simta_gettimeofday( &tv_now ) != 0 ) { return( -1 ); } e->e_etime.tv_sec = tv_now.tv_sec; if ( simta_sync ) { env_fsync( ef ); env_fsync( df ); /* fsync() does not ensure that the directory entries for the files * have been synced, so we must explicitly sync the directory. */ env_fsync( e->e_dir ); } if ( simta_mid_list_enable != 0 ) { if (( e_dll = dll_lookup_or_create( &simta_env_list, e->e_id, 0 )) == NULL ) { return( 1 ); } if ( e_dll->dll_data == NULL ) { e_dll->dll_data = e; e->e_env_list_entry = e_dll; } } if ( simta_sender_list_enable != 0 ) { if ( sender_list_add( e ) != 0 ) { return( 1 ); } } return( 0 ); }
int main( int argc, char *argv[] ) { SNET *in; SNET *out; char *line; int x; struct timeval tv; char path[ MAXPATHLEN ]; int c; if ( simta_gettimeofday( &tv ) != 0 ) { perror( "gettimeofday" ); return( 1 ); } /* XXX hard path */ sprintf( path, "%s/%ld.%ld", "/var/simta/log", tv.tv_sec, tv.tv_usec ); if (( in = snet_attach( 0, 1024 * 1024 )) == NULL ) { perror( "snet_attach" ); exit( 1 ); } if (( out = snet_open( path, O_CREAT | O_WRONLY, S_IRUSR | S_IRGRP | S_IROTH, 1024 * 1024 )) == NULL ) { perror( "snet_open" ); exit( 1 ); } snet_writef( out, "%s", argv[ 0 ] ); for ( x = 1; x < argc; x++ ) { snet_writef( out, " %s", argv[ x ] ); } snet_writef( out, "\n\n" ); opterr = 0; while (( c = getopt( argc, argv, "b:" )) != -1 ) { switch ( c ) { case 'b': if ( strlen( optarg ) == 1 ) { switch ( *optarg ) { case 'a': /* -ba ARPANET mode */ case 'd': /* -bd Daemon mode, background */ case 's': /* 501 Permission denied */ printf( "501 Mode not supported\r\n" ); exit( 1 ); } } break; default: break; } } while (( line = snet_getline( in, NULL )) != NULL ) { snet_writef( out, "%s\n", line ); } if ( snet_close( in ) != 0 ) { perror( "snet_close" ); exit( 1 ); } if ( snet_close( out ) != 0 ) { perror( "snet_close" ); exit( 1 ); } return( 0 ); }