Experimental RSS code.
[monky] / src / freebsd.c
index 8786af8..e27f480 100644 (file)
 #include <sys/types.h>
 #include <sys/vmmeter.h>
 #include <sys/user.h>
+#include <sys/ioctl.h>
 
 #include <net/if.h>
 #include <net/if_mib.h>
+#include <net/if_media.h>
+#include <net/if_var.h>
+#include <netinet/in.h>
 
 #include <devstat.h>
 #include <fcntl.h>
@@ -27,6 +31,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <dev/wi/if_wavelan_ieee.h>
+
 #include "conky.h"
 
 #define        GETSYSCTL(name, var)    getsysctl(name, &(var), sizeof (var))
@@ -97,8 +103,8 @@ update_uptime()
        time_t now;
        size_t size = sizeof (boottime);
 
-       if ((sysctl(mib, 2, &boottime, &size, NULL, 0) != -1)
-           && (boottime.tv_sec != 0)) {
+       if ((sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) &&
+                       (boottime.tv_sec != 0)) {
                time(&now);
                info.uptime = now - boottime.tv_sec;
        } else {
@@ -163,12 +169,23 @@ update_net_stats()
                ns = get_net_stat((const char *) ifa->ifa_name);
 
                if (ifa->ifa_flags & IFF_UP) {
+                       struct ifaddrs *iftmp;
+
+                       ns->up = 1;
+                       ns->linkstatus = 1;
                        last_recv = ns->recv;
                        last_trans = ns->trans;
 
                        if (ifa->ifa_addr->sa_family != AF_LINK)
                                continue;
 
+                       for (iftmp = ifa->ifa_next; iftmp != NULL &&
+                               strcmp(ifa->ifa_name, iftmp->ifa_name) == 0;
+                               iftmp = iftmp->ifa_next)
+                               if (iftmp->ifa_addr->sa_family == AF_INET)
+                                       memcpy(&(ns->addr), iftmp->ifa_addr,
+                                               iftmp->ifa_addr->sa_len);
+
                        ifd = (struct if_data *) ifa->ifa_data;
                        r = ifd->ifi_ibytes;
                        t = ifd->ifi_obytes;
@@ -191,10 +208,12 @@ update_net_stats()
 
                        ns->last_read_trans = t;
 
-
                        /* calculate speeds */
                        ns->recv_speed = (ns->recv - last_recv) / delta;
                        ns->trans_speed = (ns->trans - last_trans) / delta;
+               } else {
+                       ns->up = 0;
+                       ns->linkstatus = 0;
                }
        }
 
@@ -270,7 +289,8 @@ update_cpu_usage()
        long cp_time[CPUSTATES];
        size_t len = sizeof (cp_time);
 
-       if (cpu_setup == 0) {
+       /* add check for !info.cpu_usage since that mem is freed on a SIGUSR1 */
+       if ((cpu_setup == 0) || (!info.cpu_usage)) {
                get_cpu_count();
                cpu_setup = 1;
        }
@@ -332,19 +352,89 @@ get_acpi_temperature(int fd)
 }
 
 void
-get_battery_stuff(char *buf, unsigned int n, const char *bat)
+get_battery_stuff(char *buf, unsigned int n, const char *bat, int item)
 {
-       int battime;
+       int battime, batcapacity, batstate, ac;
+       char battery_status[64];
+       char battery_time[64];
 
        if (GETSYSCTL("hw.acpi.battery.time", battime))
                (void) fprintf(stderr,
                        "Cannot read sysctl \"hw.acpi.battery.time\"\n");
+       if (GETSYSCTL("hw.acpi.battery.life", batcapacity))
+               (void) fprintf(stderr,
+                                          "Cannot read sysctl \"hw.acpi.battery.life\"\n");
 
-       if (battime != -1)
-               snprintf(buf, n, "Discharging, remaining %d:%2.2d",
-                       battime / 60, battime % 60);
-       else
-               snprintf(buf, n, "Battery is charging");
+       if (GETSYSCTL("hw.acpi.battery.state", batstate))
+               (void) fprintf(stderr,
+                                          "Cannot read sysctl \"hw.acpi.battery.state\"\n");
+
+       if (GETSYSCTL("hw.acpi.acline", ac))
+               (void) fprintf(stderr,
+                                          "Cannot read sysctl \"hw.acpi.acline\"\n");
+
+       if (batstate == 1) {
+               if (battime != -1) {
+                       snprintf (battery_status, sizeof(battery_status)-1,
+                                 "remaining %d%%", batcapacity);
+                       snprintf (battery_time, sizeof(battery_time)-1,
+                                 "%d:%2.2d", battime / 60, battime % 60);
+                       /*
+                       snprintf(buf, n, "remaining %d%% (%d:%2.2d)",
+                                       batcapacity, battime / 60, battime % 60);
+                       */
+               }
+               else
+                       /* no time estimate available yet */
+                       snprintf(battery_status, sizeof(battery_status)-1,
+                                "remaining %d%%", batcapacity);
+                       /*
+                       snprintf(buf, n, "remaining %d%%",
+                                       batcapacity);
+                       */
+               if (ac == 1)
+                       (void) fprintf(stderr, "Discharging while on AC!\n");
+       } else {
+               snprintf (battery_status, sizeof(battery_status)-1,
+                         batstate == 2 ? "charging (%d%%)" : "charged (%d%%)", batcapacity);
+               /*
+               snprintf(buf, n, batstate == 2 ? "charging (%d%%)" : "charged (%d%%)", batcapacity);
+               */
+               if (batstate != 2 && batstate != 0)
+                       (void) fprintf(stderr, "Unknown battery state %d!\n", batstate);
+               if (ac == 0)
+                       (void) fprintf(stderr, "Charging while not on AC!\n");
+       }
+
+       switch (item) {
+        case BATTERY_STATUS:
+                {
+                        snprintf(buf, n, "%s", battery_status);
+                        break;
+                }
+        case BATTERY_TIME:
+                {
+                        snprintf(buf, n, "%s", battery_time);
+                        break;
+                }
+        default:
+                        break;
+        }
+        return;
+}
+
+int
+get_battery_perct(const char *bat)
+{
+       /* not implemented */
+       return (0);
+}
+
+int
+get_battery_perct_bar(const char *bar)
+{
+       /* not implemented */
+       return (0);
 }
 
 int
@@ -454,26 +544,36 @@ get_freq_dynamic(char *p_client_buffer, size_t client_buffer_size,
        snprintf(p_client_buffer, client_buffer_size, p_format,
                (float)((cycles[1] - cycles[0]) / microseconds) / divisor);
 #else
-       get_freq(p_client_buffer, client_buffer_size, p_format, divisor);
+       get_freq(p_client_buffer, client_buffer_size, p_format, divisor, 1);
 #endif
 }
 
-/* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */
-void
+/*void*/
+char
 get_freq(char *p_client_buffer, size_t client_buffer_size,
-               char *p_format, int divisor)
+               char *p_format, int divisor, unsigned int cpu)
 {
        int freq;
+       char *freq_sysctl;
 
-       if (!p_client_buffer || client_buffer_size <= 0
-                       || !p_format || divisor <= 0)
-               return;
+       freq_sysctl = (char *)calloc(16, sizeof(char));
+       if (freq_sysctl == NULL)
+               exit(-1);
 
-       if (GETSYSCTL("dev.cpu.0.freq", freq) == 0)
+       snprintf(freq_sysctl, 16, "dev.cpu.%d.freq", (cpu - 1));
+       
+       if (!p_client_buffer || client_buffer_size <= 0 ||
+                       !p_format || divisor <= 0)
+               return 0;
+
+       if (GETSYSCTL(freq_sysctl, freq) == 0)
                snprintf(p_client_buffer, client_buffer_size,
-                               p_format, freq/divisor);
+                               p_format, (float)freq/divisor);
        else
                snprintf(p_client_buffer, client_buffer_size, p_format, 0.0f);
+
+       free(freq_sysctl);
+       return 1;
 }
 
 void
@@ -485,7 +585,58 @@ update_top()
 void
 update_wifi_stats()
 {
-       /* XXX */
+       struct ifreq ifr;               /* interface stats */
+       struct wi_req wireq;
+       struct net_stat * ns;
+       struct ifaddrs *ifap, *ifa;
+       struct ifmediareq ifmr;
+       int s;
+
+       /*
+        * Get iface table
+        */
+       if (getifaddrs(&ifap) < 0)
+               return;
+
+       for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+               ns = get_net_stat((const char *) ifa->ifa_name);
+
+               s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+               /* Get media type */
+               bzero(&ifmr, sizeof(ifmr));
+               strlcpy(ifmr.ifm_name, ifa->ifa_name, IFNAMSIZ);
+               if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0)
+                       goto cleanup;
+               
+               /*
+                * We can monitor only wireless interfaces
+                * which not in hostap mode
+                */
+               if ((ifmr.ifm_active & IFM_IEEE80211) &&
+                               !(ifmr.ifm_active & IFM_IEEE80211_HOSTAP)) {
+                       /* Get wi status */
+                       bzero(&ifr, sizeof(ifr));
+                       strlcpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ);
+                       wireq.wi_type   = WI_RID_COMMS_QUALITY;
+                       wireq.wi_len    = WI_MAX_DATALEN;
+                       ifr.ifr_data    = (void *) &wireq;
+
+                       if (ioctl(s, SIOCGWAVELAN, (caddr_t) &ifr) < 0) {
+                               perror("ioctl (getting wi status)");
+                               exit(1);
+                       }
+
+                       /*
+                        * wi_val[0] = quality
+                        * wi_val[1] = signal
+                        * wi_val[2] = noise
+                        */
+                       ns->linkstatus = (int) wireq.wi_val[1];
+               }
+cleanup:
+               close(s);
+       }
 }
 void
 update_diskio()
@@ -612,11 +763,11 @@ proc_find_top(struct process **cpu, struct process **mem)
                tmp->name = strdup(processes[i].name);
 
                ttmp = mem[i];
+               mem[i] = tmp;
                if (ttmp != NULL) {
                        free(ttmp->name);
                        free(ttmp);
                }
-               mem[i] = tmp;
        }
 
        qsort(processes, j - 1, sizeof (struct process), comparecpu);
@@ -630,11 +781,11 @@ proc_find_top(struct process **cpu, struct process **mem)
                tmp->name = strdup(processes[i].name);
 
                ttmp = cpu[i];
+               cpu[i] = tmp;
                if (ttmp != NULL) {
                        free(ttmp->name);
                        free(ttmp);
                }
-               cpu[i] = tmp;
        }
 
 #if defined(FREEBSD_DEBUG)
@@ -668,28 +819,38 @@ char
        int fd;
        struct apm_info info;
 
+       out = (char *)calloc(16, sizeof (char));
+
        fd = open(APMDEV, O_RDONLY);
-       if (fd < 0)
-               return ("ERR");
+       if (fd < 0) {
+               strncpy(out, "ERR", 16);
+               return (out);
+       }
 
        if (apm_getinfo(fd, &info) != 0) {
                close(fd);
-               return ("ERR");
+               strncpy(out, "ERR", 16);
+               return (out);
        }
        close(fd);
 
        switch (info.ai_acline) {
                case 0:
-                       return ("off-line");
+                       strncpy(out, "off-line", 16);
+                       return (out);
                        break;
                case 1:
-                       if (info.ai_batt_stat == 3)
-                               return ("charging");
-                       else
-                               return ("on-line");
+                       if (info.ai_batt_stat == 3) {
+                               strncpy(out, "charging", 16);
+                               return (out);
+                       } else {
+                               strncpy(out, "on-line", 16);
+                               return (out);
+                       }
                        break;
                default:
-                       return ("unknown");
+                       strncpy(out, "unknown", 16);
+                       return (out);
                        break;
        }
 }
@@ -771,6 +932,11 @@ char
 
 #endif
 
+void update_entropy (void)
+{
+     /* mirrorbox: can you do anything equivalent in freebsd? -drphibes. */
+}
+
 /* empty stub so conky links */
 void
 free_all_processes(void)