Ejemplo n.º 1
0
int Init(void *_ctx) {
	int n;
	ctx = _ctx;

	moddebug("enter ts=%d\n",oesr_tstamp(ctx));

	if (!mem_ok) {
		init_memory();
		mem_ok = 1;
	}

	if (!log_ok) {
		mlog = NULL;
		if (USE_LOG) {
			if (init_log(ctx)) {
				return -1;
			}
		}
		log_ok = 1;
	}

	if (!check_ok) {
		if (check_configuration(ctx)) {
			return -1;
		}
		check_ok = 1;
	}

	if (init_variables(ctx)) {
		return -1;
	}

	if (init_counter(ctx)) {
		return -1;
	}

	moddebug("calling initialize, ts=%d\n",oesr_tstamp(ctx));

	/* this is the module initialize function */
	if (initialize()) {
		moddebug("error initializing module\n",oesr_tstamp(ctx));
		return -1;
	}

	n = init_interfaces(ctx);
	if (n == -1) {
		return -1;
	} else if (n == 0) {
		return 0;
	}

	moddebug("exit ts=%d\n",oesr_tstamp(ctx));
	return 1;
}
Ejemplo n.º 2
0
Archivo: main.c Proyecto: CoiLock/uhub
int main(int argc, char** argv)
{
	int ret = 0;

	parse_command_line(argc, argv);

	if (arg_check_config)
	{
		return check_configuration(arg_dump_config);
	}

#ifndef WIN32
	if (arg_fork)
	{
		ret = fork();
		if (ret == -1)
		{
			LOG_FATAL("Unable to fork to background!");
			return -1;
		}
		else if (ret == 0)
		{
			/* child process - detatch from TTY */
			fclose(stdin);
			fclose(stdout);
			fclose(stderr);
			close(0);
			close(1);
			close(2);
		}
		else
		{
			/* parent process */
			LOG_DEBUG("Forked to background\n");
			return 0;
		}
	}

	if (pidfile_create() == -1)
		return -1;

	if (drop_privileges() == -1)
		return -1;
#endif /* WIN32 */

	ret = main_loop();

#ifndef WIN32
	pidfile_destroy();
#endif

	return ret;
}
Ejemplo n.º 3
0
/**
    Init the filesystem, retriving contents from Item Manager

    @param conn             Unused
*/
static void* ifs_init (struct fuse_conn_info *conn)
{
    check_configuration ();

    /*
        User parameters are directly embedded in the hierarchy tree (cfr.
        parse_reference_formula()), so we can destroy the table at the end of the configuration
        file parsing
    */
    set_user_param (NULL, NULL);

    return NULL;
}
Ejemplo n.º 4
0
int main( int argc, char *argv[] )
{
	signed char c;

	const char *progname = "wavefront";

	debug_config(progname);

	progress_log_file = stdout;

	struct option long_options[] = {
		{"help",  no_argument, 0, 'h'},
		{"version", no_argument, 0, 'v'},
		{"debug", required_argument, 0, 'd'},
		{"jobs", required_argument, 0, 'n'},
		{"block-size", required_argument, 0, 'b'},
		{"debug-file", required_argument, 0, 'o'},
		{"log-file", required_argument, 0, 'l'},
		{"bitmap", required_argument, 0, 'B'},
		{"bitmap-interval", required_argument, 0, 'i'},
		{"auto", no_argument, 0, 'A'},
		{"local", no_argument, 0, 'L'},
		{"batch-type", required_argument, 0, 'T'},
		{"verify", no_argument, 0, 'V'},
        {0,0,0,0}
	};

	while((c=getopt_long(argc,argv,"n:b:d:o:l:B:i:qALDT:VX:Y:vh", long_options, NULL)) > -1) {
		switch(c) {
			case 'n':
				manual_max_jobs_running = atoi(optarg);
				break;
			case 'b':
				manual_block_size = atoi(optarg);
				break;
			case 'd':
				debug_flags_set(optarg);
				break;
			case 'o':
				debug_config_file(optarg);
				break;
			case 'B':
				progress_bitmap_file = optarg;
				break;
			case 'i':
				progress_bitmap_interval = atoi(optarg);
				break;
			case 'l':
				progress_log_file = fopen(optarg,"w");
				if(!progress_log_file) {
					fprintf(stderr,"couldn't open %s: %s\n",optarg,strerror(errno));
					return 1;
				}
				break;
			case 'A':
				wavefront_mode = WAVEFRONT_MODE_AUTO;
				break;
			case 'L':
				wavefront_mode = WAVEFRONT_MODE_MULTICORE;
				break;
			case 'T':
				wavefront_mode = WAVEFRONT_MODE_DISTRIBUTED;
				batch_system_type = batch_queue_type_from_string(optarg);
				if(batch_system_type==BATCH_QUEUE_TYPE_UNKNOWN) {
					fprintf(stderr,"unknown batch system type: %s\n",optarg);
					exit(1);
				}
				break;
			case 'V':
				verify_mode = 1;
				break;
			case 'X':
				xstart = atoi(optarg);
				break;
			case 'Y':
				ystart = atoi(optarg);
				break;
			case 'v':
				cctools_version_print(stdout, progname);
				exit(0);
				break;
			case 'h':
				show_help(progname);
				exit(0);
				break;
		}
	}

	cctools_version_debug(D_DEBUG, argv[0]);

	if( (argc-optind<3) ) {
		show_help(progname);
		exit(1);
	}

	function = argv[optind];
	xsize=atoi(argv[optind+1]);
	ysize=atoi(argv[optind+2]);
	total_cells = xsize*ysize;

	if(!verify_mode && !check_configuration(function,xsize,ysize)) exit(1);

	int ncpus = load_average_get_cpus();

	if(wavefront_mode!=WAVEFRONT_MODE_MULTICORE) {
		double task_time = measure_task_time();
		printf("Each function takes %.02lfs to run.\n",task_time);

		block_size = find_best_block_size(xsize,1000,2,task_time,average_dispatch_time);
		double distributed_time = wavefront_distributed_model(xsize,1000,2,task_time,block_size,average_dispatch_time);
		double multicore_time = wavefront_multicore_model(xsize,ncpus,task_time);
		double ideal_multicore_time = wavefront_multicore_model(xsize,xsize,task_time);
		double sequential_time = wavefront_multicore_model(xsize,1,task_time);

		printf("---------------------------------\n");
		printf("This workload would take:\n");
		printf("%.02lfs sequentially\n",sequential_time);
		printf("%.02lfs on this %d-core machine\n",multicore_time,ncpus);
		printf("%.02lfs on a %d-core machine\n",ideal_multicore_time,xsize);
		printf("%.02lfs on a 1000-node distributed system with block size %d\n",distributed_time,block_size);
		printf("---------------------------------\n");

		if(wavefront_mode==WAVEFRONT_MODE_AUTO) {
			if(multicore_time < distributed_time*2) {
				wavefront_mode = WAVEFRONT_MODE_MULTICORE;
			} else {
				wavefront_mode = WAVEFRONT_MODE_DISTRIBUTED;
			}
		}
	}

	if(wavefront_mode==WAVEFRONT_MODE_MULTICORE) {
		batch_system_type = BATCH_QUEUE_TYPE_LOCAL;
		max_jobs_running = ncpus;
	} else {
		max_jobs_running = 1000;
	}

	if(manual_block_size!=0) {
		block_size = manual_block_size;
	}

	if(manual_max_jobs_running!=0) {
		max_jobs_running = manual_max_jobs_running;
	}

	if(wavefront_mode==WAVEFRONT_MODE_MULTICORE) {
		printf("Running in multicore mode with %d CPUs.\n",max_jobs_running);
	} else {
		printf("Running in distributed mode with block size %d on up to %d CPUs\n",block_size,max_jobs_running);
	}

	batch_q = batch_queue_create(batch_system_type);

	if(verify_mode) exit(0);

	struct bitmap * b = bitmap_create(xsize+1,ysize+1);
	struct list *ready_list = list_create();
	struct itable *running_table = itable_create(0);

	struct batch_job_info info;
	UINT64_T jobid;
	struct wavefront_task *task;

	wavefront_task_initialize(b,ready_list);

	printf("Starting workload...\n");

	fprintf(progress_log_file,"# elapsed time : waiting jobs / running jobs / cells complete (percent complete)\n");

	while(1) {

		if(abort_mode) {
			while((task=list_pop_tail(ready_list))) {
				wavefront_task_delete(task);
			}

			itable_firstkey(running_table);
			while(itable_nextkey(running_table,&jobid,(void**)&task)) {
				batch_job_remove(batch_q,jobid);
			}
		}

		if(list_size(ready_list)==0 && itable_size(running_table)==0) break;

		while(1) {
			if(itable_size(running_table)>=max_jobs_running) break;

			task = list_pop_tail(ready_list);
			if(!task) break;
			
			jobid = wavefront_task_submit(task);
			if(jobid>0) {
				itable_insert(running_table,jobid,task);
				wavefront_task_mark_range(task,b,WAVEFRONT_TASK_STATE_RUNNING);
			} else {
				abort();
				sleep(1);
				list_push_head(ready_list,task);
			}
		}


		save_status(b,ready_list,running_table);

		jobid = batch_job_wait(batch_q,&info);
		if(jobid>0) {
			task = itable_remove(running_table,jobid);
			if(task) {
				if(info.exited_normally && info.exit_code==0) {
					total_dispatch_time += info.started-info.submitted;
					total_execute_time += MAX(info.finished-info.started,1);
					total_cells_complete+=task->width*task->height;
					total_jobs_complete++;

					average_dispatch_time = 1.0*total_dispatch_time / total_jobs_complete;
					average_task_time = 1.0*total_execute_time / total_cells_complete;

					wavefront_task_complete(b,ready_list,task);
				} else {
					printf("job %" PRIu64 " failed, aborting this workload\n",jobid);
					abort_mode = 1;
				}
			}
		}
	}

	save_status(b,ready_list,running_table);

	if(abort_mode) {
		printf("Workload was aborted.\n");
	} else {
		printf("Workload complete.\n");
	}

	return 0;
}
Ejemplo n.º 5
0
int main(int argc, char *argv[])
{
	char *configuration = NULL;
	char *infile = NULL;
	char *outfile = NULL;
	char *verbose = NULL;
	int version_opt = 0;
	char *logdir = NULL;
	char *logfile = NULL;
	char *home = NULL;
	int help_opt = 0;

	int c;
	
	static struct option long_options[] = {
		{"configuration",	required_argument, 0, 'c'},
		{"silent", no_argument, 0, 1},
		{"verbose", no_argument, 0, 'v'},
		{"version", no_argument, 0, 'V'},
		{"logdir", required_argument, 0, 'l'},
		{"logfile", required_argument, 0, 'L'},
		{"home", required_argument, 0, 2},
		{"infile", required_argument, 0, 'i'},
		{"outfile", required_argument, 0, 'o'},
		{"help", no_argument, 0, 'h'},
		{0, 0, 0, 0}
	};

#ifdef XCP	
	int is_bash_exist = system("command -v bash");

	if ( is_bash_exist != 0 )
	{
		fprintf(stderr, "Cannot find bash. Please ensure that bash is "
				"installed and available in the PATH\n");
		exit(2);
	}
#endif

	strcpy(progname, argv[0]);
	init_var_hash();

	while(1) {
		int option_index = 0;

		c = getopt_long(argc, argv, "i:o:c:vVl:L:h", long_options, &option_index);

		if (c == -1)
			break;
		switch(c)
		{
			case 1:
				verbose = "n";
				break;
			case 2:
				if (home)
					free (home);
				home = strdup(optarg);
				break;
			case 'i':
				if (infile)
					free(infile);
				infile = strdup(optarg);
				break;
			case 'o':
				if (outfile)
					free(outfile);
				outfile = strdup(optarg);
				break;
			case 'v':
				verbose = "y";
				break;
			case 'V':
				version_opt = 1;
				break;
			case 'l':
				if (logdir)
					free(logdir);
				logdir = strdup(optarg);
				break;
			case 'L':
				if (logfile)
					free(logfile);
				logfile = strdup(optarg);
				break;
			case 'c':
				if (configuration)
					free(configuration);
				configuration = strdup(optarg);
				break;
			case 'h':
				help_opt = 1;
				break;
			default:
				fprintf(stderr, "Invalid optin value, received code 0%o\n", c);
				exit(1);
		}
	}
	if (version_opt || help_opt)
	{
		if (version_opt)
			print_version();
		if (help_opt)
			print_help();
		exit(0);
	}
	setup_my_env();		/* Read $HOME/.pgxc_ctl */
	build_pgxc_ctl_home(home);
	if (infile)
		reset_var_val(VAR_configFile, infile);
	if (logdir)
		reset_var_val(VAR_logDir, logdir);
	if (logfile)
		reset_var_val(VAR_logFile, logfile);
	startLog(sval(VAR_logDir), sval(VAR_logFile));
	prepare_pgxc_ctl_bash(pgxc_ctl_bash_path);
	build_configuration_path(configuration);
	read_configuration();
	check_configuration();
	/*
	 * Setop output
	 */
	if (outfile)
	{
		elog(INFO, "Output file: %s\n", outfile);
		if ((outF = fopen(outfile, "w")))
			dup2(fileno(outF),2);
		else
			elog(ERROR, "ERROR: Cannot open output file %s, %s\n", outfile, strerror(errno));
	}
	else
		outF = stdout;
	/* 
	 * Startup Message
	 */
	elog(NOTICE, "   ******** PGXC_CTL START ***************\n\n");
	elog(NOTICE, "Current directory: %s\n", pgxc_ctl_home);
	/*
	 * Setup input
	 */
	if (infile)
	{
		elog(INFO, "Input file: %s\n", infile);
		inF =  fopen(infile, "r");
		if(inF == NULL)
		{
			elog(ERROR, "ERROR: Cannot open input file %s, %s\n", infile, strerror(errno));
			exit(1);
		}
	}
	else
		inF = stdin;
	/*
	 * If we have remaing arguments, they will be treated as a command to do.  Do this
	 * first, then handle the input from input file specified by -i option.
	 * If it is not found, then exit.
	 */
#if 0
	print_vars();
#endif
	if (optind < argc)
	{
		char orgBuf[MAXLINE + 1];
		char wkBuf[MAXLINE + 1];
		orgBuf[0] = 0;
		while (optind < argc)
		{
			strncat(orgBuf, argv[optind++], MAXLINE);
			strncat(orgBuf, " ", MAXLINE);
		}
		strncpy(wkBuf, orgBuf, MAXLINE);
		do_singleLine(orgBuf, wkBuf);
		if (infile)
			do_command(inF, outF);
	}
	else
		do_command(inF, outF);
	exit(0);
}
Ejemplo n.º 6
0
int main ( int argc, char* argv[] ) {

    char *distroname = NULL;
    int valid_args , c;

    while (1) {
        int option_index = 0;

        c = getopt_long_only( argc , argv , "d:" , long_options , &option_index );
        if (c == -1)
            break;
     
        switch (c) {

            case 'd':
                distroname = malloc( strlen(optarg) * sizeof(char) );
                strcpy( distroname , optarg );
                break;
     
        }
    }

    valid_args = argc - ( optind - 1 );

    if ( valid_args < 2 ) {
        print_usage( argv[0] );
        exit(1);
    }

    if ( strcmp( argv[optind] , "register" ) == 0 ) {
        if ( valid_args != 4 ) {
            printf( "Usage register\n" );
            exit(1);
        }
    }

    if ( strcmp( argv[optind] , "login" ) == 0 ) {
        if ( valid_args != 2 ) {
            printf( "Usage login\n" );
            exit(1);
        }
    }

    if ( strcmp( argv[optind] , "loginout" ) == 0 ) {
        if ( valid_args != 3 ) {
            printf( "Usage logout\n" );
            exit(1);
        }
    }

    // TODO : Use a define instead of 256 AMEBA_SESSID_MAX_LENGTH
    char *sessid = malloc( 256 * sizeof(char) );
    memset( sessid , '\0' , 256 );

    if ( strncmp( argv[optind] , "login" , 5 ) == 0 ) {

        GKeyFile *config = get_configuration();

        if ( ! check_configuration( config , 1 ) ) {
            printf("No valid configuration exists\n");
            free_configuration( config );
            exit(2);
        }

        login_node( get_configuration_value( config , "url" ) , get_configuration_value( config , "uuid" ) , sessid );

        free_configuration( config );
    }

    if ( strcmp( argv[optind] , "loginout" ) == 0 ) {

        GKeyFile *config = get_configuration();

        if ( ! check_configuration( config , 1 ) ) {
            printf("No valid configuration exists\n");
            free_configuration( config );
            exit(2);
        }

        logout_node( get_configuration_value( config , "url" ) , sessid , argv[optind+1] );

        free_configuration( config );
    }

    if ( strcmp( argv[optind] , "register" ) == 0 ) {

        nodeinfo *nodedata = get_nodeinfo( argv[optind+2] , distroname );
        if ( ! nodedata ) {
            exit(-255);
            }

        register_node( argv[optind+1] , nodedata );

        free_nodeinfo( nodedata );
    }

    free(sessid);
    exit(0);
}
Ejemplo n.º 7
0
void *process_connection(void *ptr) {
    char *server_ident = _ds_read_attribute(agent_config, "ServerIdent");
    THREAD_CTX *TTX = (THREAD_CTX *) ptr;
    AGENT_CTX *ATX = NULL;
    char *input, *cmdline = NULL, *token, *ptrptr;
    buffer *message = NULL;
    char *parms=NULL, *p=NULL;
    int i, locked = -1, invalid = 0;
    int server_mode = SSM_DSPAM;
    char *argv[64];
    char buf[1024];
    int tries = 0;
    int argc = 0;
    FILE *fd = 0;

    if (_ds_read_attribute(agent_config, "ServerMode") &&
            !strcasecmp(_ds_read_attribute(agent_config, "ServerMode"), "standard"))
    {
        server_mode = SSM_STANDARD;
    }

    if (_ds_read_attribute(agent_config, "ServerMode") &&
            !strcasecmp(_ds_read_attribute(agent_config, "ServerMode"), "auto"))
    {
        server_mode = SSM_AUTO;
    }

    /* Initialize a file descriptor hook for dspam to use as stdout */

    fd = fdopen(TTX->sockfd, "w");
    if (!fd) {
        close(TTX->sockfd);
        goto CLOSE;
    }
    setbuf(fd, NULL);

    TTX->packet_buffer = buffer_create(NULL);
    if (TTX->packet_buffer == NULL)
        goto CLOSE;

    /*
     *  Send greeting banner
     *  in auto mode, we want to look like a regular LMTP server so we don't
     *  cause any compatibility problems. in dspam mode, we can change this.
     */

    snprintf(buf, sizeof(buf), "%d DSPAM %sLMTP %s %s",
             LMTP_GREETING,
             (server_mode == SSM_DSPAM) ? "D" : "",
             VERSION,
             (server_mode == SSM_DSPAM) ? "Authentication Required" : "Ready");
    if (send_socket(TTX, buf)<=0)
        goto CLOSE;

    TTX->authenticated = 0;

    /* LHLO */

    input = daemon_expect(TTX, "LHLO");
    if (input == NULL)
        goto CLOSE;
    if (server_mode == SSM_AUTO && input[4]) {
        char buff[128];

        /*
         *  Auto-detect the server mode based on whether or not the ident is
         *  assigned a password in dspam.conf
         */

        snprintf(buff, sizeof(buff), "ServerPass.%s", input + 5);
        chomp(buff);
        if (_ds_read_attribute(agent_config, buff))
            server_mode = SSM_DSPAM;
        else
            server_mode = SSM_STANDARD;
    }
    free(input);

    /* Advertise extensions */

    if (daemon_extension(TTX, (server_ident) ? server_ident :
                         "localhost.localdomain")<=0)
        goto CLOSE;

    if (daemon_extension(TTX, "PIPELINING")<=0)
        goto CLOSE;

    if (daemon_extension(TTX, "ENHANCEDSTATUSCODES")<=0)
        goto CLOSE;

    if (server_mode == SSM_DSPAM)
        if (daemon_extension(TTX, "DSPAMPROCESSMODE")<=0)
            goto CLOSE;

    if (daemon_extension(TTX, "8BITMIME")<=0)
        goto CLOSE;

    if (daemon_reply(TTX, LMTP_OK, "", "SIZE")<=0)
        goto CLOSE;

    /* Main protocol loop */

    while(1) {
        char processmode[256];
        parms = NULL;

        /* Configure a new agent context for each pass */

        ATX = calloc(1, sizeof(AGENT_CTX));
        if (ATX == NULL) {
            LOG(LOG_CRIT, ERR_MEM_ALLOC);
            daemon_reply(TTX, LMTP_TEMP_FAIL, "4.3.0", ERR_MEM_ALLOC);
            goto CLOSE;
        }

        if (initialize_atx(ATX)) {
            LOG(LOG_ERR, ERR_AGENT_INIT_ATX);
            daemon_reply(TTX, LMTP_BAD_CMD, "5.3.0", ERR_AGENT_INIT_ATX);
            goto CLOSE;
        }

        /* MAIL FROM (and authentication, if SSM_DSPAM) */

        processmode[0] = 0;
        while(!TTX->authenticated) {
            input = daemon_expect(TTX, "MAIL FROM");

            if (RSET(input))
                goto RSET;

            if (input == NULL)
                goto CLOSE;
            else {
                char *pass, *ident;
                chomp(input);

                if (server_mode == SSM_STANDARD) {
                    TTX->authenticated = 1;

                    ATX->mailfrom[0] = 0;
                    _ds_extract_address(ATX->mailfrom, input, sizeof(ATX->mailfrom));

                    if (daemon_reply(TTX, LMTP_OK, "2.1.0", "OK")<=0) {
                        free(input);
                        goto CLOSE;
                    }
                } else {
                    char id[256];
                    pass = ident = NULL;
                    id[0] = 0;
                    if (!_ds_extract_address(id, input, sizeof(id))) {
                        pass = strtok_r(id, "@", &ptrptr);
                        ident = strtok_r(NULL, "@", &ptrptr);
                    }

                    if (pass && ident) {
                        char *serverpass;
                        char *ptr, *ptr2, *ptr3;

                        snprintf(buf, sizeof(buf), "ServerPass.%s", ident);
                        serverpass = _ds_read_attribute(agent_config, buf);

                        snprintf(buf, sizeof(buf), "ServerPass.%s", ident);
                        if (serverpass && !strcmp(pass, serverpass)) {
                            TTX->authenticated = 1;

                            /* Parse PROCESSMODE service tag */

                            ptr = strstr(input, "DSPAMPROCESSMODE=\"");
                            if (ptr) {
                                char *mode;
                                int i;
                                ptr2 = strchr(ptr, '"')+1;
                                mode = ptr2;
                                while((ptr3 = strstr(ptr2, "\\\"")))
                                    ptr2 = ptr3+2;
                                ptr3 = strchr(ptr2+2, '"');
                                if (ptr3)
                                    ptr3[0] = 0;
                                strlcpy(processmode, mode, sizeof(processmode));

                                ptr = processmode;
                                for(i=0; ptr[i]; i++) {
                                    if (ptr[i] == '\\' && ptr[i+1] == '"') {
                                        strcpy(ptr+i, ptr+i+1);
                                    }
                                }
                                LOGDEBUG("process mode: '%s'", processmode);
                            }

                            if (daemon_reply(TTX, LMTP_OK, "2.1.0", "OK")<=0) {
                                free(input);
                                goto CLOSE;
                            }
                        }
                    }
                }

                free(input);
                if (!TTX->authenticated) {
                    LOGDEBUG("fd %d authentication failure.", TTX->sockfd);

                    if (daemon_reply(TTX, LMTP_AUTH_ERROR, "5.1.0",
                                     "Authentication Required")<=0)
                    {
                        free(input);
                        goto CLOSE;
                    }

                    tries++;
                    if (tries>=3) {
                        struct timeval tv;
                        tv.tv_sec = 5;
                        tv.tv_usec = 0;
                        select(0, NULL, NULL, NULL, &tv);
                        goto CLOSE;
                    }
                }
            }
        }

        /* MAIL FROM response */

        snprintf(buf, sizeof(buf), "%d OK", LMTP_OK);

        argc = 1;
        argv[0] = "dspam";
        argv[1] = 0;

        /* Load open-LMTP configuration parameters */

        if (server_mode == SSM_STANDARD) {
            parms = _ds_read_attribute(agent_config, "ServerParameters");
            if (parms) {
                p = strdup(parms);
                if (p) {
                    token = strtok_r(p, " ", &ptrptr);
                    while(token != NULL && argc<63) {
                        argv[argc] = token;
                        argc++;
                        argv[argc] = 0;
                        token = strtok_r(NULL, " ", &ptrptr);
                    }
                }
            }
        }

        /* RCPT TO */

        while(ATX->users->items == 0 || invalid) {
            free(cmdline);
            cmdline = daemon_getline(TTX, 300);

            while(cmdline &&
                    (!strncasecmp(cmdline, "RCPT TO:", 8) ||
                     !strncasecmp(cmdline, "RSET", 4)))
            {
                char username[256];
                char *at = NULL;

                if (!strncasecmp(cmdline, "RSET", 4)) {
                    snprintf(buf, sizeof(buf), "%d OK", LMTP_OK);
                    if (send_socket(TTX, buf)<=0)
                        goto CLOSE;
                    goto RSET;
                }

                if (_ds_extract_address(username, cmdline, sizeof(username)) ||
                        username[0] == 0 || username[0] == '-' || username[0] == '@')
                {
                    if ((server_mode == SSM_DSPAM) || (server_mode == SSM_STANDARD && _ds_validate_address(username) == 0)) {
                        daemon_reply(TTX, LMTP_BAD_CMD, "5.1.2", ERR_LMTP_BAD_RCPT);
                        goto GETCMD;
                    }
                }

                if (_ds_match_attribute(agent_config, "Broken", "case"))
                    lc(username, username);

                /* Chop of @.* from the recipient */
                if (_ds_match_attribute(agent_config, "StripRcptDomain", "on")) {
                    at = strchr(username, '@');
                    if (at != NULL)
                        *at = '\0';
                }

                if (server_mode == SSM_DSPAM) {
                    nt_add(ATX->users, username);
                }
                else {
                    if (!parms || !strstr(parms, "--user "))
                        nt_add(ATX->users, username);

                    if (!ATX->recipients) {
                        ATX->recipients = nt_create(NT_CHAR);
                        if (ATX->recipients == NULL) {
                            LOG(LOG_CRIT, ERR_MEM_ALLOC);
                            goto CLOSE;
                        }
                    }
                    if (at != NULL)
                        *at = '@'; /* always add complete address (user@domain) to recipient list */
                    nt_add(ATX->recipients, username);
                }

                if (daemon_reply(TTX, LMTP_OK, "2.1.5", "OK")<=0)
                    goto CLOSE;

GETCMD:
                free(cmdline);
                cmdline = daemon_getline(TTX, 300);
            }

            if (cmdline == NULL)
                goto CLOSE;

            if (!strncasecmp(cmdline, "RSET", 4)) {
                snprintf(buf, sizeof(buf), "%d OK", LMTP_OK);
                if (send_socket(TTX, buf)<=0)
                    goto CLOSE;
                goto RSET;
            }

            if (!strncasecmp(cmdline, "quit", 4)) {
                daemon_reply(TTX, LMTP_OK, "2.0.0", "OK");
                goto CLOSE;
            }

            /* Parse DSPAMPROCESSMODE input and set up process arguments */

            if (server_mode == SSM_DSPAM && processmode[0] != 0) {
                token = strtok_r(processmode, " ", &ptrptr);
                while(token != NULL && argc<63) {
                    argv[argc] = token;
                    argc++;
                    argv[argc] = 0;
                    token = strtok_r(NULL, " ", &ptrptr);
                }
            }

            invalid = 0;
            if (process_arguments(ATX, argc, argv) || apply_defaults(ATX))
            {
                LOG(LOG_ERR, ERR_AGENT_INIT_ATX);
                daemon_reply(TTX, LMTP_NO_RCPT, "5.1.0", ERR_AGENT_INIT_ATX);
                invalid = 1;
            } else if (ATX->users->items == 0) {
                daemon_reply(TTX, LMTP_NO_RCPT, "5.1.1", ERR_AGENT_USER_UNDEFINED);
            }
        }

        ATX->sockfd = fd;
        ATX->sockfd_output = 0;

        /* Something's terribly misconfigured */

        if (check_configuration(ATX)) {
            LOG(LOG_ERR, ERR_AGENT_MISCONFIGURED);
            daemon_reply(TTX, LMTP_BAD_CMD, "5.3.5", ERR_AGENT_MISCONFIGURED);
            goto CLOSE;
        }

        /* DATA */

        if (cmdline != NULL) {
            if (strncasecmp(cmdline, "DATA", 4)) {
                if (daemon_reply(TTX, LMTP_BAD_CMD, "5.0.0", "Need DATA Here")<0)
                    goto CLOSE;
                input = daemon_expect(TTX, "DATA");
                if (input == NULL)
                    goto CLOSE;
                if (RSET(input))
                    goto RSET;
            }
        }

        if (daemon_reply(TTX, LMTP_DATA, "", INFO_LMTP_DATA)<=0)
            goto CLOSE;

        /*
         *  Read in the message from a DATA. I personally like to just hang up on
         *  a client stupid enough to pass in a NULL message for DATA, but you're
         *  welcome to do whatever you want.
         */

        message = read_sock(TTX, ATX);
        if (message == NULL || message->data == NULL || message->used == 0) {
            daemon_reply(TTX, LMTP_FAILURE, "5.2.0", ERR_LMTP_MSG_NULL);
            goto CLOSE;
        }

        /*
         *  Lock a database handle. We currently use the modulus of the socket
         *  id against the number of database connections in the cache. This
         *  seems to work rather well, as we would need to lock up the entire
         *  cache to wrap back around. And if we do wrap back around, that means
         *  we're busy enough to justify spinning on the current lock (vs. seeking
         *  out a free handle, which there likely are none).
         */

        i = (TTX->sockfd % TTX->DTX->connection_cache);
        LOGDEBUG("using database handle id %d", i);
        if (TTX->DTX->flags & DRF_RWLOCK) {
            if (ATX->operating_mode == DSM_CLASSIFY ||
                    ATX->training_mode == DST_NOTRAIN   ||
                    (ATX->training_mode == DST_TOE && ATX->classification == DSR_NONE))
            {
                pthread_rwlock_rdlock(&TTX->DTX->connections[i]->rwlock);
            } else {
                pthread_rwlock_wrlock(&TTX->DTX->connections[i]->rwlock);
            }
        } else {
            pthread_mutex_lock(&TTX->DTX->connections[i]->lock);
        }
        LOGDEBUG("handle locked");
        ATX->dbh = TTX->DTX->connections[i]->dbh;
        locked = i;

        /* Process the message by tying back into the agent functions */

        ATX->results = nt_create(NT_PTR);
        if (ATX->results == NULL) {
            LOG(LOG_CRIT, ERR_MEM_ALLOC);
            goto CLOSE;
        }
        process_users(ATX, message);

        /*
         *  Unlock the database handle as soon as we're done. We also need to
         *  refresh our handle index with a new handle if for some reason we
         *  had to re-establish a dewedged connection.
         */

        if (TTX->DTX->connections[locked]->dbh != ATX->dbh)
            TTX->DTX->connections[locked]->dbh = ATX->dbh;

        if (TTX->DTX->flags & DRF_RWLOCK) {
            pthread_rwlock_unlock(&TTX->DTX->connections[locked]->rwlock);
        } else {
            pthread_mutex_unlock(&TTX->DTX->connections[locked]->lock);
        }
        locked = -1;

        /* Send a terminating '.' if --stdout in 'dspam' mode */

        if (ATX->sockfd_output) {
            if (send_socket(TTX, ".")<=0)
                goto CLOSE;

            /* Otherwise, produce standard delivery results */

        } else {
            struct nt_node *node_nt, *node_res = NULL;
            struct nt_c c_nt;
            if (ATX->recipients)
                node_nt = c_nt_first(ATX->recipients, &c_nt);
            else
                node_nt = c_nt_first(ATX->users, &c_nt);

            if (ATX->results)
                node_res = ATX->results->first;

            while(node_res && node_nt != NULL) {
                agent_result_t result = (agent_result_t) node_res->ptr;

                if (result != NULL && result->exitcode == ERC_SUCCESS)
                {
                    if (server_mode == SSM_DSPAM) {
                        snprintf(buf, sizeof(buf),
                                 "%d 2.6.0 <%s> Message accepted for delivery: %s",
                                 LMTP_OK, (char *) node_nt->ptr,
                                 (result->classification == DSR_ISSPAM) ? "SPAM" : "INNOCENT");
                    } else {
                        snprintf(buf, sizeof(buf),
                                 "%d 2.6.0 <%s> Message accepted for delivery",
                                 LMTP_OK, (char *) node_nt->ptr);
                    }
                }
                else
                {
                    if (result != NULL && result->exitcode == ERC_PERMANENT_DELIVERY) {
                        snprintf(buf, sizeof(buf), "%d 5.3.0 <%s> %s",
                                 LMTP_FAILURE, (char *) node_nt->ptr,
                                 (result->text[0]) ? result->text : "Permanent error occured");
                    } else {
                        if (result != NULL && result->text[0]) {
                            snprintf(buf, sizeof(buf),
                                     "%d 4.3.0 <%s> %s",
                                     LMTP_TEMP_FAIL, (char *) node_nt->ptr, result->text);
                        } else {
                            snprintf(buf, sizeof(buf),
                                     "%d 4.3.0 <%s> Error occured during %s",
                                     LMTP_TEMP_FAIL, (char *) node_nt->ptr,
                                     (result != NULL && result->exitcode == ERC_DELIVERY) ? "delivery" : "processing");
                        }
                    }
                }

                if (send_socket(TTX, buf)<=0)
                    goto CLOSE;
                if (ATX->recipients)
                    node_nt = c_nt_next(ATX->recipients, &c_nt);
                else
                    node_nt = c_nt_next(ATX->users, &c_nt);
                if (node_res)
                    node_res = node_res->next;
            }
        }

        /* Cleanup and get ready for another message */

RSET:
        fflush(fd);

        buffer_destroy(message);
        message = NULL;
        if (ATX != NULL) {
            nt_destroy(ATX->users);
            nt_destroy(ATX->recipients);
            nt_destroy(ATX->results);
            free(ATX);
            ATX = NULL;
            free(cmdline);
            cmdline = NULL;
            TTX->authenticated = 0;
            /* argc = 0; */
        }

        free(p);
        p = NULL;

    } /* while(1) */

    /* Close connection and return */

CLOSE:
    if (locked>=0)
        pthread_mutex_unlock(&TTX->DTX->connections[locked]->lock);
    if (fd)
        fclose(fd);
    buffer_destroy(TTX->packet_buffer);
    if (message)
        buffer_destroy(message);
    if (ATX != NULL) {
        nt_destroy(ATX->users);
        nt_destroy(ATX->recipients);
        nt_destroy(ATX->results);
    }
    free(ATX);
    free(cmdline);
    free(TTX);
    decrement_thread_count();
    pthread_exit(0);
    return 0;
}
Ejemplo n.º 8
0
int
main (int argc, char *argv[])
{
  AGENT_CTX ATX;
  int exitcode = EXIT_SUCCESS;
  buffer *message = NULL;       /* input Message */
  int agent_init = 0;		/* agent is initialized */

  setbuf (stdout, NULL);	/* unbuffered output */
#ifdef DEBUG
  DO_DEBUG = 0;
#endif

  srand ((long) time << (long) getpid());
  umask (006);

#ifndef DAEMON
  LOG(LOG_ERR, ERR_DAEMON_NO_SUPPORT);
  exit(EXIT_FAILURE);
#endif

  /* Read dspam.conf into global config structure (ds_config_t) */

  agent_config = read_config(NULL);
  if (!agent_config) {
    LOG(LOG_ERR, ERR_AGENT_READ_CONFIG);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  if (!_ds_read_attribute(agent_config, "Home")) {
    LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  /* Set up agent context to define behavior of processor */

  if (initialize_atx(&ATX)) {
    LOG(LOG_ERR, ERR_AGENT_INIT_ATX);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  } else {
    agent_init = 1;
  }

  if (process_arguments(&ATX, argc, argv)) {
    LOG(LOG_ERR, ERR_AGENT_INIT_ATX);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  if (apply_defaults(&ATX)) {
    LOG(LOG_ERR, ERR_AGENT_INIT_ATX);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  if (check_configuration(&ATX)) {
    LOG(LOG_ERR, ERR_AGENT_MISCONFIGURED);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  /* Read the message in and apply ParseTo services */

  message = read_stdin(&ATX);
  if (message == NULL) {
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  if (ATX.users->items == 0)
  {
    LOG (LOG_ERR, ERR_AGENT_USER_UNDEFINED);
    fprintf (stderr, "%s\n", SYNTAX);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  /* Perform client-based processing */

#ifdef DAEMON
  if (_ds_read_attribute(agent_config, "ClientIdent") &&
      (_ds_read_attribute(agent_config, "ClientHost") ||
       _ds_read_attribute(agent_config, "ServerDomainSocketPath")))
  {
    exitcode = client_process(&ATX, message);
  } else {
    LOG(LOG_ERR, ERR_CLIENT_INVALID_CONFIG);
    exitcode = EINVAL;
  }
#endif

BAIL:

  if (message)
    buffer_destroy(message);

  if (agent_init)
    nt_destroy(ATX.users);

  if (agent_config)
    _ds_destroy_config(agent_config);

  exit (exitcode);
}