1/* Copyright (c) 1993-2002 2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) 3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) 4 * Copyright (c) 1987 Oliver Laumann 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2, or (at your option) 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program (see the file COPYING); if not, write to the 18 * Free Software Foundation, Inc., 19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 20 * 21 **************************************************************** 22 */ 23 24#include <sys/types.h> 25#include <fcntl.h> 26#ifdef ultrix 27# include <sys/fixpoint.h> 28#endif 29 30/* mach stuff included here to prevent index macro conflict */ 31#ifdef NeXT 32# include <sys/version.h> 33# if KERNEL_MAJOR_VERSION > 2 34# include <mach/mach.h> 35# else 36# include <mach.h> 37# endif 38#endif 39 40#include "config.h" 41#include "screen.h" 42 43#include "extern.h" 44 45#ifdef LOADAV 46 47static int GetLoadav __P((void)); 48 49static LOADAV_TYPE loadav[LOADAV_NUM]; 50static int loadok; 51 52 53 54/***************************************************************/ 55 56#if defined(linux) && !defined(LOADAV_DONE) 57#define LOADAV_DONE 58/* 59 * This is the easy way. It relies in /proc being mounted. 60 * For the big and ugly way refer to previous screen version. 61 */ 62void 63InitLoadav() 64{ 65 loadok = 1; 66} 67 68static int 69GetLoadav() 70{ 71 FILE *fp; 72 char buf[128], *s; 73 int i; 74 double d, e; 75 76 if ((fp = secfopen("/proc/loadavg", "r")) == NULL) 77 return 0; 78 *buf = 0; 79 fgets(buf, sizeof(buf), fp); 80 fclose(fp); 81 /* can't use fscanf because the decimal point symbol depends on 82 * the locale but the kernel uses always '.'. 83 */ 84 s = buf; 85 for (i = 0; i < (LOADAV_NUM > 3 ? 3 : LOADAV_NUM); i++) 86 { 87 d = e = 0; 88 while(*s == ' ') 89 s++; 90 if (*s == 0) 91 break; 92 for(;;) 93 { 94 if (*s == '.') 95 e = 1; 96 else if (*s >= '0' && *s <= '9') 97 { 98 d = d * 10 + (*s - '0'); 99 if (e) 100 e *= 10; 101 } 102 else 103 break; 104 s++; 105 } 106 loadav[i] = e ? d / e : d; 107 } 108 return i; 109} 110#endif /* linux */ 111 112/***************************************************************/ 113 114#if defined(LOADAV_GETLOADAVG) && !defined(LOADAV_DONE) 115#define LOADAV_DONE 116void 117InitLoadav() 118{ 119 loadok = 1; 120} 121 122static int 123GetLoadav() 124{ 125 return getloadavg(loadav, LOADAV_NUM); 126} 127#endif 128 129/***************************************************************/ 130 131#if defined(apollo) && !defined(LOADAV_DONE) 132#define LOADAV_DONE 133void 134InitLoadav() 135{ 136 loadok = 1; 137} 138 139static int 140GetLoadav() 141{ 142 proc1_$get_loadav(loadav); 143 return LOADAV_NUM; 144} 145#endif 146 147/***************************************************************/ 148 149#if defined(NeXT) && !defined(LOADAV_DONE) 150#define LOADAV_DONE 151 152static processor_set_t default_set; 153 154void 155InitLoadav() 156{ 157 kern_return_t error; 158 159 error = processor_set_default(host_self(), &default_set); 160 if (error != KERN_SUCCESS) 161 mach_error("Error calling processor_set_default", error); 162 else 163 loadok = 1; 164} 165 166static int 167GetLoadav() 168{ 169 unsigned int info_count; 170 struct processor_set_basic_info info; 171 host_t host; 172 173 info_count = PROCESSOR_SET_BASIC_INFO_COUNT; 174 if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, &host, (processor_set_info_t)&info, &info_count) != KERN_SUCCESS) 175 return 0; 176 loadav[0] = (float)info.load_average / LOAD_SCALE; 177 return 1; 178} 179#endif 180 181/***************************************************************/ 182 183#if defined(sun) && defined(SVR4) && !defined(LOADAV_DONE) 184#define LOADAV_DONE 185 186#include <kstat.h> 187 188static kstat_ctl_t *kc; 189 190void 191InitLoadav() 192{ 193 loadok = (kc = kstat_open()) != 0; 194} 195 196static int 197GetLoadav() 198{ 199 kstat_t *ks; 200 kstat_named_t *avgs[3]; 201 int i; 202 203 kstat_chain_update(kc); 204 if ((ks = kstat_lookup(kc, "unix", -1, "system_misc")) == 0 || kstat_read(kc, ks, (void *)0) == -1) 205 return (loadok = 0); 206 avgs[0] = kstat_data_lookup(ks, "avenrun_1min"); 207 avgs[1] = kstat_data_lookup(ks, "avenrun_5min"); 208 avgs[2] = kstat_data_lookup(ks, "avenrun_15min"); 209 for (i = 0; i < 3; i++) 210 { 211 if (avgs[i] == 0 || avgs[i]->data_type != KSTAT_DATA_ULONG) 212 return (loadok = 0); 213 loadav[i] = avgs[i]->value.ul; 214 } 215 return 3; 216} 217 218#endif 219 220/***************************************************************/ 221 222#if defined(__osf__) && defined(__alpha) && !defined(LOADAV_DONE) 223#define LOADAV_DONE 224 225struct rtentry; struct mbuf; /* shut up gcc on OSF/1 4.0 */ 226#include <sys/table.h> 227 228void 229InitLoadav() 230{ 231 loadok = 1; 232} 233 234static int 235GetLoadav() 236{ 237 struct tbl_loadavg tbl; 238 int i; 239 240 if (table(TBL_LOADAVG, 0, &tbl, 1, sizeof(struct tbl_loadavg)) != 1) 241 return 0; 242 243 if (tbl.tl_lscale) 244 { 245 /* in long */ 246 for (i = 0; i < LOADAV_NUM; i++) 247 loadav[i] = (double) tbl.tl_avenrun.l[i] / tbl.tl_lscale; 248 } 249 else 250 { 251 /* in double */ 252 for (i = 0; i < LOADAV_NUM; i++) 253 loadav[i] = tbl.tl_avenrun.d[i]; 254 } 255 return LOADAV_NUM; 256} 257#endif 258 259/***************************************************************/ 260 261#if !defined(LOADAV_DONE) 262/* 263 * The old fashion way: open kernel and read avenrun 264 * 265 * Header File includes 266 */ 267 268# ifdef NLIST_STRUCT 269# include <nlist.h> 270# else 271# include <a.out.h> 272# endif 273# ifndef NLIST_DECLARED 274extern int nlist __P((char *, struct nlist *)); 275# endif 276 277#ifdef LOADAV_USE_NLIST64 278# define nlist nlist64 279#endif 280 281static struct nlist nl[2]; 282static int kmemf; 283 284#ifdef _IBMR2 285# define nlist(u,l) knlist(l,1,sizeof(*l)) 286#endif 287 288void 289InitLoadav() 290{ 291 debug("Init Kmem...\n"); 292 if ((kmemf = open("/dev/kmem", O_RDONLY)) == -1) 293 return; 294# if !defined(_AUX_SOURCE) && !defined(AUX) 295# ifdef NLIST_NAME_UNION 296 nl[0].n_un.n_name = LOADAV_AVENRUN; 297# else 298 nl[0].n_name = LOADAV_AVENRUN; 299# endif 300# else 301 strncpy(nl[0].n_name, LOADAV_AVENRUN, sizeof(nl[0].n_name)); 302# endif 303 debug2("Searching in %s for %s\n", LOADAV_UNIX, nl[0].n_name); 304 nlist(LOADAV_UNIX, nl); 305 if (nl[0].n_value == 0) 306 { 307 close(kmemf); 308 return; 309 } 310# if 0 /* no longer needed (Al.Smith@aeschi.ch.eu.org) */ 311# ifdef sgi 312 nl[0].n_value &= (unsigned long)-1 >> 1; /* clear upper bit */ 313# endif /* sgi */ 314# endif 315 debug1("AvenrunSym found (0x%lx)!!\n", nl[0].n_value); 316 loadok = 1; 317} 318 319static int 320GetLoadav() 321{ 322 if (lseek(kmemf, (off_t) nl[0].n_value, 0) == (off_t)-1) 323 return 0; 324 if (read(kmemf, (char *) loadav, sizeof(loadav)) != sizeof(loadav)) 325 return 0; 326 return LOADAV_NUM; 327} 328#endif 329 330/***************************************************************/ 331 332#ifndef FIX_TO_DBL 333#define FIX_TO_DBL(l) ((double)(l) / LOADAV_SCALE) 334#endif 335 336void 337AddLoadav(p) 338char *p; 339{ 340 int i, j; 341 if (loadok == 0) 342 return; 343 j = GetLoadav(); 344 for (i = 0; i < j; i++) 345 { 346 sprintf(p, " %2.2f" + !i, FIX_TO_DBL(loadav[i])); 347 p += strlen(p); 348 } 349} 350 351#endif /* LOADAV */ 352