1 //==========================================================================
3 // ./lib/current/src/system.c
6 //==========================================================================
7 //####ECOSGPLCOPYRIGHTBEGIN####
8 // -------------------------------------------
9 // This file is part of eCos, the Embedded Configurable Operating System.
10 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // eCos is free software; you can redistribute it and/or modify it under
13 // the terms of the GNU General Public License as published by the Free
14 // Software Foundation; either version 2 or (at your option) any later version.
16 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 // You should have received a copy of the GNU General Public License along
22 // with eCos; if not, write to the Free Software Foundation, Inc.,
23 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 // As a special exception, if other files instantiate templates or use macros
26 // or inline functions from this file, or you compile this file and link it
27 // with other works to produce a work based on this file, this file does not
28 // by itself cause the resulting work to be covered by the GNU General Public
29 // License. However the source code for this file must still be made available
30 // in accordance with section (3) of the GNU General Public License.
32 // This exception does not invalidate any other reasons why a work based on
33 // this file might be covered by the GNU General Public License.
35 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
36 // at http://sources.redhat.com/ecos/ecos-license/
37 // -------------------------------------------
38 //####ECOSGPLCOPYRIGHTEND####
39 //####UCDSNMPCOPYRIGHTBEGIN####
41 // -------------------------------------------
43 // Portions of this software may have been derived from the UCD-SNMP
44 // project, <http://ucd-snmp.ucdavis.edu/> from the University of
45 // California at Davis, which was originally based on the Carnegie Mellon
46 // University SNMP implementation. Portions of this software are therefore
47 // covered by the appropriate copyright disclaimers included herein.
49 // The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2"
50 // -------------------------------------------
52 //####UCDSNMPCOPYRIGHTEND####
53 //==========================================================================
54 //#####DESCRIPTIONBEGIN####
59 // Purpose: Port of UCD-SNMP distribution to eCos.
63 //####DESCRIPTIONEND####
65 //==========================================================================
66 /********************************************************************
67 Copyright 1989, 1991, 1992 by Carnegie Mellon University
70 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
74 Permission to use, copy, modify and distribute this software and its
75 documentation for any purpose and without fee is hereby granted,
76 provided that the above copyright notice appears in all copies and
77 that both that copyright notice and this permission notice appear in
78 supporting documentation, and that the name of CMU and The Regents of
79 the University of California not be used in advertising or publicity
80 pertaining to distribution of the software without specific written
83 CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
84 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
85 WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR
86 THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
87 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
88 FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
89 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
90 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
91 *********************************************************************/
95 /***********************************************************
96 Copyright 1992 by Carnegie Mellon University
100 Permission to use, copy, modify, and distribute this software and its
101 documentation for any purpose and without fee is hereby granted,
102 provided that the above copyright notice appear in all copies and that
103 both that copyright notice and this permission notice appear in
104 supporting documentation, and that the name of CMU not be
105 used in advertising or publicity pertaining to distribution of the
106 software without specific, written prior permission.
108 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
109 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
110 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
111 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
112 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
113 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
115 ******************************************************************/
117 * System dependent routines go here
130 #if TIME_WITH_SYS_TIME
132 # include <sys/timeb.h>
134 # include <sys/time.h>
139 # include <sys/time.h>
145 #include <sys/types.h>
147 #if HAVE_NETINET_IN_H
148 #include <netinet/in.h>
154 #if HAVE_SYS_SOCKET_H
155 #include <sys/socket.h>
161 #if HAVE_SYS_SOCKIO_H
162 #include <sys/sockio.h>
166 #include <sys/ioctl.h>
174 #include <sys/file.h>
182 #include <sys/param.h>
184 #if HAVE_SYS_SYSCTL_H
185 #include <sys/sysctl.h>
198 #ifdef HAVE_SYS_STAT_H
199 #include <sys/stat.h>
203 #include "snmp_api.h"
206 #include "snmp_logging.h"
208 #define NUM_NETWORKS 32 /* max number of interfaces to check */
211 # define IFF_LOOPBACK 0
214 #define LOOPBACK 0x7f000001
218 /* ********************************************* */
220 # define WIN32_LEAN_AND_MEAN
221 # define WIN32IO_IS_STDIO
222 # define PATHLEN 1024
225 # include <windows.h>
228 /* The idea here is to read all the directory names into a string table
229 * (separated by nulls) and when one of the other dir functions is called
230 * return the pointer to the current file name.
233 opendir(const char *filename)
238 char scannamespc[PATHLEN];
239 char *scanname = scannamespc;
241 WIN32_FIND_DATA FindData;
244 /* check to see if filename is a directory */
245 if (stat(filename, &sbuf) < 0 || sbuf.st_mode & S_IFDIR == 0) {
249 /* get the file system characteristics */
250 /* if(GetFullPathName(filename, SNMP_MAXPATH, root, &dummy)) {
251 * if(dummy = strchr(root, '\\'))
253 * if(GetVolumeInformation(root, volname, SNMP_MAXPATH, &serial,
254 * &maxname, &flags, 0, 0)) {
255 * downcase = !(flags & FS_CASE_IS_PRESERVED);
263 /* Create the search pattern */
264 strcpy(scanname, filename);
266 if(strchr("/\\", *(scanname + strlen(scanname) - 1)) == NULL)
267 strcat(scanname, "/*");
269 strcat(scanname, "*");
271 /* do the FindFirstFile call */
272 fh = FindFirstFile(scanname, &FindData);
273 if(fh == INVALID_HANDLE_VALUE) {
277 /* Get us a DIR structure */
278 p = (DIR*)malloc(sizeof(DIR));
279 /* Newz(1303, p, 1, DIR); */
283 /* now allocate the first part of the string table for
284 * the filenames that we find.
286 idx = strlen(FindData.cFileName)+1;
287 p->start = (char*)malloc(idx);
288 /* New(1304, p->start, idx, char);*/
289 if(p->start == NULL) {
293 strcpy(p->start, FindData.cFileName);
299 /* loop finding all the files that match the wildcard
300 * (which should be all of them in this directory!).
301 * the variable idx should point one past the null terminator
302 * of the previous string found.
304 while (FindNextFile(fh, &FindData)) {
305 len = strlen(FindData.cFileName);
306 /* bump the string table size by enough for the
307 * new name and it's null terminator
309 p->start = (char*)realloc((void*)p->start, idx+len+1);
310 /* Renew(p->start, idx+len+1, char);*/
311 if(p->start == NULL) {
315 strcpy(&p->start[idx], FindData.cFileName);
317 * strlwr(&p->start[idx]);
329 /* Readdir just returns the current string pointer and bumps the
330 * string pointer to the nDllExport entry.
336 static int dummy = 0;
339 /* first set up the structure to return */
340 len = strlen(dirp->curr);
341 strcpy(dirp->dirstr.d_name, dirp->curr);
342 dirp->dirstr.d_namlen = len;
345 dirp->dirstr.d_ino = dummy++;
347 /* Now set up for the nDllExport call to readdir */
348 dirp->curr += len + 1;
349 if (dirp->curr >= (dirp->start + dirp->size)) {
353 return &(dirp->dirstr);
359 /* free the memory allocated by opendir */
368 #ifndef HAVE_GETTIMEOFDAY
370 int gettimeofday(struct timeval *tv,
373 struct _timeb timebuffer;
376 tv->tv_usec = timebuffer.millitm * 1000;
377 tv->tv_sec = timebuffer.time;
380 #endif /* !HAVE_GETTIMEOFDAY */
382 in_addr_t get_myaddr(void)
384 char local_host[130];
386 LPHOSTENT lpstHostent;
387 SOCKADDR_IN in_addr, remote_in_addr;
389 int nAddrSize = sizeof(SOCKADDR);
391 in_addr.sin_addr.s_addr = INADDR_ANY;
393 result = gethostname(local_host, sizeof(local_host));
396 lpstHostent = gethostbyname((LPSTR)local_host);
399 in_addr.sin_addr.s_addr = *((u_long FAR *) (lpstHostent->h_addr));
400 return((in_addr_t)in_addr.sin_addr.s_addr);
404 /* if we are here, than we don't have host addr */
405 hSock = socket(AF_INET, SOCK_DGRAM, 0);
406 if (hSock != INVALID_SOCKET)
408 /* connect to any port and address */
409 remote_in_addr.sin_family = AF_INET;
410 remote_in_addr.sin_len = sizeof(remote_in_addr);
411 remote_in_addr.sin_port = htons(IPPORT_ECHO);
412 remote_in_addr.sin_addr.s_addr = inet_addr("128.22.33.11");
413 result=connect(hSock,(LPSOCKADDR)&remote_in_addr,sizeof(SOCKADDR));
414 if (result != SOCKET_ERROR)
416 /* get local ip address */
417 getsockname(hSock, (LPSOCKADDR)&in_addr,(int FAR *)&nAddrSize);
421 return((in_addr_t)in_addr.sin_addr.s_addr);
424 long get_uptime (void)
426 return (0); /* not implemented */
430 winsock_startup (void)
432 WORD VersionRequested;
435 static char errmsg[100];
437 VersionRequested = MAKEWORD(1,1);
438 i = WSAStartup(VersionRequested, &stWSAData);
441 if (i == WSAVERNOTSUPPORTED)
442 sprintf(errmsg,"Unable to init. socket lib, does not support 1.1");
445 sprintf(errmsg,"Socket Startup error %d", i);
452 void winsock_cleanup (void)
458 /*******************************************************************/
461 * XXX What if we have multiple addresses?
462 * XXX Could it be computed once then cached?
464 in_addr_t get_myaddr (void)
468 struct ifreq *ifrp, ifreq;
471 struct sockaddr_in *in_addr;
474 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
476 ifc.ifc_len = sizeof(conf);
477 ifc.ifc_buf = (caddr_t)conf;
478 memset(conf,0,sizeof(conf));
479 if (ioctl(sd, SIOCGIFCONF, (char *)&ifc) < 0){
486 while (ifc.ifc_len && ifrp->ifr_name[0]) {
488 if (ioctl(sd, SIOCGIFFLAGS, (char *)&ifreq) >= 0) {
489 in_addr = (struct sockaddr_in *)&ifrp->ifr_addr;
490 if ((ifreq.ifr_flags & IFF_UP)
492 && (ifreq.ifr_flags & IFF_RUNNING)
493 #endif /* IFF_RUNNING */
494 && !(ifreq.ifr_flags & IFF_LOOPBACK)
495 && in_addr->sin_addr.s_addr != LOOPBACK){
496 #ifdef SYS_IOCTL_H_HAS_SIOCGIFADDR
497 if (ioctl(sd, SIOCGIFADDR, (char *)&ifreq) >= 0) {
498 in_addr = (struct sockaddr_in *)&(ifreq.ifr_addr);
501 return in_addr->sin_addr.s_addr;
506 sa = &ifrp->ifr_addr;
507 if (sa->sa_len <= sizeof(*sa)) {
510 ifrp=(struct ifreq *)(sa->sa_len + (char *)sa);
511 ifc.ifc_len -= sa->sa_len - sizeof(*sa);
513 ifc.ifc_len -= sizeof(*ifrp);
515 } while (!ifrp->ifr_name[0] && ifc.ifc_len);
522 #if !defined(solaris2) && !defined(linux) && !defined(cygwin) && !defined(__ECOS)
524 * Returns boottime in centiseconds(!).
525 * Caches this for future use.
527 long get_boottime (void)
529 static long boottime_csecs = 0;
530 struct timeval boottime;
531 #ifdef CAN_USE_SYSCTL
536 static struct nlist nl[] = {
538 { (char*)"_boottime" },
540 { (char*)"boottime" },
547 if ( boottime_csecs != 0 )
548 return( boottime_csecs );
550 #ifdef CAN_USE_SYSCTL
552 mib[1] = KERN_BOOTTIME;
554 len = sizeof(boottime);
556 sysctl(mib, 2, &boottime, &len, NULL, NULL);
557 boottime_csecs = (boottime.tv_sec * 100) + (boottime.tv_usec / 10000);
558 #else /* CAN_USE_SYSCTL */
559 if ((kmem = open("/dev/kmem", 0)) < 0)
561 nlist(KERNEL_LOC, nl);
562 if (nl[0].n_type == 0){
567 lseek(kmem, (long)nl[0].n_value, L_SET);
568 read(kmem, &boottime, sizeof(boottime));
570 boottime_csecs = (boottime.tv_sec * 100) + (boottime.tv_usec / 10000);
571 #endif /* CAN_USE_SYSCTL */
573 return( boottime_csecs );
578 * Returns uptime in centiseconds(!).
581 long get_uptime (void)
583 #if !defined(solaris2) && !defined(linux) && !defined(cygwin)
585 long boottime_csecs, nowtime_csecs;
587 boottime_csecs = get_boottime();
588 if (boottime_csecs == 0)
590 gettimeofday(&now,(struct timezone *)0);
591 nowtime_csecs = (now.tv_sec * 100) + (now.tv_usec / 10000);
593 return (nowtime_csecs - boottime_csecs);
597 kstat_ctl_t *ksc = kstat_open();
600 kstat_named_t *named;
604 ks = kstat_lookup (ksc, "unix", -1, "system_misc");
606 kid = kstat_read (ksc, ks, NULL);
608 named = kstat_data_lookup(ks, "lbolt");
610 lbolt = named->value.ul;
617 #endif /* solaris2 */
620 FILE *in = fopen ("/proc/uptime", "r");
621 long uptim = 0, a, b;
623 if (2 == fscanf (in, "%ld.%ld", &a, &b))
629 return (0); /* not implemented */
633 #ifndef HAVE_GETTIMEOFDAY
635 int gettimeofday(struct timeval *tv,
640 tv->tv_sec = time(NULL);
643 #endif /* !HAVE_GETTIMEOFDAY */
647 /*******************************************************************/
649 #ifndef HAVE_STRNCASECMP
651 /* test for NULL pointers before and NULL characters after
652 * comparing possibly non-NULL strings.
653 * WARNING: This function does NOT check for array overflow.
655 int strncasecmp(const char *s1, const char *s2, size_t nch)
667 for (ii = 0; (ii < nch) && *s1 && *s2; ii++, s1++, s2++)
669 res = (int) (tolower(*s1) - tolower(*s2));
687 int strcasecmp(const char *s1, const char *s2)
689 return strncasecmp(s1, s2, 1000000);
692 #endif /* HAVE_STRNCASECMP */
697 strdup(const char *src)
702 len = strlen(src) + 1;
703 if ((dst = (char *)malloc(len)) == NULL)
708 #endif /* HAVE_STRDUP */
711 int setenv(const char *name,
718 if (overwrite == 0) {
719 if (getenv(name)) return 0;
721 cp = (char*)malloc(strlen(name)+strlen(value)+2);
722 if (cp == NULL) return -1;
723 sprintf(cp, "%s=%s", name, value);
727 #endif /* HAVE_SETENV */
730 calculate_time_diff(struct timeval *now, struct timeval *then)
732 struct timeval tmp, diff;
733 memcpy(&tmp, now, sizeof(struct timeval));
735 tmp.tv_usec += 1000000L;
736 diff.tv_sec = tmp.tv_sec - then->tv_sec;
737 diff.tv_usec = tmp.tv_usec - then->tv_usec;
738 if (diff.tv_usec > 1000000L){
739 diff.tv_usec -= 1000000L;
742 return ((diff.tv_sec * 100) + (diff.tv_usec / 10000));
745 #ifndef HAVE_STRCASESTR
747 * only glibc2 has this.
749 char *strcasestr(const char *haystack, const char *needle)
751 const char *cp1=haystack, *cp2=needle;
755 /* printf("looking for '%s' in '%s'\n", needle, haystack); */
756 if (cp1 && cp2 && *cp1 && *cp2)
757 for (cp1=haystack, cp2=needle; *cp1; ) {
758 cx = cp1; cp2 = needle;
760 /* printf("T'%c' ", *cp1); */
761 if (! *cp2) { /* found the needle */
762 /* printf("\nfound '%s' in '%s'\n", needle, cx); */
768 tstch1 = toupper(*cp1);
769 tstch2 = toupper(*cp2);
770 if (tstch1 != tstch2)
772 /* printf("M'%c' ", *cp1); */
789 mkdirhier(const char *pathname, mode_t mode, int skiplast) {
791 char *ourcopy = strdup(pathname);
793 char buf[SNMP_MAXPATH];
795 entry = strtok( ourcopy, "/" );
798 /* check to see if filename is a directory */
802 entry = strtok( NULL, "/");
803 if (entry == NULL && skiplast)
805 if (stat(buf, &sbuf) < 0) {
807 snmp_log(LOG_INFO, "Creating directory: %s\n", buf);
809 CreateDirectory(buf, NULL);
814 /* exists, is it a file? */
815 if ((sbuf.st_mode & S_IFDIR) == 0) {
816 /* ack! can't make a directory on top of a file */
818 return SNMPERR_GENERR;
823 return SNMPERR_SUCCESS;
829 #include <cyg/kernel/kapi.h>
831 long get_boottime (void)
836 long get_uptime (void)
838 return cyg_current_time();