📄 util_funcs.c
字号:
/* * util_funcs.c *//* * Portions of this file are copyrighted by: * Copyright Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms specified in the COPYING file * distributed with the Net-SNMP package. */#include <net-snmp/net-snmp-config.h>#if HAVE_IO_H#include <io.h>#endif#include <stdio.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif#if HAVE_MALLOC_H#include <malloc.h>#endif#include <sys/types.h>#ifdef __alpha#ifndef _BSD#define _BSD#define _myBSD#endif#endif#if HAVE_SYS_WAIT_H# include <sys/wait.h>#endif#ifdef __alpha#ifdef _myBSD#undef _BSD#undef _myBSD#endif#endif#ifndef WEXITSTATUS# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)#endif#ifndef WIFEXITED# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)#endif#if TIME_WITH_SYS_TIME# ifdef WIN32# include <sys/timeb.h># else# include <sys/time.h># endif# include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#if HAVE_UNISTD_H#include <unistd.h>#endif#if HAVE_FCNTL_H#include <fcntl.h>#endif#include <errno.h>#include <signal.h>#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#include <ctype.h>#if HAVE_WINSOCK_H#include <winsock.h>#endif#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if HAVE_BASETSD_H#include <basetsd.h>#define ssize_t SSIZE_T#endif#if HAVE_RAISE#define alarm raise#endif#ifdef HAVE_SYS_STAT_H#include <sys/stat.h>#endif#include <net-snmp/net-snmp-includes.h>#include <net-snmp/agent/net-snmp-agent-includes.h>#include "struct.h"#include "util_funcs.h"#include "utilities/execute.h"#if HAVE_LIMITS_H#include "limits.h"#endif#ifdef USING_UCD_SNMP_ERRORMIB_MODULE#include "ucd-snmp/errormib.h"#else#define setPerrorstatus(x) snmp_log_perror(x)#endif#ifdef NETSNMP_EXCACHETIMEstatic long cachetime;#endifextern int numprocs, numextens;voidExit(int var){ snmp_log(LOG_ERR, "Server Exiting with code %d\n", var); exit(var);}/** deprecated, use netsnmp_mktemp instead */const char *make_tempfile(void){ static char name[32]; int fd = -1; strcpy(name, get_temp_file_pattern());#ifdef HAVE_MKSTEMP fd = mkstemp(name);#else if (mktemp(name)) {# ifndef WIN32 fd = open(name, O_CREAT | O_EXCL | O_WRONLY);# else /* Win32 needs _S_IREAD | _S_IWRITE to set permissions on file after closing */ fd = _open(name, _O_CREAT, _S_IREAD | _S_IWRITE | _O_EXCL | _O_WRONLY);# endif }#endif if (fd >= 0) { close(fd); DEBUGMSGTL(("make_tempfile", "temp file created: %s\n", name)); return name; } snmp_log(LOG_ERR,"make_tempfile: error creating file %s\n", name); return NULL;}intshell_command(struct extensible *ex){#if HAVE_SYSTEM const char *ofname; char shellline[STRMAX]; FILE *shellout; ofname = make_tempfile(); if (ofname == NULL) { ex->output[0] = 0; ex->result = 127; return ex->result; } snprintf(shellline, sizeof(shellline), "%s > %s", ex->command, ofname); shellline[ sizeof(shellline)-1 ] = 0; ex->result = system(shellline); ex->result = WEXITSTATUS(ex->result); shellout = fopen(ofname, "r"); if (shellout != NULL) { if (fgets(ex->output, sizeof(ex->output), shellout) == NULL) { ex->output[0] = 0; } fclose(shellout); } unlink(ofname);#else ex->output[0] = 0; ex->result = 0;#endif return (ex->result);}#define MAXOUTPUT 300intexec_command(struct extensible *ex){#if defined (HAVE_EXECV) || defined (WIN32) int fd; FILE *file; if ((fd = get_exec_output(ex)) != -1) { file = fdopen(fd, "r"); if (fgets(ex->output, sizeof(ex->output), file) == NULL) { ex->output[0] = 0; } fclose(file); wait_on_exec(ex); } else#endif /* HAVE_EXECV */ { ex->output[0] = 0; ex->result = 0; } return (ex->result);}struct extensible *get_exten_instance(struct extensible *exten, size_t inst){ int i; if (exten == NULL) return (NULL); for (i = 1; i != (int) inst && exten != NULL; i++) exten = exten->next; return (exten);}voidwait_on_exec(struct extensible *ex){#if defined(WIN32) && !defined (mingw32) int rc; if (ex->tid != 0 && ex->pid != 0) { HANDLE hThread = (HANDLE) ex->tid; HANDLE hProcess = (HANDLE) ex->pid; rc = WaitForSingleObject(hProcess, NETSNMP_TIMEOUT_WAITFORSINGLEOBJECT); DEBUGMSGT(("exec:wait_on_exec","WaitForSingleObject rc=(%d)\n",rc )); rc = CloseHandle( hThread ); DEBUGMSGT(("exec:wait_on_exec","CloseHandle hThread=(%d)\n",rc )); rc = CloseHandle( hProcess ); DEBUGMSGT(("exec:wait_on_exec","CloseHandle hProcess=(%d)\n",rc )); ex->pid = 0; ex->tid = 0; }#else#ifndef NETSNMP_EXCACHETIME if (ex->pid && waitpid(ex->pid, &ex->result, 0) < 0) { setPerrorstatus("waitpid"); } ex->pid = 0;#endif /* NETSNMP_EXCACHETIME */#endif /* WIN32 */}#define MAXARGS 30intget_exec_output(struct extensible *ex){#if HAVE_EXECV char cachefile[STRMAX]; char cache[NETSNMP_MAXCACHESIZE]; ssize_t cachebytes; int cfd;#ifdef NETSNMP_EXCACHETIME long curtime; static char lastcmd[STRMAX]; static int lastresult;#endif DEBUGMSGTL(("exec:get_exec_output","calling %s\n", ex->command)); sprintf(cachefile, "%s/%s", get_persistent_directory(), NETSNMP_CACHEFILE);#ifdef NETSNMP_EXCACHETIME curtime = time(NULL); if (curtime > (cachetime + NETSNMP_EXCACHETIME) || strcmp(ex->command, lastcmd) != 0) { strcpy(lastcmd, ex->command); cachetime = curtime;#endif cachebytes = NETSNMP_MAXCACHESIZE; ex->result = run_exec_command( ex->command, NULL, cache, &cachebytes ); unlink(cachefile); /* * XXX Use SNMP_FILEMODE_CLOSED instead of 644? */ if ((cfd = open(cachefile, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) { snmp_log(LOG_ERR,"can not create cache file\n"); setPerrorstatus(cachefile); cachetime = 0; return -1; } if (cachebytes > 0) write(cfd, (void *) cache, cachebytes); close(cfd);#ifdef NETSNMP_EXCACHETIME lastresult = ex->result; } else { ex->result = lastresult; }#endif DEBUGMSGTL(("exec:get_exec_output","using cached value\n")); if ((cfd = open(cachefile, O_RDONLY)) < 0) { snmp_log(LOG_ERR,"can not open cache file\n"); setPerrorstatus(cachefile); return -1; } return (cfd);#else /* !HAVE_EXECV */#if defined(WIN32) && !defined(HAVE_EXECV)/* MSVC and MinGW. Cygwin already works as it has execv and fork */ int fd; /* Reference: MS tech note: 190351 */ HANDLE hOutputReadTmp, hOutputRead, hOutputWrite = NULL; HANDLE hErrorWrite; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; sa.nLength= sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; DEBUGMSGTL(("exec:get_exec_output","calling %s\n", ex->command)); /* Child temporary output pipe with Inheritance on (sa.bInheritHandle is true) */ if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) { DEBUGMSGTL(("util_funcs", "get_exec_pipes CreatePipe ChildOut: %d\n", GetLastError())); return -1; } /* Copy the stdout handle to the stderr handle in case the child closes one of * its stdout handles. */ if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, GetCurrentProcess(), &hErrorWrite,0, TRUE,DUPLICATE_SAME_ACCESS)) { DEBUGMSGTL(("util_funcs", "get_exec_output DuplicateHandle: %d\n", GetLastError())); return -1; } /* Create new copies of the input and output handles but set bInheritHandle to * FALSE so the new handle can not be inherited. Otherwise the handles can not * be closed. */ if (!DuplicateHandle(GetCurrentProcess(), hOutputReadTmp, GetCurrentProcess(), &hOutputRead, 0, FALSE, DUPLICATE_SAME_ACCESS)) { DEBUGMSGTL(("util_funcs", "get_exec_output DupliateHandle ChildOut: %d\n", GetLastError())); CloseHandle(hErrorWrite); return -1; } /* Close the temporary output and input handles */ if (!CloseHandle(hOutputReadTmp)) { DEBUGMSGTL(("util_funcs", "get_exec_output CloseHandle (hOutputReadTmp): %d\n", GetLastError())); CloseHandle(hErrorWrite); CloseHandle(hOutputRead); return -1; } /* Associates a C run-time file descriptor with an existing operating-system file handle. */ fd = _open_osfhandle((long) hOutputRead, 0); /* Set up STARTUPINFO for CreateProcess with the handles and have it hide the window * for the new process. */ ZeroMemory(&si,sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.hStdOutput = hOutputWrite; si.hStdError = hErrorWrite; si.wShowWindow = SW_HIDE; /* Launch the process that you want to redirect. Example snmpd.conf pass_persist: * pass_persist .1.3.6.1.4.1.2021.255 c:/perl/bin/perl c:/temp/pass_persisttest */ if (!CreateProcess(NULL, ex->command, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { DEBUGMSGTL(("util_funcs","get_exec_output CreateProcess:'%s' %d\n",ex->command, GetLastError())); CloseHandle(hErrorWrite); CloseHandle(hOutputRead); return -1; } /* Set global child process handle */ ex->pid = (int)pi.hProcess; ex->tid = (int)pi.hThread; /* Close pipe handles to make sure that no handles to the write end of the * output pipe are maintained in this process or else the pipe will * not close when the child process exits and any calls to ReadFile * will hang. */ if (!CloseHandle(hOutputWrite)){ DEBUGMSGTL(("util_funcs","get_exec_output CloseHandle hOutputWrite: %d\n",ex->command, GetLastError())); return -1; } if (!CloseHandle(hErrorWrite)) { DEBUGMSGTL(("util_funcs","get_exec_output CloseHandle hErrorWrite: %d\n",ex->command, GetLastError())); return -1; } return fd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -