Пример #1
0
static void htmlnorm_setup(void)
{
        cl_init(CL_INIT_DEFAULT);
	dconf_setup();
	dir = cli_gentemp(NULL);
	fail_unless(!!dir, "cli_gentemp failed");
}
Пример #2
0
static int clamav_load_database()
{
    int ret    = 0;    /* return value */
    int reload = 0;

    /* libclamav initialization */
    if (CLAMAV_G(cl_initcalled) == 0){
		if((ret = cl_init(CL_INIT_DEFAULT)) != CL_SUCCESS) {
			php_error(E_WARNING, "cl_init: failed : error code %i (%s)\n", ret, cl_strerror(ret));
			return FAILURE;
		} else {
			CLAMAV_G(cl_initcalled) = 1;
		}
	}

	/* database reload */
    if (CLAMAV_G(dbstat.dir) != NULL && cl_statchkdir(&CLAMAV_G(dbstat)) == 1) {
		reload = 1;
        cl_statfree(&CLAMAV_G(dbstat));
	}

	/* load engine */
    if (!(CLAMAV_G(dbengine) = cl_engine_new())){
        php_error(E_WARNING, "Can’t create new engine\n");
        return FAILURE;
    }

	if (CLAMAV_G(dbpath) == NULL) CLAMAV_G(dbpath) = (char *) cl_retdbdir();

    /* database loading */
    if ((ret = cl_load(CLAMAV_G(dbpath), CLAMAV_G(dbengine), &CLAMAV_G(sig_num), CL_DB_STDOPT)) != CL_SUCCESS) {
        php_error(E_WARNING, "cl_load: failed : error code %i (%s)\n", ret, cl_strerror(ret));
        return FAILURE;
    }

	/* compile signature database */
    if ((ret = cl_engine_compile(CLAMAV_G(dbengine))) != CL_SUCCESS) {
        php_error(E_WARNING, "cl_engine_compile : error code %i (%s\n", ret, cl_strerror(ret));
        return FAILURE;
    }

    /* allocate cl_stat */
    if (!reload) memset(&CLAMAV_G(dbstat), 0, sizeof(struct cl_stat));

	/* database stats */
    if ((ret = cl_statinidir(CLAMAV_G(dbpath), &CLAMAV_G(dbstat))) != CL_SUCCESS) {
        php_error(E_WARNING, "cl_statinidir : error code %i (%s\n", ret, cl_strerror(ret));
        return FAILURE;
	}

    /* set engine parameters */
    cl_engine_set_num(CLAMAV_G(dbengine), CL_ENGINE_MAX_FILES, CLAMAV_G(maxfiles));
    cl_engine_set_num(CLAMAV_G(dbengine), CL_ENGINE_MAX_FILESIZE, CLAMAV_G(maxfilesize));
    cl_engine_set_num(CLAMAV_G(dbengine), CL_ENGINE_MAX_SCANSIZE, CLAMAV_G(maxscansize));
    cl_engine_set_num(CLAMAV_G(dbengine), CL_ENGINE_MAX_RECURSION, CLAMAV_G(maxreclevel));
    cl_engine_set_num(CLAMAV_G(dbengine), CL_ENGINE_KEEPTMP, CLAMAV_G(keeptmp));
    cl_engine_set_str(CLAMAV_G(dbengine), CL_ENGINE_TMPDIR, CLAMAV_G(tmpdir));

    return ret;
}
Пример #3
0
CWHandle CWInit(void)
{
    CWHandle cwh = malloc(sizeof(struct CWHandle_T));
    cl_init(CL_INIT_DEFAULT);
    cwh->engine = cl_engine_new();
    cwh->dboptions = CL_DB_CVDNOTMP;
    return cwh;
}
Пример #4
0
static void jstest_setup(void)
{
    cl_init(CL_INIT_DEFAULT);
    state = cli_js_init();
    fail_unless(!!state, "js init");
    tmpdir = cli_gentemp(NULL);
    fail_unless(!!tmpdir,"js tmp dir");
    fail_unless_fmt(mkdir(tmpdir, 0700) == 0, "tempdir mkdir of %s failed: %s", tmpdir, strerror(errno));
}
Пример #5
0
int main(int argc, const char *argv[])
{
  unsigned int width = 2048, height = 2048;

  float * __restrict__ input;
  float * __restrict__ output;

  struct Stats bw_buffer, bw_image2d;

  cl_init();

  bandwidth_cl_prepare();

  posix_memalign((void **) &input , 32, width * height * 4 * sizeof(float));
  posix_memalign((void **) &output, 32, width * height * 4 * sizeof(float));

  /* run usual */

  for(int k=0; k<NTRIES; k++)
    {
      TIME_START(bw_buffer)
        {
          CL_WRITE_BUFFER

          buffer_cl (input_tex,
                     output_tex,
                     width,
                     height);

          CL_READ_BUFFER
        }
      TIME_END(bw_buffer, k)
    }

  for(int k=0; k<NTRIES; k++)
    {
      TIME_START(bw_image2d)
        {
          CL_WRITE_IMAGE2D

          image2d_cl (input_tex,
                      output_tex,
                      width,
                      height);

          CL_READ_IMAGE2D
        }
      TIME_END(bw_image2d, k)
    }

  printf("[Results]\n");

  printf("- Global memory:  %lf GB/s\n", (width * height) / (1024 * 1024 * bw_buffer.min)  );
  printf("- Texture Memory: %lf GB/s\n", (width * height) / (1024 * 1024 * bw_image2d.min) );

  return 0;
}
Пример #6
0
int scanmanager()
{
	struct cl_engine *engine;
	char *file, cwd[1024];
	const char *filename;
	struct stat sb;
	cl_init();
	engine = cl_engine_new();
	return 0;
}
Пример #7
0
int main(int argc, char** argv) {
  Vector* v = (Vector*) malloc(sizeof(Vector));

  v_init(v, 0);

  int i;

  printf("[test-1] push 10 closures to bottom\n");
  for (i = 0; i < 10; i++) {
    Closure* c = (Closure*) malloc(sizeof(Closure));
    cl_init(c);
    c->level = i;
    v_push_closure(v, c);
  }
  v_print(v);

  printf("[test-2] push 10 closures next to their roots\n");
  for (i = 0; i < 10; i++) {
    Closure* c = (Closure*) malloc(sizeof(Closure));
    cl_init(c);
    c->level = i;
    v_push_closure(v, c);
  }
  v_print(v);

  printf("[test-3] pop 10 closures from top\n");
  for (i = 0; i < 10; i++) {
    Closure* c = v_pop_top(v);
    cl_free(c);
  }
  v_print(v);

  printf("[test-4] pop 10 closures from bot\n");
  for (i = 0; i < 10; i++) {
    Closure* c = v_pop_bottom(v);
    cl_free(c);
  }
  v_print(v);

  v_free(v);

  return 0;
}
Пример #8
0
VirusScan::VirusScan(TrayNotify *tn)
{
    numSignatures = 0;
    fTypes[0] = ".EXE";
    fTypes[1] = ".BAT";
    fTypes[2] = ".BIN";
    fTypes[3] = ".DLL";
    fTypes[4] = ".COM";
    fTypes[5] = ".INF";
    fTypes[6] = ".INI";
    fTypes[7] = ".PDF";
    fTypes[8] = ".DOC";
    fTypes[9] = ".DOCX";
    fTypes[10] = ".PPT";
    fTypes[11] = ".PPTX";
    fTypes[12] = ".SYS";
    fTypes[13] = ".VBS";

    /* Init AV engine */
    int res = cl_init(0);
    cl = cl_engine_new();
    if (res != CL_SUCCESS)
    {
        ErrorLog::logErrorToFile("*CRITICAL*", "Unable to initialize AV engine: ", (char*)cl_strerror(res));
        std::cout << cl_strerror(res);
        return;
    }

    res = cl_load(cl_retdbdir(), cl, &numSignatures, CL_DB_STDOPT);
    if (res != CL_SUCCESS)
    {
        ErrorLog::logErrorToFile("*CRITICAL*", "Unable to load AV engine signatures. Check for db folder?: ", (char*)cl_strerror(res));
        std::cout << cl_strerror(res);
        return;
    }

    res = cl_engine_compile(cl);
    if (res != CL_SUCCESS)
    {
        ErrorLog::logErrorToFile("*CRITICAL*", "Unable to compile AV engine rules: ", (char*)cl_strerror(res));
        std::cout << cl_strerror(res);
        return;
    }

    char msgStr[100];
    sprintf(msgStr, "ClamAV engine initialized. %d signatures loaded.", numSignatures);

    ErrorLog::logErrorToFile("*INFO*", msgStr);
    tn->sendMessage(msgStr, "ClamAV");
    tn->setHoverMessage("UsbNinja Daemon\nClamAV Loaded");

}
Пример #9
0
static void engine_setup(void)
{
    unsigned int sigs = 0;
    const char *hdb = OBJDIR"/clamav.hdb";

    init_testfiles();
    if (!inited)
	fail_unless(cl_init(CL_INIT_DEFAULT) == 0, "cl_init");
    inited = 1;
    g_engine = cl_engine_new();
    fail_unless(!!g_engine, "engine");
    fail_unless_fmt(cl_load(hdb, g_engine, &sigs, CL_DB_STDOPT) == 0, "cl_load %s", hdb);
    fail_unless(sigs == 1, "sigs");
    fail_unless(cl_engine_compile(g_engine) == 0, "cl_engine_compile");
}
Пример #10
0
int main(int argc, char **argv)
{
	(void)argc;
	(void)argv;

	if (init_events_init())
		return 1;

	start_logging();

	if (init_rand_seed())
		return 1;

	if (ensure_single_instance())
		return 1;

	if (conf_load())
		return 1;

	if (cl_init())
		return 1;

	if (start_task_queue())
		return 1;

	if (start_state_manager())
		return 1;

	if (start_debug_console())
		return 1;

	if (enqueue_task(main2, NULL))
		return 1;

	if (start_rpc_svc())
		return 1;

	return 0;
}
Пример #11
0
void Engine::InitOpenCL()
{
	cl_init(m_device, m_context, m_queue);
	std::string				clDC(clDreamcaster_Source[0]);
	cl::Program::Sources	clDCSrc = cl::Program::Sources(1, std::make_pair(clDC.c_str(), clDC.size() )  );

	cl::Program	clDCProg(m_context, clDCSrc);
	cl_int error;
	std::vector<cl::Device>	devices; devices.push_back(m_device);
	error = clDCProg.build(devices);//, clOptions);
	if (error != CL_SUCCESS) 
	{
		cl_int error2;
		std::string str = clDCProg.getBuildInfo<CL_PROGRAM_BUILD_LOG>(m_device, &error2);
		itk_clSafeCall( error2 );
		itk_clThrowBuildLog( str );
	}
	itk_clSafeCall(error);

	// create cl kernels
	K_raycast_batch = cl::Kernel(clDCProg, "raycast_batch", &error);
	itk_clSafeCall(error);
}
Пример #12
0
// executive entrypoint
int main(int argc, char** argv) {
  // init libclamav
  if (cl_init(CL_INIT_DEFAULT) != CL_SUCCESS) {
    printf("could not init clamAV.\n");
    return 1;
  }

  // load virus db and compile the av engine
  struct cl_engine* engine = cl_engine_new();
  const char* db_dir = cl_retdbdir();
  unsigned int signature_count = 0;
  printf("loading from database at %s\n", db_dir);
  if (cl_load(db_dir, engine, &signature_count, CL_DB_STDOPT) != CL_SUCCESS ||
    cl_engine_compile(engine) != CL_SUCCESS) {
    printf("failed to load db/compile AV engine.\n");
    return 1;
  }
  printf("%d virus signatures loaded.\n", signature_count);


  // create a socket to listen on
  int s = socket(AF_INET, SOCK_STREAM, 0);
  if (s == -1) {
    printf("could not create socket. reason: %s\n", strerror(errno));
    return 1;
  }

  // setup socket options such that the port can be reused quickly after
  // program termination
  struct sockaddr_in local_sockaddr;
  local_sockaddr.sin_family = AF_INET;
  local_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  local_sockaddr.sin_port = htons(PROXY_PORT);
  int one = 1;
  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
    printf("could not set socket options. reason: %s\n", strerror(errno));
    return 1;
  }

  // bind socket to the sockaddr_in structure
  if (bind(s, (struct sockaddr*) &local_sockaddr,
    sizeof(local_sockaddr)) == -1) {
    printf("could not bind to socket. reason: %s\n", strerror(errno));
  return 1;
  }

    // set socket to listening mode
  if (listen(s, QUEUE_SIZE) == -1) {
    printf("could not listen on socket. reason: %s\n", strerror(errno));
  }

  while (1) {
      // wait for a TCP connection. the accept() function will block until the
      // TCP handshake is complete.
    struct sockaddr_in remote_sockaddr;
    socklen_t address_len = sizeof(remote_sockaddr);
      int client; // client socket
      client = accept(s, (struct sockaddr*) &remote_sockaddr, &address_len);
      if (client == -1) continue;

      // setup thread parameters
      pthread_t tid;
      thread_params_t* params = (thread_params_t*)
      malloc(sizeof(thread_params_t));
      if (params == NULL) {
        printf("error allocating memory.\n");
        return 1;
      }
      params->socket_id = client;
      params->cl_engine = engine;

      // create the thread and pass the parameters over
      if (pthread_create(&tid, NULL, proxy_thread, params) != 0) {
        printf("error creating thread.\n");
        return 1;
      }
    }
 // free up scan engine (do this once you no longer need to scan files)
  cl_engine_free(engine);
  return 0;
}
Пример #13
0
int main(int argc, char *argv[])
{
  if (!vstr_init())
    errno = ENOMEM, err(EXIT_FAILURE, "%s", __func__);

  vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '$');
  vstr_sc_fmt_add_all(NULL);
  
  if (!(io_r = vstr_make_base(NULL))) /* used in cmd line */
    errno = ENOMEM, err(EXIT_FAILURE, "%s", __func__);
  if (!(io_w = vstr_make_base(NULL)))
    errno = ENOMEM, err(EXIT_FAILURE, "%s", __func__);
  
  if (!socket_poll_init(0, SOCKET_POLL_TYPE_MAP_DIRECT))
    errno = ENOMEM, err(EXIT_FAILURE, "%s", __func__);

  srand(getpid() ^ time(NULL)); /* doesn't need to be secure... just different
                                 * for different runs */
  
  cl_signals();
  
  cl_init();
  
  cl_cmd_line(argc, argv);

  cl_beg();
  
  while (io_ind_w && (io_w->len || evnt_waiting() || io_ind_r || io_r->len))
  {
    int ready = evnt_poll();
    struct timeval tv;
    
    if ((ready == -1) && (errno != EINTR))
      err(EXIT_FAILURE, "%s", __func__);
    if (ready == -1)
      continue;

    evnt_out_dbg3("1");
    ready = cl_scan_io_fds(ready);
    evnt_out_dbg3("2");
    evnt_scan_fds(ready, CL_MAX_WAIT_SEND);
    evnt_out_dbg3("3");
    evnt_scan_send_fds();
    evnt_out_dbg3("4");
    
    gettimeofday(&tv, NULL);
    timer_q_run_norm(&tv);

    evnt_out_dbg3("5");
    evnt_scan_send_fds();
    evnt_out_dbg3("6");
  }
  evnt_out_dbg3("E");

  vstr_free_base(io_r);
  vstr_free_base(io_w);

  timer_q_del_base(cl_timeout_base);
  timer_q_del_base(cl_timer_connect_base);
  
  evnt_close_all();
  
  vlg_free(vlg);
  
  vlg_exit();
  
  vstr_exit();
  
  MALLOC_CHECK_EMPTY();
  
  exit (EXIT_SUCCESS);
}
Пример #14
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;
}
Пример #15
0
int init_virusdb()
{
     int ret;
     unsigned int no = 0;
     virusdb = malloc(sizeof(struct virus_db));
     memset(virusdb, 0, sizeof(struct virus_db));
     if (!virusdb)
          return 0;
#ifdef HAVE_LIBCLAMAV_095
     if((ret = cl_init(CL_INIT_DEFAULT))) {
        ci_debug_printf(1, "!Can't initialize libclamav: %s\n", cl_strerror(ret));
        return 0;
    }

     if(!(virusdb->db = cl_engine_new())) {
	 ci_debug_printf(1, "Clamav DB load: Cannot create new clamav engine\n");
	 return 0;
     }

     if ((ret = cl_load(cl_retdbdir(), virusdb->db, &no, CL_DB_STDOPT))) {
          ci_debug_printf(1, "Clamav DB load: cl_load failed: %s\n",
                          cl_strerror(ret));
#elif defined(HAVE_LIBCLAMAV_09X)
     if ((ret = cl_load(cl_retdbdir(), &(virusdb->db), &no, CL_DB_STDOPT))) {
          ci_debug_printf(1, "Clamav DB load: cl_load failed: %s\n",
                          cl_strerror(ret));
#else
     if ((ret = cl_loaddbdir(cl_retdbdir(), &(virusdb->db), &no))) {
          ci_debug_printf(1, "cl_loaddbdir: %s\n", cl_perror(ret));
#endif
          return 0;
     }
#ifdef HAVE_LIBCLAMAV_095
     if ((ret = cl_engine_compile(virusdb->db))) {
#else
     if ((ret = cl_build(virusdb->db))) {
#endif
          ci_debug_printf(1, "Database initialization error: %s\n",
                          cl_strerror(ret));
#ifdef HAVE_LIBCLAMAV_095
	  cl_engine_free(virusdb->db);
#else
          cl_free(virusdb->db);
#endif
          free(virusdb);
          virusdb = NULL;
          return 0;
     }
     ci_thread_mutex_init(&db_mutex);
     virusdb->refcount = 1;
     old_virusdb = NULL;
     return 1;
}

/*
  Instead of using struct virus_db and refcount's someone can use the cl_dup function
  of clamav library, but it is  undocumented so I did not use it.
  The following implementation we are starting to reload clamav db while threads are 
  scanning for virus but we are not allow any child to start a new scan until we are 
  loading DB.
*/
/*#define DB_NO_FULL_LOCK 1*/
#undef DB_NO_FULL_LOCK
int reload_virusdb()
{
     struct virus_db *vdb = NULL;
     int ret;
     unsigned int no = 0;
     ci_thread_mutex_lock(&db_mutex);
     if (old_virusdb) {
          ci_debug_printf(1, "Clamav DB reload pending, cancelling.\n");
          ci_thread_mutex_unlock(&db_mutex);
          return 0;
     }
#ifdef DB_NO_FULL_LOCK
     ci_thread_mutex_unlock(&db_mutex);
#endif
     vdb = malloc(sizeof(struct virus_db));
     if (!vdb)
          return 0;
     memset(vdb, 0, sizeof(struct virus_db));
     ci_debug_printf(9, "db_reload going to load db\n");
#ifdef HAVE_LIBCLAMAV_095
     if(!(vdb->db = cl_engine_new())) {
	 ci_debug_printf(1, "Clamav DB load: Cannot create new clamav engine\n");
	 return 0;
     }
     if ((ret = cl_load(cl_retdbdir(), vdb->db, &no, CL_DB_STDOPT))) {
          ci_debug_printf(1, "Clamav DB reload: cl_load failed: %s\n",
                          cl_strerror(ret));
#elif defined(HAVE_LIBCLAMAV_09X)
     if ((ret = cl_load(cl_retdbdir(), &(vdb->db), &no, CL_DB_STDOPT))) {
          ci_debug_printf(1, "Clamav DB reload: cl_load failed: %s\n",
                          cl_strerror(ret));
#else
     if ((ret = cl_loaddbdir(cl_retdbdir(), &(vdb->db), &no))) {
          ci_debug_printf(1, "Clamav DB reload: cl_loaddbdir failed: %s\n",
                          cl_perror(ret));
#endif
          return 0;
     }
     ci_debug_printf(9, "loaded. Going to build\n");
#ifdef HAVE_LIBCLAMAV_095
     if ((ret = cl_engine_compile(vdb->db))) {
#else
     if ((ret = cl_build(vdb->db))) {
#endif
          ci_debug_printf(1,
                          "Clamav DB reload: Database initialization error: %s\n",
                          cl_strerror(ret));
#ifdef HAVE_LIBCLAMAV_095
	  cl_engine_free(vdb->db);
#else
          cl_free(vdb->db);
#endif
          free(vdb);
          vdb = NULL;
#ifdef DB_NO_FULL_LOCK
          /*no lock needed */
#else
          ci_thread_mutex_unlock(&db_mutex);
#endif
          return 0;
     }
     ci_debug_printf(9, "Done releasing.....\n");
#ifdef DB_NO_FULL_LOCK
     ci_thread_mutex_lock(&db_mutex);
#endif
     old_virusdb = virusdb;
     old_virusdb->refcount--;
     ci_debug_printf(9, "Old VirusDB refcount:%d\n", old_virusdb->refcount);
     if (old_virusdb->refcount <= 0) {
#ifdef HAVE_LIBCLAMAV_095
	  cl_engine_free(old_virusdb->db);
#else
          cl_free(old_virusdb->db);
#endif
          free(old_virusdb);
          old_virusdb = NULL;
     }
     virusdb = vdb;
     virusdb->refcount = 1;
     ci_thread_mutex_unlock(&db_mutex);
     return 1;
}

CL_ENGINE *get_virusdb()
{
     struct virus_db *vdb;
     ci_thread_mutex_lock(&db_mutex);
     vdb = virusdb;
     vdb->refcount++;
     ci_thread_mutex_unlock(&db_mutex);
     return vdb->db;
}

void release_virusdb(CL_ENGINE * db)
{
     ci_thread_mutex_lock(&db_mutex);
     if (virusdb && db == virusdb->db)
          virusdb->refcount--;
     else if (old_virusdb && (db == old_virusdb->db)) {
          old_virusdb->refcount--;
          ci_debug_printf(9, "Old VirusDB refcount: %d\n",
                          old_virusdb->refcount);
          if (old_virusdb->refcount <= 0) {
#ifdef HAVE_LIBCLAMAV_095
	      cl_engine_free(old_virusdb->db);
#else
               cl_free(old_virusdb->db);
#endif
               free(old_virusdb);
               old_virusdb = NULL;
          }
     }
     else {
          ci_debug_printf(1,
                          "BUG in srv_clamav service! please contact the author\n");
     }
     ci_thread_mutex_unlock(&db_mutex);
}

void destroy_virusdb()
{
     if (virusdb) {
#ifdef HAVE_LIBCLAMAV_095
	  cl_engine_free(virusdb->db);
#else
          cl_free(virusdb->db);
#endif
          free(virusdb);
          virusdb = NULL;
     }
     if (old_virusdb) {
#ifdef HAVE_LIBCLAMAV_095
	  cl_engine_free(old_virusdb->db);
#else
          cl_free(old_virusdb->db);
#endif
          free(old_virusdb);
          old_virusdb = NULL;
     }
}

void set_istag(ci_service_xdata_t * srv_xdata)
{
     char istag[SERVICE_ISTAG_SIZE + 1];
     char str_version[64];
     char *daily_path;
     char *s1, *s2;
     struct cl_cvd *d1;
     int version = 0, cfg_version = 0;
     struct stat daily_stat;

     /*instead of 128 should be strlen("/daily.inc/daily.info")+1*/
     daily_path = malloc(strlen(cl_retdbdir()) + 128);
     if (!daily_path)           /*???????? */
          return;
     sprintf(daily_path, "%s/daily.cvd", cl_retdbdir());
     
     if(stat(daily_path,&daily_stat) != 0){
	 /* if the clamav_lib_path/daily.cvd does not exists
	  */
	 sprintf(daily_path, "%s/daily.cld", cl_retdbdir());
     
	 if(stat(daily_path,&daily_stat) != 0){
	     /*
	       else try to use the clamav_lib_path/daily.inc/daly.info file instead" */
	     sprintf(daily_path, "%s/daily.inc/daily.info", cl_retdbdir());
	 }
     }

     if ((d1 = cl_cvdhead(daily_path))) {
          version = d1->version;
          free(d1);
     }
     free(daily_path);

     s1 = (char *) cl_retver();
     s2 = str_version;
     while (*s1 != '\0' && s2 - str_version < 64) {
          if (*s1 != '.') {
               *s2 = *s1;
               s2++;
          }
          s1++;
     }
     *s2 = '\0';
     /*cfg_version maybe must set by user when he is changing 
        the srv_clamav configuration.... */
     snprintf(istag, SERVICE_ISTAG_SIZE, "-%.3d-%s-%d%d",
              cfg_version, str_version, cl_retflevel(), version);
     istag[SERVICE_ISTAG_SIZE] = '\0';
     ci_service_set_istag(srv_xdata, istag);
}
Пример #16
0
int main(int argc, char **argv)
{
        static struct cl_engine *engine = NULL;
	const struct optstruct *opt;
#ifndef	_WIN32
        struct passwd *user = NULL;
	struct sigaction sa;
	struct rlimit rlim;
#endif
	time_t currtime;
	const char *dbdir, *cfgfile;
	char *pua_cats = NULL, *pt;
	int ret, tcpsock = 0, localsock = 0, i, min_port, max_port;
	unsigned int sigs = 0;
	int lsockets[2], nlsockets = 0;
	unsigned int dboptions = 0;
#ifdef C_LINUX
	STATBUF sb;
#endif

    if(check_flevel())
	exit(1);

#ifndef _WIN32
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = SIG_IGN;
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGUSR2, &sa, NULL);
#endif

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

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

    if(optget(opts, "debug")->enabled) {
#if defined(C_LINUX)
	/* [email protected]: create a dump if needed */
	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
	if(setrlimit(RLIMIT_CORE, &rlim) < 0)
	    perror("setrlimit");
#endif
	debug_mode = 1;
    }

    /* parse the config file */
    cfgfile = optget(opts, "config-file")->strarg;
    pt = strdup(cfgfile);
    if((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) {
	fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", pt);
	free(pt);
	return 1;
    }
    free(pt);

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

    /* drop privileges */
#ifndef _WIN32
    if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
	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 in %s\n", cfgfile);
	    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;
	}
    }
#endif

    /* initialize logger */
    logg_lock = !optget(opts, "LogFileUnlock")->enabled;
    logg_time = optget(opts, "LogTime")->enabled;
    logok = optget(opts, "LogClean")->enabled;
    logg_size = optget(opts, "LogFileMaxSize")->numarg;
    logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled;
    if (logg_size)
        logg_rotate = optget(opts, "LogRotate")->enabled;
    mprintf_send_timeout = optget(opts, "SendBufTimeout")->numarg;

    do { /* logger initialized */

    if((opt = optget(opts, "LogFile"))->enabled) {
	char timestr[32];
	logg_file = opt->strarg;
	if(!cli_is_abspath(logg_file)) {
	    fprintf(stderr, "ERROR: LogFile requires full path.\n");
	    ret = 1;
	    break;
	}
	time(&currtime);
	if(logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) {
	    fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
	    ret = 1;
	    break;
	}
    } else
	logg_file = NULL;

    if (optget(opts,"DevLiblog")->enabled)
	cl_set_clcb_msg(msg_callback);
    if((ret = cl_init(CL_INIT_DEFAULT))) {
	logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
	ret = 1;
	break;
    }

    if(optget(opts, "Debug")->enabled) /* enable debug messages in libclamav */ {
	cl_debug();
	logg_verbose = 2;
    }

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

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

	openlog("clamd", LOG_PID, fac);
	logg_syslog = 1;
    }
#endif

#ifdef C_LINUX
    procdev = 0;
    if(CLAMSTAT("/proc", &sb) != -1 && !sb.st_size)
	procdev = sb.st_dev;
#endif

    /* check socket type */

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

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

    if(!tcpsock && !localsock) {
	logg("!Please define server type (local and/or TCP).\n");
	ret = 1;
	break;
    }

    logg("#clamd daemon %s (OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE")\n", get_version());

#ifndef _WIN32
    if(user)
	logg("#Running as user %s (UID %u, GID %u)\n", user->pw_name, user->pw_uid, user->pw_gid);
#endif

#if defined(RLIMIT_DATA) && defined(C_BSD)
    if (getrlimit(RLIMIT_DATA, &rlim) == 0) {
       /* bb #1941.
        * On 32-bit FreeBSD if you set ulimit -d to >2GB then mmap() will fail
        * too soon (after ~120 MB).
        * Set limit lower than 2G if on 32-bit */
       uint64_t lim = rlim.rlim_cur;
       if (sizeof(void*) == 4 &&
           lim > (1ULL << 31)) {
           rlim.rlim_cur = 1ULL << 31;
           if (setrlimit(RLIMIT_DATA, &rlim) < 0)
               logg("!setrlimit(RLIMIT_DATA) failed: %s\n", strerror(errno));
           else
               logg("Running on 32-bit system, and RLIMIT_DATA > 2GB, lowering to 2GB!\n");
       }
    }
#endif


    if(logg_size)
	logg("#Log file size limited to %u bytes.\n", logg_size);
    else
	logg("#Log file size limit disabled.\n");

    min_port = optget(opts, "StreamMinPort")->numarg;
    max_port = optget(opts, "StreamMaxPort")->numarg;
    if (min_port < 1024 || min_port > max_port || max_port > 65535) {
	logg("!Invalid StreamMinPort/StreamMaxPort: %d, %d\n", min_port, max_port);
	ret = 1;
	break;
    }

    if(!(engine = cl_engine_new())) {
	logg("!Can't initialize antivirus engine\n");
	ret = 1;
	break;
    }

    /* load the database(s) */
    dbdir = optget(opts, "DatabaseDirectory")->strarg;
    logg("#Reading databases from %s\n", dbdir);

    if(optget(opts, "DetectPUA")->enabled) {
	dboptions |= CL_DB_PUA;

	if((opt = optget(opts, "ExcludePUA"))->enabled) {
	    dboptions |= CL_DB_PUA_EXCLUDE;
	    i = 0;
	    logg("#Excluded PUA categories:");
	    while(opt) {
		if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
		    logg("!Can't allocate memory for pua_cats\n");
		    cl_engine_free(engine);
		    ret = 1;
		    break;
		}
		logg("# %s", opt->strarg);
		sprintf(pua_cats + i, ".%s", opt->strarg);
		i += strlen(opt->strarg) + 1;
		pua_cats[i] = 0;
		opt = opt->nextarg;
	    }
	    if (ret)
		break;
	    logg("#\n");
	    pua_cats[i] = '.';
	    pua_cats[i + 1] = 0;
	}

	if((opt = optget(opts, "IncludePUA"))->enabled) {
	    if(pua_cats) {
		logg("!ExcludePUA and IncludePUA cannot be used at the same time\n");
		free(pua_cats);
		ret = 1;
		break;
	    }
	    dboptions |= CL_DB_PUA_INCLUDE;
	    i = 0;
	    logg("#Included PUA categories:");
	    while(opt) {
		if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
		    logg("!Can't allocate memory for pua_cats\n");
		    ret = 1;
		    break;
		}
		logg("# %s", opt->strarg);
		sprintf(pua_cats + i, ".%s", opt->strarg);
		i += strlen(opt->strarg) + 1;
		pua_cats[i] = 0;
		opt = opt->nextarg;
	    }
	    if (ret)
		break;
	    logg("#\n");
	    pua_cats[i] = '.';
	    pua_cats[i + 1] = 0;
	}

	if(pua_cats) {
	    if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) {
		logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret));
		free(pua_cats);
		ret = 1;
		break;
	    }
	    free(pua_cats);
	}
    } else {
	logg("#Not loading PUA signatures.\n");
    }

    if(optget(opts, "OfficialDatabaseOnly")->enabled) {
	dboptions |= CL_DB_OFFICIAL_ONLY;
	logg("#Only loading official signatures.\n");
    }

    /* set the temporary dir */
    if((opt = optget(opts, "TemporaryDirectory"))->enabled) {
	if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) {
	    logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret));
	    ret = 1;
	    break;
	}
    }

    cl_engine_set_clcb_hash(engine, hash_callback);
    detstats_clear();

    if(optget(opts, "LeaveTemporaryFiles")->enabled)
	cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1);

    if(optget(opts, "PhishingSignatures")->enabled)
	dboptions |= CL_DB_PHISHING;
    else
	logg("#Not loading phishing signatures.\n");

    if(optget(opts,"Bytecode")->enabled) {
	dboptions |= CL_DB_BYTECODE;
	if((opt = optget(opts,"BytecodeSecurity"))->enabled) {
	    enum bytecode_security s;
	    if (!strcmp(opt->strarg, "TrustSigned")) {
		s = CL_BYTECODE_TRUST_SIGNED;
		logg("#Bytecode: Security mode set to \"TrustSigned\".\n");
	    } else if (!strcmp(opt->strarg, "Paranoid")) {
		s = CL_BYTECODE_TRUST_NOTHING;
		logg("#Bytecode: Security mode set to \"Paranoid\".\n");
	    } else {
		logg("!Unable to parse bytecode security setting:%s\n",
		    opt->strarg);
		ret = 1;
		break;
	    }
	    if ((ret = cl_engine_set_num(engine, CL_ENGINE_BYTECODE_SECURITY, s))) {
		logg("^Invalid bytecode security setting %s: %s\n", opt->strarg, cl_strerror(ret));
		ret = 1;
		break;
	    }
	}
	if((opt = optget(opts,"BytecodeUnsigned"))->enabled) {
	    dboptions |= CL_DB_BYTECODE_UNSIGNED;
	    logg("#Bytecode: Enabled support for unsigned bytecode.\n");
	}
	if((opt = optget(opts,"BytecodeMode"))->enabled) {
	    enum bytecode_mode mode;
	    if (!strcmp(opt->strarg, "ForceJIT"))
		mode = CL_BYTECODE_MODE_JIT;
	    else if(!strcmp(opt->strarg, "ForceInterpreter"))
		mode = CL_BYTECODE_MODE_INTERPRETER;
	    else if(!strcmp(opt->strarg, "Test"))
		mode = CL_BYTECODE_MODE_TEST;
	    else
		mode = CL_BYTECODE_MODE_AUTO;
	    cl_engine_set_num(engine, CL_ENGINE_BYTECODE_MODE, mode);
	}
	if((opt = optget(opts,"BytecodeTimeout"))->enabled) {
	    cl_engine_set_num(engine, CL_ENGINE_BYTECODE_TIMEOUT, opt->numarg);
	}
    } else
	logg("#Bytecode support disabled.\n");

    if(optget(opts,"PhishingScanURLs")->enabled)
	dboptions |= CL_DB_PHISHING_URLS;
    else
	logg("#Disabling URL based phishing detection.\n");

    if(optget(opts,"DevACOnly")->enabled) {
	logg("#Only using the A-C matcher.\n");
	cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1);
    }

    if((opt = optget(opts, "DevACDepth"))->enabled) {
        cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, opt->numarg);
	logg("#Max A-C depth set to %u\n", (unsigned int) opt->numarg);
    }

    if((ret = cl_load(dbdir, engine, &sigs, dboptions))) {
	logg("!%s\n", cl_strerror(ret));
	ret = 1;
	break;
    }

    if (optget(opts, "DisableCertCheck")->enabled)
        engine->dconf->pe |= PE_CONF_DISABLECERT;

    logg("#Loaded %u signatures.\n", sigs);
    if((ret = cl_engine_compile(engine)) != 0) {
	logg("!Database initialization error: %s\n", cl_strerror(ret));
	ret = 1;
	break;
    }

    if(tcpsock) {
	if ((lsockets[nlsockets] = tcpserver(opts)) == -1) {
	    ret = 1;
	    break;
	}
	nlsockets++;
    }
#ifndef _WIN32
    if(localsock) {
	mode_t sock_mode, umsk = umask(0777); /* socket is created with 000 to avoid races */
	if ((lsockets[nlsockets] = localserver(opts)) == -1) {
	    ret = 1;
	    umask(umsk);
	    break;
	}
	umask(umsk); /* restore umask */
	if(optget(opts, "LocalSocketGroup")->enabled) {
	    char *gname = optget(opts, "LocalSocketGroup")->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);
		    ret = 1;
		    break;
		}
		sock_gid = pgrp->gr_gid;
	    }
	    if(chown(optget(opts, "LocalSocket")->strarg, -1, sock_gid)) {
		logg("!Failed to change socket ownership to group %s\n", gname);
		ret = 1;
		break;
	    }
	}
	if(optget(opts, "LocalSocketMode")->enabled) {
	    char *end;
	    sock_mode = strtol(optget(opts, "LocalSocketMode")->strarg, &end, 8);
	    if(*end) {
		logg("!Invalid LocalSocketMode %s\n", optget(opts, "LocalSocketMode")->strarg);
		ret = 1;
		break;
	    }
	} else
	    sock_mode = 0777 /* & ~umsk*/; /* conservative default: umask was 0 in clamd < 0.96 */

	if(chmod(optget(opts, "LocalSocket")->strarg, sock_mode & 0666)) {
	    logg("!Cannot set socket permission to %s\n", optget(opts, "LocalSocketMode")->strarg);
	    ret = 1;
	    break;
	}

	nlsockets++;
    }

    /* fork into background */
    if(!optget(opts, "Foreground")->enabled) {
#ifdef C_BSD	    
	/* workaround for OpenBSD bug, see https://wwws.clamav.net/bugzilla/show_bug.cgi?id=885 */
	for(ret=0;ret<nlsockets;ret++) {
		if (fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) | O_NONBLOCK) == -1) {
            logg("!fcntl for lsockets[] failed\n");
            close(lsockets[ret]);
            ret = 1;
            break;
        }
	}
#endif
	gengine = engine;
	atexit(free_engine);
	if(daemonize() == -1) {
	    logg("!daemonize() failed: %s\n", strerror(errno));
	    ret = 1;
	    break;
	}
	gengine = NULL;
#ifdef C_BSD
	for(ret=0;ret<nlsockets;ret++) {
		if (fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) & ~O_NONBLOCK) == -1) {
            logg("!fcntl for lsockets[] failed\n");
            close(lsockets[ret]);
            ret = 1;
            break;
        }
	}
#endif
	if(!debug_mode)
	    if(chdir("/") == -1)
		logg("^Can't change current working directory to root\n");

    } else
        foreground = 1;
#endif

    ret = recvloop_th(lsockets, nlsockets, engine, dboptions, opts);

    } while (0);

    logg("*Closing the main socket%s.\n", (nlsockets > 1) ? "s" : "");

    for (i = 0; i < nlsockets; i++) {
	closesocket(lsockets[i]);
    }

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

    logg_close();
    optfree(opts);

    return ret;
}
Пример #17
0
/*
 * main --
 *	This is the main loop for the standalone curses editor.
 */
int
main(int argc, char **argv)
{
	static int reenter;
	CL_PRIVATE *clp;
	GS *gp;
	WIN *wp;
	size_t rows, cols;
	int rval;
	char **p_av, **t_av;
	const char *ttype;

	/* If loaded at 0 and jumping through a NULL pointer, stop. */
	if (reenter++)
		abort();

	/* Create and initialize the global structure. */
	__global_list = gp = gs_init(argv[0]);

	/*
	 * Strip out any arguments that vi isn't going to understand.  There's
	 * no way to portably call getopt twice, so arguments parsed here must
	 * be removed from the argument list.
	 */
	for (p_av = t_av = argv;;) {
		if (*t_av == NULL) {
			*p_av = NULL;
			break;
		}
		if (!strcmp(*t_av, "--")) {
			while ((*p_av++ = *t_av++) != NULL);
			break;
		}
		*p_av++ = *t_av++;
	}

	/* Create new window */
	wp = gs_new_win(gp);
		
	/* Create and initialize the CL_PRIVATE structure. */
	clp = cl_init(wp);

	/*
	 * Initialize the terminal information.
	 *
	 * We have to know what terminal it is from the start, since we may
	 * have to use termcap/terminfo to find out how big the screen is.
	 */
	if ((ttype = getenv("TERM")) == NULL) {
		if (isatty(STDIN_FILENO))
			fprintf(stderr, "%s: warning: TERM is not set\n",
			    gp->progname);
		ttype = "unknown";
	}
	term_init(gp->progname, ttype);

	/* Add the terminal type to the global structure. */
	if ((OG_D_STR(gp, GO_TERM) =
	    OG_STR(gp, GO_TERM) = strdup(ttype)) == NULL)
		perr(gp->progname, NULL);

	/* Figure out how big the screen is. */
	if (cl_ssize(NULL, 0, &rows, &cols, NULL))
		exit (1);

	/* Add the rows and columns to the global structure. */
	OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = rows;
	OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = cols;

	/* Ex wants stdout to be buffered. */
	(void)setvbuf(stdout, NULL, _IOFBF, 0);

	/* Start catching signals. */
	if (sig_init(gp, NULL))
		exit (1);

	/* Run ex/vi. */
	rval = editor(wp, argc, argv);

	/* Clean out the global structure. */
	gs_end(gp);

	/* Clean up signals. */
	sig_end(gp);

	/* Clean up the terminal. */
	(void)cl_quit(gp);

	/*
	 * XXX
	 * Reset the O_MESG option.
	 */
	if (clp->tgw != TGW_UNKNOWN)
		(void)cl_omesg(NULL, clp, clp->tgw == TGW_SET);

	/*
	 * XXX
	 * Reset the X11 xterm icon/window name.
	 */
	if (F_ISSET(clp, CL_RENAME))
		cl_setname(gp, clp->oname);

	/* If a killer signal arrived, pretend we just got it. */
	if (clp->killersig) {
		(void)signal(clp->killersig, SIG_DFL);
		(void)kill(getpid(), clp->killersig);
		/* NOTREACHED */
	}

	/* Free the global and CL private areas. */
#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
	cl_end(clp);
	free(gp);
#endif

	exit (rval);
}
Пример #18
0
/* FIXME: No it doesn't!  pcAddress is not ever referenced in this
 * function.
 * CreepLord: Fixed much better way (will accept dns hostnames)
 */
int dbs_server_init(void)
{
	int sd;
	struct sockaddr_in sinInterface;
	int val;
	t_addr	* servaddr;
		
	dbs_server_connection_list=list_create();

	if (d2dbs_d2ladder_init()==-1)
	{
		eventlog(eventlog_level_error,__FUNCTION__,"d2ladder_init() failed");
		return -1;
	}

	if (cl_init(DEFAULT_HASHTBL_LEN, DEFAULT_GS_MAX)==-1)
	{
		eventlog(eventlog_level_error,__FUNCTION__,"cl_init() failed");
		return -1;
	}

	if (psock_init()<0)
	{
		eventlog(eventlog_level_error,__FUNCTION__,"psock_init() failed");
		return -1;
	}
	
	sd = psock_socket(PSOCK_PF_INET, PSOCK_SOCK_STREAM, PSOCK_IPPROTO_TCP);
	if (sd==-1)
	{
		eventlog(eventlog_level_error,__FUNCTION__,"psock_socket() failed : %s",strerror(psock_errno()));
		return -1;
	}

	val = 1;
	if (psock_setsockopt(sd, PSOCK_SOL_SOCKET, PSOCK_SO_REUSEADDR, &val, sizeof(val)) < 0)
	{
		eventlog(eventlog_level_error,__FUNCTION__,"psock_setsockopt() failed : %s",strerror(psock_errno()));
	}

        if (!(servaddr=addr_create_str(d2dbs_prefs_get_servaddrs(),INADDR_ANY,DEFAULT_LISTEN_PORT)))
	{
		eventlog(eventlog_level_error,__FUNCTION__,"could not get servaddr");
		return -1;
	}
	
	sinInterface.sin_family = PSOCK_AF_INET;
	sinInterface.sin_addr.s_addr = htonl(addr_get_ip(servaddr));
	sinInterface.sin_port = htons(addr_get_port(servaddr));
	if (psock_bind(sd, (struct sockaddr*)&sinInterface, (psock_t_socklen)sizeof(struct sockaddr_in)) < 0)
	{
		eventlog(eventlog_level_error,__FUNCTION__,"psock_bind() failed : %s",strerror(psock_errno()));
		return -1;
	}
	if (psock_listen(sd, LISTEN_QUEUE) < 0)
	{
		eventlog(eventlog_level_error,__FUNCTION__,"psock_listen() failed : %s",strerror(psock_errno()));
		return -1;
	}
	addr_destroy(servaddr);
	return sd;
}
Пример #19
0
/*
 * main --
 *	This is the main loop for the standalone curses editor.
 */
int
main(int argc, char *argv[])
{
	CL_PRIVATE *clp;
	GS *gp;
	size_t rows, cols;
	int rval;
	char *ttype;

	/* Create and initialize the global structure. */
	__global_list = gp = gs_init();

	/* Create and initialize the CL_PRIVATE structure. */
	clp = cl_init(gp);

	/*
	 * Initialize the terminal information.
	 *
	 * We have to know what terminal it is from the start, since we may
	 * have to use termcap/terminfo to find out how big the screen is.
	 */
	if ((ttype = getenv("TERM")) == NULL)
		ttype = "unknown";
	term_init(ttype);

	/* Add the terminal type to the global structure. */
	if ((OG_D_STR(gp, GO_TERM) =
	    OG_STR(gp, GO_TERM) = strdup(ttype)) == NULL)
		err(1, NULL);

	/* Figure out how big the screen is. */
	if (cl_ssize(NULL, 0, &rows, &cols, NULL))
		exit (1);

	/* Add the rows and columns to the global structure. */
	OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = rows;
	OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = cols;

	/* Ex wants stdout to be buffered. */
	(void)setvbuf(stdout, NULL, _IOFBF, 0);

	/* Start catching signals. */
	if (sig_init(gp, NULL))
		exit (1);

	/* Run ex/vi. */
	rval = editor(gp, argc, argv);

	/* Clean up signals. */
	sig_end(gp);

	/* Clean up the terminal. */
	(void)cl_quit(gp);

	/*
	 * XXX
	 * Reset the O_MESG option.
	 */
	if (clp->tgw != TGW_UNKNOWN)
		(void)cl_omesg(NULL, clp, clp->tgw == TGW_SET);

	/*
	 * XXX
	 * Reset the X11 xterm icon/window name.
	 */
	if (F_ISSET(clp, CL_RENAME)) {
		(void)printf(XTERM_RENAME, ttype);
		(void)fflush(stdout);
	}

	/* If a killer signal arrived, pretend we just got it. */
	if (clp->killersig) {
		(void)signal(clp->killersig, SIG_DFL);
		(void)kill(getpid(), clp->killersig);
		/* NOTREACHED */
	}

	/* Free the global and CL private areas. */
#if defined(DEBUG) || defined(PURIFY)
	free(clp);
	free(gp);
#endif

	exit (rval);
}
Пример #20
0
BOOL init() {
    char whereami[PATH_MAX], *slash;
    int ret;

    ret = GetModuleFileName((HINSTANCE)&__ImageBase, whereami, sizeof(whereami) -1);
    if(!ret || ret == sizeof(whereami) -1) {
	printf("ERROR: GetModuleFileName failed\n");
	return FALSE;
    }

    whereami[sizeof(whereami)-1] = '\0';
    slash = strrchr(whereami, '\\');
    if(!slash) {
	printf("ERROR: No slash found in path %s\n", whereami);
	return FALSE;
    }

    slash++;
    *slash='\0';
    SetDllDirectory(whereami);
    __try {
	cl_set_clcb_msg(msg_callback);
	ret = cl_init(CL_INIT_DEFAULT);
    }
    __except(EXCEPTION_EXECUTE_HANDLER) { ret = -1; }

    SetDllDirectory(NULL);
    if(ret) {
	printf("ERROR: Failed cl_init() returned %d\n", ret);
	return FALSE;
    }

    strncpy(slash, "clamav_log_verbose", sizeof(whereami) - (slash - whereami));
    whereami[sizeof(whereami)-1] = '\0';
    logg_verbose = access(whereami, 0) == -1 ? 0 : 1;

    strncpy(slash, "clamav.log", sizeof(whereami) - (slash - whereami));
    whereami[sizeof(whereami)-1] = '\0';
    logg_nowarn = 0;
    logg_lock = 0;
    logg_time = 1;
    // bb #5659: force log rotation at 100 MB
    logg_size = 104857600;
    logg_rotate = 1;
    logg_file = strdup(whereami);
    if(!logg_file) {
	printf("ERROR: failed to duplicate log filename\n");
	return FALSE;
    }
    strncpy(slash, "clamav.old.log", sizeof(whereami) - (slash - whereami));
    whereami[sizeof(whereami)-1] = '\0';
    if(!MoveFileEx(logg_file, whereami, MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH))
	DeleteFile(logg_file);
    logg_noflush = 1;/* only flush on errors and warnings */
    if(logg("ClamAV core initialized (version %s, flevel %d)\n", cl_retver(), cl_retflevel())<0) {
	printf("ERROR: logg failed\n");
	return FALSE;
    }

    if(init_errors()) {
	logg("!Failed to initialize errors\n");
	return FALSE;
    }
    ret = interface_setup();
    logg("ClamAV module initialization %s\n", ret == TRUE ? "succeeded" : "failed! Aborting...");
    return ret;
}
Пример #21
0
int main(int argc, char **argv)
{
    int fd, ret;
    unsigned long int size = 0;
    unsigned int sigs = 0;
    long double mb;
    const char *virname;
    struct cl_engine *engine;

    if(argc != 2) {
        printf("Usage: %s file\n", argv[0]);
        return 2;
    }

    if((fd = open(argv[1], O_RDONLY)) == -1) {
        printf("Can't open file %s\n", argv[1]);
        return 2;
    }

    if((ret = cl_init(CL_INIT_DEFAULT)) != CL_SUCCESS) {
        printf("Can't initialize libclamav: %s\n", cl_strerror(ret));
        return 2;
    }

    if(!(engine = cl_engine_new())) {
        printf("Can't create new engine\n");
        return 2;
    }

    /* load all available databases from default directory */
    if((ret = cl_load(cl_retdbdir(), engine, &sigs, CL_DB_STDOPT)) != CL_SUCCESS) {
        printf("cl_load: %s\n", cl_strerror(ret));
        close(fd);
        cl_engine_free(engine);
        return 2;
    }

    printf("Loaded %u signatures.\n", sigs);

    /* build engine */
    if((ret = cl_engine_compile(engine)) != CL_SUCCESS) {
        printf("Database initialization error: %s\n", cl_strerror(ret));;
        cl_engine_free(engine);
        close(fd);
        return 2;
    }

    /* scan file descriptor */
    if((ret = cl_scandesc(fd, &virname, &size, engine, CL_SCAN_STDOPT)) == CL_VIRUS) {
        printf("Virus detected: %s\n", virname);
    } else {
        if(ret == CL_CLEAN) {
            printf("No virus detected.\n");
        } else {
            printf("Error: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            close(fd);
            return 2;
        }
    }
    close(fd);

    /* free memory */
    cl_engine_free(engine);

    /* calculate size of scanned data */
    mb = size * (CL_COUNT_PRECISION / 1024) / 1024.0;
    printf("Data scanned: %2.2Lf MB\n", mb);

    return ret == CL_VIRUS ? 1 : 0;
}
Пример #22
0
/*
 * main --
 *	This is the main loop for the standalone curses editor.
 */
int
main(int argc, char *argv[])
{
	static int reenter;
	CL_PRIVATE *clp;
	GS *gp;
	size_t rows, cols;
	int rval;
	char *ttype;
#ifdef RUNNING_IP
	char *ip_arg;
	char **p_av, **t_av;
#endif

	/* If loaded at 0 and jumping through a NULL pointer, stop. */
	if (reenter++)
		abort();

	/* Create and initialize the global structure. */
	__global_list = gp = gs_init(argv[0]);

	/*
	 * Strip out any arguments that vi isn't going to understand.  There's
	 * no way to portably call getopt twice, so arguments parsed here must
	 * be removed from the argument list.
	 */
#ifdef RUNNING_IP
	ip_arg = NULL;
	for (p_av = t_av = argv;;) {
		if (*t_av == NULL) {
			*p_av = NULL;
			break;
		}
		if (!strcmp(*t_av, "--")) {
			while ((*p_av++ = *t_av++) != NULL);
			break;
		}
		if (!memcmp(*t_av, "-I", sizeof("-I") - 1)) {
			if (t_av[0][2] != '\0') {
				ip_arg = t_av[0] + 2;
				++t_av;
				--argc;
				continue;
			}
			if (t_av[1] != NULL) {
				ip_arg = t_av[1];
				t_av += 2;
				argc -= 2;
				continue;
			}
		}
		*p_av++ = *t_av++;
	}

	/*
	 * If we're being called as an editor library, we're done here, we
	 * get loaded with the curses screen, we don't share much code.
	 */
	if (ip_arg != NULL)
		exit (ip_main(argc, argv, gp, ip_arg));
#endif
		
	/* Create and initialize the CL_PRIVATE structure. */
	clp = cl_init(gp);

	/*
	 * Initialize the terminal information.
	 *
	 * We have to know what terminal it is from the start, since we may
	 * have to use termcap/terminfo to find out how big the screen is.
	 */
	if ((ttype = getenv("TERM")) == NULL)
		ttype = "unknown";
	term_init(gp->progname, ttype);

	/* Add the terminal type to the global structure. */
	if ((OG_D_STR(gp, GO_TERM) =
	    OG_STR(gp, GO_TERM) = strdup(ttype)) == NULL)
		perr(gp->progname, NULL);

	/* Figure out how big the screen is. */
	if (cl_ssize(NULL, 0, &rows, &cols, NULL))
		exit (1);

	/* Add the rows and columns to the global structure. */
	OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = rows;
	OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = cols;

	/* Ex wants stdout to be buffered. */
	(void)setvbuf(stdout, NULL, _IOFBF, 0);

	/* Start catching signals. */
	if (sig_init(gp, NULL))
		exit (1);

	/* Run ex/vi. */
	rval = editor(gp, argc, argv);

	/* Clean up signals. */
	sig_end(gp);

	/* Clean up the terminal. */
	(void)cl_quit(gp);

	/*
	 * XXX
	 * Reset the O_MESG option.
	 */
	if (clp->tgw != TGW_UNKNOWN)
		(void)cl_omesg(NULL, clp, clp->tgw == TGW_SET);

	/*
	 * XXX
	 * Reset the X11 xterm icon/window name.
	 */
	if (F_ISSET(clp, CL_RENAME)) {
		(void)printf(XTERM_RENAME, ttype);
		(void)fflush(stdout);
	}

	/* If a killer signal arrived, pretend we just got it. */
	if (clp->killersig) {
		(void)signal(clp->killersig, SIG_DFL);
		(void)kill(getpid(), clp->killersig);
		/* NOTREACHED */
	}

	/* Free the global and CL private areas. */
#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
	free(clp);
	free(gp);
#endif

	exit (rval);
}
Пример #23
0
int main(int argc, char **argv)
{
	const struct optstruct *opt;
#ifndef	C_WINDOWS
        struct passwd *user = NULL;
#endif
	time_t currtime;
	const char *dbdir, *cfgfile;
	char *pua_cats = NULL, *pt;
	int ret, tcpsock = 0, localsock = 0, i, min_port, max_port;
	unsigned int sigs = 0;
	int lsockets[2], nlsockets = 0;
	unsigned int dboptions = 0;
#ifdef C_LINUX
	struct stat sb;
#endif

#ifdef C_WINDOWS
    if(!pthread_win32_process_attach_np()) {
	mprintf("!Can't start the win32 pthreads layer\n");
        return 1;
    }
#endif

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

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

    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
	debug_mode = 1;
    }

    /* parse the config file */
    cfgfile = optget(opts, "config-file")->strarg;
    pt = strdup(cfgfile);
    if((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) {
	fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", pt);
	free(pt);
	return 1;
    }
    free(pt);

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

    umask(0);

    /* drop privileges */
#if (!defined(C_OS2)) && (!defined(C_WINDOWS))
    if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
	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 in %s\n", cfgfile);
	    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;
	}
    }
#endif

    /* initialize logger */
    logg_lock = !optget(opts, "LogFileUnlock")->enabled;
    logg_time = optget(opts, "LogTime")->enabled;
    logok = optget(opts, "LogClean")->enabled;
    logg_size = optget(opts, "LogFileMaxSize")->numarg;
    logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled;
    mprintf_send_timeout = optget(opts, "SendBufTimeout")->numarg;

    do { /* logger initialized */

    if((opt = optget(opts, "LogFile"))->enabled) {
	char timestr[32];
	logg_file = opt->strarg;
	if(strlen(logg_file) < 2 || (logg_file[0] != '/' && logg_file[0] != '\\' && logg_file[1] != ':')) {
	    fprintf(stderr, "ERROR: LogFile requires full path.\n");
	    ret = 1;
	    break;
	}
	time(&currtime);
	if(logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) {
	    fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
	    ret = 1;
	    break;
	}
    } else
	logg_file = NULL;

    if((ret = cl_init(CL_INIT_DEFAULT))) {
	logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
	ret = 1;
	break;
    }

    if(optget(opts, "Debug")->enabled) /* enable debug messages in libclamav */ {
	cl_debug();
	logg_verbose = 2;
    }

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

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

	openlog("clamd", LOG_PID, fac);
	logg_syslog = 1;
    }
#endif

#ifdef C_LINUX
    procdev = 0;
    if(stat("/proc", &sb) != -1 && !sb.st_size)
	procdev = sb.st_dev;
#endif

    /* check socket type */

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

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

    if(!tcpsock && !localsock) {
	logg("!Please define server type (local and/or TCP).\n");
	ret = 1;
	break;
    }

    logg("#clamd daemon %s (OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE")\n", get_version());

#ifndef C_WINDOWS
    if(user)
	logg("#Running as user %s (UID %u, GID %u)\n", user->pw_name, user->pw_uid, user->pw_gid);
#endif

    if(logg_size)
	logg("#Log file size limited to %d bytes.\n", logg_size);
    else
	logg("#Log file size limit disabled.\n");

    min_port = optget(opts, "StreamMinPort")->numarg;
    max_port = optget(opts, "StreamMaxPort")->numarg;
    if (min_port < 1024 || min_port > max_port || max_port > 65535) {
	logg("!Invalid StreamMinPort/StreamMaxPort: %d, %d\n", min_port, max_port);
	ret = 1;
	break;
    }

    if(!(engine = cl_engine_new())) {
	logg("!Can't initialize antivirus engine\n");
	ret = 1;
	break;
    }

    /* load the database(s) */
    dbdir = optget(opts, "DatabaseDirectory")->strarg;
    logg("#Reading databases from %s\n", dbdir);

    if(optget(opts, "DetectPUA")->enabled) {
	dboptions |= CL_DB_PUA;

	if((opt = optget(opts, "ExcludePUA"))->enabled) {
	    dboptions |= CL_DB_PUA_EXCLUDE;
	    i = 0;
	    logg("#Excluded PUA categories:");
	    while(opt) {
		if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
		    logg("!Can't allocate memory for pua_cats\n");
		    cl_engine_free(engine);
		    ret = 1;
		    break;
		}
		logg("# %s", opt->strarg);
		sprintf(pua_cats + i, ".%s", opt->strarg);
		i += strlen(opt->strarg) + 1;
		pua_cats[i] = 0;
		opt = opt->nextarg;
	    }
	    if (ret)
		break;
	    logg("#\n");
	    pua_cats[i] = '.';
	    pua_cats[i + 1] = 0;
	}

	if((opt = optget(opts, "IncludePUA"))->enabled) {
	    if(pua_cats) {
		logg("!ExcludePUA and IncludePUA cannot be used at the same time\n");
		free(pua_cats);
		ret = 1;
		break;
	    }
	    dboptions |= CL_DB_PUA_INCLUDE;
	    i = 0;
	    logg("#Included PUA categories:");
	    while(opt) {
		if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
		    logg("!Can't allocate memory for pua_cats\n");
		    ret = 1;
		    break;
		}
		logg("# %s", opt->strarg);
		sprintf(pua_cats + i, ".%s", opt->strarg);
		i += strlen(opt->strarg) + 1;
		pua_cats[i] = 0;
		opt = opt->nextarg;
	    }
	    if (ret)
		break;
	    logg("#\n");
	    pua_cats[i] = '.';
	    pua_cats[i + 1] = 0;
	}

	if(pua_cats) {
	    if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) {
		logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret));
		free(pua_cats);
		ret = 1;
		break;
	    }
	    free(pua_cats);
	}
    } else {
	logg("#Not loading PUA signatures.\n");
    }

    /* set the temporary dir */
    if((opt = optget(opts, "TemporaryDirectory"))->enabled) {
	if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) {
	    logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret));
	    ret = 1;
	    break;
	}
    }

    if(optget(opts, "LeaveTemporaryFiles")->enabled)
	cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1);

    if(optget(opts, "PhishingSignatures")->enabled)
	dboptions |= CL_DB_PHISHING;
    else
	logg("#Not loading phishing signatures.\n");

    if(optget(opts,"PhishingScanURLs")->enabled)
	dboptions |= CL_DB_PHISHING_URLS;
    else
	logg("#Disabling URL based phishing detection.\n");

    if(optget(opts,"DevACOnly")->enabled) {
	logg("#Only using the A-C matcher.\n");
	cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1);
    }

    if((opt = optget(opts, "DevACDepth"))->enabled) {
        cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, opt->numarg);
	logg("#Max A-C depth set to %u\n", (unsigned int) opt->numarg);
    }

    if((ret = cl_load(dbdir, engine, &sigs, dboptions))) {
	logg("!%s\n", cl_strerror(ret));
	ret = 1;
	break;
    }

    logg("#Loaded %u signatures.\n", sigs);
    if((ret = cl_engine_compile(engine)) != 0) {
	logg("!Database initialization error: %s\n", cl_strerror(ret));
	ret = 1;
	break;
    }

    if(tcpsock) {
#ifdef C_WINDOWS
	    WSADATA wsaData;

	if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) {
	    logg("!Error at WSAStartup(): %d\n", WSAGetLastError());
	    ret = 1;
	    break;
	}
#endif
	if ((lsockets[nlsockets] = tcpserver(opts)) == -1) {
	    ret = 1;
	    break;
	}
	nlsockets++;
    }

    if(localsock) {
	if ((lsockets[nlsockets] = localserver(opts)) == -1) {
	    ret = 1;
	    break;
	}
	nlsockets++;
    }

    /* fork into background */
    if(!optget(opts, "Foreground")->enabled) {
#ifdef C_BSD	    
	/* workaround for OpenBSD bug, see https://wwws.clamav.net/bugzilla/show_bug.cgi?id=885 */
	for(ret=0;ret<nlsockets;ret++) {
		fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) | O_NONBLOCK);
	}
#endif
	if(daemonize() == -1) {
	    logg("!daemonize() failed\n");
	    ret = 1;
	    break;
	}
#ifdef C_BSD
	for(ret=0;ret<nlsockets;ret++) {
		fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) & ~O_NONBLOCK);
	}
#endif
	if(!debug_mode)
	    if(chdir("/") == -1)
		logg("^Can't change current working directory to root\n");

    } else
        foreground = 1;

    ret = recvloop_th(lsockets, nlsockets, engine, dboptions, opts);

    } while (0);

    logg("*Closing the main socket%s.\n", (nlsockets > 1) ? "s" : "");

    for (i = 0; i < nlsockets; i++) {
	closesocket(lsockets[i]);
    }

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

#ifdef C_WINDOWS
    if(tcpsock)
	WSACleanup();

    if(!pthread_win32_process_detach_np()) {
	logg("!Can't stop the win32 pthreads layer\n");
	logg_close();
	optfree(opts);
	return 1;
    }
#endif

    logg_close();
    optfree(opts);

    return ret;
}
Пример #24
0
int scanmanager(const struct optstruct *opts)
{
    int ret = 0, i;
    unsigned int options = 0, dboptions = 0, dirlnk = 1, filelnk = 1;
    struct cl_engine *engine;
    STATBUF sb;
    char *file, cwd[1024], *pua_cats = NULL;
    const char *filename;
    const struct optstruct *opt;
#ifndef _WIN32
    struct rlimit rlim;
#endif

    dirlnk = optget(opts, "follow-dir-symlinks")->numarg;
    if(dirlnk > 2) {
        logg("!--follow-dir-symlinks: Invalid argument\n");
        return 2;
    }

    filelnk = optget(opts, "follow-file-symlinks")->numarg;
    if(filelnk > 2) {
        logg("!--follow-file-symlinks: Invalid argument\n");
        return 2;
    }

    if(optget(opts, "yara-rules")->enabled) {
	char *p = optget(opts, "yara-rules")->strarg;
	if(strcmp(p, "yes")) {
	    if(!strcmp(p, "only"))
		dboptions |= CL_DB_YARA_ONLY;
	    else if (!strcmp(p, "no"))
		dboptions |= CL_DB_YARA_EXCLUDE;
	}

    }

    if(optget(opts, "phishing-sigs")->enabled)
        dboptions |= CL_DB_PHISHING;

    if(optget(opts, "official-db-only")->enabled)
        dboptions |= CL_DB_OFFICIAL_ONLY;

    if(optget(opts,"phishing-scan-urls")->enabled)
        dboptions |= CL_DB_PHISHING_URLS;

    if(optget(opts,"bytecode")->enabled)
        dboptions |= CL_DB_BYTECODE;

    if((ret = cl_init(CL_INIT_DEFAULT))) {
        logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
        return 2;
    }

    if(!(engine = cl_engine_new())) {
        logg("!Can't initialize antivirus engine\n");
        return 2;
    }

    cl_engine_set_clcb_virus_found(engine, clamscan_virus_found_cb);
    
    if (optget(opts, "disable-cache")->enabled)
        cl_engine_set_num(engine, CL_ENGINE_DISABLE_CACHE, 1);

    if (optget(opts, "disable-pe-stats")->enabled) {
        cl_engine_set_num(engine, CL_ENGINE_DISABLE_PE_STATS, 1);
    }

    if (optget(opts, "enable-stats")->enabled) {
        cl_engine_stats_enable(engine);
    }

    if (optget(opts, "stats-timeout")->enabled) {
        cl_engine_set_num(engine, CL_ENGINE_STATS_TIMEOUT, optget(opts, "StatsTimeout")->numarg);
    }

    if (optget(opts, "stats-host-id")->enabled) {
        char *p = optget(opts, "stats-host-id")->strarg;

        if (strcmp(p, "default")) {
            if (!strcmp(p, "none")) {
                cl_engine_set_clcb_stats_get_hostid(engine, NULL);
            } else if (!strcmp(p, "anonymous")) {
                strcpy(hostid, STATS_ANON_UUID);
            } else {
                if (strlen(p) > 36) {
                    logg("!Invalid HostID\n");

                    cl_engine_set_clcb_stats_submit(engine, NULL);
                    cl_engine_free(engine);
                    return 2;
                }

                strcpy(hostid, p);
            }

            cl_engine_set_clcb_stats_get_hostid(engine, get_hostid);
        }
    }

    if(optget(opts, "detect-pua")->enabled) {
        dboptions |= CL_DB_PUA;
        if((opt = optget(opts, "exclude-pua"))->enabled) {
            dboptions |= CL_DB_PUA_EXCLUDE;
            i = 0;
            while(opt) {
                if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
                    logg("!Can't allocate memory for pua_cats\n");

                    cl_engine_free(engine);
                    return 2;
                }

                sprintf(pua_cats + i, ".%s", opt->strarg);
                i += strlen(opt->strarg) + 1;
                pua_cats[i] = 0;

                opt = opt->nextarg;
            }
            pua_cats[i] = '.';
            pua_cats[i + 1] = 0;
        }

        if((opt = optget(opts, "include-pua"))->enabled) {
            if(pua_cats) {
                logg("!--exclude-pua and --include-pua cannot be used at the same time\n");

                cl_engine_free(engine);
                free(pua_cats);
                return 2;
            }

            dboptions |= CL_DB_PUA_INCLUDE;
            i = 0;
            while(opt) {
                if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
                    logg("!Can't allocate memory for pua_cats\n");
                    cl_engine_free(engine);
                    return 2;
                }

                sprintf(pua_cats + i, ".%s", opt->strarg);
                i += strlen(opt->strarg) + 1;
                pua_cats[i] = 0;

                opt = opt->nextarg;
            }

            pua_cats[i] = '.';
            pua_cats[i + 1] = 0;
        }

        if(pua_cats) {
            if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) {
                logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret));

                free(pua_cats);
                cl_engine_free(engine);
                return 2;
            }

            free(pua_cats);
        }
    }

    if(optget(opts, "dev-ac-only")->enabled)
        cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1);

    if(optget(opts, "dev-ac-depth")->enabled)
        cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, optget(opts, "dev-ac-depth")->numarg);

    if(optget(opts, "leave-temps")->enabled)
        cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1);

    if(optget(opts, "force-to-disk")->enabled)
        cl_engine_set_num(engine, CL_ENGINE_FORCETODISK, 1);

    if(optget(opts, "bytecode-unsigned")->enabled)
        dboptions |= CL_DB_BYTECODE_UNSIGNED;

    if((opt = optget(opts,"bytecode-timeout"))->enabled)
        cl_engine_set_num(engine, CL_ENGINE_BYTECODE_TIMEOUT, opt->numarg);

    if (optget(opts, "nocerts")->enabled)
        cl_engine_set_num(engine, CL_ENGINE_DISABLE_PE_CERTS, 1);

    if (optget(opts, "dumpcerts")->enabled)
        cl_engine_set_num(engine, CL_ENGINE_PE_DUMPCERTS, 1);

    if((opt = optget(opts,"bytecode-mode"))->enabled) {
        enum bytecode_mode mode;

        if (!strcmp(opt->strarg, "ForceJIT"))
            mode = CL_BYTECODE_MODE_JIT;
        else if(!strcmp(opt->strarg, "ForceInterpreter"))
            mode = CL_BYTECODE_MODE_INTERPRETER;
        else if(!strcmp(opt->strarg, "Test"))
            mode = CL_BYTECODE_MODE_TEST;
        else
            mode = CL_BYTECODE_MODE_AUTO;

        cl_engine_set_num(engine, CL_ENGINE_BYTECODE_MODE, mode);
    }

    if((opt = optget(opts, "statistics"))->enabled) {
	while(opt) {
	    if (!strcasecmp(opt->strarg, "bytecode")) {
		dboptions |= CL_DB_BYTECODE_STATS;
	    }
	    else if (!strcasecmp(opt->strarg, "pcre")) {
		dboptions |= CL_DB_PCRE_STATS;
	    }
	    opt = opt->nextarg;
        }
    }

    if((opt = optget(opts, "tempdir"))->enabled) {
        if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) {
            logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if((opt = optget(opts, "database"))->active) {
        while(opt) {
            if((ret = cl_load(opt->strarg, engine, &info.sigs, dboptions))) {
                logg("!%s\n", cl_strerror(ret));

                cl_engine_free(engine);
                return 2;
            }

            opt = opt->nextarg;
        }
    } else {
        char *dbdir = freshdbdir();

        if((ret = cl_load(dbdir, engine, &info.sigs, dboptions))) {
            logg("!%s\n", cl_strerror(ret));

            free(dbdir);
            cl_engine_free(engine);
            return 2;
        }

        free(dbdir);
    }

    /* pcre engine limits - required for cl_engine_compile */
    if ((opt = optget(opts, "pcre-match-limit"))->active) {
        if ((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MATCH_LIMIT, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_PCRE_MATCH_LIMIT) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 2;
        }
    }

    if ((opt = optget(opts, "pcre-recmatch-limit"))->active) {
        if ((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_RECMATCH_LIMIT, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_PCRE_RECMATCH_LIMIT) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 2;
        }
    }

    if((ret = cl_engine_compile(engine)) != 0) {
        logg("!Database initialization error: %s\n", cl_strerror(ret));;

        cl_engine_free(engine);
        return 2;
    }

    if(optget(opts, "archive-verbose")->enabled) {
        cl_engine_set_clcb_meta(engine, meta);
        cl_engine_set_clcb_pre_cache(engine, pre);
        cl_engine_set_clcb_post_scan(engine, post);
    }

    /* set limits */

    if((opt = optget(opts, "max-scansize"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if((opt = optget(opts, "max-filesize"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

#ifndef _WIN32
    if(getrlimit(RLIMIT_FSIZE, &rlim) == 0) {
        if(rlim.rlim_cur < (rlim_t) cl_engine_get_num(engine, CL_ENGINE_MAX_FILESIZE, NULL))
            logg("^System limit for file size is lower than engine->maxfilesize\n");
        if(rlim.rlim_cur < (rlim_t) cl_engine_get_num(engine, CL_ENGINE_MAX_SCANSIZE, NULL))
            logg("^System limit for file size is lower than engine->maxscansize\n");
    } else {
        logg("^Cannot obtain resource limits for file size\n");
    }
#endif

    if((opt = optget(opts, "max-files"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILES, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_FILES) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if((opt = optget(opts, "max-recursion"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECURSION, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_RECURSION) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    /* Engine max sizes */

    if((opt = optget(opts, "max-embeddedpe"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_EMBEDDEDPE, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_EMBEDDEDPE) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if((opt = optget(opts, "max-htmlnormalize"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNORMALIZE, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_HTMLNORMALIZE) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if((opt = optget(opts, "max-htmlnotags"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNOTAGS, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_HTMLNOTAGS) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if((opt = optget(opts, "max-scriptnormalize"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCRIPTNORMALIZE, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_SCRIPTNORMALIZE) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if((opt = optget(opts, "max-ziptypercg"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ZIPTYPERCG, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_ZIPTYPERCG) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if((opt = optget(opts, "max-partitions"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_PARTITIONS, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_PARTITIONS) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if((opt = optget(opts, "max-iconspe"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ICONSPE, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_ICONSPE) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if((opt = optget(opts, "max-rechwp3"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECHWP3, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_RECHWP3) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if ((opt = optget(opts, "timelimit"))->active) {
        if ((ret = cl_engine_set_num(engine, CL_ENGINE_TIME_LIMIT, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_TIME_LIMIT) failed: %s\n", cl_strerror(ret));

            cl_engine_free(engine);
            return 2;
        }
    }

    if ((opt = optget(opts, "pcre-max-filesize"))->active) {
        if ((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MAX_FILESIZE, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_PCRE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 2;
        }
    }

    /* set scan options */
    if(optget(opts, "allmatch")->enabled) {
        options |= CL_SCAN_ALLMATCHES;
    }

    if(optget(opts,"phishing-ssl")->enabled)
        options |= CL_SCAN_PHISHING_BLOCKSSL;

    if(optget(opts,"phishing-cloak")->enabled)
        options |= CL_SCAN_PHISHING_BLOCKCLOAK;

    if(optget(opts,"partition-intersection")->enabled)
        options |= CL_SCAN_PARTITION_INTXN;

    if(optget(opts,"heuristic-scan-precedence")->enabled)
        options |= CL_SCAN_HEURISTIC_PRECEDENCE;

    if(optget(opts, "scan-archive")->enabled)
        options |= CL_SCAN_ARCHIVE;

    if(optget(opts, "detect-broken")->enabled)
        options |= CL_SCAN_BLOCKBROKEN;

    if(optget(opts, "block-encrypted")->enabled)
        options |= CL_SCAN_BLOCKENCRYPTED;

    if(optget(opts, "block-macros")->enabled)
        options |= CL_SCAN_BLOCKMACROS;

    if(optget(opts, "scan-pe")->enabled)
        options |= CL_SCAN_PE;

    if(optget(opts, "scan-elf")->enabled)
        options |= CL_SCAN_ELF;

    if(optget(opts, "scan-ole2")->enabled)
        options |= CL_SCAN_OLE2;

    if(optget(opts, "scan-pdf")->enabled)
        options |= CL_SCAN_PDF;

    if(optget(opts, "scan-swf")->enabled)
        options |= CL_SCAN_SWF;

    if(optget(opts, "scan-html")->enabled && optget(opts, "normalize")->enabled)
        options |= CL_SCAN_HTML;

    if(optget(opts, "scan-mail")->enabled)
        options |= CL_SCAN_MAIL;

    if(optget(opts, "scan-xmldocs")->enabled)
        options |= CL_SCAN_XMLDOCS;

    if(optget(opts, "scan-hwp3")->enabled)
        options |= CL_SCAN_HWP3;

    if(optget(opts, "algorithmic-detection")->enabled)
        options |= CL_SCAN_ALGORITHMIC;

    if(optget(opts, "block-max")->enabled) {
        options |= CL_SCAN_BLOCKMAX;
    }

#ifdef HAVE__INTERNAL__SHA_COLLECT
    if(optget(opts, "dev-collect-hashes")->enabled)
        options |= CL_SCAN_INTERNAL_COLLECT_SHA;
#endif

    if(optget(opts, "dev-performance")->enabled)
        options |= CL_SCAN_PERFORMANCE_INFO;

    if(optget(opts, "detect-structured")->enabled) {
        options |= CL_SCAN_STRUCTURED;

        if((opt = optget(opts, "structured-ssn-format"))->enabled) {
            switch(opt->numarg) {
            case 0:
                options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
                break;
            case 1:
                options |= CL_SCAN_STRUCTURED_SSN_STRIPPED;
                break;
            case 2:
                options |= (CL_SCAN_STRUCTURED_SSN_NORMAL | CL_SCAN_STRUCTURED_SSN_STRIPPED);
                break;
            default:
                logg("!Invalid argument for --structured-ssn-format\n");
                return 2;
            }
        } else {
            options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
        }

        if((opt = optget(opts, "structured-ssn-count"))->active) {
            if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_SSN_COUNT, opt->numarg))) {
                logg("!cli_engine_set_num(CL_ENGINE_MIN_SSN_COUNT) failed: %s\n", cl_strerror(ret));

                cl_engine_free(engine);
                return 2;
            }
        }

        if((opt = optget(opts, "structured-cc-count"))->active) {
            if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_CC_COUNT, opt->numarg))) {
                logg("!cli_engine_set_num(CL_ENGINE_MIN_CC_COUNT) failed: %s\n", cl_strerror(ret));
                cl_engine_free(engine);
                return 2;
            }
        }
    } else {
        options &= ~CL_SCAN_STRUCTURED;
    }

#ifdef C_LINUX
    procdev = (dev_t) 0;
    if(CLAMSTAT("/proc", &sb) != -1 && !sb.st_size)
        procdev = sb.st_dev;
#endif

#if HAVE_JSON
    if (optget(opts, "gen-json")->enabled)
        options |= CL_SCAN_FILE_PROPERTIES;
#endif

    /* check filetype */
    if(!opts->filename && !optget(opts, "file-list")->enabled) {
        /* we need full path for some reasons (eg. archive handling) */
        if(!getcwd(cwd, sizeof(cwd))) {
            logg("!Can't get absolute pathname of current working directory\n");
            ret = 2;
        } else {
            CLAMSTAT(cwd, &sb);
            scandirs(cwd, engine, opts, options, 1, sb.st_dev);
        }

    } else if(opts->filename && !optget(opts, "file-list")->enabled && !strcmp(opts->filename[0], "-")) { /* read data from stdin */
        ret = scanstdin(engine, opts, options);
    } else {
        if(opts->filename && optget(opts, "file-list")->enabled)
            logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n");

        while((filename = filelist(opts, &ret)) && (file = strdup(filename))) {
            if(LSTAT(file, &sb) == -1) {
                perror(file);
                logg("^%s: Can't access file\n", file);
                ret = 2;
            } else {
                for(i = strlen(file) - 1; i > 0; i--) {
                    if(file[i] == *PATHSEP)
                        file[i] = 0;
                    else
                        break;
                }

                if(S_ISLNK(sb.st_mode)) {
                    if(dirlnk == 0 && filelnk == 0) {
                        if(!printinfected)
                            logg("%s: Symbolic link\n", file);
                    } else if(CLAMSTAT(file, &sb) != -1) {
                        if(S_ISREG(sb.st_mode) && filelnk) {
                            scanfile(file, engine, opts, options);
                        } else if(S_ISDIR(sb.st_mode) && dirlnk) {
                            scandirs(file, engine, opts, options, 1, sb.st_dev);
                        } else {
                            if(!printinfected)
                                logg("%s: Symbolic link\n", file);
                        }
                    }
                } else if(S_ISREG(sb.st_mode)) {
                    scanfile(file, engine, opts, options);
                } else if(S_ISDIR(sb.st_mode)) {
                    scandirs(file, engine, opts, options, 1, sb.st_dev);
                } else {
                    logg("^%s: Not supported file type\n", file);
                    ret = 2;
                }
            }

            free(file);
        }
    }

    if((opt = optget(opts, "statistics"))->enabled) {
	while(opt) {
	    if (!strcasecmp(opt->strarg, "bytecode")) {
		cli_sigperf_print();
		cli_sigperf_events_destroy();
	    }
#if HAVE_PCRE
	    else if (!strcasecmp(opt->strarg, "pcre")) {
		cli_pcre_perf_print();
		cli_pcre_perf_events_destroy();
	    }
#endif
	    opt = opt->nextarg;
        }
    }

    /* free the engine */
    cl_engine_free(engine);

    /* overwrite return code - infection takes priority */
    if(info.ifiles)
        ret = 1;
    else if(info.errors)
        ret = 2;

    return ret;
}