Example #1
0
/*
 * command is called with argc==0 when checking for -V or -v option
 * In this case return 0 when -v or -V or unknown option, otherwise
 *   the shift count to the command is returned
 */
int	b_command(register int argc,char *argv[],Shbltin_t *context)
{
	register int n, flags=0;
	register Shell_t *shp = context->shp;
	opt_info.index = opt_info.offset = 0;
	while((n = optget(argv,sh_optcommand))) switch(n)
	{
	    case 'p':
		if(sh_isoption(SH_RESTRICTED))
			 errormsg(SH_DICT,ERROR_exit(1),e_restricted,"-p");
		sh_onstate(SH_DEFPATH);
		break;
	    case 'v':
		flags |= X_FLAG;
		break;
	    case 'V':
		flags |= V_FLAG;
		break;
	    case 'x':
		shp->xargexit = 1;
		break;
	    case ':':
		if(argc==0)
			return(0);
		errormsg(SH_DICT,2, "%s", opt_info.arg);
		break;
	    case '?':
		if(argc==0)
			return(0);
		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
		break;
	}
	if(argc==0)
		return(flags?0:opt_info.index);
	argv += opt_info.index;
	if(error_info.errors || !*argv)
		errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
	return(whence(shp,argv, flags));
}
Example #2
0
int
b_basename(int argc,register char *argv[], void* context)
{
	register int  n;

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	while (n = optget(argv, usage)) switch (n)
	{
	case ':':
		error(2, "%s", opt_info.arg);
		break;
	case '?':
		error(ERROR_usage(2), "%s", opt_info.arg);
		break;
	}
	argv += opt_info.index;
	argc -= opt_info.index;
	if(error_info.errors || argc < 1 || argc > 2)
		error(ERROR_usage(2), "%s", optusage(NiL));
	namebase(sfstdout,argv[0],argv[1]);
	return(0);
}
Example #3
0
int
onas_fan_checkowner (int pid, const struct optstruct *opts)
{
    char path[32];
    STATBUF sb;
    const struct optstruct *opt;

    if (!(opt = optget (opts, "OnAccessExcludeUID"))->enabled)
        return 0;

    snprintf (path, sizeof (path), "/proc/%u", pid);
    if (CLAMSTAT (path, &sb) == 0)
    {
        while (opt)
        {
            if (opt->numarg == (long long) sb.st_uid)
                return 1;
            opt = opt->nextarg;
        }
    }
    return 0;
}
Example #4
0
int
b_basename(int argc, register char** argv, Shbltin_t* context)
{
	char*	string;
	char*	suffix = 0;
	int	all = 0;

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'a':
			all = 1;
			continue;
		case 's':
			all = 1;
			suffix = opt_info.arg;
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	argc -= opt_info.index;
	if (error_info.errors || argc < 1 || !all && argc > 2)
		error(ERROR_usage(2), "%s", optusage(NiL));
	if (!all)
		namebase(sfstdout, argv[0], argv[1]);
	else
		while (string = *argv++)
			namebase(sfstdout, string, suffix);
	return 0;
}
Example #5
0
File: misc.c Project: att/ast
//
// Builtin `exec`.
//
int b_exec(int argc, char *argv[], Shbltin_t *context) {
    UNUSED(argc);
    struct login logdata;
    int n;
    logdata.clear = 0;
    logdata.arg0 = NULL;
    logdata.sh = context->shp;
    logdata.sh->st.ioset = 0;
    while ((n = optget(argv, sh_optexec))) {
        switch (n) {
            case 'a': {
                logdata.arg0 = opt_info.arg;
                break;
            }
            case 'c': {
                logdata.clear = 1;
                break;
            }
            case ':': {
                errormsg(SH_DICT, 2, "%s", opt_info.arg);
                break;
            }
            case '?': {
                errormsg(SH_DICT, ERROR_usage(0), "%s", opt_info.arg);
                return 2;
            }
            default: { break; }
        }
    }

    argv += opt_info.index;
    if (error_info.errors) {
        errormsg(SH_DICT, ERROR_usage(2), "%s", optusage(NULL));
        __builtin_unreachable();
    }
    if (*argv) B_login(0, argv, (Shbltin_t *)&logdata);
    return 0;
}
Example #6
0
static void milter_exit(int sig) {
    const struct optstruct *opt;

    logg("*clamav-milter: milter_exit, signal %d\n", sig);

#ifndef _WIN32
    if((opt = optget(opts, "MilterSocket"))) {
        if(unlink(opt->strarg) == -1)
            logg("!Can't unlink the socket file %s\n", opt->strarg);
        else
            logg("Socket file removed.\n");
    }
#endif

    logg("clamav-milter: stopped\n");

    optfree(opts);

    logg_close();
    cpool_free();
    localnets_free();
    whitelist_free();
}
Example #7
0
/*
 *  for the whence command
 */
int	b_whence(int argc,char *argv[],Shbltin_t *context)
{
	register int flags=0, n;
	register Shell_t *shp = context->shp;
	NOT_USED(argc);
	if(*argv[0]=='t')
		flags = V_FLAG;
	while((n = optget(argv,sh_optwhence))) switch(n)
	{
	    case 'a':
		flags |= A_FLAG;
		/* FALL THRU */
	    case 'v':
		flags |= V_FLAG;
		break;
	    case 'f':
		flags |= F_FLAG;
		break;
	    case 'p':
		flags |= P_FLAG;
		flags &= ~V_FLAG;
		break;
	    case 'q':
		flags |= Q_FLAG;
		break;
	    case ':':
		errormsg(SH_DICT,2, "%s", opt_info.arg);
		break;
	    case '?':
		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
		break;
	}
	argv += opt_info.index;
	if(error_info.errors || !*argv)
		errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
	return(whence(shp, argv, flags));
}
Example #8
0
void clamd_virus_found_cb(int fd, const char *virname, void *ctx)
{
    struct cb_context *c = ctx;
    struct scan_cb_data *d = c->scandata;
    const char *fname;
    
    if (d == NULL)
        return;
    if (!(d->options & CL_SCAN_ALLMATCHES))
        return;
    if (virname == NULL)
        return;

    fname = (c && c->filename) ? c->filename : "(filename not set)";

    if (virname) {
        conn_reply_virus(d->conn, fname, virname);
        if(c->virsize > 0 && optget(d->opts, "ExtendedDetectionInfo")->enabled)
            logg("~%s: %s(%s:%llu) FOUND\n", fname, virname, c->virhash, c->virsize);
        logg("~%s: %s FOUND\n", fname, virname);
    }

    return;
}
Example #9
0
int    b_eval(int argc,char *argv[], void *extra)
{
	register int r;
	register Shell_t *shp = ((Shbltin_t*)extra)->shp;
	NOT_USED(argc);
	while (r = optget(argv,sh_opteval)) switch (r)
	{
	    case ':':
		errormsg(SH_DICT,2, "%s", opt_info.arg);
		break;
	    case '?':
		errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg);
		return(2);
	}
	if(error_info.errors)
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
	argv += opt_info.index;
	if(*argv && **argv)
	{
		sh_offstate(SH_MONITOR);
		sh_eval(sh_sfeval(argv),0);
	}
	return(shp->exitval);
}
Example #10
0
int localserver(const struct optstruct *opts)
{
	struct sockaddr_un server;
	int sockfd, backlog;
	STATBUF foo;
	char *estr;

    memset((char *) &server, 0, sizeof(server));
    server.sun_family = AF_UNIX;
    strncpy(server.sun_path, optget(opts, "LocalSocket")->strarg, sizeof(server.sun_path));
    server.sun_path[sizeof(server.sun_path)-1]='\0';

    if((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
	estr = strerror(errno);
	logg("!LOCAL: Socket allocation error: %s\n", estr);
	return -1;
    }

    if(bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) == -1) {
	if(errno == EADDRINUSE) {
	    if(connect(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) >= 0) {
		logg("!LOCAL: Socket file %s is in use by another process.\n", server.sun_path);
		close(sockfd);
		return -1;
	    }
	    if(optget(opts, "FixStaleSocket")->enabled) {
		logg("#LOCAL: Removing stale socket file %s\n", server.sun_path);
		if(unlink(server.sun_path) == -1) {
		    estr = strerror(errno);
		    logg("!LOCAL: Socket file %s could not be removed: %s\n", server.sun_path, estr);
		    close(sockfd);
		    return -1;
		}
		if(bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) == -1) {
		    estr = strerror(errno);
		    logg("!LOCAL: Socket file %s could not be bound: %s (unlink tried)\n", server.sun_path, estr);
		    close(sockfd);
		    return -1;
		}
	    } else if(CLAMSTAT(server.sun_path, &foo) != -1) {
		logg("!LOCAL: Socket file %s exists. Either remove it, or configure a different one.\n", server.sun_path);
		close(sockfd);
		return -1;
	    }
	} else {
	    estr = strerror(errno);
	    logg("!LOCAL: Socket file %s could not be bound: %s\n", server.sun_path, estr);
	    close(sockfd);
	    return -1;
	}
    }

    logg("#LOCAL: Unix socket file %s\n", server.sun_path);

    backlog = optget(opts, "MaxConnectionQueueLength")->numarg;
    logg("#LOCAL: Setting connection queue length to %d\n", backlog);

    if(listen(sockfd, backlog) == -1) {
	estr = strerror(errno);
	logg("!LOCAL: listen() error: %s\n", estr);
	close(sockfd);
	return -1;
    }

    return sockfd;
}
Example #11
0
int
b_rm(int argc, register char** argv, void* context)
{
	State_t		state;
	FTS*		fts;
	FTSENT*		ent;
	int		set3d;

	cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
	memset(&state, 0, sizeof(state));
	state.context = context;
	state.fs3d = fs3d(FS3D_TEST);
	state.terminal = isatty(0);
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'd':
			state.directory = 1;
			continue;
		case 'f':
			state.force = 1;
			state.interactive = 0;
			continue;
		case 'i':
			state.interactive = 1;
			state.force = 0;
			continue;
		case 'r':
		case 'R':
			state.recursive = 1;
			continue;
		case 'F':
#if _lib_fsync
			state.clobber = 1;
#else
			error(1, "%s not implemented on this system", opt_info.name);
#endif
			continue;
		case 'u':
			state.unconditional = 1;
			continue;
		case 'v':
			state.verbose = 1;
			continue;
		case '?':
			error(ERROR_USAGE|4, "%s", opt_info.arg);
			break;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (*argv && streq(*argv, "-") && !streq(*(argv - 1), "--"))
		argv++;
	if (error_info.errors || !*argv)
		error(ERROR_USAGE|4, "%s", optusage(NiL));

	/*
	 * do it
	 */

	if (state.interactive)
		state.verbose = 0;
	state.uid = geteuid();
	state.unconditional = state.unconditional && state.recursive && state.force;
	if (state.recursive && state.fs3d)
	{
		set3d = state.fs3d;
		state.fs3d = 0;
		fs3d(0);
	}
	else
		set3d = 0;
	if (fts = fts_open(argv, FTS_PHYSICAL, NiL))
	{
		while (!sh_checksig(context) && (ent = fts_read(fts)) && !rm(&state, ent));
		fts_close(fts);
	}
	else if (!state.force)
		error(ERROR_SYSTEM|2, "%s: cannot remove", argv[0]);
	if (set3d)
		fs3d(set3d);
	return error_info.errors != 0;
}
Example #12
0
/* returns
 *  -1 on fatal error (shutdown)
 *  0 on ok
 *  >0 errors encountered
 */
int command(client_conn_t *conn, int *virus)
{
    int desc = conn->sd;
    struct cl_engine *engine = conn->engine;
    unsigned int options = conn->options;
    const struct optstruct *opts = conn->opts;
    int type = -1; /* TODO: make this enum */
    int maxdirrec;
    int ret = 0;
    int flags = CLI_FTW_STD;

    struct scan_cb_data scandata;
    struct cli_ftw_cbdata data;
    unsigned ok, error, total;
    STATBUF sb;
    jobgroup_t *group = NULL;

    if (thrmgr_group_need_terminate(conn->group)) {
	logg("$Client disconnected while command was active\n");
	if (conn->scanfd != -1)
	    close(conn->scanfd);
	return 1;
    }
    thrmgr_setactiveengine(engine);

    data.data = &scandata;
    memset(&scandata, 0, sizeof(scandata));
    scandata.id = conn->id;
    scandata.group = conn->group;
    scandata.odesc = desc;
    scandata.conn = conn;
    scandata.options = options;
    scandata.engine = engine;
    scandata.opts = opts;
    scandata.thr_pool = conn->thrpool;
    scandata.toplevel_path = conn->filename;

    switch (conn->cmdtype) {
	case COMMAND_SCAN:
	    thrmgr_setactivetask(NULL, "SCAN");
	    type = TYPE_SCAN;
	    break;
	case COMMAND_CONTSCAN:
	    thrmgr_setactivetask(NULL, "CONTSCAN");
	    type = TYPE_CONTSCAN;
	    break;
	case COMMAND_MULTISCAN: {
	    int multiscan, max, alive;

	    /* use MULTISCAN only for directories (bb #1869) */
	    if (STAT(conn->filename, &sb) == 0 &&
		!S_ISDIR(sb.st_mode)) {
		thrmgr_setactivetask(NULL, "CONTSCAN");
		type = TYPE_CONTSCAN;
		break;
	    }

	    pthread_mutex_lock(&conn->thrpool->pool_mutex);
	    multiscan = conn->thrpool->thr_multiscan;
	    max = conn->thrpool->thr_max;
	    if (multiscan+1 < max)
		conn->thrpool->thr_multiscan = multiscan+1;
	    else {
		alive = conn->thrpool->thr_alive;
		ret = -1;
	    }
	    pthread_mutex_unlock(&conn->thrpool->pool_mutex);
	    if (ret) {
		/* multiscan has 1 control thread, so there needs to be at least
		   1 threads that is a non-multiscan controlthread to scan and
		   make progress. */
		logg("^Not enough threads for multiscan. Max: %d, Alive: %d, Multiscan: %d+1\n",
		     max, alive, multiscan);
		conn_reply(conn, conn->filename, "Not enough threads for multiscan. Increase MaxThreads.", "ERROR");
		return 1;
	    }
	    flags &= ~CLI_FTW_NEED_STAT;
	    thrmgr_setactivetask(NULL, "MULTISCAN");
	    type = TYPE_MULTISCAN;
	    scandata.group = group = thrmgr_group_new();
	    if (!group) {
	      if(optget(opts, "ExitOnOOM")->enabled)
		return -1;
	      else
		return 1;
	    }
	    break;
	    }
	case COMMAND_MULTISCANFILE:
	    thrmgr_setactivetask(NULL, "MULTISCANFILE");
	    scandata.group = NULL;
	    scandata.type = TYPE_SCAN;
	    scandata.thr_pool = NULL;
	    /* TODO: check ret value */
	    ret = scan_callback(NULL, conn->filename, conn->filename, visit_file, &data);	    /* callback freed it */
	    conn->filename = NULL;
	    *virus = scandata.infected;
	    if (ret == CL_BREAK) {
		thrmgr_group_terminate(conn->group);
		return 1;
	    }
	    return scandata.errors > 0 ? scandata.errors : 0;
	case COMMAND_FILDES:
	    thrmgr_setactivetask(NULL, "FILDES");
#ifdef HAVE_FD_PASSING
	    if (conn->scanfd == -1) {
		conn_reply_error(conn, "FILDES: didn't receive file descriptor.");
		return 1;
	    }
	    else {
		ret = scanfd(conn, NULL, engine, options, opts, desc, 0);
		if (ret == CL_VIRUS) {
		    *virus = 1;
		    ret = 0;
		} else if (ret == CL_EMEM) {
		    if(optget(opts, "ExitOnOOM")->enabled)
			ret = -1;
		    else
		        ret = 1;
		} else if (ret == CL_ETIMEOUT) {
			thrmgr_group_terminate(conn->group);
			ret = 1;
		} else
		    ret = 0;
		logg("$Closed fd %d\n", conn->scanfd);
		close(conn->scanfd);
	    }
	    return ret;
#else
	    conn_reply_error(conn, "FILDES support not compiled in.");
	    close(conn->scanfd);
	    return 0;
#endif
	case COMMAND_STATS:
	    thrmgr_setactivetask(NULL, "STATS");
	    if (conn->group)
		mdprintf(desc, "%u: ", conn->id);
	    thrmgr_printstats(desc, conn->term);
	    return 0;
	case COMMAND_STREAM:
	    thrmgr_setactivetask(NULL, "STREAM");
	    ret = scanstream(desc, NULL, engine, options, opts, conn->term);
	    if (ret == CL_VIRUS)
		*virus = 1;
	    if (ret == CL_EMEM) {
		if(optget(opts, "ExitOnOOM")->enabled)
		    return -1;
		else
		    return 1;
	    }
	    return 0;
	case COMMAND_INSTREAMSCAN:
	    thrmgr_setactivetask(NULL, "INSTREAM");
	    ret = scanfd(conn, NULL, engine, options, opts, desc, 1);
	    if (ret == CL_VIRUS) {
		*virus = 1;
		ret = 0;
	    } else if (ret == CL_EMEM) {
		if(optget(opts, "ExitOnOOM")->enabled)
		    ret = -1;
		else
 		    ret = 1;
	    } else if (ret == CL_ETIMEOUT) {
		thrmgr_group_terminate(conn->group);
		ret = 1;
	    } else
		ret = 0;
	    if (ftruncate(conn->scanfd, 0) == -1) {
		/* not serious, we're going to close it and unlink it anyway */
		logg("*ftruncate failed: %d\n", errno);
	    }
	    close(conn->scanfd);
	    conn->scanfd = -1;
	    cli_unlink(conn->filename);
	    return ret;
	default:
	    logg("!Invalid command distpached: %d\n", conn->cmdtype);
	    return 1;
    }

    scandata.type = type;
    maxdirrec = optget(opts, "MaxDirectoryRecursion")->numarg;
    if (optget(opts, "FollowDirectorySymlinks")->enabled)
	flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
    if (optget(opts, "FollowFileSymlinks")->enabled)
	flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;

    if(!optget(opts, "CrossFilesystems")->enabled)
	if(STAT(conn->filename, &sb) == 0)
	    scandata.dev = sb.st_dev;

    ret = cli_ftw(conn->filename, flags,  maxdirrec ? maxdirrec : INT_MAX, scan_callback, &data, scan_pathchk);
    if (ret == CL_EMEM) {
	if(optget(opts, "ExitOnOOM")->enabled)
	    return -1;
	else
	    return 1;
    }
    if (scandata.group && type == TYPE_MULTISCAN) {
	thrmgr_group_waitforall(group, &ok, &error, &total);
	pthread_mutex_lock(&conn->thrpool->pool_mutex);
	conn->thrpool->thr_multiscan--;
	pthread_mutex_unlock(&conn->thrpool->pool_mutex);
    } else {
	error = scandata.errors;
	total = scandata.total;
	ok = total - error - scandata.infected;
    }

    if (ok + error == total && (error != total)) {
	if (conn_reply_single(conn, conn->filename, "OK") == -1)
	    ret = CL_ETIMEOUT;
    }
    *virus = total - (ok + error);

    if (ret == CL_ETIMEOUT)
	thrmgr_group_terminate(conn->group);
    return error;
}
Example #13
0
/* returns:
 *  <0 for error
 *     -1 out of memory
 *     -2 other
 *   0 for async dispatched
 *   1 for command completed (connection can be closed)
 */
int execute_or_dispatch_command(client_conn_t *conn, enum commands cmd, const char *argument)
{
    int desc = conn->sd;
    char term = conn->term;
    const struct cl_engine *engine = conn->engine;
    /* execute commands that can be executed quickly on the recvloop thread,
     * these must:
     *  - not involve any operation that can block for a long time, such as disk
     *  I/O
     *  - send of atomic message is allowed.
     * Dispatch other commands */
    if (conn->group) {
	switch (cmd) {
	    case COMMAND_FILDES:
	    case COMMAND_SCAN:
	    case COMMAND_END:
	    case COMMAND_INSTREAM:
	    case COMMAND_INSTREAMSCAN:
	    case COMMAND_VERSION:
	    case COMMAND_PING:
	    case COMMAND_STATS:
	    case COMMAND_COMMANDS:
		/* These commands are accepted inside IDSESSION */
		break;
	    default:
		/* these commands are not recognized inside an IDSESSION */
		conn_reply_error(conn, "Command invalid inside IDSESSION.");
		logg("$SESSION: command is not valid inside IDSESSION: %d\n", cmd);
		conn->group = NULL;
		return 1;
	}
    }

    switch (cmd) {
	case COMMAND_SHUTDOWN:
	    pthread_mutex_lock(&exit_mutex);
	    progexit = 1;
	    pthread_mutex_unlock(&exit_mutex);
	    return 1;
	case COMMAND_RELOAD:
	    pthread_mutex_lock(&reload_mutex);
	    reload = 1;
	    pthread_mutex_unlock(&reload_mutex);
	    mdprintf(desc, "RELOADING%c", term);
	    /* we set reload flag, and we'll reload before closing the
	     * connection */
	    return 1;
	case COMMAND_PING:
	    if (conn->group)
		mdprintf(desc, "%u: PONG%c", conn->id, term);
	    else
		mdprintf(desc, "PONG%c", term);
	    return conn->group ? 0 : 1;
	case COMMAND_VERSION:
	    {
		if (conn->group)
		    mdprintf(desc, "%u: ", conn->id);
		print_ver(desc, conn->term, engine);
		return conn->group ? 0 : 1;
	    }
	case COMMAND_COMMANDS:
	    {
		if (conn->group)
		    mdprintf(desc, "%u: ", conn->id);
		print_commands(desc, conn->term, engine);
		return conn->group ? 0 : 1;
	    }
	case COMMAND_DETSTATSCLEAR:
	    {
		detstats_clear();
		return 1;
	    }
	case COMMAND_DETSTATS:
	    {
		detstats_print(desc, conn->term);
		return 1;
	    }
	case COMMAND_INSTREAM:
	    {
		int rc = cli_gentempfd(optget(conn->opts, "TemporaryDirectory")->strarg, &conn->filename, &conn->scanfd);
		if (rc != CL_SUCCESS)
		    return rc;
		conn->quota = optget(conn->opts, "StreamMaxLength")->numarg;
		conn->mode = MODE_STREAM;
		return 0;
	    }
	case COMMAND_STREAM:
	case COMMAND_MULTISCAN:
	case COMMAND_CONTSCAN:
	case COMMAND_STATS:
	case COMMAND_FILDES:
	case COMMAND_SCAN:
	case COMMAND_INSTREAMSCAN:
	    return dispatch_command(conn, cmd, argument);
	case COMMAND_IDSESSION:
	    conn->group = thrmgr_group_new();
	    if (!conn->group)
		return CL_EMEM;
	    return 0;
	case COMMAND_END:
	    if (!conn->group) {
		/* end without idsession? */
		conn_reply_single(conn, NULL, "UNKNOWN COMMAND");
		return 1;
	    }
	    /* need to close connection  if we were last in group */
	    return 1;
	/*case COMMAND_UNKNOWN:*/
	default:
	    conn_reply_single(conn, NULL, "UNKNOWN COMMAND");
	    return 1;
    }
}
Example #14
0
int	b_hist(int argc,char *argv[], void *extra)
{
	register History_t *hp;
	register char *arg;
	register int flag,fdo;
	register Shell_t *shp = ((Shbltin_t*)extra)->shp;
	Sfio_t *outfile;
	char *fname;
	int range[2], incr, index2, indx= -1;
	char *edit = 0;		/* name of editor */
	char *replace = 0;		/* replace old=new */
	int lflag = 0, nflag = 0, rflag = 0;
#if SHOPT_HISTEXPAND
	int pflag = 0;
#endif
	Histloc_t location;
	NOT_USED(argc);
	if(!sh_histinit((void*)shp))
		errormsg(SH_DICT,ERROR_system(1),e_histopen);
	hp = shp->gd->hist_ptr;
	while((flag = optget(argv,sh_opthist))) switch(flag)
	{
	    case 'e':
		edit = opt_info.arg;
		break;
	    case 'n':
		nflag++;
		break;
	    case 'l':
		lflag++;
		break;
	    case 'r':
		rflag++;
		break;
	    case 's':
		edit = "-";
		break;
#if SHOPT_HISTEXPAND
	    case 'p':
		pflag++;
		break;
#endif
	    case 'N':
		if(indx<=0)
		{
			if((flag = hist_max(hp) - opt_info.num-1) < 0)
				flag = 1;
			range[++indx] = flag;
			break;
		}
	    case ':':
		errormsg(SH_DICT,2, "%s", opt_info.arg);
		break;
	    case '?':
		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
		break;
	}
	if(error_info.errors)
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
	argv += (opt_info.index-1);
#if SHOPT_HISTEXPAND
	if(pflag)
	{
		hist_cancel(hp);
		pflag = 0;
		while(arg=argv[1])
		{
			flag = hist_expand(arg,&replace);
			if(!(flag & HIST_ERROR))
				sfputr(sfstdout, replace, '\n');
			else
				pflag = 1;
			if(replace)
				free(replace);
			argv++;
		}
		return pflag;
	}
#endif
	flag = indx;
	while(flag<1 && (arg=argv[1]))
	{
		/* look for old=new argument */
		if(!replace && strchr(arg+1,'='))
		{
			replace = arg;
			argv++;
			continue;
		}
		else if(isdigit(*arg) || *arg == '-')
		{
			/* see if completely numeric */
			do	arg++;
			while(isdigit(*arg));
			if(*arg==0)
			{
				arg = argv[1];
				range[++flag] = (int)strtol(arg, (char**)0, 10);
				if(*arg == '-')
					range[flag] += (hist_max(hp)-1);
				argv++;
				continue;
			}
		}
		/* search for last line starting with string */
		location = hist_find(hp,argv[1],hist_max(hp)-1,0,-1);
		if((range[++flag] = location.hist_command) < 0)
			errormsg(SH_DICT,ERROR_exit(1),e_found,argv[1]);
		argv++;
	}
	if(flag <0)
	{
		/* set default starting range */
		if(lflag)
		{
			flag = hist_max(hp)-16;
			if(flag<1)
				flag = 1;
		}
		else
			flag = hist_max(hp)-2;
		range[0] = flag;
		flag = 0;
	}
	index2 = hist_min(hp);
	if(range[0]<index2)
		range[0] = index2;
	if(flag==0)
		/* set default termination range */
		range[1] = ((lflag && !edit)?hist_max(hp)-1:range[0]);
	if(range[1]>=(flag=(hist_max(hp) - !lflag)))
		range[1] = flag;
	/* check for valid ranges */
	if(range[1]<index2 || range[0]>=flag)
		errormsg(SH_DICT,ERROR_exit(1),e_badrange,range[0],range[1]);
	if(edit && *edit=='-' && range[0]!=range[1])
		errormsg(SH_DICT,ERROR_exit(1),e_eneedsarg);
	/* now list commands from range[rflag] to range[1-rflag] */
	incr = 1;
	flag = rflag>0;
	if(range[1-flag] < range[flag])
		incr = -1;
	if(lflag)
	{
		outfile = sfstdout;
		arg = "\n\t";
	}
	else
	{
		if(!(fname=pathtmp(NIL(char*),0,0,NIL(int*))))
			errormsg(SH_DICT,ERROR_exit(1),e_create,"");
		if((fdo=open(fname,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) < 0)
			errormsg(SH_DICT,ERROR_system(1),e_create,fname);
		outfile= sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fdo,SF_WRITE);
		arg = "\n";
		nflag++;
	}
	while(1)
	{
		if(nflag==0)
			sfprintf(outfile,"%d\t",range[flag]);
		else if(lflag)
			sfputc(outfile,'\t');
		hist_list(shp->gd->hist_ptr,outfile,hist_tell(shp->gd->hist_ptr,range[flag]),0,arg);
		if(lflag)
			sh_sigcheck(shp);
		if(range[flag] == range[1-flag])
			break;
		range[flag] += incr;
	}
	if(lflag)
		return(0);
	sfclose(outfile);
	hist_eof(hp);
	arg = edit;
	if(!arg && !(arg=nv_getval(sh_scoped(shp,HISTEDIT))) && !(arg=nv_getval(sh_scoped(shp,FCEDNOD))))
		arg = (char*)e_defedit;
#ifdef apollo
	/*
	 * Code to support the FC using the pad editor.
	 * Exampled of how to use: HISTEDIT=pad
	 */
	if (strcmp (arg, "pad") == 0)
	{
		extern int pad_create(char*);
		sh_close(fdo);
		fdo = pad_create(fname);
		pad_wait(fdo);
		unlink(fname);
		strcat(fname, ".bak");
		unlink(fname);
		lseek(fdo,(off_t)0,SEEK_SET);
	}
	else
	{
#endif /* apollo */
	if(*arg != '-')
	{
		char *com[3];
		com[0] =  arg;
		com[1] =  fname;
		com[2] = 0;
		error_info.errors = sh_eval(sh_sfeval(com),0);
	}
	fdo = sh_chkopen(fname);
	unlink(fname);
	free((void*)fname);
#ifdef apollo
	}
#endif /* apollo */
	/* don't history fc itself unless forked */
	error_info.flags |= ERROR_SILENT;
	if(!sh_isstate(SH_FORKED))
		hist_cancel(hp);
	sh_onstate(SH_HISTORY);
	sh_onstate(SH_VERBOSE);	/* echo lines as read */
	if(replace)
		hist_subst(error_info.id,fdo,replace);
	else if(error_info.errors == 0)
	{
		char buff[IOBSIZE+1];
		Sfio_t *iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fdo,SF_READ);
		/* read in and run the command */
		if(shp->hist_depth++ > HIST_RECURSE)
			errormsg(SH_DICT,ERROR_exit(1),e_toodeep,"history");
		sh_eval(iop,1);
		shp->hist_depth--;
	}
Example #15
0
int
b_cut(int argc, char** argv, void* context)
{
	register char*		cp = 0;
	register Sfio_t*	fp;
	char*			s;
	int			n;
	Cut_t*			cut;
	int			mode = 0;
	Delim_t			wdelim;
	Delim_t			ldelim;
	size_t			reclen = 0;

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	wdelim.chr = '\t';
	ldelim.chr = '\n';
	wdelim.len = ldelim.len = 1;
	for (;;)
	{
		switch (n = optget(argv, usage))
		{
		case 0:
			break;
		case 'b':
		case 'c':
			if(mode&C_FIELDS)
			{
				error(2, "f option already specified");
				continue;
			}
			cp = opt_info.arg;
			if(n=='b')
				mode |= C_BYTES;
			else
				mode |= C_CHARS;
			continue;
		case 'D':
			ldelim.str = opt_info.arg;
			if (mbwide())
			{
				s = opt_info.arg;
				ldelim.chr = mbchar(s);
				if ((n = s - opt_info.arg) > 1)
				{
					ldelim.len = n;
					continue;
				}
			}
			ldelim.chr = *(unsigned char*)opt_info.arg;
			ldelim.len = 1;
			continue;
		case 'd':
			wdelim.str = opt_info.arg;
			if (mbwide())
			{
				s = opt_info.arg;
				wdelim.chr = mbchar(s);
				if ((n = s - opt_info.arg) > 1)
				{
					wdelim.len = n;
					continue;
				}
			}
			wdelim.chr = *(unsigned char*)opt_info.arg;
			wdelim.len = 1;
			continue;
		case 'f':
			if(mode&(C_CHARS|C_BYTES))
			{
				error(2, "c option already specified");
				continue;
			}
			cp = opt_info.arg;
			mode |= C_FIELDS;
			continue;
		case 'n':
			mode |= C_NOSPLIT;
			continue;
		case 'N':
			mode |= C_NONEWLINE;
			continue;
		case 'R':
		case 'r':
			if(opt_info.num>0)
				reclen = opt_info.num;
			continue;
		case 's':
			mode |= C_SUPRESS;
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors)
		error(ERROR_usage(2), "%s",optusage(NiL));
	if(!cp)
	{
		error(2, "b, c or f option must be specified");
		error(ERROR_usage(2), "%s", optusage(NiL));
	}
	if(!*cp)
		error(3, "non-empty b, c or f option must be specified");
	if((mode & (C_FIELDS|C_SUPRESS)) == C_SUPRESS)
		error(3, "s option requires f option");
	cut = cutinit(mode, cp, &wdelim, &ldelim, reclen);
	if(cp = *argv)
		argv++;
	do
	{
		if(!cp || streq(cp,"-"))
			fp = sfstdin;
		else if(!(fp = sfopen(NiL,cp,"r")))
		{
			error(ERROR_system(0),"%s: cannot open",cp);
			continue;
		}
		if(mode&C_FIELDS)
			cutfields(cut,fp,sfstdout);
		else
			cutcols(cut,fp,sfstdout);
		if(fp!=sfstdin)
			sfclose(fp);
	} while(cp = *argv++);
	if (sfsync(sfstdout))
		error(ERROR_system(0), "write error");
	return error_info.errors != 0;
}
Example #16
0
int	b_kill(int argc,char *argv[],void *extra)
{
	register char *signame;
	register int sig=SIGTERM, flag=0, n;
	register Shell_t *shp = ((Shbltin_t*)extra)->shp;
	NOT_USED(argc);
	while((n = optget(argv,sh_optkill))) switch(n)
	{
		case ':':
			if((signame=argv[opt_info.index++]) && (sig=sig_number(shp,signame+1))>=0)
				goto endopts;
			opt_info.index--;
			errormsg(SH_DICT,2, "%s", opt_info.arg);
			break;
		case 'n':
			sig = (int)opt_info.num;
			goto endopts;
		case 's':
			flag |= S_FLAG;
			signame = opt_info.arg;
			goto endopts;
		case 'l':
			flag |= L_FLAG;
			break;
		case '?':
			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
			break;
	}
endopts:
	argv += opt_info.index;
	if(*argv && strcmp(*argv,"--")==0 && strcmp(*(argv-1),"--")!=0)
		argv++;
	if(error_info.errors || flag==(L_FLAG|S_FLAG) || (!(*argv) && !(flag&L_FLAG)))
		errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
	/* just in case we send a kill -9 $$ */
	sfsync(sfstderr);
	if(flag&L_FLAG)
	{
		if(!(*argv))
			sig_list(shp,0);
		else while(signame = *argv++)
		{
			if(isdigit(*signame))
				sig_list(shp,((int)strtol(signame, (char**)0, 10)&0177)+1);
			else
			{
				if((sig=sig_number(shp,signame))<0)
				{
					shp->exitval = 2;
					errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
				}
				sfprintf(sfstdout,"%d\n",sig);
			}
		}
		return(shp->exitval);
	}
	if(flag&S_FLAG)
	{
		if((sig=sig_number(shp,signame)) < 0 || sig > shp->gd->sigmax)
			errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
	}
	if(job_walk(sfstdout,job_kill,sig,argv))
		shp->exitval = 1;
	return(shp->exitval);
}
Example #17
0
int
b_mktemp(int argc, char** argv, Shbltin_t* context)
{
	mode_t		mode = 0;
	mode_t		mask;
	int		fd;
	int		i;
	int		quiet = 0;
	int		unsafe = 0;
	int*		fdp = &fd;
	char*		dir = "";
	char*		pfx;
	char*		t;
	char		path[PATH_MAX];

	cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'd':
			fdp = 0;
			continue;
		case 'm':
			mode = strperm(pfx = opt_info.arg, &opt_info.arg, S_IRWXU);
			if (*opt_info.arg)
				error(ERROR_exit(0), "%s: invalid mode", pfx);
			continue;
		case 'p':
			if ((t = getenv("TMPDIR")) && *t)
				dir = 0;
			else
				dir = opt_info.arg;
			continue;
		case 'q':
			quiet = 1;
			continue;
		case 't':
			dir = 0;
			continue;
		case 'u':
			unsafe = 1;
			fdp = 0;
			continue;
		case 'R':
			if (!pathtemp(NiL, 0, opt_info.arg, "/seed", NiL))
				error(2, "%s: regression test initializtion failed", opt_info.arg);
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors || (pfx = *argv++) && *argv)
		error(ERROR_usage(2), "%s", optusage(NiL));
	mask = umask(0);
	if (!mode)
		mode = (fdp ? (S_IRUSR|S_IWUSR) : S_IRWXU) & ~mask;
	umask(~mode & (S_IRWXU|S_IRWXG|S_IRWXO));
	if (!pfx)
	{
		pfx = "tmp_";
		if (dir && !*dir)
			dir = 0;
	}
	if (t = strrchr(pfx, '/'))
	{
		i = ++t - pfx;
		dir = fmtbuf(i);
		memcpy(dir, pfx, i);
		dir[i] = 0;
		pfx = t;
	}
	for (;;)
	{
		if (!pathtemp(path, sizeof(path), dir, pfx, fdp))
		{
			if (quiet)
				error_info.errors++;
			else
				error(ERROR_SYSTEM|2, "cannot create temporary path");
			break;
		}
		if (fdp || unsafe || !mkdir(path, mode))
		{
			if (fdp)
				close(*fdp);
			sfputr(sfstdout, path, '\n');
			break;
		}
		if (sh_checksig(context))
		{
			error_info.errors++;
			break;
		}
	}
	umask(mask);
	return error_info.errors != 0;
}
Example #18
0
int client(const struct optstruct *opts, int *infected, int *err)
{
	int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0;
	const char *fname;

    scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !optget(opts, "file-list")->enabled && !opts->filename[1]);
    remote = isremote(opts) | optget(opts, "stream")->enabled;
#ifdef HAVE_FD_PASSING
    if(!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) {
	scantype = FILDES;
	session = optget(opts, "multiscan")->enabled;
    } else 
#endif
    if(remote || scandash) {
	scantype = STREAM;
	session = optget(opts, "multiscan")->enabled;
    } 
    else if(optget(opts, "multiscan")->enabled) scantype = MULTI;
    else if(optget(opts, "allmatch")->enabled) scantype = ALLMATCH;
    else scantype = CONT;

    maxrec = optget(clamdopts, "MaxDirectoryRecursion")->numarg;
    maxstream = optget(clamdopts, "StreamMaxLength")->numarg;
    if (optget(clamdopts, "FollowDirectorySymlinks")->enabled)
	flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
    if (optget(clamdopts, "FollowFileSymlinks")->enabled)
	flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
    flags |= CLI_FTW_TRIM_SLASHES;

    *infected = 0;

    if(scandash) {
	int sockd, ret;
	STATBUF sb;
	if(FSTAT(0, &sb) < 0) {
	    logg("client.c: fstat failed for file name \"%s\", with %s\n.", 
		 opts->filename[0], strerror(errno));
	    return 2;
	}
	if((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM;
	if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL)) >= 0)
	    *infected = ret;
	else
	    errors = 1;
	if(sockd >= 0) closesocket(sockd);
    } else if(opts->filename || optget(opts, "file-list")->enabled) {
	if(opts->filename && optget(opts, "file-list")->enabled)
	    logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n");

	while((fname = filelist(opts, NULL))) {
	    if(!strcmp(fname, "-")) {
		logg("!Scanning from standard input requires \"-\" to be the only file argument\n");
		continue;
	    }
	    errors += client_scan(fname, scantype, infected, err, maxrec, session, flags);
	    /* this may be too strict
	    if(errors >= 10) {
		logg("!Too many errors\n");
		break;
	    }
	    */
	}
    } else {
	errors = client_scan("", scantype, infected, err, maxrec, session, flags);
    }
    return *infected ? 1 : (errors ? 2 : 0);
}
Example #19
0
int main(int argc, char **argv)
{
	int ds, dms, ret;
	double mb, rmb;
	struct timeval t1, t2;
#ifndef _WIN32
	sigset_t sigset;
#endif
	struct optstruct *opts;
	const struct optstruct *opt;

    if(check_flevel())
	exit(2);

#if !defined(_WIN32) && !defined(C_BEOS)
    sigemptyset(&sigset);
    sigaddset(&sigset, SIGXFSZ);
    sigprocmask(SIG_SETMASK, &sigset, NULL);
#endif

    cl_initialize_crypto();


    if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMSCAN, 0, NULL)) == NULL) {
	mprintf("!Can't parse command line options\n");
	return 2;
    }

    if(optget(opts, "verbose")->enabled) {
	mprintf_verbose = 1;
	logg_verbose = 1;
    }

    if(optget(opts, "quiet")->enabled)
	mprintf_quiet = 1;

    if(optget(opts, "stdout")->enabled)
	mprintf_stdout = 1;


    if(optget(opts, "debug")->enabled) {
#if defined(C_LINUX)
	    /* [email protected]: create a dump if needed */
	    struct rlimit rlim;

	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
	if(setrlimit(RLIMIT_CORE, &rlim) < 0)
	    perror("setrlimit");
#endif
	cl_debug(); /* enable debug messages */
    }

    if (optget(opts, "gen-mdb")->enabled) {
        cl_always_gen_section_hash();
    }

    if(optget(opts, "version")->enabled) {
	print_version(optget(opts, "database")->strarg);
	optfree(opts);
	return 0;
    }

    if(optget(opts, "help")->enabled) {
	optfree(opts);
    	help();
	return 0;
    }

    if(optget(opts, "recursive")->enabled)
	recursion = 1;

    if(optget(opts, "infected")->enabled)
	printinfected = 1;

    if(optget(opts, "suppress-ok-results")->enabled)
	printclean = 0;

    if(optget(opts, "bell")->enabled)
	bell = 1;

    /* initialize logger */
    if((opt = optget(opts, "log"))->enabled) {
	logg_file = opt->strarg;
	if(logg("#\n-------------------------------------------------------------------------------\n\n")) {
	    mprintf("!Problem with internal logger.\n");
	    optfree(opts);
	    return 2;
	}
    } else 
	logg_file = NULL;

    if(actsetup(opts)) {
	optfree(opts);
	logg_close();
	exit(2);
    }

    memset(&info, 0, sizeof(struct s_info));

    gettimeofday(&t1, NULL);

    ret = scanmanager(opts);

    if(!optget(opts, "no-summary")->enabled) {
	gettimeofday(&t2, NULL);

    ds = t2.tv_sec - t1.tv_sec;
	dms = t2.tv_usec - t1.tv_usec;
	ds -= (dms < 0) ? (1):(0);
	dms += (dms < 0) ? (1000000):(0);
	logg("\n----------- SCAN SUMMARY -----------\n");
	logg("Known viruses: %u\n", info.sigs);
	logg("Engine version: %s\n", get_version());
	logg("Scanned directories: %u\n", info.dirs);
	logg("Scanned files: %u\n", info.files);
	logg("Infected files: %u\n", info.ifiles);
	if(info.errors)
	    logg("Total errors: %u\n", info.errors);
	if(notremoved) {
	    logg("Not removed: %u\n", notremoved);
	}
	if(notmoved) {
	    logg("Not %s: %u\n", optget(opts, "copy")->enabled ? "moved" : "copied", notmoved);
	}
	mb = info.blocks * (CL_COUNT_PRECISION / 1024) / 1024.0;
	logg("Data scanned: %2.2lf MB\n", mb);
	rmb = info.rblocks * (CL_COUNT_PRECISION / 1024) / 1024.0;
	logg("Data read: %2.2lf MB (ratio %.2f:1)\n", rmb, info.rblocks ? (double)info.blocks/(double)info.rblocks : 0);
	logg("Time: %u.%3.3u sec (%u m %u s)\n", ds, dms/1000, ds/60, ds%60);
    }

    optfree(opts);

    cl_cleanup_crypto();

    return ret;
}
Example #20
0
int init_actions(struct optstruct *opts) {
    const struct optstruct *opt;

    if(!(opt = optget(opts, "LogInfected"))->enabled || !strcasecmp(opt->strarg, "Off"))
	loginfected = LOGINF_NONE;
    else if(!strcasecmp(opt->strarg, "Basic"))
	loginfected = LOGINF_BASIC;
    else if(!strcasecmp(opt->strarg, "Full"))
	loginfected = LOGINF_FULL;
    else {
	logg("!Invalid setting %s for option LogInfected\n", opt->strarg);
	return 1;
    }

    if((opt = optget(opts, "LogClean"))->enabled) {
	if(!strcasecmp(opt->strarg, "Basic"))
	    loginfected |= LOGCLN_BASIC;
	else if(!strcasecmp(opt->strarg, "Full"))
	    loginfected |= LOGCLN_FULL;
	else if(strcasecmp(opt->strarg, "Off")) {
	    logg("!Invalid setting %s for option LogClean\n", opt->strarg);
	    return 1;
	}
    }

    if((opt = optget(opts, "VirusAction"))->enabled)
	viraction = strdup(opt->strarg);

    if((opt = optget(opts, "OnFail"))->enabled) {
	switch(parse_action(opt->strarg)) {
	case 0:
	    FailAction = SMFIS_ACCEPT;
	    break;
	case 1:
	    FailAction = SMFIS_TEMPFAIL;
	    break;
	case 2:
	    FailAction = SMFIS_REJECT;
	    break;
	default:
	    logg("!Invalid action %s for option OnFail\n", opt->strarg);
	    return 1;
	}
    } else FailAction = SMFIS_TEMPFAIL;

    if((opt = optget(opts, "OnClean"))->enabled) {
	switch(parse_action(opt->strarg)) {
	case 0:
	    CleanAction = action_accept;
	    break;
	case 1:
	    CleanAction = action_defer;
	    break;
	case 2:
	    CleanAction = action_reject;
	    break;
	case 3:
	    CleanAction = action_blackhole;
	    break;
	case 4:
	    CleanAction = action_quarantine;
	    break;
	default:
	    logg("!Invalid action %s for option OnClean\n", opt->strarg);
	    return 1;
	}
    } else CleanAction = action_accept;

    if((opt = optget(opts, "OnInfected"))->enabled) {
	switch(parse_action(opt->strarg)) {
	case 0:
	    InfectedAction = action_accept;
	    break;
	case 1:
	    InfectedAction = action_defer;
	    break;
	case 3:
	    InfectedAction = action_blackhole;
	    break;
	case 4:
	    InfectedAction = action_quarantine;
	    break;
	case 2:
	    InfectedAction = action_reject_msg;
	    if((opt = optget(opts, "RejectMsg"))->enabled) {
		const char *src = opt->strarg;
		char *dst, c;
		int gotpctv = 0;

		rejectfmt = dst = malloc(strlen(src) * 4 + 1);
		if(!dst) {
		    logg("!Failed to allocate memory for RejectMsg\n");
		    return 1;
		}
		while ((c = *src++)) {
		    if(!isprint(c)) {
			logg("!RejectMsg contains non printable characters\n");
			free(rejectfmt);
			return 1;
		    }
		    *dst++ = c;
		    if(c == '%') {
			if(*src == 'v') {
			    if(gotpctv) {
				logg("!%%v may appear at most once in RejectMsg\n");
				free(rejectfmt);
				return 1;
			    }
			    gotpctv |= 1;
			    src++;
			    *dst++ = 's';
			} else {
			    dst[0] = dst[1] = dst[2] = '%';
			    dst += 3;
			}
		    }
		}
		*dst = '\0';
	    }
	    break;
	default:
	    logg("!Invalid action %s for option OnInfected\n", opt->strarg);
	    return 1;
	}
    } else InfectedAction = action_quarantine;
    return 0;
}
Example #21
0
int main (int argc, char **argv) {
    int norun;
    char *schemaname;
    char *sexpr, *ssofile;
    char *aexpr, *afile, *asofile;
    char *prefix;
    char *ccflags, *ldflags;
    DDSsplitter_t *splitterp;
    struct rlimit rl;
    channel_t *chanp;
    DDSheader_t hdr;
    Sfio_t *ifp;
    int ret;

    if (AGGRinit () == -1)
        SUerror ("ddssplitnaggr", "AGGRinit failed");
    DDSinit ();
    schemaname = NULL;
    sexpr = NULL, ssofile = NULL;
    aexpr = NULL, afile = NULL, asofile = NULL;
    prefix = "dds.aggr";
    classp = "ddssplitnaggr";
    keytype = AGGR_TYPE_STRING, keylen = -1;
    valtype = AGGR_TYPE_FLOAT, vallen = AGGRtypelens[valtype];
    framen = 1;
    dictincr = 1, itemincr = 1;
    queuen = 1000000;
    appendflag = 0;
    schemap = NULL;
    ccflags = ldflags = "";
    norun = 0;
    for (;;) {
        switch (optget (argv, usage)) {
        case -100:
            schemaname = opt_info.arg;
            continue;
        case -230:
            sexpr = opt_info.arg;
            continue;
        case -232:
            ssofile = opt_info.arg;
            continue;
        case -270:
            aexpr = opt_info.arg;
            continue;
        case -271:
            afile = opt_info.arg;
            continue;
        case -272:
            asofile = opt_info.arg;
            continue;
        case -300:
            prefix = opt_info.arg;
            continue;
        case -301:
            classp = opt_info.arg;
            continue;
        case -302:
            if (AGGRparsetype (opt_info.arg, &keytype, &keylen) == -1)
                SUerror ("ddssplitnaggr", "bad argument for -kt option");
            continue;
        case -303:
            if (AGGRparsetype (opt_info.arg, &valtype, &vallen) == -1)
                SUerror ("ddssplitnaggr", "bad argument for -vt option");
            continue;
        case -304:
            framen = opt_info.num;
            continue;
        case -305:
            dictincr = opt_info.num;
            continue;
        case -306:
            itemincr = opt_info.num;
            continue;
        case -307:
            queuen = opt_info.num;
            continue;
        case -308:
            appendflag = 1;
            continue;
        case -400:
            ccflags = opt_info.arg;
            continue;
        case -401:
            ldflags = opt_info.arg;
            continue;
        case -999:
            SUwarnlevel++;
            continue;
        case '?':
            SUusage (0, "ddssplitnaggr", opt_info.arg);
            norun = 1;
            continue;
        case ':':
            SUusage (1, "ddssplitnaggr", opt_info.arg);
            norun = 2;
            continue;
        }
        break;
    }
    if (norun)
        return norun - 1;
    argc -= opt_info.index, argv += opt_info.index;
    if (!sexpr && !ssofile) {
        SUusage (1, "ddssplitnaggr", opt_info.arg);
        return 1;
    }
    if (!aexpr && !afile && !asofile) {
        SUusage (1, "ddssplitnaggr", opt_info.arg);
        return 1;
    }
    if (argc > 1)
        SUerror ("ddssplitnaggr", "too many parameters");
    if (getrlimit (RLIMIT_NOFILE, &rl) != -1) {
        rl.rlim_cur = rl.rlim_max;
        setrlimit (RLIMIT_NOFILE, &rl);
    }
    ifp = sfstdin;
    if (argc == 1 && !(ifp = sfopen (NULL, argv[0], "r")))
        SUerror ("ddssplitnaggr", "sfopen failed for %s", argv[0]);
    if (!(ifp = SUsetupinput (ifp, 1048576)))
        SUerror ("ddssplitnaggr", "setupinput failed");
    if (!asofile && DDSparseexpr (aexpr, afile, &ae) == -1)
        SUerror ("ddssplitnaggr", "DDSparseexpr failed");
    if (!asofile && !ae.loop) {
        SUusage (1, "ddssplitnaggr", opt_info.arg);
        return 1;
    }
    if ((ret = DDSreadheader (ifp, &hdr)) == -1)
        SUerror ("ddssplitnaggr", "DDSreadheader failed");
    if (ret == -2)
        goto done;
    if (ret == 0) {
        if (hdr.schemap)
            schemap = hdr.schemap;
        else if (hdr.schemaname)
            schemaname = hdr.schemaname;
    }
    if (!schemap) {
        if (!schemaname)
            SUerror ("ddssplitnaggr", "no schema specified");
        if (!(schemap = DDSloadschema (schemaname, NULL, NULL)))
            SUerror ("ddssplitnaggr", "DDSloadschema failed");
    }
    if (!ssofile) {
        if (!(splitterp = DDScreatesplitter (schemap, sexpr, ccflags, ldflags)))
            SUerror ("ddssplitnaggr", "DDScreatesplitter failed");
    } else {
        if (!(splitterp = DDSloadsplitter (schemap, ssofile)))
            SUerror ("ddssplitnaggr", "DDSloadsplitter failed");
    }
    if ((*splitterp->init) (prefix, channelopen, channelreopen, channelclose))
        SUerror ("ddssplitnaggr", "splitterp->init failed");
    if (!asofile) {
        if (!(aggregatorp = DDScreateaggregator (
            schemap, &ae, valtype, ccflags, ldflags
        )))
            SUerror ("ddssplitnaggr", "DDScreateaggregator failed");
    } else {
        if (!(aggregatorp = DDSloadaggregator (schemap, asofile)))
            SUerror ("ddssplitnaggr", "DDSloadaggregator failed");
    }
    while ((ret = DDSreadrecord (
        ifp, schemap->recbuf, schemap
    )) == schemap->recsize) {
        if (!(chanp = (*splitterp->work) (schemap->recbuf, schemap->recsize)))
            SUerror ("ddssplitnaggr", "splitterp->work failed");
        (*aggregatorp->work) (schemap->recbuf, schemap->recsize, chanp->afp);
        ret = 0;
    }
    if (ret != 0)
        SUerror ("ddssplitnaggr", "incomplete read");
    if ((*splitterp->term) ())
        SUerror ("ddssplitnaggr", "splitterp->term failed");
    DDSdestroyaggregator (aggregatorp);
    DDSdestroysplitter (splitterp);

done:
    if (AGGRterm () == -1)
        SUerror ("ddssplitnaggr", "AGGRterm failed");
    DDSterm ();
    return 0;
}
Example #22
0
int main(int argc, char *argv[])
{
    FILE *f;
    struct cli_bc *bc;
    struct cli_bc_ctx *ctx;
    int rc, dbgargc, bc_stats=0;
    struct optstruct *opts;
    const struct optstruct *opt;
    unsigned funcid=0, i;
    struct cli_all_bc bcs;
    int fd = -1;
    unsigned tracelevel;

    if(check_flevel())
	exit(1);

    opts = optparse(NULL, argc, argv, 1, OPT_CLAMBC, 0, NULL);
    if (!opts) {
	fprintf(stderr, "ERROR: Can't parse command line options\n");
	exit(1);
    }
    if(optget(opts, "version")->enabled) {
	printf("Clam AntiVirus Bytecode Testing Tool %s\n", get_version());
	cl_init(CL_INIT_DEFAULT);
	cli_bytecode_printversion();
	optfree(opts);
	exit(0);
    }
    if(optget(opts, "help")->enabled || !opts->filename) {
	optfree(opts);
	help();
	exit(0);
    }
    f = fopen(opts->filename[0], "r");
    if (!f) {
	fprintf(stderr, "Unable to load %s\n", argv[1]);
	optfree(opts);
	exit(2);
    }

    bc = malloc(sizeof(*bc));
    if (!bc) {
	fprintf(stderr, "Out of memory\n");
	optfree(opts);
	exit(3);
    }

    if (optget(opts,"debug")->enabled) {
	cl_debug();
	debug_flag=1;
    }
    rc = cl_init(CL_INIT_DEFAULT);
    if (rc != CL_SUCCESS) {
	fprintf(stderr,"Unable to init libclamav: %s\n", cl_strerror(rc));
	optfree(opts);
	exit(4);
    }

    dbgargc=1;
    while (opts->filename[dbgargc]) dbgargc++;

    if (dbgargc > 1)
	cli_bytecode_debug(dbgargc, opts->filename);

    if (optget(opts, "force-interpreter")->enabled) {
	bcs.engine = NULL;
    } else {
	rc = cli_bytecode_init(&bcs);
	if (rc != CL_SUCCESS) {
	    fprintf(stderr,"Unable to init bytecode engine: %s\n", cl_strerror(rc));
	    optfree(opts);
	    exit(4);
	}
    }

    bcs.all_bcs = bc;
    bcs.count = 1;

    if((opt = optget(opts, "statistics"))->enabled) {
	while(opt) {
	    if (!strcasecmp(opt->strarg, "bytecode"))
		bc_stats=1;
	    opt = opt->nextarg;
        }
    }

    rc = cli_bytecode_load(bc, f, NULL, optget(opts, "trust-bytecode")->enabled, bc_stats);
    if (rc != CL_SUCCESS) {
	fprintf(stderr,"Unable to load bytecode: %s\n", cl_strerror(rc));
	optfree(opts);
	exit(4);
    }
    fclose(f);
    if (bc->state == bc_skip) {
	fprintf(stderr,"bytecode load skipped\n");
	exit(0);
    }
    if (debug_flag)
	printf("[clambc] Bytecode loaded\n");
    if (optget(opts, "info")->enabled) {
	cli_bytecode_describe(bc);
    } else if (optget(opts, "printsrc")->enabled) {
        print_src(opts->filename[0]);
    } else if (optget(opts, "printbcir")->enabled) {
        cli_bytetype_describe(bc);
        cli_bytevalue_describe(bc, 0);
        cli_bytefunc_describe(bc, 0);
    } else {
	cli_ctx cctx;
	struct cl_engine *engine = cl_engine_new();
	fmap_t *map = NULL;
	memset(&cctx, 0, sizeof(cctx));
	if (!engine) {
	    fprintf(stderr,"Unable to create engine\n");
	    optfree(opts);
	    exit(3);
	}
	rc = cl_engine_compile(engine);
	if (rc) {
	    fprintf(stderr,"Unable to compile engine: %s\n", cl_strerror(rc));
	    optfree(opts);
	    exit(4);
	}
	rc = cli_bytecode_prepare2(engine, &bcs, BYTECODE_ENGINE_MASK);
	if (rc != CL_SUCCESS) {
	    fprintf(stderr,"Unable to prepare bytecode: %s\n", cl_strerror(rc));
	    optfree(opts);
	    exit(4);
	}
	if (debug_flag)
	    printf("[clambc] Bytecode prepared\n");

	ctx = cli_bytecode_context_alloc();
	if (!ctx) {
	    fprintf(stderr,"Out of memory\n");
	    exit(3);
	}
	ctx->ctx = &cctx;
	cctx.engine = engine;
	cctx.fmap = cli_calloc(sizeof(fmap_t*), engine->maxreclevel+2);
	if (!cctx.fmap) {
	    fprintf(stderr,"Out of memory\n");
	    exit(3);
	}
	memset(&dbg_state, 0, sizeof(dbg_state));
	dbg_state.file = "<libclamav>";
	dbg_state.line = 0;
	dbg_state.col = 0;
	dbg_state.showline = !optget(opts, "no-trace-showsource")->enabled;
	tracelevel = optget(opts, "trace")->numarg;
	cli_bytecode_context_set_trace(ctx, tracelevel,
				       tracehook,
				       tracehook_op,
				       tracehook_val,
				       tracehook_ptr);

	if (opts->filename[1]) {
	    funcid = atoi(opts->filename[1]);
	}
	cli_bytecode_context_setfuncid(ctx, bc, funcid);
	if (debug_flag)
	    printf("[clambc] Running bytecode function :%u\n", funcid);

	if (opts->filename[1]) {
	    i=2;
	    while (opts->filename[i]) {
		rc = cli_bytecode_context_setparam_int(ctx, i-2, atoi(opts->filename[i]));
		if (rc != CL_SUCCESS) {
		    fprintf(stderr,"Unable to set param %u: %s\n", i-2, cl_strerror(rc));
		}
		i++;
	    }
	}

	if ((opt = optget(opts,"input"))->enabled) {
	    fd = open(opt->strarg, O_RDONLY);
	    if (fd == -1) {
		fprintf(stderr, "Unable to open input file %s: %s\n", opt->strarg, strerror(errno));
		optfree(opts);
		exit(5);
	    }
	    map = fmap(fd, 0, 0);
	    if (!map) {
		fprintf(stderr, "Unable to map input file %s\n", opt->strarg);
		exit(5);
	    }
	    rc = cli_bytecode_context_setfile(ctx, map);
	    if (rc != CL_SUCCESS) {
		fprintf(stderr, "Unable to set file %s: %s\n", opt->strarg, cl_strerror(rc));
		optfree(opts);
		exit(5);
	    }
	}
	/* for testing */
	ctx->hooks.match_counts = deadbeefcounts;
	ctx->hooks.match_offsets = deadbeefcounts;
	rc = cli_bytecode_run(&bcs, bc, ctx);
	if (rc != CL_SUCCESS) {
	    fprintf(stderr,"Unable to run bytecode: %s\n", cl_strerror(rc));
	} else {
	    uint64_t v;
	    if (debug_flag)
		printf("[clambc] Bytecode run finished\n");
	    v = cli_bytecode_context_getresult_int(ctx);
	    if (debug_flag)
		printf("[clambc] Bytecode returned: 0x%llx\n", (long long)v);
	}
	cli_bytecode_context_destroy(ctx);
	if (map)
	    funmap(map);
	cl_engine_free(engine);
	free(cctx.fmap);
    }
    cli_bytecode_destroy(bc);
    cli_bytecode_done(&bcs);
    free(bc);
    optfree(opts);
    if (fd != -1)
	close(fd);
    if (debug_flag)
	printf("[clambc] Exiting\n");
    cl_cleanup_crypto();
    return 0;
}
Example #23
0
int main (int argc, char **argv) {
    int norun;
    int mode;
    char *sofile;
    char *schemaname, *oschemaname;
    DDSschema_t *schemap, *oschemap;
    int fieldi;
    DDSheader_t hdr;
    char buf[10000];
    Sfio_t *ifp;
    int ret;
    char *kexpr;
    char *fexpr, *ffile;
    char *sexpr;
    char *gexpr, *gfile;
    char *eexpr;
    char *cexpr, *cfile;
    char *aexpr, *afile;
    char *pexpr, *pfile;
    int valtype, vallen;
    int fastflag;
    char *ccflags, *ldflags;
    DDSexpr_t fe;
    DDSexpr_t ge;
    DDSexpr_t ce;
    DDSexpr_t ae;
    DDSexpr_t pe;

    if (AGGRinit () == -1)
        SUerror ("ddscc", "AGGRinit failed");
    DDSinit ();
    mode = 0;
    sofile = "ddsobj.so";
    schemaname = oschemaname = NULL;
    schemap = NULL, oschemap = NULL;
    kexpr = NULL;
    fexpr = NULL, ffile = NULL;
    sexpr = NULL;
    gexpr = NULL, gfile = NULL;
    eexpr = NULL;
    cexpr = NULL, cfile = NULL;
    aexpr = NULL, afile = NULL;
    pexpr = NULL, pfile = NULL;
    valtype = AGGR_TYPE_INT, vallen = AGGRtypelens[valtype];
    fastflag = FALSE;
    ccflags = ldflags = "";
    norun = 0;
    for (;;) {
        switch (optget (argv, usage)) {
        case -150:
            mode = MODE_LOADER;
            continue;
        case -151:
            mode = MODE_SORTER;
            continue;
        case -152:
            mode = MODE_FILTER;
            continue;
        case -153:
            mode = MODE_SPLITTER;
            continue;
        case -154:
            mode = MODE_GROUPER;
            continue;
        case -155:
            mode = MODE_EXTRACTOR;
            continue;
        case -156:
            mode = MODE_CONVERTER;
            continue;
        case -157:
            mode = MODE_COUNTER;
            continue;
        case -158:
            mode = MODE_AGGREGATOR;
            continue;
        case -159:
            mode = MODE_PRINTER;
            continue;
        case -200:
            sofile = opt_info.arg;
            continue;
        case -100:
            schemaname = opt_info.arg;
            continue;
        case -101:
            oschemaname = opt_info.arg;
            continue;
        case -210:
            kexpr = opt_info.arg;
            continue;
        case -220:
            fexpr = opt_info.arg;
            continue;
        case -221:
            ffile = opt_info.arg;
            continue;
        case -230:
            sexpr = opt_info.arg;
            continue;
        case -240:
            gexpr = opt_info.arg;
            continue;
        case -241:
            gfile = opt_info.arg;
            continue;
        case -250:
            eexpr = opt_info.arg;
            continue;
        case -260:
            cexpr = opt_info.arg;
            continue;
        case -261:
            cfile = opt_info.arg;
            continue;
        case -270:
            aexpr = opt_info.arg;
            continue;
        case -271:
            afile = opt_info.arg;
            continue;
        case -290:
            pexpr = opt_info.arg;
            continue;
        case -291:
            pfile = opt_info.arg;
            continue;
        case -303:
            if (AGGRparsetype (opt_info.arg, &valtype, &vallen) == -1)
                SUerror ("ddscc", "bad argument for -vt option");
            continue;
        case -400:
            ccflags = opt_info.arg;
            continue;
        case -401:
            ldflags = opt_info.arg;
            continue;
        case -402:
            fastflag = TRUE;
            continue;
        case -999:
            SUwarnlevel++;
            continue;
        case '?':
            SUusage (0, "ddscc", opt_info.arg);
            norun = 1;
            continue;
        case ':':
            SUusage (1, "ddscc", opt_info.arg);
            norun = 2;
            continue;
        }
        break;
    }
    if (norun)
        return norun - 1;
    argc -= opt_info.index, argv += opt_info.index;
    if (mode == MODE_LOADER)
        schemaname = oschemaname;
    if (mode == 0 || argc > 1) {
        SUusage (0, "ddscc", opt_info.arg);
        return 1;
    }
    ifp = sfstdin;
    if (argc == 1)
        if (!(ifp = sfopen (NULL, argv[0], "r")))
            SUerror ("ddscc", "sfopen failed for %s", argv[0]);
    if ((ret = DDSreadheader (ifp, &hdr)) == -1)
        SUerror ("ddscc", "DDSreadheader failed");
    if (ret == 0) {
        if (hdr.schemap)
            schemap = hdr.schemap;
        if (hdr.schemaname)
            schemaname = hdr.schemaname;
    }
    if (!schemap) {
        if (!schemaname)
            SUerror ("ddscc", "no schema specified");
        if (!(schemap = DDSloadschema (schemaname, NULL, NULL)))
            SUerror ("ddscc", "DDSloadschema failed");
    }
    if (mode == MODE_LOADER) {
        if (!oschemaname)
            SUerror ("ddscc", "no output schema specified");
        if (!(oschemap = DDSloadschema (oschemaname, NULL, NULL)))
            SUerror ("ddscc", "DDSloadschema failed for oschemap");
        if (!DDScompileloader (oschemap, sofile, ccflags, ldflags))
            SUerror ("ddscc", "DDScompileloader failed");
    }
    if (mode == MODE_SORTER) {
        if (!kexpr) {
            for (fieldi = 0; fieldi < schemap->fieldn; fieldi++) {
                if (fieldi > 0)
                    strcat (buf, " ");
                strcat (buf, schemap->fields[fieldi].name);
            }
            kexpr = buf;
        }
        if (!DDScompilesorter (
            schemap, kexpr, sofile, ccflags, ldflags, fastflag
        ))
            SUerror ("ddscc", "DDScompilesorter failed");
    }
    if (mode == MODE_FILTER) {
        if (!fexpr && !ffile)
            fexpr = "{ KEEP; }";
        if (DDSparseexpr (fexpr, ffile, &fe) == -1)
            SUerror ("ddscc", "DDSparseexpr failed");
        if (!DDScompilefilter (schemap, &fe, sofile, ccflags, ldflags))
            SUerror ("ddscc", "DDScompilefilter failed");
    }
    if (mode == MODE_SPLITTER) {
        if (!sexpr)
            SUerror ("ddscc", "missing expression");
        if (!DDScompilesplitter (schemap, sexpr, sofile, ccflags, ldflags))
            SUerror ("ddscc", "DDScompilesplitter failed");
    }
    if (mode == MODE_GROUPER) {
        if (!gexpr && !gfile)
            SUerror ("ddscc", "missing expression");
        if (DDSparseexpr (gexpr, gfile, &ge) == -1)
            SUerror ("ddscc", "DDSparseexpr failed");
        if (!DDScompilegrouper (schemap, &ge, sofile, ccflags, ldflags))
            SUerror ("ddscc", "DDScompilegrouper failed");
    }
    if (mode == MODE_EXTRACTOR) {
        if (!eexpr)
            SUerror ("ddscc", "missing expression");
        if (!DDScompileextractor (
            schemap, NULL, eexpr, sofile, ccflags, ldflags
        ))
            SUerror ("ddscc", "DDScompileextractor failed");
    }
    if (mode == MODE_CONVERTER) {
        if (!cexpr && !cfile)
            SUerror ("ddscc", "missing expression");
        if (!oschemaname)
            SUerror ("ddscc", "no output schema specified");
        if (!(oschemap = DDSloadschema (oschemaname, NULL, NULL)))
            SUerror ("ddscc", "DDSloadschema failed for oschemap");
        if (DDSparseexpr (cexpr, cfile, &ce) == -1)
            SUerror ("ddscc", "DDSparseexpr failed");
        if (!DDScompileconverter (
            schemap, oschemap, &ce, sofile, ccflags, ldflags
        ))
            SUerror ("ddscc", "DDScompileconverter failed");
    }
    if (mode == MODE_COUNTER) {
        if (!kexpr || strcmp (kexpr, "all") == 0) {
            for (fieldi = 0; fieldi < schemap->fieldn; fieldi++) {
                if (cexpr && strcmp (cexpr, schemap->fields[fieldi].name) == 0)
                    continue;
                if (fieldi > 0)
                    strcat (buf, " ");
                strcat (buf, schemap->fields[fieldi].name);
            }
            kexpr = buf;
        }
        if (!DDScompilecounter (
            schemap, kexpr, cexpr, sofile, ccflags, ldflags
        ))
            SUerror ("ddscc", "DDScompilecounter failed");
    }
    if (mode == MODE_AGGREGATOR) {
        if (!aexpr && !afile)
            aexpr = "{ KEEP; }";
        if (DDSparseexpr (aexpr, afile, &ae) == -1)
            SUerror ("ddscc", "DDSparseexpr failed");
        if (!DDScompileaggregator (
            schemap, &ae, valtype, sofile, ccflags, ldflags
        ))
            SUerror ("ddscc", "DDScompileaggregator failed");
    }
    if (mode == MODE_PRINTER) {
        if (!pexpr && !pfile)
            pexpr = "{ KEEP; }";
        if (DDSparseexpr (pexpr, pfile, &pe) == -1)
            SUerror ("ddscc", "DDSparseexpr failed");
        if (!DDScompileprinter (schemap, &pe, sofile, ccflags, ldflags))
            SUerror ("ddscc", "DDScompileprinter failed");
    }
    DDSterm ();
    return 0;
}
Example #24
0
int
b_fold(int argc, char** argv, Shbltin_t* context)
{
	register int n, width=WIDTH;
	register Sfio_t *fp;
	register char *cp;
	char *cont="\n";
	size_t contsize = 1;
	char cols[1<<CHAR_BIT];

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	memset(cols, 0, sizeof(cols));
	cols['\t'] = T_TAB;
	cols['\b'] = T_BS;
	cols['\n'] = T_NL;
	cols['\r'] = T_RET;
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'b':
			cols['\r'] = cols['\b'] = 0;
			cols['\t'] = cols[' '];
			continue;
		case 'c':
			contsize = stresc(cont = strdup(opt_info.arg));
			continue;
		case 'd':
			if (n = *opt_info.arg)
				cols[n] = T_SP;
			continue;
		case 's':
			cols[' '] = T_SP;
			if(cols['\t']==0)
				cols['\t'] = T_SP;
			continue;
		case 'w':
			if ((width = opt_info.num) <= 0)
				error(2, "%d: width must be positive", opt_info.num);
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			continue;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			continue;
		}
		break;
	}
	argv += opt_info.index;
	argc -= opt_info.index;
	if(error_info.errors)
		error(ERROR_usage(2),"%s", optusage(NiL));
	if(cp = *argv)
		argv++;
	do
	{
		if(!cp || streq(cp,"-"))
			fp = sfstdin;
		else if(!(fp = sfopen(NiL,cp,"r")))
		{
			error(ERROR_system(0),"%s: cannot open",cp);
			error_info.errors = 1;
			continue;
		}
		fold(fp,sfstdout,width,cont,contsize,cols);
		if(fp!=sfstdin)
			sfclose(fp);
	}
	while(cp= *argv++);
	return(error_info.errors);
}
Example #25
0
int	b_ulimit(int argc,char *argv[],void *extra)
{
	register char *limit;
	register int mode=0, n;
	register unsigned long hit = 0;
	Shell_t *shp = ((Shbltin_t*)extra)->shp;
#ifdef _lib_getrlimit
	struct rlimit rlp;
#endif /* _lib_getrlimit */
	const Limit_t* tp;
	char* conf;
	int label, unit, nosupport;
	rlim_t i;
	char tmp[32];
        Optdisc_t disc;
        memset(&disc, 0, sizeof(disc));
        disc.version = OPT_VERSION;
        disc.infof = infof;
	opt_info.disc = &disc;
	while((n = optget(argv,sh_optulimit))) switch(n)
	{
		case 'H':
			mode |= HARD;
			continue;
		case 'S':
			mode |= SOFT;
			continue;
		case 'a':
			hit = ~0;
			break;
		default:
			if(n < 0)
				hit |= (1L<<(-(n+1)));
			else
				errormsg(SH_DICT,2, e_notimp, opt_info.name);
			break;
		case ':':
			errormsg(SH_DICT,2, "%s", opt_info.arg);
			break;
		case '?':
			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
			break;
	}
	opt_info.disc = 0;
	/* default to -f */
	limit = argv[opt_info.index];
	if(hit==0)
		for(n=0; shtab_limits[n].option; n++)
			if(shtab_limits[n].index == RLIMIT_FSIZE)
			{
				hit |= (1L<<n);
				break;
			}
	/* only one option at a time for setting */
	label = (hit&(hit-1));
	if(error_info.errors || (limit && label) || argc>opt_info.index+1)
		errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
	if(mode==0)
		mode = (HARD|SOFT);
	for(tp = shtab_limits; tp->option && hit; tp++,hit>>=1)
	{
		if(!(hit&1))
			continue;
		nosupport = (n = tp->index) == RLIMIT_UNKNOWN;
		unit = shtab_units[tp->type];
		if(limit)
		{
			if(shp->subshell && !shp->subshare)
				sh_subfork();
			if(strcmp(limit,e_unlimited)==0)
				i = INFINITY;
			else
			{
				char *last;
				if((i=sh_strnum(limit,&last,2))==INFINITY || *last)
					errormsg(SH_DICT,ERROR_system(1),e_number,limit);
				i *= unit;
			}
			if(nosupport)
				errormsg(SH_DICT,ERROR_system(1),e_readonly,tp->name);
			else
			{
#ifdef _lib_getrlimit
				if(getrlimit(n,&rlp) <0)
					errormsg(SH_DICT,ERROR_system(1),e_number,limit);
				if(mode&HARD)
					rlp.rlim_max = i;
				if(mode&SOFT)
					rlp.rlim_cur = i;
				if(setrlimit(n,&rlp) <0)
					errormsg(SH_DICT,ERROR_system(1),e_overlimit,limit);
#else
				if((i=vlimit(n,i)) < 0)
					errormsg(SH_DICT,ERROR_system(1),e_number,limit);
#endif /* _lib_getrlimit */
			}
		}
		else
		{
			if(!nosupport)
			{
#ifdef  _lib_getrlimit
				if(getrlimit(n,&rlp) <0)
					errormsg(SH_DICT,ERROR_system(1),e_number,limit);
				if(mode&HARD)
					i = rlp.rlim_max;
				if(mode&SOFT)
					i = rlp.rlim_cur;
#else
#   ifdef _lib_ulimit
				n--;
#   endif /* _lib_ulimit */
				i = -1;
				if((i=vlimit(n,i)) < 0)
					errormsg(SH_DICT,ERROR_system(1),e_number,limit);
#endif /* _lib_getrlimit */
			}
			if(label)
			{
				if(tp->type != LIM_COUNT)
					sfsprintf(tmp,sizeof(tmp),"%s (%ss)", tp->description, e_units[tp->type]);
				else
					sfsprintf(tmp,sizeof(tmp),"%s", tp->name);
				sfprintf(sfstdout,"%-30s (-%c)  ",tmp,tp->option);
			}
			if(nosupport)
			{
				if(!tp->conf || !*(conf = astconf(tp->conf, NiL, NiL)))
					conf = (char*)e_nosupport;
				sfputr(sfstdout,conf,'\n');
			}
			else if(i!=INFINITY)
			{
				i += (unit-1);
				sfprintf(sfstdout,"%I*d\n",sizeof(i),i/unit);
			}
			else
				sfputr(sfstdout,e_unlimited,'\n');
		}
	}
	return(0);
}
Example #26
0
int b___regress__(int argc, char** argv, void *extra)
{
	register Shell_t*	shp = ((Shbltin_t*)extra)->shp;
	int			n;

	for (;;)
	{
		switch (n = optget(argv, usage))
		{
		case '?':
			errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg);
			break;
		case ':':
			errormsg(SH_DICT, 2, "%s", opt_info.arg);
			break;
		case 0:
			break;
		default:
			if (n < -100)
			{
				n = -(n + 100);
				if (opt_info.arg || opt_info.number)
					sh_onregress(n);
				else
					sh_offregress(n);
				switch (n)
				{
				case REGRESS_egid:
					if (sh_isregress(n))
					{
						intercept_egid = intercept_sgid = (gid_t)opt_info.number;
						TRACE(egid, argv[0], ("%d", intercept_egid));
					}
					else
						TRACE(egid, argv[0], ("%s", "off"));
					break;
				case REGRESS_euid:
					if (sh_isregress(n))
					{
						intercept_euid = intercept_suid = (uid_t)opt_info.number;
						TRACE(euid, argv[0], ("%d", intercept_euid));
					}
					else
						TRACE(euid, argv[0], ("%s", "off"));
					break;
				case REGRESS_p_suid:
					if (sh_isregress(n))
					{
						intercept_p_suid = (uid_t)opt_info.number;
						TRACE(p_suid, argv[0], ("%d", intercept_p_suid));
					}
					else
						TRACE(p_suid, argv[0], ("%s", "off"));
					break;
				case REGRESS_source:
					TRACE(source, argv[0], ("%s", sh_isregress(n) ? "on" : "off"));
					break;
				case REGRESS_etc:
					if (sh_isregress(n))
					{
						intercept_etc = opt_info.arg;
						TRACE(etc, argv[0], ("%s", intercept_etc));
					}
					else
						TRACE(etc, argv[0], ("%s", "off"));
					break;
				}
			}
			continue;
		}
		break;
	}
	if (error_info.errors || *(argv + opt_info.index))
		errormsg(SH_DICT, ERROR_usage(2), "%s", optusage(NiL));
	return 0;
}
Example #27
0
/* Inits the communication layer
 * Returns 0 if clamd is local, non zero if clamd is remote */
static int isremote(const struct optstruct *opts) {
    int s, ret;
    const struct optstruct *opt;
    char *ipaddr, port[10];
    struct addrinfo hints, *info, *p;
    int res;

    UNUSEDPARAM(opts);

#ifndef _WIN32
    if((opt = optget(clamdopts, "LocalSocket"))->enabled) {
        memset((void *)&nixsock, 0, sizeof(nixsock));
        nixsock.sun_family = AF_UNIX;
        strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path));
        nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0';
        return 0;
    }
#endif
    if(!(opt = optget(clamdopts, "TCPSocket"))->enabled)
        return 0;

    snprintf(port, sizeof(port), "%lld", optget(clamdopts, "TCPSocket")->numarg);

    opt = optget(clamdopts, "TCPAddr");
    while (opt) {
        ipaddr = NULL;
        if (opt->strarg)
            ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg);

        memset(&hints, 0x00, sizeof(struct addrinfo));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;

        if ((res = getaddrinfo(ipaddr, port, &hints, &info))) {
            logg("!Can't lookup clamd hostname: %s\n", gai_strerror(res));
            opt = opt->nextarg;
            continue;
        }

        for (p = info; p != NULL; p = p->ai_next) {
            if((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
                logg("isremote: socket() returning: %s.\n", strerror(errno));
                continue;
            }

            switch (p->ai_family) {
            case AF_INET:
                ((struct sockaddr_in *)(p->ai_addr))->sin_port = htons(INADDR_ANY);
                break;
            case AF_INET6:
                ((struct sockaddr_in6 *)(p->ai_addr))->sin6_port = htons(INADDR_ANY);
                break;
            default:
                break;
            }

            ret = bind(s, p->ai_addr, p->ai_addrlen);
            if (ret) {
                if (errno == EADDRINUSE) {
                    /* 
                     * If we can't bind, then either we're attempting to listen on an IP that isn't
                     * ours or that clamd is already listening on.
                     */
                    closesocket(s);
                    freeaddrinfo(info);
                    return 0;
                }

                closesocket(s);
                freeaddrinfo(info);
                return 1;
            }

            closesocket(s);
        }

        freeaddrinfo(info);

        opt = opt->nextarg;
    }

    return 0;
}
Example #28
0
int main (int argc, char **argv) {
    int norun;
    char *rulesfile, *statefile;
    int newflag, checkflag;

    Sfio_t *ifp, *ofp;
    int osm;
    DDSschema_t *schemap;
    DDSheader_t hdr;
    int ret;

    VG_alarm_t adata;
    ruleev_t *ruleevp;
    cc_t *ccp;
    nd_t *ndp;
    ev_t *evp;
    sl_inv_nd2cc_t *nd2ccp;
    char *currdate, *s;
    int maxalarmkeepmin;

    schemap = NULL;
    osm = DDS_HDR_NAME | DDS_HDR_DESC;
    rulesfile = NULL;
    statefile = NULL;
    currdate = NULL;
    newflag = FALSE;
    checkflag = FALSE;
    norun = 0;
    for (;;) {
        switch (optget (argv, usage)) {
        case -100:
            rulesfile = opt_info.arg;
            continue;
        case -101:
            statefile = opt_info.arg;
            continue;
        case -102:
            currdate = opt_info.arg;
            continue;
        case -200:
            newflag = TRUE;
            continue;
        case -201:
            checkflag = TRUE;
            continue;
        case -999:
            SUwarnlevel++;
            continue;
        case '?':
            SUusage (0, "vggce", opt_info.arg);
            norun = 1;
            continue;
        case ':':
            SUusage (1, "vggce", opt_info.arg);
            norun = 2;
            continue;
        }
        break;
    }
    if (norun)
        return norun - 1;
    argc -= opt_info.index, argv += opt_info.index;

    ifp = ofp = NULL;
    if (!rulesfile || !statefile || !currdate || strlen (currdate) != 10) {
        SUwarning (0, "vggce", "missing arguments");
        goto failsafe1;
    }

    DDSinit ();
    if (!(ifp = SUsetupinput (sfstdin, 1048576))) {
        SUwarning (0, "vggce", "setupinput failed");
        goto failsafe1;
    }
    if (!(ofp = SUsetupoutput (NULL, sfstdout, 1048576))) {
        SUwarning (0, "vggce", "setupoutput failed");
        goto failsafe1;
    }
    if ((ret = DDSreadheader (ifp, &hdr)) == -1) {
        SUwarning (0, "vggce", "DDSreadheader failed");
        goto failsafe1;
    }
    if (ret == -2)
        goto done;
    if (ret == 0) {
        if (hdr.schemap)
            schemap = hdr.schemap;
    }
    if (!schemap) {
        SUwarning (0, "vggce", "DDSloadschema failed");
        goto failsafe1;
    }
    if (!hdr.schemap && schemap)
        hdr.schemap = schemap;
    hdr.contents = osm;
    hdr.vczspec = "";
    if (osm && DDSwriteheader (ofp, &hdr) == -1) {
        SUwarning (0, "vggce", "DDSwriteheader failed");
        goto failsafe1;
    }

    s = getenv ("DEFAULTTMODE");
    if (!(ftmode = vmstrdup (Vmheap, s ? s : VG_ALARM_S_MODE_KEEP))) {
        SUwarning (0, "vggce", "cannot copy tmode");
        goto failsafe1;
    }
    if ((rtmode = strchr (ftmode, ':')))
        *rtmode++ = 0;
    else
        rtmode = ftmode;

    currtime = 0;
    maxalarmkeepmin = atoi (getenv ("MAXALARMKEEPMIN"));
    sl_inv_nd2ccopen (getenv ("INVND2CCFILE"));

    if (sevmapload (getenv ("SEVMAPFILE")) == -1) {
        SUwarning (0, "vggce", "cannot load sevmap file");
        goto failsafe1;
    }
    if (initgraph () == -1) {
        SUwarning (0, "vggce", "initgraph failed");
        goto failsafe1;
    }
    if (initcorr () == -1) {
        SUwarning (0, "vggce", "initcorr failed");
        goto failsafe1;
    }
    if (loadrules (rulesfile) == -1) {
        SUwarning (0, "vggce", "loadrules failed");
        goto failsafe1;
    }
    if (checkflag)
        goto done;
    if (!newflag && loadevstate (statefile) == -1) {
        SUwarning (0, "vggce", "loadstate failed");
        goto failsafe1;
    }

    ccmark++;
    evmark++;

    while ((
        ret = DDSreadrecord (ifp, &adata, schemap)
    ) == sizeof (VG_alarm_t)) {
        VG_warning (0, "GCE INFO", "read alarm %s", adata.s_text);

        if (
            !DATEMATCH (currdate, adata.s_dateissued) ||
            adata.s_sortorder != VG_ALARM_N_SO_NORMAL ||
            adata.s_pmode != VG_ALARM_N_PMODE_PROCESS
        )
            goto write;

        if (currtime < adata.s_timeissued)
            currtime = adata.s_timeissued;

        if (!(ruleevp = matchruleev (&adata)))
            goto write;

        if (!(nd2ccp = sl_inv_nd2ccfind (adata.s_level1, adata.s_id1)))
            goto write;

        if (!(ccp = insertcc (nd2ccp->sl_cclevel, nd2ccp->sl_ccid, TRUE))) {
            SUwarning (0, "vggce", "cannot insert cc %s", nd2ccp->sl_ccid);
            goto failsafe1;
        }
        if (ccp->svcpm < 1)
            goto write;

        if (!(ndp = findnd (adata.s_level1, adata.s_id1))) {
            SUwarning (0, "vggce", "cannot find nd %s", adata.s_id1);
            goto failsafe1;
        }

        if (!(evp = insertev (
            adata.s_timeissued, adata.s_type, ccp, ndp, ruleevp
        ))) {
            SUwarning (0, "vggce", "cannot insert ev");
            goto failsafe1;
        }
        if (evp->svcpm < 1)
            goto write;

        if (insertndevent (ndp, evp) == -1) {
            SUwarning (0, "vggce", "cannot insert ev in nd");
            goto failsafe1;
        }

write:
        if (DDSwriterecord (ofp, &adata, schemap) != sizeof (VG_alarm_t)) {
            SUwarning (0, "vggce", "cannot write alarm");
            goto failsafe1;
        }
        VG_warning (0, "GCE INFO", "wrote alarm");
    }

    ndmark++;

    if (pruneevs (currtime - 60 * maxalarmkeepmin, 1) == -1) {
        SUwarning (0, "vggce", "cannot prune evs (1)");
        goto failsafe1;
    }

    calcsvcvalues (SVC_MODE_NOEV, -1, -1);
    calcsvcvalues (SVC_MODE_OLDEV, 0, 0);
    calcsvcvalues (SVC_MODE_NEWEV, 0, 1);

    if (updatealarms (SVC_MODE_OLDEV, SVC_MODE_NEWEV, 1) == -1) {
        SUwarning (0, "vggce", "cannot update alarms (1)");
        goto failsafe1;
    }

    evmark++;
//    ccmark++;

    if (pruneevs (currtime - 60 * maxalarmkeepmin, 2) == -1) {
        SUwarning (0, "vggce", "cannot prune evs");
        goto failsafe1;
    }

    calcsvcvalues (SVC_MODE_PRUNE, 2, 2);

    if (updatealarms (SVC_MODE_NEWEV, SVC_MODE_PRUNE, 2) == -1) {
        SUwarning (0, "vggce", "cannot update alarms (2)");
        goto failsafe1;
    }

    if (saveevstate (statefile) == -1) {
        SUwarning (0, "vggce", "savestate failed");
        goto failsafe1;
    }

    VG_warning (0, "GCE INFO", "events=%d", evpm);

    if (ret != 0)
        SUerror ("vggce", "failed to read full record");

done:
    DDSterm ();
    return 0;

failsafe1:
    SUwarning (0, "vggce", "IN FAILSAFE MODE");
    if (sfmove (ifp, ofp, -1, -1) == -1)
        SUwarning (0, "vggce", "cannot copy data");
    return 101;
}
Example #29
0
int	b_trap(int argc,char *argv[],void *extra)
{
	register char *arg = argv[1];
	register int sig, clear = 0, dflag = 0, pflag = 0;
	register Shell_t *shp = ((Shbltin_t*)extra)->shp;
	NOT_USED(argc);
	while (sig = optget(argv, sh_opttrap)) switch (sig)
	{
	    case 'p':
		pflag=1;
		break;
	    case ':':
		errormsg(SH_DICT,2, "%s", opt_info.arg);
		break;
	    case '?':
		errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
		return(2);
		break;
	}
	argv += opt_info.index;
	if(error_info.errors)
		errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
	if(arg = *argv)
	{
		char *action = arg;
		if(!dflag && !pflag)
		{
			/* first argument all digits or - means clear */
			while(isdigit(*arg))
				arg++;
			clear = (arg!=action && *arg==0);
			if(!clear)
			{
				++argv;
				if(*action=='-' && action[1]==0)
					clear++;
				/*
				 * NOTE: 2007-11-26: workaround for tests/signal.sh
				 * if function semantics can be worked out then it
				 * may merit a -d,--default option
				 */
				else if(*action=='+' && action[1]==0 && shp->st.self == &shp->global)
				{
					clear++;
					dflag++;
				}
			}
			if(!argv[0])
				errormsg(SH_DICT,ERROR_exit(1),e_condition);
		}
		while(arg = *argv++)
		{
			sig = sig_number(shp,arg);
			if(sig<0)
			{
				errormsg(SH_DICT,2,e_trap,arg);
				return(1);
			}
			/* internal traps */
			if(sig&SH_TRAP)
			{
				sig &= ~SH_TRAP;
				if(sig>SH_DEBUGTRAP)
				{
					errormsg(SH_DICT,2,e_trap,arg);
					return(1);
				}
				if(pflag)
				{
					if(arg=shp->st.trap[sig])
						sfputr(sfstdout,sh_fmtq(arg),'\n');
					continue;
				}
				if(shp->st.trap[sig])
					free(shp->st.trap[sig]);
				shp->st.trap[sig] = 0;
				if(!clear && *action)
					shp->st.trap[sig] = strdup(action);
				if(sig == SH_DEBUGTRAP)
				{
					if(shp->st.trap[sig])
						shp->trapnote |= SH_SIGTRAP;
					else
						shp->trapnote = 0;
				}
				continue;
			}
			if(sig>shp->gd->sigmax)
			{
				errormsg(SH_DICT,2,e_trap,arg);
				return(1);
			}
			else if(pflag)
			{
				char **trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
				if(arg=trapcom[sig])
					sfputr(sfstdout,arg,'\n');
			}
			else if(clear)
			{
				sh_sigclear(sig);
				if(dflag)
					signal(sig,SIG_DFL);
			}
			else
			{
				if(sig >= shp->st.trapmax)
					shp->st.trapmax = sig+1;
				arg = shp->st.trapcom[sig];
				sh_sigtrap(sig);
				shp->st.trapcom[sig] = (shp->sigflag[sig]&SH_SIGOFF) ? Empty : strdup(action);
				if(arg && arg != Empty)
					free(arg);
			}
		}
	}
	else /* print out current traps */
		sig_list(shp,-1);
	return(0);
}
Example #30
0
int main(int argc, char **argv) {
    char *my_socket, *pt;
    const struct optstruct *opt;
    struct optstruct *opts;
    time_t currtime;
    mode_t umsk;
    int ret;

    cl_initialize_crypto();

    memset(&descr, 0, sizeof(struct smfiDesc));
    descr.xxfi_name = "ClamAV";			/* filter name */
    descr.xxfi_version = SMFI_VERSION;		/* milter version */
    descr.xxfi_flags = SMFIF_QUARANTINE;	/* flags */
    descr.xxfi_connect = clamfi_connect;	/* connection info filter */
    descr.xxfi_envfrom = clamfi_envfrom;	/* envelope sender filter */
    descr.xxfi_envrcpt = clamfi_envrcpt;	/* envelope recipient filter */
    descr.xxfi_header = clamfi_header;		/* header filter */
    descr.xxfi_body = clamfi_body;		/* body block */
    descr.xxfi_eom = clamfi_eom;		/* end of message */
    descr.xxfi_abort = clamfi_abort;		/* message aborted */

    opts = optparse(NULL, argc, argv, 1, OPT_MILTER, 0, NULL);
    if (!opts) {
	mprintf("!Can't parse command line options\n");
	return 1;
    }

    if(optget(opts, "help")->enabled) {
	printf("Usage: %s [-c <config-file>]\n\n", argv[0]);
	printf("    --help                   -h       Show this help\n");
	printf("    --version                -V       Show version and exit\n");
	printf("    --config-file <file>     -c       Read configuration from file\n\n");
	optfree(opts);
	return 0;
    }

    if(opts->filename) {
	int x;
	for(x = 0; opts->filename[x]; x++)
	    mprintf("^Ignoring option %s\n", opts->filename[x]);
    }

    if(optget(opts, "version")->enabled) {
	printf("clamav-milter %s\n", get_version());
	optfree(opts);
	return 0;
    }

    pt = strdup(optget(opts, "config-file")->strarg);
    if (pt == NULL) {
	printf("Unable to allocate memory for config file\n");
	return 1;
    }
    if((opts = optparse(pt, 0, NULL, 1, OPT_MILTER, 0, opts)) == NULL) {
	printf("%s: cannot parse config file %s\n", argv[0], pt);
	free(pt);
	return 1;
    }
    free(pt);

    if((opt = optget(opts, "Chroot"))->enabled) {
	if(chdir(opt->strarg) != 0) {
	    logg("!Cannot change directory to %s\n", opt->strarg);
	    return 1;
	}
	if(chroot(opt->strarg) != 0) {
	    logg("!chroot to %s failed. Are you root?\n", opt->strarg);
	    return 1;
	}
    }

    pt = optget(opts, "AddHeader")->strarg;
    if (strcasecmp(pt, "No")) {
	char myname[255];

	if (((opt = optget(opts, "ReportHostname"))->enabled &&
	     strncpy(myname, opt->strarg, sizeof(myname))) ||
	    !gethostname(myname, sizeof(myname))) {

	    myname[sizeof(myname)-1] = '\0';
	    snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s at %s",
		     get_version(), myname);
	} else {
	    snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s",
		     get_version());
	}
	xvirushdr[sizeof(xvirushdr)-1] = '\0';

	descr.xxfi_flags |= SMFIF_ADDHDRS;

	if (strcasecmp(pt, "Add")) { /* Replace or Yes */
	    descr.xxfi_flags |= SMFIF_CHGHDRS;
	    addxvirus = 1;
	} else { /* Add */
	    addxvirus = 2;
	}
    }

    if(!(my_socket = optget(opts, "MilterSocket")->strarg)) {
	logg("!Please configure the MilterSocket directive\n");
	logg_close();
	optfree(opts);
	return 1;
    }

    if(smfi_setconn(my_socket) == MI_FAILURE) {
	logg("!smfi_setconn failed\n");
	logg_close();
	optfree(opts);
	return 1;
    }
    if(smfi_register(descr) == MI_FAILURE) {
	logg("!smfi_register failed\n");
	logg_close();
	optfree(opts);
	return 1;
    }
    opt = optget(opts, "FixStaleSocket");
    umsk = umask(0777); /* socket is created with 000 to avoid races */
    if(smfi_opensocket(opt->enabled) == MI_FAILURE) {
	logg("!Failed to create socket %s\n", my_socket);
	logg_close();
	optfree(opts);
	return 1;
    }
    umask(umsk); /* restore umask */
    if(strncmp(my_socket, "inet:", 5) && strncmp(my_socket, "inet6:", 6)) {
	/* set group ownership and perms on the local socket */
	char *sock_name = my_socket;
	mode_t sock_mode;
	if(!strncmp(my_socket, "unix:", 5))
	    sock_name += 5;
	if(!strncmp(my_socket, "local:", 6))
	    sock_name += 6;
	if(*my_socket == ':')
	    sock_name ++;

	if(optget(opts, "MilterSocketGroup")->enabled) {
	    char *gname = optget(opts, "MilterSocketGroup")->strarg, *end;
	    gid_t sock_gid = strtol(gname, &end, 10);
	    if(*end) {
		struct group *pgrp = getgrnam(gname);
		if(!pgrp) {
		    logg("!Unknown group %s\n", gname);
		    logg_close();
		    optfree(opts);
		    return 1;
		}
		sock_gid = pgrp->gr_gid;
	    }
	    if(chown(sock_name, -1, sock_gid)) {
		logg("!Failed to change socket ownership to group %s\n", gname);
		logg_close();
		optfree(opts);
		return 1;
	    }
	}

	if ((opt = optget(opts, "User"))->enabled) {
	    struct passwd *user;
	    if ((user = getpwnam(opt->strarg)) == NULL) {
		logg("ERROR: Can't get information about user %s.\n",
			opt->strarg);
		logg_close();
		optfree(opts);
		return 1;
	    }

	    if(chown(sock_name, user->pw_uid, -1)) {
		logg("!Failed to change socket ownership to user %s\n", user->pw_name);
		optfree(opts);
		logg_close();
		return 1;
	    }
	}

	if(optget(opts, "MilterSocketMode")->enabled) {
	    char *end;
	    sock_mode = strtol(optget(opts, "MilterSocketMode")->strarg, &end, 8);
	    if(*end) {
		logg("!Invalid MilterSocketMode %s\n", optget(opts, "MilterSocketMode")->strarg);
		logg_close();
		optfree(opts);
		return 1;
	    }
	} else
	    sock_mode = 0777 & ~umsk;

	if(chmod(sock_name, sock_mode & 0666)) {
	    logg("!Cannot set milter socket permission to %s\n", optget(opts, "MilterSocketMode")->strarg);
	    logg_close();
	    optfree(opts);
	    return 1;
	}
    }

    if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
        struct passwd *user = NULL;
	if((user = getpwnam(opt->strarg)) == NULL) {
	    fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg);
	    optfree(opts);
	    return 1;
	}

	if(optget(opts, "AllowSupplementaryGroups")->enabled) {
#ifdef HAVE_INITGROUPS
	    if(initgroups(opt->strarg, user->pw_gid)) {
		fprintf(stderr, "ERROR: initgroups() failed.\n");
		optfree(opts);
		return 1;
	    }
#else
	    mprintf("!AllowSupplementaryGroups: initgroups() is not available, please disable AllowSupplementaryGroups\n");
	    optfree(opts);
	    return 1;
#endif
	} else {
#ifdef HAVE_SETGROUPS
	    if(setgroups(1, &user->pw_gid)) {
		fprintf(stderr, "ERROR: setgroups() failed.\n");
		optfree(opts);
		return 1;
	    }
#endif
	}

	if(setgid(user->pw_gid)) {
	    fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid);
	    optfree(opts);
	    return 1;
	}

	if(setuid(user->pw_uid)) {
	    fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid);
	    optfree(opts);
	    return 1;
	}
    }

    logg_lock = !optget(opts, "LogFileUnlock")->enabled;
    logg_time = optget(opts, "LogTime")->enabled;
    logg_size = optget(opts, "LogFileMaxSize")->numarg;
    logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled;
    if (logg_size)
        logg_rotate = optget(opts, "LogRotate")->enabled;

    if((opt = optget(opts, "LogFile"))->enabled) {
	logg_file = opt->strarg;
	if(!cli_is_abspath(logg_file)) {
	    fprintf(stderr, "ERROR: LogFile requires full path.\n");
	    logg_close();
	    optfree(opts);
	    return 1;
	}
    } else
	logg_file = NULL;

#if defined(USE_SYSLOG) && !defined(C_AIX)
    if(optget(opts, "LogSyslog")->enabled) {
	int fac;

	opt = optget(opts, "LogFacility");
	if((fac = logg_facility(opt->strarg)) == -1) {
	    logg("!LogFacility: %s: No such facility.\n", opt->strarg);
	    logg_close();
	    optfree(opts);
	    return 1;
	}

	openlog("clamav-milter", LOG_PID, fac);
	logg_syslog = 1;
    }
#endif

    time(&currtime);
    if(logg("#+++ Started at %s", ctime(&currtime))) {
	fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
	logg_close();
	optfree(opts);
	return 1;
    }
    if((opt = optget(opts, "TemporaryDirectory"))->enabled)
	tempdir = opt->strarg;

    if(localnets_init(opts) || init_actions(opts)) {
	logg_close();
	optfree(opts);
	return 1;
    }

    if((opt = optget(opts, "Whitelist"))->enabled && whitelist_init(opt->strarg)) {
	localnets_free();
	logg_close();
	optfree(opts);
	return 1;
    }

    if((opt = optget(opts, "SkipAuthenticated"))->enabled && smtpauth_init(opt->strarg)) {
	localnets_free();
	whitelist_free();
	logg_close();
	optfree(opts);
	return 1;
    }

    multircpt = optget(opts, "SupportMultipleRecipients")->enabled;
    
    if(!optget(opts, "Foreground")->enabled) {
	if(daemonize() == -1) {
	    logg("!daemonize() failed\n");
	    localnets_free();
	    whitelist_free();
	    cpool_free();
	    logg_close();
	    optfree(opts);
	    return 1;
	}
	if(chdir("/") == -1)
	    logg("^Can't change current working directory to root\n");
    }

    maxfilesize = optget(opts, "MaxFileSize")->numarg;
    if(!maxfilesize) {
	logg("^Invalid MaxFileSize, using default (%d)\n", CLI_DEFAULT_MAXFILESIZE);
	maxfilesize = CLI_DEFAULT_MAXFILESIZE;
    }
    readtimeout = optget(opts, "ReadTimeout")->numarg;

    cpool_init(opts);
    if (!cp) {
	logg("!Failed to init the socket pool\n");
	localnets_free();
	whitelist_free();
	logg_close();
	optfree(opts);
	return 1;
    }	

    if((opt = optget(opts, "PidFile"))->enabled) {
	FILE *fd;
	mode_t old_umask = umask(0002);

	if((fd = fopen(opt->strarg, "w")) == NULL) {
	    logg("!Can't save PID in file %s\n", opt->strarg);
	} else {
	    if (fprintf(fd, "%u\n", (unsigned int)getpid())<0) {
	    	logg("!Can't save PID in file %s\n", opt->strarg);
	    }
	    fclose(fd);
	}
	umask(old_umask);
    }

    ret = smfi_main();

    optfree(opts);

    logg_close();
    cpool_free();
    localnets_free();
    whitelist_free();

    return ret;
}