/* * 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)); }
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); }
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; }
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; }
// // 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; }
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(); }
/* * 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)); }
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; }
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); }
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; }
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; }
/* 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; }
/* 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; } }
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--; }
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; }
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); }
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; }
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); }
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; }
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; }
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; }
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; }
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; }
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); }
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); }
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; }
/* 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; }
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; }
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); }
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; }