static int home_or_pro(const OSVERSIONINFOEX osinfo, char **name) { int r; if (osinfo.wSuiteMask & VER_SUITE_PERSONAL) { r = sg_concat_string(name, " Home Edition"); } else { r = sg_concat_string(name, " Professional"); } return r; }
sg_network_io_stats *sg_get_network_io_stats(int *entries){ int interfaces; sg_network_io_stats *network_stat_ptr; #ifdef SOLARIS kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *knp; #endif #ifdef LINUX FILE *f; /* Horrible big enough, but it should be easily big enough */ char line[8096]; regex_t regex; regmatch_t line_match[9]; #endif #ifdef ALLBSD struct ifaddrs *net, *net_ptr; struct if_data *net_data; #endif #ifdef WIN32 PMIB_IFTABLE if_table; MIB_IFROW if_row; int i, no, j; /* used for duplicate interface names. 5 for space, hash, up to two * numbers and terminating slash */ char buf[5]; #endif #ifdef ALLBSD if(getifaddrs(&net) != 0){ sg_set_error_with_errno(SG_ERROR_GETIFADDRS, NULL); return NULL; } interfaces=0; for(net_ptr=net;net_ptr!=NULL;net_ptr=net_ptr->ifa_next){ if(net_ptr->ifa_addr->sa_family != AF_LINK) continue; if (VECTOR_RESIZE(network_stats, interfaces + 1) < 0) { return NULL; } network_stat_ptr=network_stats+interfaces; if (sg_update_string(&network_stat_ptr->interface_name, net_ptr->ifa_name) < 0) { return NULL; } net_data=(struct if_data *)net_ptr->ifa_data; network_stat_ptr->rx=net_data->ifi_ibytes; network_stat_ptr->tx=net_data->ifi_obytes; network_stat_ptr->ipackets=net_data->ifi_ipackets; network_stat_ptr->opackets=net_data->ifi_opackets; network_stat_ptr->ierrors=net_data->ifi_ierrors; network_stat_ptr->oerrors=net_data->ifi_oerrors; network_stat_ptr->collisions=net_data->ifi_collisions; network_stat_ptr->systime=time(NULL); interfaces++; } freeifaddrs(net); #endif #ifdef SOLARIS if ((kc = kstat_open()) == NULL) { sg_set_error(SG_ERROR_KSTAT_OPEN, NULL); return NULL; } interfaces=0; for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { if (strcmp(ksp->ks_class, "net") == 0) { kstat_read(kc, ksp, NULL); #ifdef SOL7 #define LRX "rbytes" #define LTX "obytes" #define LIPACKETS "ipackets" #define LOPACKETS "opackets" #define VALTYPE value.ui32 #else #define LRX "rbytes64" #define LTX "obytes64" #define LIPACKETS "ipackets64" #define LOPACKETS "opackets64" #define VALTYPE value.ui64 #endif /* Read rx */ if((knp=kstat_data_lookup(ksp, LRX))==NULL){ /* This is a network interface, but it doesn't * have the rbytes/obytes values; for instance, * the loopback devices have this behaviour * (although they do track packets in/out). */ /* FIXME: Show packet counts when byte counts * not available. */ continue; } /* Create new network_stats */ if (VECTOR_RESIZE(network_stats, interfaces + 1) < 0) { return NULL; } network_stat_ptr=network_stats+interfaces; /* Finish reading rx */ network_stat_ptr->rx=knp->VALTYPE; /* Read tx */ if((knp=kstat_data_lookup(ksp, LTX))==NULL){ continue; } network_stat_ptr->tx=knp->VALTYPE; /* Read ipackets */ if((knp=kstat_data_lookup(ksp, LIPACKETS))==NULL){ continue; } network_stat_ptr->ipackets=knp->VALTYPE; /* Read opackets */ if((knp=kstat_data_lookup(ksp, LOPACKETS))==NULL){ continue; } network_stat_ptr->opackets=knp->VALTYPE; /* Read ierrors */ if((knp=kstat_data_lookup(ksp, "ierrors"))==NULL){ continue; } network_stat_ptr->ierrors=knp->value.ui32; /* Read oerrors */ if((knp=kstat_data_lookup(ksp, "oerrors"))==NULL){ continue; } network_stat_ptr->oerrors=knp->value.ui32; /* Read collisions */ if((knp=kstat_data_lookup(ksp, "collisions"))==NULL){ continue; } network_stat_ptr->collisions=knp->value.ui32; /* Read interface name */ if (sg_update_string(&network_stat_ptr->interface_name, ksp->ks_name) < 0) { return NULL; } /* Store systime */ network_stat_ptr->systime=time(NULL); interfaces++; } } kstat_close(kc); #endif #ifdef LINUX f=fopen("/proc/net/dev", "r"); if(f==NULL){ sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/net/dev"); return NULL; } /* read the 2 lines.. Its the title, so we dont care :) */ fgets(line, sizeof(line), f); fgets(line, sizeof(line), f); if((regcomp(®ex, "^ *([^:]+): *([0-9]+) +([0-9]+) +([0-9]+) +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +([0-9]+) +([0-9]+) +([0-9]+) +[0-9]+ +[0-9]+ +([0-9]+)", REG_EXTENDED))!=0){ sg_set_error(SG_ERROR_PARSE, NULL); return NULL; } interfaces=0; while((fgets(line, sizeof(line), f)) != NULL){ if((regexec(®ex, line, 9, line_match, 0))!=0){ continue; } if (VECTOR_RESIZE(network_stats, interfaces + 1) < 0) { return NULL; } network_stat_ptr=network_stats+interfaces; if(network_stat_ptr->interface_name!=NULL){ free(network_stat_ptr->interface_name); } network_stat_ptr->interface_name=sg_get_string_match(line, &line_match[1]); network_stat_ptr->rx=sg_get_ll_match(line, &line_match[2]); network_stat_ptr->tx=sg_get_ll_match(line, &line_match[5]); network_stat_ptr->ipackets=sg_get_ll_match(line, &line_match[3]); network_stat_ptr->opackets=sg_get_ll_match(line, &line_match[6]); network_stat_ptr->ierrors=sg_get_ll_match(line, &line_match[4]); network_stat_ptr->oerrors=sg_get_ll_match(line, &line_match[7]); network_stat_ptr->collisions=sg_get_ll_match(line, &line_match[8]); network_stat_ptr->systime=time(NULL); interfaces++; } fclose(f); regfree(®ex); #endif #ifdef CYGWIN sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin"); return NULL; #endif #ifdef HPUX sg_set_error(SG_ERROR_UNSUPPORTED, "HP-UX"); return NULL; #endif #ifdef WIN32 interfaces = 0; if((if_table = win32_get_devices()) == NULL) { sg_set_error(SG_ERROR_DEVICES, "network"); return NULL; } if(VECTOR_RESIZE(network_stats, if_table->dwNumEntries) < 0) { free(if_table); return NULL; } for (i=0; i<if_table->dwNumEntries; i++) { network_stat_ptr=network_stats+i; if_row = if_table->table[i]; if(sg_update_string(&network_stat_ptr->interface_name, if_row.bDescr) < 0) { free(if_table); return NULL; } network_stat_ptr->tx = if_row.dwOutOctets; network_stat_ptr->rx = if_row.dwInOctets; network_stat_ptr->ipackets = if_row.dwInUcastPkts + if_row.dwInNUcastPkts; network_stat_ptr->opackets = if_row.dwOutUcastPkts + if_row.dwOutNUcastPkts; network_stat_ptr->ierrors = if_row.dwInErrors; network_stat_ptr->oerrors = if_row.dwOutErrors; network_stat_ptr->collisions = 0; /* can't do that */ network_stat_ptr->systime = time(NULL); interfaces++; } free(if_table); /* Please say there's a nicer way to do this... If windows has two (or * more) identical network cards, GetIfTable returns them with the same * name, not like in Device Manager where the other has a #2 etc after * it. So, add the #number here. Should we be doing this? Or should the * end programs be dealing with duplicate names? Currently breaks * watch.pl in rrdgraphing. But Unix does not have the issue of * duplicate net device names. */ for (i=0; i<interfaces; i++) { no = 2; for(j=i+1; j<interfaces; j++) { network_stat_ptr=network_stats+j; if(strcmp(network_stats[i].interface_name, network_stat_ptr->interface_name) == 0) { if(snprintf(buf, sizeof(buf), " #%d", no) < 0) { break; } if(sg_concat_string(&network_stat_ptr->interface_name, buf) != 0) { return NULL; } no++; } } } #endif *entries=interfaces; return network_stats; }
static char *get_os_name(const OSVERSIONINFOEX osinfo) { char *name; char tmp[10]; int r = 0; /* we only compile on 2k or newer, which is version 5 * Covers 2000, XP and 2003 */ if (osinfo.dwMajorVersion != 5) { return "Unknown"; } switch(osinfo.dwMinorVersion) { case 0: /* Windows 2000 */ name = strdup(WINDOWS2000); if(name == NULL) { goto out; } if (osinfo.wProductType == VER_NT_WORKSTATION) { r = home_or_pro(osinfo, &name); } else if (osinfo.wSuiteMask & VER_SUITE_DATACENTER) { r = sg_concat_string(&name, " Datacenter Server"); } else if (osinfo.wSuiteMask & VER_SUITE_ENTERPRISE) { r = sg_concat_string(&name, " Advanced Server"); } else { r = sg_concat_string(&name, " Server"); } break; case 1: /* Windows XP */ name = strdup(WINDOWSXP); if(name == NULL) { goto out; } r = home_or_pro(osinfo, &name); break; case 2: /* Windows 2003 */ name = strdup(WINDOWS2003); if(name == NULL) { goto out; } if (osinfo.wSuiteMask & VER_SUITE_DATACENTER) { r = sg_concat_string(&name, " Datacenter Edition"); } else if (osinfo.wSuiteMask & VER_SUITE_ENTERPRISE) { r = sg_concat_string(&name, " Enterprise Edition"); } else if (osinfo.wSuiteMask & VER_SUITE_BLADE) { r = sg_concat_string(&name, " Web Edition"); } else { r = sg_concat_string(&name, " Standard Edition"); } break; default: name = strdup("Windows 2000 based"); break; } if(r != 0) { free (name); return NULL; } /* Add on service pack version */ if (osinfo.wServicePackMajor != 0) { if(osinfo.wServicePackMinor == 0) { if(snprintf(tmp, sizeof(tmp), " SP%d", osinfo.wServicePackMajor) != -1) { r = sg_concat_string(&name, tmp); } } else { if(snprintf(tmp, sizeof(tmp), " SP%d.%d", osinfo.wServicePackMajor, osinfo.wServicePackMinor) != -1) { r = sg_concat_string(&name, tmp); } } if(r) { free(name); return NULL; } } return name; out: /* strdup failed */ sg_set_error_with_errno(SG_ERROR_MALLOC, NULL); return NULL; }
static char * get_os_name(const OSVERSIONINFOEX osinfo, SYSTEM_INFO sysinfo) { char *name; char tmp[10]; int r = 0; /* we only compile on 2k or newer, which is version 5 * Covers 2000, XP and 2003 */ if (osinfo.dwMajorVersion != 5) { return "Unknown"; } switch(osinfo.dwMinorVersion) { case 0: /* Windows 2000 */ name = strdup(WINDOWS2000); if(name == NULL) { goto out; } if (osinfo.wProductType == VER_NT_WORKSTATION) { r = home_or_pro(osinfo, &name); } else if (osinfo.wSuiteMask & VER_SUITE_DATACENTER) { r = sg_concat_string(&name, " Datacenter Server"); } else if (osinfo.wSuiteMask & VER_SUITE_ENTERPRISE) { r = sg_concat_string(&name, " Advanced Server"); } else { r = sg_concat_string(&name, " Server"); } break; case 1: /* Windows XP */ name = strdup(WINDOWSXP); if(name == NULL) { goto out; } r = home_or_pro(osinfo, &name); break; case 2: /* Windows 2003 */ /* XXX complete detection using http://msdn.microsoft.com/en-us/library/ms724833%28VS.85%29.aspx */ if( (osinfo.wProductType == VER_NT_WORKSTATION) && (sysinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) ) { name = strdup(WINDOWSXP); r = home_or_pro(osinfo, &name); r = sg_concat_string(&name, " x64 Edition"); } else { name = strdup(WINDOWS2003); } if(name == NULL) { goto out; } if (osinfo.wSuiteMask & VER_SUITE_DATACENTER) { r = sg_concat_string(&name, " Datacenter Edition"); } else if (osinfo.wSuiteMask & VER_SUITE_ENTERPRISE) { r = sg_concat_string(&name, " Enterprise Edition"); } else if (osinfo.wSuiteMask & VER_SUITE_BLADE) { r = sg_concat_string(&name, " Web Edition"); } else { r = sg_concat_string(&name, " Standard Edition"); } break; default: name = strdup("Windows 2000 based"); break; } if(r != 0) { free (name); return NULL; } /* Add on service pack version */ if (osinfo.wServicePackMajor != 0) { if(osinfo.wServicePackMinor == 0) { if(snprintf(tmp, sizeof(tmp), " SP%d", osinfo.wServicePackMajor) != -1) { r = sg_concat_string(&name, tmp); } } else { if(snprintf(tmp, sizeof(tmp), " SP%d.%d", osinfo.wServicePackMajor, osinfo.wServicePackMinor) != -1) { r = sg_concat_string(&name, tmp); } } if(r) { free(name); return NULL; } } return name; out: /* strdup failed */ SET_ERROR_WITH_ERRNO("os", SG_ERROR_MALLOC, "get_os_name: strdup() failed"); return NULL; }