net-snmp
5.4.1
|
00001 /* 00002 * system.c 00003 */ 00004 /* Portions of this file are subject to the following copyright(s). See 00005 * the Net-SNMP's COPYING file for more details and other copyrights 00006 * that may apply: 00007 */ 00008 /*********************************************************** 00009 Copyright 1992 by Carnegie Mellon University 00010 00011 All Rights Reserved 00012 00013 Permission to use, copy, modify, and distribute this software and its 00014 documentation for any purpose and without fee is hereby granted, 00015 provided that the above copyright notice appear in all copies and that 00016 both that copyright notice and this permission notice appear in 00017 supporting documentation, and that the name of CMU not be 00018 used in advertising or publicity pertaining to distribution of the 00019 software without specific, written prior permission. 00020 00021 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 00022 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 00023 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 00024 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00025 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 00026 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00027 SOFTWARE. 00028 ******************************************************************/ 00029 /* 00030 * Portions of this file are copyrighted by: 00031 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. 00032 * Use is subject to license terms specified in the COPYING file 00033 * distributed with the Net-SNMP package. 00034 */ 00035 /* 00036 * System dependent routines go here 00037 */ 00038 #include <net-snmp/net-snmp-config.h> 00039 #include <stdio.h> 00040 #include <ctype.h> 00041 #include <errno.h> 00042 00043 #if HAVE_UNISTD_H 00044 #include <unistd.h> 00045 #endif 00046 #if HAVE_STDLIB_H 00047 #include <stdlib.h> 00048 #endif 00049 00050 #if TIME_WITH_SYS_TIME 00051 # ifdef WIN32 00052 # include <sys/timeb.h> 00053 # else 00054 # include <sys/time.h> 00055 # endif 00056 # include <time.h> 00057 #else 00058 # if HAVE_SYS_TIME_H 00059 # include <sys/time.h> 00060 # else 00061 # include <time.h> 00062 # endif 00063 #endif 00064 00065 #include <sys/types.h> 00066 00067 #if HAVE_NETINET_IN_H 00068 #include <netinet/in.h> 00069 #endif 00070 00071 #if HAVE_WINSOCK_H 00072 #include <winsock.h> 00073 #endif 00074 #if HAVE_SYS_SOCKET_H 00075 #include <sys/socket.h> 00076 #endif 00077 #if HAVE_NET_IF_H 00078 #include <net/if.h> 00079 #endif 00080 00081 #if HAVE_SYS_SOCKIO_H 00082 #include <sys/sockio.h> 00083 #endif 00084 00085 #if HAVE_SYS_IOCTL_H 00086 #include <sys/ioctl.h> 00087 #endif 00088 00089 #ifdef HAVE_NLIST_H 00090 #include <nlist.h> 00091 #endif 00092 00093 #if HAVE_SYS_FILE_H 00094 #include <sys/file.h> 00095 #endif 00096 00097 #if HAVE_KSTAT_H 00098 #include <kstat.h> 00099 #endif 00100 00101 #if HAVE_SYS_PARAM_H 00102 #include <sys/param.h> 00103 #endif 00104 #if HAVE_SYS_SYSCTL_H 00105 #include <sys/sysctl.h> 00106 #endif 00107 00108 #if HAVE_STRING_H 00109 #include <string.h> 00110 #else 00111 #include <strings.h> 00112 #endif 00113 00114 #if HAVE_DMALLOC_H 00115 #include <dmalloc.h> 00116 #endif 00117 00118 #ifdef HAVE_SYS_STAT_H 00119 #include <sys/stat.h> 00120 #endif 00121 #if HAVE_FCNTL_H 00122 #include <fcntl.h> 00123 #endif 00124 00125 #if defined(hpux10) || defined(hpux11) 00126 #include <sys/pstat.h> 00127 #endif 00128 00129 #if HAVE_SYS_UTSNAME_H 00130 #include <sys/utsname.h> 00131 #endif 00132 00133 #if HAVE_SYS_SYSTEMCFG_H 00134 #include <sys/systemcfg.h> 00135 #endif 00136 00137 #if HAVE_SYS_SYSTEMINFO_H 00138 #include <sys/systeminfo.h> 00139 #endif 00140 00141 #include <net-snmp/types.h> 00142 #include <net-snmp/output_api.h> 00143 #include <net-snmp/utilities.h> 00144 #include <net-snmp/library/system.h> /* for "internal" definitions */ 00145 00146 #include <net-snmp/library/snmp_api.h> 00147 #include <net-snmp/library/read_config.h> /* for get_temp_file_pattern() */ 00148 00149 #ifndef IFF_LOOPBACK 00150 # define IFF_LOOPBACK 0 00151 #endif 00152 00153 #ifdef INADDR_LOOPBACK 00154 # define LOOPBACK INADDR_LOOPBACK 00155 #else 00156 # define LOOPBACK 0x7f000001 00157 #endif 00158 00181 int 00182 netsnmp_daemonize(int quit_immediately, int stderr_log) 00183 { 00184 int i = 0; 00185 DEBUGMSGT(("daemonize","deamonizing...\n")); 00186 #if HAVE_FORK 00187 /* 00188 * Fork to return control to the invoking process and to 00189 * guarantee that we aren't a process group leader. 00190 */ 00191 i = fork(); 00192 if (i != 0) { 00193 /* Parent. */ 00194 DEBUGMSGT(("daemonize","first fork returned %d.\n", i)); 00195 if(i == -1) { 00196 snmp_log(LOG_ERR,"first fork failed (errno %d) in " 00197 "netsnmp_daemonize()\n", errno); 00198 return -1; 00199 } 00200 if (quit_immediately) { 00201 DEBUGMSGT(("daemonize","parent exiting\n")); 00202 exit(0); 00203 } 00204 } else { 00205 /* Child. */ 00206 #ifdef HAVE_SETSID 00207 /* Become a process/session group leader. */ 00208 setsid(); 00209 #endif 00210 /* 00211 * Fork to let the process/session group leader exit. 00212 */ 00213 if ((i = fork()) != 0) { 00214 DEBUGMSGT(("daemonize","second fork returned %d.\n", i)); 00215 if(i == -1) { 00216 snmp_log(LOG_ERR,"second fork failed (errno %d) in " 00217 "netsnmp_daemonize()\n", errno); 00218 } 00219 /* Parent. */ 00220 exit(0); 00221 } 00222 #ifndef WIN32 00223 else { 00224 /* Child. */ 00225 00226 DEBUGMSGT(("daemonize","child continuing\n")); 00227 00228 /* Avoid keeping any directory in use. */ 00229 chdir("/"); 00230 00231 if (!stderr_log) { 00232 /* 00233 * Close inherited file descriptors to avoid 00234 * keeping unnecessary references. 00235 */ 00236 close(0); 00237 close(1); 00238 close(2); 00239 00240 /* 00241 * Redirect std{in,out,err} to /dev/null, just in 00242 * case. 00243 */ 00244 open("/dev/null", O_RDWR); 00245 dup(0); 00246 dup(0); 00247 } 00248 } 00249 #endif /* !WIN32 */ 00250 } 00251 #endif /* HAVE_FORK */ 00252 return i; 00253 } 00254 00255 /* 00256 * ********************************************* 00257 */ 00258 #ifdef WIN32 00259 # define WIN32_LEAN_AND_MEAN 00260 # define WIN32IO_IS_STDIO 00261 # define PATHLEN 1024 00262 00263 # include <tchar.h> 00264 # include <windows.h> 00265 00266 /* 00267 * MinGW defines WIN32, but has working dirent stuff. 00268 */ 00269 #ifndef HAVE_DIRENT_H 00270 00271 /* 00272 * The idea here is to read all the directory names into a string table 00273 * * (separated by nulls) and when one of the other dir functions is called 00274 * * return the pointer to the current file name. 00275 */ 00276 DIR * 00277 opendir(const char *filename) 00278 { 00279 DIR *p; 00280 long len; 00281 long idx; 00282 char scannamespc[PATHLEN]; 00283 char *scanname = scannamespc; 00284 struct stat sbuf; 00285 WIN32_FIND_DATA FindData; 00286 HANDLE fh; 00287 00288 /* 00289 * check to see if filename is a directory 00290 */ 00291 if ((stat(filename, &sbuf) < 0) || ((sbuf.st_mode & S_IFDIR) == 0)) { 00292 return NULL; 00293 } 00294 00295 /* 00296 * get the file system characteristics 00297 */ 00298 /* 00299 * if(GetFullPathName(filename, SNMP_MAXPATH, root, &dummy)) { 00300 * * if(dummy = strchr(root, '\\')) 00301 * * *++dummy = '\0'; 00302 * * if(GetVolumeInformation(root, volname, SNMP_MAXPATH, &serial, 00303 * * &maxname, &flags, 0, 0)) { 00304 * * downcase = !(flags & FS_CASE_IS_PRESERVED); 00305 * * } 00306 * * } 00307 * * else { 00308 * * downcase = TRUE; 00309 * * } 00310 */ 00311 00312 /* 00313 * Create the search pattern 00314 */ 00315 strcpy(scanname, filename); 00316 00317 if (strchr("/\\", *(scanname + strlen(scanname) - 1)) == NULL) 00318 strcat(scanname, "/*"); 00319 else 00320 strcat(scanname, "*"); 00321 00322 /* 00323 * do the FindFirstFile call 00324 */ 00325 fh = FindFirstFile(scanname, &FindData); 00326 if (fh == INVALID_HANDLE_VALUE) { 00327 return NULL; 00328 } 00329 00330 /* 00331 * Get us a DIR structure 00332 */ 00333 p = (DIR *) malloc(sizeof(DIR)); 00334 /* 00335 * Newz(1303, p, 1, DIR); 00336 */ 00337 if (p == NULL) 00338 return NULL; 00339 00340 /* 00341 * now allocate the first part of the string table for 00342 * * the filenames that we find. 00343 */ 00344 idx = strlen(FindData.cFileName) + 1; 00345 p->start = (char *) malloc(idx); 00346 /* 00347 * New(1304, p->start, idx, char); 00348 */ 00349 if (p->start == NULL) { 00350 free(p); 00351 return NULL; 00352 } 00353 strcpy(p->start, FindData.cFileName); 00354 /* 00355 * if(downcase) 00356 * * strlwr(p->start); 00357 */ 00358 p->nfiles = 0; 00359 00360 /* 00361 * loop finding all the files that match the wildcard 00362 * * (which should be all of them in this directory!). 00363 * * the variable idx should point one past the null terminator 00364 * * of the previous string found. 00365 */ 00366 while (FindNextFile(fh, &FindData)) { 00367 len = strlen(FindData.cFileName); 00368 /* 00369 * bump the string table size by enough for the 00370 * * new name and it's null terminator 00371 */ 00372 p->start = (char *) realloc((void *) p->start, idx + len + 1); 00373 /* 00374 * Renew(p->start, idx+len+1, char); 00375 */ 00376 if (p->start == NULL) { 00377 free(p); 00378 return NULL; 00379 } 00380 strcpy(&p->start[idx], FindData.cFileName); 00381 /* 00382 * if (downcase) 00383 * * strlwr(&p->start[idx]); 00384 */ 00385 p->nfiles++; 00386 idx += len + 1; 00387 } 00388 FindClose(fh); 00389 p->size = idx; 00390 p->curr = p->start; 00391 return p; 00392 } 00393 00394 00395 /* 00396 * Readdir just returns the current string pointer and bumps the 00397 * * string pointer to the nDllExport entry. 00398 */ 00399 struct direct * 00400 readdir(DIR * dirp) 00401 { 00402 int len; 00403 static int dummy = 0; 00404 00405 if (dirp->curr) { 00406 /* 00407 * first set up the structure to return 00408 */ 00409 len = strlen(dirp->curr); 00410 strcpy(dirp->dirstr.d_name, dirp->curr); 00411 dirp->dirstr.d_namlen = len; 00412 00413 /* 00414 * Fake an inode 00415 */ 00416 dirp->dirstr.d_ino = dummy++; 00417 00418 /* 00419 * Now set up for the nDllExport call to readdir 00420 */ 00421 dirp->curr += len + 1; 00422 if (dirp->curr >= (dirp->start + dirp->size)) { 00423 dirp->curr = NULL; 00424 } 00425 00426 return &(dirp->dirstr); 00427 } else 00428 return NULL; 00429 } 00430 00431 /* 00432 * free the memory allocated by opendir 00433 */ 00434 int 00435 closedir(DIR * dirp) 00436 { 00437 free(dirp->start); 00438 free(dirp); 00439 return 1; 00440 } 00441 #endif /* HAVE_DIRENT_H */ 00442 00443 #ifndef HAVE_GETTIMEOFDAY 00444 00445 int 00446 gettimeofday(struct timeval *tv, struct timezone *tz) 00447 { 00448 struct _timeb timebuffer; 00449 00450 _ftime(&timebuffer); 00451 tv->tv_usec = timebuffer.millitm * 1000; 00452 tv->tv_sec = timebuffer.time; 00453 return (0); 00454 } 00455 #endif /* !HAVE_GETTIMEOFDAY */ 00456 00457 in_addr_t 00458 get_myaddr(void) 00459 { 00460 char local_host[130]; 00461 int result; 00462 LPHOSTENT lpstHostent; 00463 SOCKADDR_IN in_addr, remote_in_addr; 00464 SOCKET hSock; 00465 int nAddrSize = sizeof(SOCKADDR); 00466 00467 in_addr.sin_addr.s_addr = INADDR_ANY; 00468 00469 result = gethostname(local_host, sizeof(local_host)); 00470 if (result == 0) { 00471 lpstHostent = gethostbyname((LPSTR) local_host); 00472 if (lpstHostent) { 00473 in_addr.sin_addr.s_addr = 00474 *((u_long FAR *) (lpstHostent->h_addr)); 00475 return ((in_addr_t) in_addr.sin_addr.s_addr); 00476 } 00477 } 00478 00479 /* 00480 * if we are here, than we don't have host addr 00481 */ 00482 hSock = socket(AF_INET, SOCK_DGRAM, 0); 00483 if (hSock != INVALID_SOCKET) { 00484 /* 00485 * connect to any port and address 00486 */ 00487 remote_in_addr.sin_family = AF_INET; 00488 remote_in_addr.sin_port = htons(IPPORT_ECHO); 00489 remote_in_addr.sin_addr.s_addr = inet_addr("0.0.0.0"); 00490 result = 00491 connect(hSock, (LPSOCKADDR) & remote_in_addr, 00492 sizeof(SOCKADDR)); 00493 if (result != SOCKET_ERROR) { 00494 /* 00495 * get local ip address 00496 */ 00497 getsockname(hSock, (LPSOCKADDR) & in_addr, 00498 (int FAR *) &nAddrSize); 00499 } 00500 closesocket(hSock); 00501 } 00502 return ((in_addr_t) in_addr.sin_addr.s_addr); 00503 } 00504 00505 long 00506 get_uptime(void) 00507 { 00508 long return_value = 0; 00509 DWORD buffersize = (sizeof(PERF_DATA_BLOCK) + 00510 sizeof(PERF_OBJECT_TYPE)), 00511 type = REG_EXPAND_SZ; 00512 PPERF_DATA_BLOCK perfdata = NULL; 00513 00514 /* 00515 * min requirement is one PERF_DATA_BLOCK plus one PERF_OBJECT_TYPE 00516 */ 00517 perfdata = (PPERF_DATA_BLOCK) malloc(buffersize); 00518 if (!perfdata) 00519 return 0; 00520 00521 memset(perfdata, 0, buffersize); 00522 00523 RegQueryValueEx(HKEY_PERFORMANCE_DATA, 00524 "Global", NULL, &type, (LPBYTE) perfdata, &buffersize); 00525 00526 /* 00527 * we can not rely on the return value since there is always more so 00528 * we check the signature 00529 */ 00530 00531 if (wcsncmp(perfdata->Signature, L"PERF", 4) == 0) { 00532 /* 00533 * signature ok, and all we need is in the in the PERF_DATA_BLOCK 00534 */ 00535 return_value = (long) ((perfdata->PerfTime100nSec.QuadPart / 00536 (LONGLONG) 100000)); 00537 } else 00538 return_value = GetTickCount() / 10; 00539 00540 RegCloseKey(HKEY_PERFORMANCE_DATA); 00541 free(perfdata); 00542 00543 return return_value; 00544 } 00545 00546 char * 00547 winsock_startup(void) 00548 { 00549 WORD VersionRequested; 00550 WSADATA stWSAData; 00551 int i; 00552 static char errmsg[100]; 00553 00554 /* winsock 1: use MAKEWORD(1,1) */ 00555 /* winsock 2: use MAKEWORD(2,2) */ 00556 00557 VersionRequested = MAKEWORD(2,2); 00558 i = WSAStartup(VersionRequested, &stWSAData); 00559 if (i != 0) { 00560 if (i == WSAVERNOTSUPPORTED) 00561 sprintf(errmsg, 00562 "Unable to init. socket lib, does not support 1.1"); 00563 else { 00564 sprintf(errmsg, "Socket Startup error %d", i); 00565 } 00566 return (errmsg); 00567 } 00568 return (NULL); 00569 } 00570 00571 void 00572 winsock_cleanup(void) 00573 { 00574 WSACleanup(); 00575 } 00576 00577 #else /* ! WIN32 */ 00578 /*******************************************************************/ 00579 00580 /* 00581 * XXX What if we have multiple addresses? Or no addresses for that matter? 00582 * XXX Could it be computed once then cached? Probably not worth it (not 00583 * used very often). 00584 */ 00585 in_addr_t 00586 get_myaddr(void) 00587 { 00588 int sd, i, lastlen = 0; 00589 struct ifconf ifc; 00590 struct ifreq *ifrp = NULL; 00591 in_addr_t addr; 00592 char *buf = NULL; 00593 00594 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00595 return 0; 00596 } 00597 00598 /* 00599 * Cope with lots of interfaces and brokenness of ioctl SIOCGIFCONF on 00600 * some platforms; see W. R. Stevens, ``Unix Network Programming Volume 00601 * I'', p.435. 00602 */ 00603 00604 for (i = 8;; i += 8) { 00605 buf = (char *) calloc(i, sizeof(struct ifreq)); 00606 if (buf == NULL) { 00607 close(sd); 00608 return 0; 00609 } 00610 ifc.ifc_len = i * sizeof(struct ifreq); 00611 ifc.ifc_buf = (caddr_t) buf; 00612 00613 if (ioctl(sd, SIOCGIFCONF, (char *) &ifc) < 0) { 00614 if (errno != EINVAL || lastlen != 0) { 00615 /* 00616 * Something has gone genuinely wrong. 00617 */ 00618 free(buf); 00619 close(sd); 00620 return 0; 00621 } 00622 /* 00623 * Otherwise, it could just be that the buffer is too small. 00624 */ 00625 } else { 00626 if (ifc.ifc_len == lastlen) { 00627 /* 00628 * The length is the same as the last time; we're done. 00629 */ 00630 break; 00631 } 00632 lastlen = ifc.ifc_len; 00633 } 00634 free(buf); 00635 } 00636 00637 for (ifrp = ifc.ifc_req; 00638 (char *)ifrp < (char *)ifc.ifc_req + ifc.ifc_len; 00639 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN 00640 ifrp = (struct ifreq *)(((char *) ifrp) + 00641 sizeof(ifrp->ifr_name) + 00642 ifrp->ifr_addr.sa_len) 00643 #else 00644 ifrp++ 00645 #endif 00646 ) { 00647 if (ifrp->ifr_addr.sa_family != AF_INET) { 00648 continue; 00649 } 00650 addr = ((struct sockaddr_in *) &(ifrp->ifr_addr))->sin_addr.s_addr; 00651 00652 if (ioctl(sd, SIOCGIFFLAGS, (char *) ifrp) < 0) { 00653 continue; 00654 } 00655 if ((ifrp->ifr_flags & IFF_UP) 00656 #ifdef IFF_RUNNING 00657 && (ifrp->ifr_flags & IFF_RUNNING) 00658 #endif /* IFF_RUNNING */ 00659 && !(ifrp->ifr_flags & IFF_LOOPBACK) 00660 && addr != LOOPBACK) { 00661 /* 00662 * I *really* don't understand why this is necessary. Perhaps for 00663 * some broken platform? Leave it for now. JBPN 00664 */ 00665 #ifdef SYS_IOCTL_H_HAS_SIOCGIFADDR 00666 if (ioctl(sd, SIOCGIFADDR, (char *) ifrp) < 0) { 00667 continue; 00668 } 00669 addr = 00670 ((struct sockaddr_in *) &(ifrp->ifr_addr))->sin_addr. 00671 s_addr; 00672 #endif 00673 free(buf); 00674 close(sd); 00675 return addr; 00676 } 00677 } 00678 free(buf); 00679 close(sd); 00680 return 0; 00681 } 00682 00683 00684 #if !defined(solaris2) && !defined(linux) && !defined(cygwin) 00685 /* 00686 * Returns boottime in centiseconds(!). 00687 * Caches this for future use. 00688 */ 00689 long 00690 get_boottime(void) 00691 { 00692 static long boottime_csecs = 0; 00693 #if defined(hpux10) || defined(hpux11) 00694 struct pst_static pst_buf; 00695 #else 00696 struct timeval boottime; 00697 #ifdef NETSNMP_CAN_USE_SYSCTL 00698 int mib[2]; 00699 size_t len; 00700 #elif defined(NETSNMP_CAN_USE_NLIST) 00701 int kmem; 00702 static struct nlist nl[] = { 00703 #if !defined(hpux) 00704 {(char *) "_boottime"}, 00705 #else 00706 {(char *) "boottime"}, 00707 #endif 00708 {(char *) ""} 00709 }; 00710 #endif /* NETSNMP_CAN_USE_SYSCTL */ 00711 #endif /* hpux10 || hpux 11 */ 00712 00713 00714 if (boottime_csecs != 0) 00715 return (boottime_csecs); 00716 00717 #if defined(hpux10) || defined(hpux11) 00718 pstat_getstatic(&pst_buf, sizeof(struct pst_static), 1, 0); 00719 boottime_csecs = pst_buf.boot_time * 100; 00720 #elif NETSNMP_CAN_USE_SYSCTL 00721 mib[0] = CTL_KERN; 00722 mib[1] = KERN_BOOTTIME; 00723 00724 len = sizeof(boottime); 00725 00726 sysctl(mib, 2, &boottime, &len, NULL, 0); 00727 boottime_csecs = (boottime.tv_sec * 100) + (boottime.tv_usec / 10000); 00728 #elif defined(NETSNMP_CAN_USE_NLIST) 00729 if ((kmem = open("/dev/kmem", 0)) < 0) 00730 return 0; 00731 nlist(KERNEL_LOC, nl); 00732 if (nl[0].n_type == 0) { 00733 close(kmem); 00734 return 0; 00735 } 00736 00737 lseek(kmem, (long) nl[0].n_value, L_SET); 00738 read(kmem, &boottime, sizeof(boottime)); 00739 close(kmem); 00740 boottime_csecs = (boottime.tv_sec * 100) + (boottime.tv_usec / 10000); 00741 #else 00742 return 0; 00743 #endif /* hpux10 || hpux 11 */ 00744 00745 return (boottime_csecs); 00746 } 00747 #endif 00748 00749 /* 00750 * Returns uptime in centiseconds(!). 00751 */ 00752 long 00753 get_uptime(void) 00754 { 00755 #if !defined(solaris2) && !defined(linux) && !defined(cygwin) && !defined(aix4) && !defined(aix5) 00756 struct timeval now; 00757 long boottime_csecs, nowtime_csecs; 00758 00759 boottime_csecs = get_boottime(); 00760 if (boottime_csecs == 0) 00761 return 0; 00762 gettimeofday(&now, (struct timezone *) 0); 00763 nowtime_csecs = (now.tv_sec * 100) + (now.tv_usec / 10000); 00764 00765 return (nowtime_csecs - boottime_csecs); 00766 #endif 00767 00768 #if defined(aix4) || defined(aix5) 00769 struct nlist nl; 00770 int kmem; 00771 time_t lbolt; 00772 nl.n_name = "lbolt"; 00773 if(knlist(&nl, 1, sizeof(struct nlist)) != 0) return(0); 00774 if(nl.n_type == 0 || nl.n_value == 0) return(0); 00775 if((kmem = open("/dev/mem", 0)) < 0) return 0; 00776 lseek(kmem, (long) nl.n_value, L_SET); 00777 read(kmem, &lbolt, sizeof(lbolt)); 00778 close(kmem); 00779 return(lbolt); 00780 #endif 00781 00782 #ifdef solaris2 00783 kstat_ctl_t *ksc = kstat_open(); 00784 kstat_t *ks; 00785 kid_t kid; 00786 kstat_named_t *named; 00787 u_long lbolt = 0; 00788 00789 if (ksc) { 00790 ks = kstat_lookup(ksc, "unix", -1, "system_misc"); 00791 if (ks) { 00792 kid = kstat_read(ksc, ks, NULL); 00793 if (kid != -1) { 00794 named = kstat_data_lookup(ks, "lbolt"); 00795 if (named) { 00796 #ifdef KSTAT_DATA_UINT32 00797 lbolt = named->value.ui32; 00798 #else 00799 lbolt = named->value.ul; 00800 #endif 00801 } 00802 } 00803 } 00804 kstat_close(ksc); 00805 } 00806 return lbolt; 00807 #endif /* solaris2 */ 00808 00809 #ifdef linux 00810 FILE *in = fopen("/proc/uptime", "r"); 00811 long uptim = 0, a, b; 00812 if (in) { 00813 if (2 == fscanf(in, "%ld.%ld", &a, &b)) 00814 uptim = a * 100 + b; 00815 fclose(in); 00816 } 00817 return uptim; 00818 #endif /* linux */ 00819 00820 #ifdef cygwin 00821 return (0); /* not implemented */ 00822 #endif 00823 } 00824 00825 #endif /* ! WIN32 */ 00826 /*******************************************************************/ 00827 00828 #ifndef HAVE_STRNCASECMP 00829 00830 /* 00831 * test for NULL pointers before and NULL characters after 00832 * * comparing possibly non-NULL strings. 00833 * * WARNING: This function does NOT check for array overflow. 00834 */ 00835 int 00836 strncasecmp(const char *s1, const char *s2, size_t nch) 00837 { 00838 size_t ii; 00839 int res = -1; 00840 00841 if (!s1) { 00842 if (!s2) 00843 return 0; 00844 return (-1); 00845 } 00846 if (!s2) 00847 return (1); 00848 00849 for (ii = 0; (ii < nch) && *s1 && *s2; ii++, s1++, s2++) { 00850 res = (int) (tolower(*s1) - tolower(*s2)); 00851 if (res != 0) 00852 break; 00853 } 00854 00855 if (ii == nch) { 00856 s1--; 00857 s2--; 00858 } 00859 00860 if (!*s1) { 00861 if (!*s2) 00862 return 0; 00863 return (-1); 00864 } 00865 if (!*s2) 00866 return (1); 00867 00868 return (res); 00869 } 00870 00871 int 00872 strcasecmp(const char *s1, const char *s2) 00873 { 00874 return strncasecmp(s1, s2, 1000000); 00875 } 00876 00877 #endif /* HAVE_STRNCASECMP */ 00878 00879 00880 #ifndef HAVE_STRDUP 00881 char * 00882 strdup(const char *src) 00883 { 00884 int len; 00885 char *dst; 00886 00887 len = strlen(src) + 1; 00888 if ((dst = (char *) malloc(len)) == NULL) 00889 return (NULL); 00890 strcpy(dst, src); 00891 return (dst); 00892 } 00893 #endif /* HAVE_STRDUP */ 00894 00895 #ifndef HAVE_SETENV 00896 int 00897 setenv(const char *name, const char *value, int overwrite) 00898 { 00899 char *cp; 00900 int ret; 00901 00902 if (overwrite == 0) { 00903 if (getenv(name)) 00904 return 0; 00905 } 00906 cp = (char *) malloc(strlen(name) + strlen(value) + 2); 00907 if (cp == NULL) 00908 return -1; 00909 sprintf(cp, "%s=%s", name, value); 00910 ret = putenv(cp); 00911 #ifdef WIN32 00912 free(cp); 00913 #endif 00914 return ret; 00915 } 00916 #endif /* HAVE_SETENV */ 00917 00918 /* returns centiseconds */ 00919 int 00920 calculate_time_diff(struct timeval *now, struct timeval *then) 00921 { 00922 struct timeval tmp, diff; 00923 memcpy(&tmp, now, sizeof(struct timeval)); 00924 tmp.tv_sec--; 00925 tmp.tv_usec += 1000000L; 00926 diff.tv_sec = tmp.tv_sec - then->tv_sec; 00927 diff.tv_usec = tmp.tv_usec - then->tv_usec; 00928 if (diff.tv_usec > 1000000L) { 00929 diff.tv_usec -= 1000000L; 00930 diff.tv_sec++; 00931 } 00932 return ((diff.tv_sec * 100) + (diff.tv_usec / 10000)); 00933 } 00934 00935 /* returns diff in rounded seconds */ 00936 u_int 00937 calculate_sectime_diff(struct timeval *now, struct timeval *then) 00938 { 00939 struct timeval tmp, diff; 00940 memcpy(&tmp, now, sizeof(struct timeval)); 00941 tmp.tv_sec--; 00942 tmp.tv_usec += 1000000L; 00943 diff.tv_sec = tmp.tv_sec - then->tv_sec; 00944 diff.tv_usec = tmp.tv_usec - then->tv_usec; 00945 if (diff.tv_usec > 1000000L) { 00946 diff.tv_usec -= 1000000L; 00947 diff.tv_sec++; 00948 } 00949 if (diff.tv_usec >= 500000L) 00950 return diff.tv_sec + 1; 00951 return diff.tv_sec; 00952 } 00953 00954 #ifndef HAVE_STRCASESTR 00955 /* 00956 * only glibc2 has this. 00957 */ 00958 char * 00959 strcasestr(const char *haystack, const char *needle) 00960 { 00961 const char *cp1 = haystack, *cp2 = needle; 00962 const char *cx; 00963 int tstch1, tstch2; 00964 00965 /* 00966 * printf("looking for '%s' in '%s'\n", needle, haystack); 00967 */ 00968 if (cp1 && cp2 && *cp1 && *cp2) 00969 for (cp1 = haystack, cp2 = needle; *cp1;) { 00970 cx = cp1; 00971 cp2 = needle; 00972 do { 00973 /* 00974 * printf("T'%c' ", *cp1); 00975 */ 00976 if (!*cp2) { /* found the needle */ 00977 /* 00978 * printf("\nfound '%s' in '%s'\n", needle, cx); 00979 */ 00980 return (char *) cx; 00981 } 00982 if (!*cp1) 00983 break; 00984 00985 tstch1 = toupper(*cp1); 00986 tstch2 = toupper(*cp2); 00987 if (tstch1 != tstch2) 00988 break; 00989 /* 00990 * printf("M'%c' ", *cp1); 00991 */ 00992 cp1++; 00993 cp2++; 00994 } 00995 while (1); 00996 if (*cp1) 00997 cp1++; 00998 } 00999 /* 01000 * printf("\n"); 01001 */ 01002 if (cp1 && *cp1) 01003 return (char *) cp1; 01004 01005 return NULL; 01006 } 01007 #endif 01008 01009 int 01010 mkdirhier(const char *pathname, mode_t mode, int skiplast) 01011 { 01012 struct stat sbuf; 01013 char *ourcopy = strdup(pathname); 01014 char *entry; 01015 char buf[SNMP_MAXPATH]; 01016 char *st = NULL; 01017 01018 #if defined (WIN32) || defined (cygwin) 01019 /* convert backslash to forward slash */ 01020 for (entry = ourcopy; *entry; entry++) 01021 if (*entry == '\\') 01022 *entry = '/'; 01023 #endif 01024 01025 entry = strtok_r(ourcopy, "/", &st); 01026 01027 buf[0] = '\0'; 01028 01029 #if defined (WIN32) || defined (cygwin) 01030 /* 01031 * Check if first entry contains a drive-letter 01032 * e.g "c:/path" 01033 */ 01034 if ((entry) && (':' == entry[1]) && 01035 (('\0' == entry[2]) || ('/' == entry[2]))) { 01036 strcat(buf, entry); 01037 entry = strtok_r(NULL, "/", &st); 01038 } 01039 #endif 01040 01041 /* 01042 * check to see if filename is a directory 01043 */ 01044 while (entry) { 01045 strcat(buf, "/"); 01046 strcat(buf, entry); 01047 entry = strtok_r(NULL, "/", &st); 01048 if (entry == NULL && skiplast) 01049 break; 01050 if (stat(buf, &sbuf) < 0) { 01051 /* 01052 * DNE, make it 01053 */ 01054 snmp_log(LOG_INFO, "Creating directory: %s\n", buf); 01055 #ifdef WIN32 01056 if (CreateDirectory(buf, NULL) == 0) 01057 #else 01058 if (mkdir(buf, mode) == -1) 01059 #endif 01060 { 01061 free(ourcopy); 01062 return SNMPERR_GENERR; 01063 } 01064 } else { 01065 /* 01066 * exists, is it a file? 01067 */ 01068 if ((sbuf.st_mode & S_IFDIR) == 0) { 01069 /* 01070 * ack! can't make a directory on top of a file 01071 */ 01072 free(ourcopy); 01073 return SNMPERR_GENERR; 01074 } 01075 } 01076 } 01077 free(ourcopy); 01078 return SNMPERR_SUCCESS; 01079 } 01080 01087 const char * 01088 netsnmp_mktemp(void) 01089 { 01090 static char name[32]; 01091 int fd = -1; 01092 01093 strcpy(name, get_temp_file_pattern()); 01094 #ifdef HAVE_MKSTEMP 01095 fd = mkstemp(name); 01096 #else 01097 if (mktemp(name)) { 01098 # ifndef WIN32 01099 fd = open(name, O_CREAT | O_EXCL | O_WRONLY); 01100 # else 01101 /* 01102 * Win32 needs _S_IREAD | _S_IWRITE to set permissions on file 01103 * after closing 01104 */ 01105 fd = _open(name, _O_CREAT, 01106 _S_IREAD | _S_IWRITE | _O_EXCL | _O_WRONLY); 01107 # endif 01108 } 01109 #endif 01110 if (fd >= 0) { 01111 close(fd); 01112 DEBUGMSGTL(("netsnmp_mktemp", "temp file created: %s\n", 01113 name)); 01114 return name; 01115 } 01116 snmp_log(LOG_ERR, "netsnmp_mktemp: error creating file %s\n", 01117 name); 01118 return NULL; 01119 } 01120 01121 /* 01122 * This function was created to differentiate actions 01123 * that are appropriate for Linux 2.4 kernels, but not later kernels. 01124 * 01125 * This function can be used to test kernels on any platform that supports uname(). 01126 * 01127 * If not running a platform that supports uname(), return -1. 01128 * 01129 * If ospname matches, and the release matches up through the prefix, 01130 * return 0. 01131 * If the release is ordered higher, return 1. 01132 * Be aware that "ordered higher" is not a guarantee of correctness. 01133 */ 01134 int 01135 netsnmp_os_prematch(const char *ospmname, 01136 const char *ospmrelprefix) 01137 { 01138 #if HAVE_SYS_UTSNAME_H 01139 static int printOSonce = 1; 01140 struct utsname utsbuf; 01141 if ( 0 != uname(&utsbuf)) 01142 return -1; 01143 01144 if (printOSonce) { 01145 printOSonce = 0; 01146 /* show the four elements that the kernel can be sure of */ 01147 DEBUGMSGT(("daemonize","sysname '%s',\nrelease '%s',\nversion '%s',\nmachine '%s'\n", 01148 utsbuf.sysname, utsbuf.release, utsbuf.version, utsbuf.machine)); 01149 } 01150 if (0 != strcasecmp(utsbuf.sysname, ospmname)) return -1; 01151 01152 /* Required to match only the leading characters */ 01153 return strncasecmp(utsbuf.release, ospmrelprefix, strlen(ospmrelprefix)); 01154 01155 #else 01156 01157 return -1; 01158 01159 #endif /* HAVE_SYS_UTSNAME_H */ 01160 } 01161 01168 int 01169 netsnmp_os_kernel_width(void) 01170 { 01171 #ifdef irix6 01172 char buf[8]; 01173 sysinfo(_MIPS_SI_OS_NAME, buf, 7); 01174 if (strncmp("IRIX64", buf, 6) == 0) { 01175 return 64; 01176 } else if (strncmp("IRIX", buf, 4) == 0) { 01177 return 32; 01178 } else { 01179 return -1; 01180 } 01181 #elif defined(aix4) || defined(aix5) 01182 return (__KERNEL_32() ? 32 : (__KERNEL_64() ? 64 : -1)); 01183 #elif defined(osf4) || defined(osf5) || defined(__alpha) 01184 return 64; /* Alpha is always 64bit */ 01185 #else 01186 /* kernel width detection not implemented */ 01187 return -1; 01188 #endif 01189 } 01190