/* ** $RCSfile: ShowSys.c,v $ ** $Filename: ShowSys.c $ ** $Revision: 1.7 $ ** $Date: 2001/04/28 16:28:28 $ ** ** sysmon.library Task display command ShowSys (version 1.8) ** ** (C) Copyright 1995-2001 by Etienne Vogt ** 64/32 Division algorithm kindly provided by Thomas Richter */ #include #include #include #include #include #include #include #include #define __USE_SYSBASE #include #include #include #include #include #include #include #include "sysmon.h" #include "sysmon_protos.h" #include "sysmon_pragmas.h" #define TIBUFMAX 30 #define TNAMEMAX 31 #define NT_CLI NT_USER struct tiBuffer { struct TaskInfo tib_tinfo; char tib_name[TNAMEMAX]; UBYTE tib_type; LONG tib_clinum; ULONG tib_stacksize; ULONG tib_sigalloc; ULONG tib_sigwait; ULONG tib_sigrecvd; ULONG tib_sigexcept; BYTE tib_pri; UBYTE tib_flags; UBYTE tib_state; }; struct tiBufArray { struct tiBufArray *tba_Link; struct tiBuffer tba_bufs[TIBUFMAX]; }; struct ExecBase *SysBase; struct DosLibrary *DOSBase; struct SysmonBase *SysmonBase; struct Device *TimerBase; struct timerequest myTimeReq; static struct WBStartup *wbmsg; static struct RDArgs *myrda; ULONG __saveds main(void); static void cleanexit(ULONG rc); static char *uptimestr(struct EClockVal *clockval, ULONG clockrate); static char *cputimestr(struct EClockVal *clockval, ULONG clockrate); static char *taskstate(UBYTE state, ULONG sigwait); static char *taskflags(UBYTE flags, UBYTE moreflags); static char *tasktype(UBYTE type, LONG clinum); static char *bstr2c(BSTR bstring); static char *cpustr(UWORD cpuflags); static char *filterctrl(char *string); static ULONG EClockDivide(struct EClockVal *numerator, ULONG denominator); APTR SPrintf(STRPTR buffer, STRPTR format, ...); void freetibufs(struct tiBufArray *tibufs); static UBYTE version[] = "$VER: ShowSys 1.8 (18.11.2001)"; static UBYTE template[] = "FULL/S"; #define OPT_FULL 0 #define OPTMAX 1 ULONG __saveds main(void) /* No startup code */ { struct Process *myproc; ULONG EClockRate; struct tiBufArray *tibufs; LONG opts[OPTMAX]; SysBase = *(struct ExecBase **)4; DOSBase = NULL; SysmonBase = NULL; TimerBase = NULL; wbmsg = NULL; myrda = NULL; myproc = (struct Process *)FindTask(NULL); if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36)) == NULL) { Alert(AT_Recovery|AG_OpenLib|AO_DOSLib); return 100; } if (!(myproc->pr_CLI)) /* If started from WB, exit cleanly */ { WaitPort(&(myproc->pr_MsgPort)); wbmsg = (struct WBStartup *)GetMsg(&(myproc->pr_MsgPort)); cleanexit(20); } if ((SysmonBase = (struct SysmonBase *)OpenLibrary("sysmon.library",1)) == NULL) { if (DOSBase->dl_lib.lib_Version >= 36) PutStr("ShowSys : Couldn't open sysmon.library V1+.\n"); cleanexit(20); } if (OpenDevice(TIMERNAME, UNIT_ECLOCK, (struct IORequest *)&myTimeReq, 0L)) { Alert(AT_Recovery|AG_OpenDev|AO_TimerDev); cleanexit(100); } else { char Workbench[8], NodeName[16]; struct EClockVal UpTime; struct DateTime SysTime; UBYTE strDate[LEN_DATSTRING], strTime[LEN_DATSTRING]; memset((char *)opts, 0, sizeof(opts)); if ((myrda = ReadArgs(template, opts, NULL)) == NULL) { PrintFault(IoErr(),"ShowSys"); cleanexit(20); } TimerBase = myTimeReq.tr_node.io_Device; EClockRate = ReadEClock(&UpTime); if (GetVar("Workbench", Workbench, sizeof(Workbench) - 1, GVF_GLOBAL_ONLY) > 0) Printf("AmigaOS %s", Workbench); else PutStr("AmigaOS ?????"); if (GetVar("HostName", NodeName, sizeof(NodeName) - 1, GVF_GLOBAL_ONLY) > 0) Printf(" at %s", NodeName); else PutStr(" at ????? "); DateStamp(&SysTime.dat_Stamp); SysTime.dat_Format = FORMAT_DOS; SysTime.dat_Flags = 0; SysTime.dat_StrDay = NULL; SysTime.dat_StrDate = strDate; SysTime.dat_StrTime = strTime; if (DateToStr(&SysTime)) Printf(" %s %s", SysTime.dat_StrDate, SysTime.dat_StrTime); else Printf(" "); Printf(" UpTime :%s\n", uptimestr(&UpTime, EClockRate)); } Printf("Address Name State Pri CPU [%.5s] Type\n",cpustr(SysBase->AttnFlags)); if (opts[OPT_FULL]) Printf("> Stack SigAlloc SigWait SigRecvd SigExcpt Flags Dispatch\n"); if ((tibufs = AllocVec(sizeof(struct tiBufArray), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) { PutStr("ShowSys : No memory for TaskInfo buffers.\n"); cleanexit(20); } else { struct TaskInfo *tinfo = NULL; struct tiBufArray *tba = tibufs; struct tiBuffer *buf; int j, i = 0, numtask = 0; smLockTaskTable(LTTF_READ); while (tinfo = smNextTaskInfo(tinfo)) { struct Task *task; struct CommandLineInterface *cli; char *comname; int n; numtask++; buf = &tba->tba_bufs[i]; memcpy(buf, tinfo, sizeof(struct TaskInfo)); task = tinfo->ti_Task; if (task->tc_Node.ln_Name) strcpy(buf->tib_name, filterctrl(task->tc_Node.ln_Name)); else strcpy(buf->tib_name, "<< No Name >>"); buf->tib_flags = task->tc_Flags; buf->tib_state = task->tc_State; buf->tib_sigalloc = task->tc_SigAlloc; buf->tib_sigwait = task->tc_SigWait; buf->tib_sigrecvd = task->tc_SigRecvd; buf->tib_sigexcept = task->tc_SigExcept; if (buf->tib_state == TS_WAIT && task->tc_SigWait == 0) buf->tib_state = TS_STOP; buf->tib_pri = task->tc_Node.ln_Pri; buf->tib_type = task->tc_Node.ln_Type; if (buf->tib_type == NT_PROCESS && (cli = BADDR(((struct Process *)task)->pr_CLI))) { buf->tib_clinum = ((struct Process *)task)->pr_TaskNum; buf->tib_type = NT_CLI; buf->tib_stacksize = cli->cli_DefaultStack * sizeof(ULONG); if (cli->cli_Module && (comname = bstr2c(cli->cli_CommandName)) && (n = strlen(buf->tib_name)) < TNAMEMAX - 4) { comname = filterctrl(FilePart(comname)); strcat(buf->tib_name, " ("); strncat(buf->tib_name, comname, TNAMEMAX - n - 4); strcat(buf->tib_name, ")"); } } else if (buf->tib_type == NT_PROCESS) buf->tib_stacksize = ((struct Process *)task)->pr_StackSize; else buf->tib_stacksize = (ULONG)task->tc_SPUpper - (ULONG)task->tc_SPLower; if (++i == TIBUFMAX) { struct tiBufArray *tba1; if (tba1 = AllocVec(sizeof(struct tiBufArray), MEMF_PUBLIC | MEMF_CLEAR)) { tba->tba_Link = tba1; tba = tba1; i = 0; } else { smUnLockTaskTable(LTTF_READ); freetibufs(tibufs); Printf("ShowSys : No memory for TaskInfo buffers.\n"); cleanexit(20); } } } smUnLockTaskTable(LTTF_READ); for (j = 0, tba = tibufs, i = 0 ; j < numtask ; j++) { buf = &tba->tba_bufs[i]; Printf("%08lx %-30.30s %-5s %4ld %16s %-8s\n", buf->tib_tinfo.ti_Task, buf->tib_name, taskstate(buf->tib_state, buf->tib_sigwait), buf->tib_pri, cputimestr(&buf->tib_tinfo.ti_CPUTime, EClockRate), tasktype(buf->tib_type, buf->tib_clinum)); if (opts[OPT_FULL]) Printf(">%7lu %08lx %08lx %08lx %08lx %8s %10lu\n", buf->tib_stacksize, buf->tib_sigalloc, buf->tib_sigwait, buf->tib_sigrecvd, buf->tib_sigexcept, taskflags(buf->tib_flags, buf->tib_tinfo.ti_Flags), buf->tib_tinfo.ti_DispCount); if (CheckSignal(SIGBREAKF_CTRL_C)) { PutStr("*** BREAK ***\n"); break; } if (++i == TIBUFMAX) { tba = tba->tba_Link; i = 0; } } freetibufs(tibufs); } cleanexit(0); } static void cleanexit(ULONG rc) { if (TimerBase) CloseDevice((struct IORequest *)&myTimeReq); if (SysmonBase) CloseLibrary((struct Library *)SysmonBase); if (myrda) FreeArgs(myrda); if (wbmsg) { Forbid(); ReplyMsg((struct Message *)wbmsg); } if (DOSBase) CloseLibrary((struct Library *)DOSBase); Exit(rc); } static char *uptimestr(struct EClockVal *clockval, ULONG clockrate) { static char buffer[16]; ULONG seconds; UWORD updays, uphours, upminutes, upseconds; seconds = EClockDivide(clockval, clockrate); updays = seconds / (24*60*60); seconds %= 24*60*60; uphours = seconds / (60*60); seconds %= 60*60; upminutes = seconds / 60; upseconds = seconds % 60; SPrintf(buffer, "%4lu-%02lu:%02lu:%02lu", updays, uphours, upminutes, upseconds); return buffer; } static char *cputimestr(struct EClockVal *clockval, ULONG clockrate) { static char buffer[18]; ULONG seconds; UWORD cpudays, cpuhours, cpuminutes, cpuseconds, cpumillis; seconds = EClockDivide(clockval, clockrate); cpudays = seconds / (24*60*60); seconds %= 24*60*60; cpuhours = seconds / (60*60); seconds %= 60*60; cpuminutes = seconds / 60; cpuseconds = seconds % 60; cpumillis = clockval->ev_lo / (clockrate / 1000); if (cpumillis == 1000) cpumillis--; SPrintf(buffer, "%3lu-%02lu:%02lu:%02lu.%03lu", cpudays, cpuhours, cpuminutes, cpuseconds, cpumillis); return buffer; } 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; } static char *taskflags(UBYTE flags, UBYTE moreflags) { static char buffer[9]; buffer[0] = (flags & TF_LAUNCH) ? 'L' : '-'; buffer[1] = (flags & TF_SWITCH) ? 'S' : '-'; buffer[2] = (flags & TF_EXCEPT) ? 'E' : '-'; buffer[3] = (flags & TF_STACKCHK) ? 'C' : '-'; buffer[4] = (flags & TF_ETASK) ? 'X' : '-'; buffer[5] = (flags & TF_PROCTIME) ? 'P' : '-'; buffer[6] = (moreflags & TIF_INEXCEPT) ? 'I' : '-'; buffer[7] = (moreflags & TIF_WAKEUP) ? 'W' : '-'; buffer[8] = '\0'; return buffer; } static char *taskstate(UBYTE state, ULONG sigwait) { switch(state) { case TS_INVALID: return "INVLD"; case TS_ADDED: return "ADDED"; case TS_RUN: return "RUN"; case TS_READY: return "READY"; case TS_WAIT: if (sigwait == 0) return "STOP"; else if (sigwait == SIGF_ABORT) return "SWABO"; else if (sigwait == SIGF_CHILD) return "SWCHI"; else if (sigwait == SIGF_SINGLE) return "SWSIN"; else if (sigwait == SIGF_INTUITION) return "SWINT"; else if (sigwait == SIGF_NET) return "SWNET"; else if (sigwait == SIGF_DOS) return "SWDOS"; else if (sigwait == SIGBREAKF_CTRL_C) return "SWBRC"; else if (sigwait == SIGBREAKF_CTRL_D) return "SWBRD"; else if (sigwait == SIGBREAKF_CTRL_E) return "SWBRE"; else if (sigwait == SIGBREAKF_CTRL_F) return "SWBRF"; else return "WAIT"; case TS_EXCEPT: return "EXCPT"; case TS_REMOVED: return "REMVD"; case TS_STOP: return "STOP"; case TS_FROZEN: return "FROZN"; case TS_HIBERNATE: return "HIBER"; case TS_PAGEFLTWAIT: return "PGFWT"; case TS_WAITAND: return "WAITA"; case TS_TRAP: return "TRAP"; case TS_FREEWAIT: return "FREWT"; default: return "?????"; } } static char *tasktype(UBYTE type, LONG clinum) { static char buffer[10]; switch(type) { case NT_TASK: SPrintf(buffer,"Task"); break; case NT_PROCESS: SPrintf(buffer,"Process"); break; case NT_CLI: SPrintf(buffer,"Cli %-4ld",clinum); break; default: SPrintf(buffer,"???"); break; } return buffer; } #define AFB_68060 7 #define AFF_68060 (1L<<7) static char *cpustr(UWORD cpuflags) { if (cpuflags & AFF_68060) return "68060"; else if (cpuflags & AFF_68040) return "68040"; else if (cpuflags & AFF_68030) return "68030"; else if (cpuflags & AFF_68020) return "68020"; else if (cpuflags & AFF_68010) return "68010"; else return "68000"; } static char *bstr2c(BSTR bstring) { static char buffer[256]; char *ptr; int n; if ((ptr = BADDR(bstring)) == NULL || (n = *ptr++) == 0) return NULL; strncpy(buffer, ptr, n); buffer[n] = 0; return buffer; } static char *filterctrl(char *string) { static char buffer[TNAMEMAX]; int i; for (i = 0 ; *string && i < TNAMEMAX - 1 ; i++, string++) { if ((*string & 0x7f) < ' ') buffer[i] = '.'; else buffer[i] = *string; } buffer[i] = 0; return buffer; } APTR SPrintf(STRPTR buffer, STRPTR format, ...) { return smVSPrintf(buffer, format, &format + 1); } void freetibufs(struct tiBufArray *tibufs) { struct tiBufArray *nexttba; do { nexttba = tibufs->tba_Link; FreeVec(tibufs); } while (tibufs = nexttba); }