source: branches/blt4/lang/tcl/src/RpSysinfo.c @ 1932

Last change on this file since 1932 was 1403, checked in by gah, 16 years ago

Fix for no sysinfo on OSX

File size: 6.9 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture::sysinfo
4 *
5 *  This is an interface to the system sysinfo() function, which gives
6 *  information about system load averages, use of virtual memory, etc.
7 * ======================================================================
8 *  AUTHOR:  Michael McLennan, Purdue University
9 *  Copyright (c) 2004-2006  Purdue Research Foundation
10 *
11 *  See the file "license.terms" for information on usage and
12 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * ======================================================================
14 */
15#include "config.h"
16#include <tcl.h>
17#include <stdlib.h>
18#include <stddef.h>
19#include <string.h>
20
21static Tcl_CmdProc RpSysinfoCmd;
22
23
24/*
25 * ------------------------------------------------------------------------
26 *  RpSysinfo_Init()
27 *
28 *  Called in Rappture_Init() to initialize the commands defined
29 *  in this file.
30 * ------------------------------------------------------------------------
31 */
32int
33RpSysinfo_Init(interp)
34    Tcl_Interp *interp;  /* interpreter being initialized */
35{
36    /* install the sysinfo command */
37    Tcl_CreateCommand(interp, "::Rappture::sysinfo", RpSysinfoCmd,
38        (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
39
40    return TCL_OK;
41}
42
43#ifndef HAVE_SYSINFO
44
45static int
46RpSysinfoCmd(cdata, interp, argc, argv)
47    ClientData cdata;         /* not used */
48    Tcl_Interp *interp;       /* interpreter handling this request */
49    int argc;                 /* number of command line args */
50    CONST84 char *argv[];     /* strings for command line args */
51{
52    Tcl_SetResult(interp, "command not implemented: no sysinfo", TCL_STATIC);
53    return TCL_ERROR;
54}
55
56#else
57
58#ifdef HAVE_SYS_SYSINFO_H
59#include <sys/sysinfo.h>
60#endif  /* HAVE_SYS_SYSINFO_H */
61
62#define RP_SLOT_LONG   1
63#define RP_SLOT_ULONG  2
64#define RP_SLOT_USHORT 3
65#define RP_SLOT_LOAD   4
66
67struct rpSysinfoList {
68    const char *name;           /* Name of this system parameter */
69    int type;                   /* Parameter type (long, unsigned long,
70                                 * etc.) */
71    int offset;                 /* Offset into sysinfo struct */
72};
73
74#ifdef offsetof
75#define Offset(type, field) ((int) offsetof(type, field))
76#else
77#define Offset(type, field) ((int) ((char *) &((type *) 0)->field))
78#endif
79
80static struct rpSysinfoList RpSysinfoList [] = {
81    {"freeram",   RP_SLOT_ULONG,  Offset(struct sysinfo, freeram)},
82    {"freeswap",  RP_SLOT_ULONG,  Offset(struct sysinfo, freeswap)},
83    {"load1",     RP_SLOT_LOAD,   Offset(struct sysinfo, loads[0])},
84    {"load5",     RP_SLOT_LOAD,   Offset(struct sysinfo, loads[1])},
85    {"load15",    RP_SLOT_LOAD,   Offset(struct sysinfo, loads[2])},
86    {"procs",     RP_SLOT_USHORT, Offset(struct sysinfo, procs)},
87    {"totalram",  RP_SLOT_ULONG,  Offset(struct sysinfo, totalram)},
88    {"totalswap", RP_SLOT_ULONG,  Offset(struct sysinfo, totalswap)},
89    {"uptime",    RP_SLOT_LONG,   Offset(struct sysinfo, uptime)},
90    {NULL, 0, 0}
91};
92
93static Tcl_Obj* RpSysinfoValue(struct sysinfo *sinfo, int idx);
94
95/*
96 * ------------------------------------------------------------------------
97 *  RpSysinfoCmd()
98 *
99 *  Invoked whenever someone uses the "sysinfo" command to get info
100 *  about system load.  Handles the following syntax:
101 *
102 *      sysinfo ?<keyword>...?
103 *
104 *  With no extra args, it returns a list of the form "key1 val1 key2
105 *  val2 ..." with all known system info.  Otherwise, it treats each
106 *  argument as a desired keyword and returns only the values for the
107 *  specified keywords.
108 *
109 *  Returns TCL_OK on success, and TCL_ERROR (along with an error
110 *  message in the interpreter) if anything goes wrong.
111 * ------------------------------------------------------------------------
112 */
113static int
114RpSysinfoCmd(cdata, interp, argc, argv)
115    ClientData cdata;         /* not used */
116    Tcl_Interp *interp;       /* interpreter handling this request */
117    int argc;                 /* number of command line args */
118    CONST84 char *argv[];     /* strings for command line args */
119{
120    char c;
121    int n, i;
122    struct sysinfo info;
123    Tcl_Obj *resultPtr;
124
125    if (sysinfo(&info) < 0) {
126        Tcl_SetResult(interp, "oops! can't query system info", TCL_STATIC);
127        return TCL_ERROR;
128    }
129    resultPtr = Tcl_GetObjResult(interp);
130
131    /*
132     *  If no args are given, return all info in the form:
133     *    key1 value1 key2 value2 ...
134     */
135    if (argc < 2) {
136        for (i=0; RpSysinfoList[i].name != NULL; i++) {
137            Tcl_ListObjAppendElement(interp, resultPtr,
138                Tcl_NewStringObj(RpSysinfoList[i].name, -1));
139            Tcl_ListObjAppendElement(interp, resultPtr,
140                RpSysinfoValue(&info, i));
141        }
142        return TCL_OK;
143    }
144
145    /*
146     *  Query and return each of the specified values.
147     */
148    for (n=1; n < argc; n++) {
149        c = *argv[n];
150        for (i=0; RpSysinfoList[i].name != NULL; i++) {
151            if (c == *RpSysinfoList[i].name
152                  && strcmp(argv[n], RpSysinfoList[i].name) == 0) {
153                break;
154            }
155        }
156
157        /* couldn't find the name in the list?  then return an error */
158        if (RpSysinfoList[i].name == NULL) {
159            Tcl_ResetResult(interp);
160            Tcl_AppendResult(interp, "bad parameter \"",
161                argv[n], "\": should be one of ", (char*)NULL);
162            for (i=0; RpSysinfoList[i].name != NULL; i++) {
163                Tcl_AppendResult(interp, (i == 0) ? "" : ", ",
164                    RpSysinfoList[i].name, (char*)NULL);
165            }
166            return TCL_ERROR;
167        }
168        Tcl_ListObjAppendElement(interp, resultPtr, RpSysinfoValue(&info, i));
169    }
170    return TCL_OK;
171}
172
173/*
174 * ------------------------------------------------------------------------
175 *  RpSysinfoValue()
176 *
177 *  Returns the value for a desired system info parameter, specified as
178 *  as offset into the global RpSysinfoList array.  The value is returned
179 *  as a Tcl_Obj, which should be used or freed by the caller.
180 * ------------------------------------------------------------------------
181 */
182static Tcl_Obj*
183RpSysinfoValue(sinfo, idx)
184    struct sysinfo *sinfo;    /* system load info */
185    int idx;                  /* index for desired sysinfo value */
186{
187    char *ptr;
188    int ival; long lval; double dval, loadscale;
189    ptr = (char*)sinfo + RpSysinfoList[idx].offset;
190
191    switch (RpSysinfoList[idx].type) {
192        case RP_SLOT_LONG:
193            return Tcl_NewLongObj(*(long*)ptr);
194            break;
195        case RP_SLOT_ULONG:
196            lval = *(unsigned long*)ptr;
197            return Tcl_NewLongObj(lval);
198            break;
199        case RP_SLOT_USHORT:
200            ival = *(unsigned short*)ptr;
201            return Tcl_NewIntObj(ival);
202            break;
203        case RP_SLOT_LOAD:
204            loadscale = (double)(1 << SI_LOAD_SHIFT);
205            dval = (double)(*(unsigned long*)ptr)/loadscale;
206            return Tcl_NewDoubleObj(dval);
207            break;
208    }
209    return NULL;
210}
211
212#endif /*HAVE_SYSINFO*/
Note: See TracBrowser for help on using the repository browser.