From wmcbrine@clark.net Thu Jun 19 23:43:21 1997 Date: 17 Jun 1997 17:01:53 GMT From: William McBrine Newsgroups: comp.os.minix Subject: "uptime" for Minix One thing I really missed in Minix was the "uptime" command. So, I wrote my own. Perhaps this will be of use to others. Suggestions for improvements welcome. (To compile this, just type "cc uptime.c -o uptime":) /* uptime for Minix (and other systems), version 0.2 * Reports time/users only; no load report * * by William McBrine , June 17, 1997 * Public domain * * This version of "uptime" relies on the wtmp file, so it can be a little * slow. Although written for Minix 2.0, it's portable; I compiled and ran * it under Linux/i386 and Solaris/Sparc without modification. * */ #include #include #include #include #include #define WTMPPATH "/usr/adm/wtmp" #define UTMPPATH "/etc/utmp" void plural(const int x) { if (x != 1) printf("s"); } int ampm(int x) { if (x > 12) x -= 12; if (!x) x = 12; return x; } int main(void) { FILE *wtmpfile; struct utmp wtrec; struct tm tboot, tnow; time_t boottime, now; int years, days, hours, mins, ucount = 0; /* Find last reboot */ if ((wtmpfile = fopen(WTMPPATH, "r")) == NULL) { printf("Cannot find %s\n", WTMPPATH); exit(1); } while (fread(&wtrec, sizeof(struct utmp), 1, wtmpfile) == 1) if (wtrec.ut_line[0] == '~') boottime = wtrec.ut_time; fclose(wtmpfile); /* Find last reboot -- backwards version * I thought it would be faster to scan backwards from the end of the file * and stop after the last '~'. This did speed things up on my Minix and * Linux systems, but was taking so long on my ISP's Solaris box (with a 15 * meg wtmp file) that I aborted it before it finished. Maybe it fouled up * the cache's strategy? Anyway, try this if you like. * * long wtpoint = 0; * * if ((wtmpfile = fopen(WTMPPATH, "r")) == NULL) { * printf("Cannot find %s\n", WTMPPATH); * exit(1); * } * do { * wtpoint -= sizeof(struct utmp); * fseek(wtmpfile, wtpoint, SEEK_END); * fread(&wtrec, sizeof(struct utmp), 1, wtmpfile); * } while ((!ferror(wtmpfile)) && (wtrec.ut_line[0] != '~')); * boottime = wtrec.ut_time; * fclose(wtmpfile); * */ /* Count users */ if ((wtmpfile = fopen(UTMPPATH, "r")) == NULL) { printf("Cannot find %s\n", UTMPPATH); exit(1); } while (fread(&wtrec, sizeof(struct utmp), 1, wtmpfile) == 1) if ((wtrec.ut_user[0]) && (wtrec.ut_type == USER_PROCESS)) ucount++; fclose(wtmpfile); /* Calculate uptime */ time(&now); tboot = *(localtime(&boottime)); tnow = *(localtime(&now)); years = tnow.tm_year - tboot.tm_year; days = tnow.tm_yday - tboot.tm_yday; hours = tnow.tm_hour - tboot.tm_hour; mins = tnow.tm_min - tboot.tm_min; if (mins < 0) { mins += 60; hours -= 1; } if (hours < 0) { hours += 24; days -= 1; } if (days < 0) { days += 365; /* No attempt to deal with leap years */ years -= 1; } /* I've never actually seen a system with an uptime over a year, * so I don't know what the original "uptime" does in that case. :-) * I hope this will suffice. */ /* Report */ printf("%3d:%02d%cm up ", ampm(tnow.tm_hour), tnow.tm_min, (tnow.tm_hour < 12) ? 'a' : 'p'); if (years > 0) { printf("%d year", years); plural(years); printf(", "); } if (days > 0) { printf("%d day", days); plural(days); printf(", "); } if (hours > 0) printf("%2d:%02d,", hours, mins); else printf("%d min,", mins); printf("%3d user", ucount); plural(ucount); printf("\n"); return 0; } -- William McBrine | http://www.clark.net/pub/wmcbrine/html/ wmcbrine@clark.net | Unsolicited commercial emailers will be annihilated