/* * Swrun MIB architecture support * * $Id: swrun.c 15768 2007-01-22 16:18:29Z rstory $ */ /* * Copyright (C) 2007 Apple, Inc. All rights reserved. * Use is subject to license terms specified in the COPYING file * distributed with the Net-SNMP package. */ #include #include #include #include #include #include "swrun.h" #include "swrun_private.h" #if HAVE_PCRE_H #include #endif netsnmp_feature_child_of(software_running, libnetsnmpmibs) netsnmp_feature_child_of(swrun_max_processes, software_running) netsnmp_feature_child_of(swrun_count_processes_by_name, software_running) netsnmp_feature_child_of(swrun_count_processes_by_regex, software_running) /**---------------------------------------------------------------------*/ /* * local static vars */ static int _swrun_init = 0; int _swrun_max = 0; static netsnmp_cache *swrun_cache = NULL; static netsnmp_container *swrun_container = NULL; /* * local static prototypes */ static void _swrun_entry_release(netsnmp_swrun_entry * entry, void *unused); /** * initialization */ void init_swrun(void) { DEBUGMSGTL(("swrun:access", "init\n")); if (1 == _swrun_init) return; _swrun_init = 1; (void)netsnmp_swrun_container(); netsnmp_arch_swrun_init(); (void) netsnmp_swrun_cache(); } void shutdown_swrun(void) { DEBUGMSGTL(("swrun:access", "shutdown\n")); } int swrun_count_processes(int include_kthreads) { netsnmp_swrun_entry *entry; netsnmp_iterator *it; int i = 0; netsnmp_cache_check_and_reload(swrun_cache); if ( !swrun_container ) return 0; /* or -1 */ if (include_kthreads) return ( swrun_container ? CONTAINER_SIZE(swrun_container) : 0 ); it = CONTAINER_ITERATOR( swrun_container ); while ((entry = (netsnmp_swrun_entry*)ITERATOR_NEXT( it )) != NULL) { if (4 == entry->hrSWRunType) i++; } ITERATOR_RELEASE( it ); return i; } #ifndef NETSNMP_FEATURE_REMOVE_SWRUN_MAX_PROCESSES int swrun_max_processes( void ) { return _swrun_max; } #endif /* NETSNMP_FEATURE_REMOVE_SWRUN_MAX_PROCESSES */ #ifndef NETSNMP_FEATURE_REMOVE_SWRUN_COUNT_PROCESSES_BY_REGEX #if HAVE_PCRE_H int swrun_count_processes_by_regex( char *name, struct real_pcre *regexp ) { netsnmp_swrun_entry *entry; netsnmp_iterator *it; int i = 0; int found_ndx[30]; int found; char fullCommand[64 + 128 + 128 + 3]; netsnmp_cache_check_and_reload(swrun_cache); if ( !swrun_container || !name || !regexp ) return 0; /* or -1 */ it = CONTAINER_ITERATOR( swrun_container ); while ((entry = (netsnmp_swrun_entry*)ITERATOR_NEXT( it )) != NULL) { /* need to assemble full command back so regexps can get full picture */ sprintf(fullCommand, "%s %s", entry->hrSWRunPath, entry->hrSWRunParameters); found = pcre_exec(regexp, NULL, fullCommand, strlen(fullCommand), 0, 0, found_ndx, 30); if (found > 0) { i++; } } ITERATOR_RELEASE( it ); return i; } #endif /* HAVE_PCRE_H */ #endif /* NETSNMP_FEATURE_REMOVE_SWRUN_COUNT_PROCESSES_BY_REGEX */ #ifndef NETSNMP_FEATURE_REMOVE_SWRUN_COUNT_PROCESSES_BY_NAME int swrun_count_processes_by_name( char *name ) { netsnmp_swrun_entry *entry; netsnmp_iterator *it; int i = 0; netsnmp_cache_check_and_reload(swrun_cache); if ( !swrun_container || !name ) return 0; /* or -1 */ it = CONTAINER_ITERATOR( swrun_container ); while ((entry = (netsnmp_swrun_entry*)ITERATOR_NEXT( it )) != NULL) { if (0 == strcmp( entry->hrSWRunName, name )) i++; } ITERATOR_RELEASE( it ); return i; } #endif /* NETSNMP_FEATURE_REMOVE_SWRUN_COUNT_PROCESSES_BY_NAME */ /**---------------------------------------------------------------------*/ /* * cache functions */ static int _cache_load( netsnmp_cache *cache, void *magic ) { netsnmp_swrun_container_load( swrun_container, 0 ); return 0; } static void _cache_free( netsnmp_cache *cache, void *magic ) { netsnmp_swrun_container_free_items( swrun_container ); return; } /** * create swrun cache */ netsnmp_cache * netsnmp_swrun_cache(void) { oid hrSWRunTable_oid[] = { 1, 3, 6, 1, 2, 1, 25, 4, 2 }; size_t hrSWRunTable_oid_len = OID_LENGTH(hrSWRunTable_oid); if ( !swrun_cache ) { swrun_cache = netsnmp_cache_create(30, /* timeout in seconds */ _cache_load, _cache_free, hrSWRunTable_oid, hrSWRunTable_oid_len); if (swrun_cache) swrun_cache->flags = NETSNMP_CACHE_DONT_INVALIDATE_ON_SET; } return swrun_cache; } /**---------------------------------------------------------------------*/ /* * container functions */ /** * create swrun container */ netsnmp_container * netsnmp_swrun_container(void) { DEBUGMSGTL(("swrun:container", "init\n")); /* * create the container. */ if (!swrun_container) { swrun_container = netsnmp_container_find("swrun:table_container"); if (NULL == swrun_container) return NULL; swrun_container->container_name = strdup("swrun container"); } return swrun_container; } /** * load swrun information in specified container * * @param container empty container to be filled. * pass NULL to have the function create one. * @param load_flags flags to modify behaviour. Examples: * NETSNMP_SWRUN_ALL_OR_NONE * * @retval NULL error * @retval !NULL pointer to container */ netsnmp_container* netsnmp_swrun_container_load(netsnmp_container* user_container, u_int load_flags) { netsnmp_container* container = user_container; int rc; DEBUGMSGTL(("swrun:container:load", "load\n")); netsnmp_assert(1 == _swrun_init); if (NULL == container) container = netsnmp_swrun_container(); if (NULL == container) { snmp_log(LOG_ERR, "no container specified/found for swrun\n"); return NULL; } rc = netsnmp_arch_swrun_container_load(container, load_flags); if (0 != rc) { if (NULL == user_container) { netsnmp_swrun_container_free(container, NETSNMP_SWRUN_NOFLAGS); container = NULL; } else if (load_flags & NETSNMP_SWRUN_ALL_OR_NONE) { DEBUGMSGTL(("swrun:container:load", " discarding partial results\n")); netsnmp_swrun_container_free_items(container); } } return container; } void netsnmp_swrun_container_free(netsnmp_container *container, u_int free_flags) { DEBUGMSGTL(("swrun:container", "free\n")); if (NULL == container) { snmp_log(LOG_ERR, "invalid container for netsnmp_swrun_container_free\n"); return; } if(! (free_flags & NETSNMP_SWRUN_DONT_FREE_ITEMS)) netsnmp_swrun_container_free_items(container); CONTAINER_FREE(container); } void netsnmp_swrun_container_free_items(netsnmp_container *container) { DEBUGMSGTL(("swrun:container", "free_items\n")); if (NULL == container) { snmp_log(LOG_ERR, "invalid container for netsnmp_swrun_container_free_items\n"); return; } /* * free all items. */ CONTAINER_CLEAR(container, (netsnmp_container_obj_func*)_swrun_entry_release, NULL); } /**---------------------------------------------------------------------*/ /* * swrun_entry functions */ /** */ netsnmp_swrun_entry * netsnmp_swrun_entry_get_by_index(netsnmp_container *container, oid index) { netsnmp_index tmp; DEBUGMSGTL(("swrun:entry", "by_index\n")); netsnmp_assert(1 == _swrun_init); if (NULL == container) { snmp_log(LOG_ERR, "invalid container for netsnmp_swrun_entry_get_by_index\n"); return NULL; } tmp.len = 1; tmp.oids = &index; return (netsnmp_swrun_entry *) CONTAINER_FIND(container, &tmp); } /** */ netsnmp_swrun_entry * netsnmp_swrun_entry_create(int32_t index) { netsnmp_swrun_entry *entry = SNMP_MALLOC_TYPEDEF(netsnmp_swrun_entry); if(NULL == entry) return NULL; entry->hrSWRunIndex = index; entry->hrSWRunType = 1; /* unknown */ entry->hrSWRunStatus = 2; /* runnable */ entry->oid_index.len = 1; entry->oid_index.oids = (oid *) & entry->hrSWRunIndex; return entry; } /** */ NETSNMP_INLINE void netsnmp_swrun_entry_free(netsnmp_swrun_entry * entry) { if (NULL == entry) return; /* * SNMP_FREE not needed, for any of these, * since the whole entry is about to be freed */ free(entry); } /**---------------------------------------------------------------------*/ /* * Utility routines */ /** */ static void _swrun_entry_release(netsnmp_swrun_entry * entry, void *context) { netsnmp_swrun_entry_free(entry); } #ifdef TEST int main(int argc, char *argv[]) { const char *tokens = getenv("SNMP_DEBUG"); netsnmp_container_init_list(); /** swrun,verbose:swrun,9:swrun,8:swrun,5:swrun */ if (tokens) debug_register_tokens(tokens); else debug_register_tokens("swrun"); snmp_set_do_debugging(1); init_swrun(); netsnmp_swrun_container_load(NULL, 0); shutdown_swrun(); return 0; } #endif