/* ** $RCSfile: Uptime.c,v $ ** $Filename: Uptime.c $ ** $Revision: 1.0 $ ** $Date: $ ** ** Modified by Etienne Vogt from the SysInfo.library example by Petri Nordlund ** This file is public domain. */ /* * This is a fairly complete uptime-program, based on the example provided * with the original Executive-based SysInfo.library, which has been modified * for use with Sysmon. * It supports multiuser.library support to show the number of users currently * logged in. */ #include #include #include #include #define __USE_SYSBASE #include #include #include #include #include #include "SysInfo.h" #include "SysInfo_protos.h" #include "SysInfo_pragmas.h" #include "/sysmon.h" #include "/sysmon_protos.h" #include "/sysmon_pragmas.h" #include #include #include #include /* PROTOTYPES */ int main(int argc, char **argv); static void cleanexit(ULONG rc); static void AddUser(ULONG user, UWORD *uids, ULONG *nusers); static ULONG CountTasks(void); static void GetTime(void); static void Users(void); static void LoadAverages(void); static void Uptime(void); static ULONG EClockDivide(struct EClockVal *numerator, ULONG denominator); /* VARIABLES */ struct muBase *muBase = NULL; struct SysInfo *si = NULL; struct Library *SysInfoBase = NULL; extern struct ExecBase *SysBase; extern struct DosLibrary *DOSBase; struct SysmonBase *SysmonBase = NULL; struct Device *TimerBase = NULL; struct timerequest myTimeReq; static UBYTE version[] = "$VER: Uptime 1.0 (3.8.2001)"; int main(int argc, char **argv) { if ((SysmonBase = (struct SysmonBase *)OpenLibrary("sysmon.library",1)) == NULL) { puts("Can't open sysmon.library."); cleanexit(RETURN_FAIL); } if (!(SysInfoBase = OpenLibrary(SYSINFONAME, SYSINFOVERSION))) { puts("Can't open SysInfo.library."); cleanexit(RETURN_FAIL); } /* Initialize SysInfo.library, this will make the connection to the * server-process and allocate the SysInfo-structure. */ if (!(si = InitSysInfo())) { puts("Can't initialize SysInfo."); cleanexit(RETURN_FAIL); } if (OpenDevice(TIMERNAME, UNIT_ECLOCK, (struct IORequest *)&myTimeReq, 0L)) { printf("Can't open %s\n", TIMERNAME); cleanexit(RETURN_FAIL); } else TimerBase = myTimeReq.tr_node.io_Device; /* If this fails, we'll just output "1 user" */ muBase = (struct muBase *) OpenLibrary(MULTIUSERNAME, MULTIUSERVERSION); GetTime(); printf(", "); Uptime(); printf(", "); Users(); printf(", "); LoadAverages(); printf("\n"); cleanexit(RETURN_OK); } /* * Exit. Free everything. */ static void cleanexit(ULONG rc) { if (muBase) CloseLibrary((struct Library *)muBase); if (TimerBase) CloseDevice((struct IORequest *)&myTimeReq); /* Free SysInfo.library */ if (si) FreeSysInfo(si); if (SysInfoBase) CloseLibrary(SysInfoBase); if (SysmonBase) CloseLibrary((struct Library *)SysmonBase); exit(rc); } /* * Print system time */ static void GetTime(void) { struct DateTime dtime; char timestr[LEN_DATSTRING+1]; DateStamp(&dtime.dat_Stamp); dtime.dat_Format = FORMAT_DOS; dtime.dat_Flags = 0; dtime.dat_StrDay = NULL; dtime.dat_StrDate = NULL; dtime.dat_StrTime = timestr; DateToStr(&dtime); printf(timestr); } /* * Print number of users (from Multiuser if available) */ static void Users(void) { ULONG nusers = 1; if(muBase) { ULONG numtasks; UWORD *uids; smLockTaskTable(LTTF_READ); /* Count the number of tasks currently in system */ numtasks = CountTasks(); /* Allocate memory for each task */ if (uids=AllocVec(numtasks*sizeof(UWORD),MEMF_CLEAR|MEMF_PUBLIC)) { struct TaskInfo *tinfo = NULL; /* Find out how many different uids there are */ nusers = 0; while (tinfo = smNextTaskInfo(tinfo)) AddUser(muGetTaskOwner(tinfo->ti_Task), uids, &nusers); FreeVec(uids); } smUnLockTaskTable(LTTF_READ); } if ((nusers>1) || (nusers==0)) printf("%d users", nusers); else printf("%d user",nusers); } static void AddUser(ULONG user, UWORD *uids, ULONG *nusers) { UWORD uid; BOOL found = FALSE; ULONG i; if (user) { uid = user>>16; for (i=0; !found && (i<*nusers); i++) found = (uids[i] == uid); if (!found) uids[(*nusers)++] = uid; } } static ULONG CountTasks(void) { ULONG i = 0; struct TaskInfo *tinfo = NULL; while (tinfo = smNextTaskInfo(tinfo)) i++; return i; } /* * Print uptime from timer.device EClock. */ static void Uptime(void) { struct EClockVal UpTime; ULONG EClockRate; ULONG days, hrs, mins; EClockRate = ReadEClock(&UpTime); mins = EClockDivide(&UpTime, 60*EClockRate); days = mins / (24*60); mins %= 24*60; hrs = mins / 60; mins %= 60; if (days || hrs || mins) printf("up "); if (days > 0) { if (days > 1) printf("%d days ", days); else printf("%d day ", days); } if (hrs > 0) printf("%d:%02d", hrs, mins); else { if ((mins > 1) || (mins == 0)) printf("%d mins", mins); else printf("%d min", mins); } } static ULONG EClockDivide(struct EClockVal *numerator, ULONG denominator) { int bits; ULONG d1,d2,d3; d1 = 0x0; d2 = numerator->ev_hi; d3 = numerator->ev_lo; for (bits = 0; bits < 64; bits++) { /* now left-shift d1,d2,d3 */ d1 <<= 1; if (d2 & 0x80000000) d1 |= 0x1; d2 <<= 1; if (d3 & 0x80000000) d2 |= 0x1; d3 <<= 1; if (d1 >= denominator) { d1 -= denominator; d3 |= 0x1; } } /* fill in the remainder */ numerator->ev_lo = d1; /* return the quotient, or the low part of it, at least */ return d3; } /* * Print load averages */ static void LoadAverages(void) { struct SI_LoadAverage load; /* This will be filled by GetLoadAverage() */ GetLoadAverage(si, &load); /* Ask SysInfo.library for current load averages */ printf("load:"); switch (si->loadavg_type) { case LOADAVG_FIXEDPNT: /* Convert fixed point values to floating point values */ if (si->loadavg_time1) printf(" %.2f",(float) load.lavg_fixed.load1 / (float) si->fscale); else printf(" N/A"); if (si->loadavg_time2) printf(" %.2f",(float) load.lavg_fixed.load2 / (float) si->fscale); else printf(" N/A"); if (si->loadavg_time3) printf(" %.2f",(float) load.lavg_fixed.load3 / (float) si->fscale); else printf(" N/A"); break; default: /* Load average type is not supported */ printf("-"); } }