1044 lines
26 KiB
C
1044 lines
26 KiB
C
/*
|
|
SPY.C
|
|
|
|
Written by DavidW
|
|
Started on 12/11/91
|
|
|
|
Derived from earlier work by Poh Siew, GeoffO, Joe, CharlesD, JohnH, & PeterM.
|
|
*/
|
|
|
|
#include <p_std.h>
|
|
#include <p_file.h>
|
|
#include <epoc.h>
|
|
#include <wlib.h>
|
|
#include <hwif.h>
|
|
|
|
GLREF_C VOID wsReport(HANDLE);
|
|
GLREF_C VOID MonitorBandWidth(VOID);
|
|
GLREF_C VOID DisableReads(UINT flag);
|
|
|
|
GLREF_D UBYTE DatHeapLocked;
|
|
|
|
LOCAL_D TEXT *cmds[]=
|
|
{
|
|
"dChange data",
|
|
"hUse decimal",
|
|
"pChange processes",
|
|
"uUpdate",
|
|
"bBand width",
|
|
"tTimer off",
|
|
"rRefresh rate",
|
|
"nLog client",
|
|
"mLog all clients",
|
|
"cCompress heaps",
|
|
"wRewalk failed process",
|
|
"gGoto process",
|
|
"lReset least stack",
|
|
"kKill process",
|
|
"xExit",
|
|
NULL
|
|
};
|
|
|
|
#define DISPLAY_ITEMS 5
|
|
#define TIMER_ITEMS 2
|
|
#define LOG_ITEMS 2
|
|
#define SPECIAL_ITEMS 6
|
|
|
|
#define ITEMS_BEFORE_DISPLAY 0
|
|
#define ITEMS_BEFORE_TIMER DISPLAY_ITEMS
|
|
#define ITEMS_BEFORE_LOG (ITEMS_BEFORE_TIMER+TIMER_ITEMS)
|
|
#define ITEMS_BEFORE_SPECIAL (ITEMS_BEFORE_LOG+LOG_ITEMS)
|
|
|
|
#define USE_ITEM 1
|
|
#define TIMER_ITEM ITEMS_BEFORE_TIMER
|
|
|
|
LOCAL_D H_MENU_DATA mdata[]=
|
|
{
|
|
"Display",DISPLAY_ITEMS,
|
|
"Timer",TIMER_ITEMS,
|
|
"Log",LOG_ITEMS,
|
|
"Special",SPECIAL_ITEMS,
|
|
NULL
|
|
};
|
|
|
|
GLDEF_D TEXT ** _cmds=(&cmds[0]);
|
|
GLDEF_D H_MENU_DATA * _mdata=(&mdata[0]);
|
|
|
|
|
|
LOCAL_D UINT MainWid;
|
|
|
|
#define TEXT_HEIGHT 10
|
|
#define TEXT_ASCENT 8
|
|
|
|
#define LAY_TOP_BORDER 4
|
|
#define Y_TO_FIRST_PROCESS 15
|
|
|
|
#define SCREEN_WIDTH 240
|
|
#define LAY_LEFT_BORDER 4
|
|
#define LAY_RIGHT_BORDER 4
|
|
|
|
#define NAME_COLUMN_INDENT 4
|
|
#define NAME_COLUMN_WIDTH 74
|
|
#define X_TO_FIRST_COLUMN (LAY_LEFT_BORDER+NAME_COLUMN_INDENT+NAME_COLUMN_WIDTH)
|
|
#define FIRST_COLUMN_WIDTH 32
|
|
#define SECOND_COLUMN_WIDTH 50
|
|
#define THIRD_COLUMN_WIDTH 72
|
|
#define TRAILING_INDENT 4
|
|
#define X_TO_END (SCREEN_WIDTH-LAY_RIGHT_BORDER)
|
|
|
|
LOCAL_D UWORD cwid[3]={FIRST_COLUMN_WIDTH,SECOND_COLUMN_WIDTH,THIRD_COLUMN_WIDTH};
|
|
|
|
typedef struct
|
|
{
|
|
TEXT name[E_MAX_NAME+2];
|
|
UWORD bytes_allocated;
|
|
UWORD bytes_free;
|
|
UWORD seg_size;
|
|
UWORD last_free;
|
|
UWORD least_stack;
|
|
UWORD priority;
|
|
UWORD stack_pointer;
|
|
UWORD pid;
|
|
UWORD cells_allocated;
|
|
UWORD cells_free;
|
|
UWORD iosemcnt;
|
|
UWORD status;
|
|
} PROCESS_DATA;
|
|
|
|
#define PROCESS_SYSTEM 1
|
|
#define PROCESS_APPLICATION 2
|
|
#define PROCESS_ALL 3
|
|
|
|
LOCAL_D UWORD which_processes=PROCESS_ALL;
|
|
|
|
LOCAL_D UWORD using_decimal=FALSE;
|
|
LOCAL_D UWORD lastbflags=0;
|
|
|
|
#define DISPLAY_PROCESS_NAME 0
|
|
#define DISPLAY_BYTES_ALLOCED 1
|
|
#define DISPLAY_BYTES_FREE 2
|
|
#define DISPLAY_SEG_SIZE 3
|
|
#define DISPLAY_LAST_FREE 4
|
|
#define DISPLAY_LEAST_STACK 5
|
|
#define DISPLAY_PRIORITY 6
|
|
#define DISPLAY_STACK_POINTER 7
|
|
#define DISPLAY_PID 8
|
|
#define DISPLAY_CELLS_ALLOCED 9
|
|
#define DISPLAY_CELLS_FREE 10
|
|
#define DISPLAY_IOSEMCNT 11
|
|
#define DISPLAY_STATUS 12
|
|
|
|
LOCAL_D TEXT *titles[13]=
|
|
{
|
|
"Process name",
|
|
"Alloc bytes",
|
|
"Bytes free",
|
|
"Seg size",
|
|
"Last free",
|
|
"Lst stack",
|
|
"Priority",
|
|
"Stack ptr",
|
|
"Proc ID",
|
|
"Alloc cells",
|
|
"Cells free",
|
|
"IO count",
|
|
"Status"
|
|
};
|
|
|
|
LOCAL_D TEXT *statuses[]=
|
|
{
|
|
"Curr",
|
|
"Busy",
|
|
"TimQ",
|
|
"Susp",
|
|
"Wait"
|
|
};
|
|
|
|
LOCAL_D UWORD col[4]=
|
|
{
|
|
DISPLAY_PROCESS_NAME,
|
|
DISPLAY_BYTES_ALLOCED,
|
|
DISPLAY_CELLS_ALLOCED,
|
|
DISPLAY_LEAST_STACK
|
|
};
|
|
|
|
LOCAL_D PROCESS_DATA proc[E_MAX_PROCESSES-1];
|
|
LOCAL_D UWORD numproc;
|
|
LOCAL_D HANDLE failpid=NULL;
|
|
|
|
typedef struct mblock
|
|
{
|
|
UWORD mlen;
|
|
struct mblock *mnext;
|
|
} MBLOCK;
|
|
|
|
#define SZMBLK sizeof(MBLOCK)
|
|
#define SZHD sizeof(UWORD)
|
|
|
|
#define ERR_FREECELL_BEYOND_MEMHIGH 1
|
|
#define ERR_FREECELL_GOES_BACKWARDS 2
|
|
#define ERR_CELL_LENGTH_TOO_SMALL 3
|
|
#define ERR_CELL_LENGTH_ODD 4
|
|
#define ERR_ALLOCED_CELLS_OVERRUN_FREE 5
|
|
#define ERR_TOTALS_DONT_MATCH 6
|
|
|
|
LOCAL_D TEXT *heap_errors[]=
|
|
{
|
|
"Free cell beyond memhigh",
|
|
"Free cell goes backwards",
|
|
"Cell length too small",
|
|
"Cell length odd",
|
|
"Alloced cells don't end at next free cell",
|
|
"Total free + total alloced != segment size"
|
|
};
|
|
|
|
#define STACK_READ_SIZE 256
|
|
|
|
LOCAL_D UWORD selproc=0;
|
|
LOCAL_D UWORD topproc=0;
|
|
|
|
LOCAL_D LONG timint=50;
|
|
LOCAL_D VOID *timcb;
|
|
LOCAL_D WORD timstat;
|
|
LOCAL_D UWORD using_timer=TRUE;
|
|
|
|
|
|
LOCAL_C VOID QueueTimer(VOID)
|
|
{
|
|
if (using_timer)
|
|
p_ioa4(timcb,P_FRELATIVE,&timstat,&timint);
|
|
}
|
|
|
|
LOCAL_C VOID CancelTimer(VOID)
|
|
{
|
|
if (using_timer)
|
|
{
|
|
p_iow2(timcb,P_FCANCEL);
|
|
p_waitstat(&timstat);
|
|
}
|
|
}
|
|
|
|
LOCAL_C INT GetWidth(TEXT *pb)
|
|
{
|
|
return(gTextWidth(WS_FONT_BASE,G_STY_NORMAL,pb,p_slen(pb)));
|
|
}
|
|
|
|
LOCAL_C VOID DrawTitles(VOID)
|
|
{
|
|
INT i;
|
|
INT totwid;
|
|
INT width[4];
|
|
INT gap;
|
|
TEXT *buf;
|
|
P_RECT box;
|
|
|
|
totwid=0;
|
|
for (i=0; i<=3; i++)
|
|
totwid+=(width[i]=GetWidth(titles[col[i]]));
|
|
gap=(X_TO_END-LAY_LEFT_BORDER-totwid)/3;
|
|
box.tl.x=LAY_LEFT_BORDER;
|
|
box.tl.y=LAY_TOP_BORDER;
|
|
box.br.y=LAY_TOP_BORDER+TEXT_HEIGHT;
|
|
for (i=0; i<=3; i++)
|
|
{
|
|
if (i==3)
|
|
box.br.x=X_TO_END;
|
|
else
|
|
box.br.x=box.tl.x+width[i]+gap;
|
|
buf=(titles[col[i]]);
|
|
gPrintBoxText(&box,TEXT_ASCENT,G_TEXT_ALIGN_LEFT,0,buf,p_slen(buf));
|
|
box.tl.x=box.br.x;
|
|
}
|
|
}
|
|
|
|
LOCAL_C VOID InvertLine(INT j)
|
|
{
|
|
P_EXTENT ext;
|
|
|
|
ext.tl.x=LAY_LEFT_BORDER;
|
|
ext.tl.y=Y_TO_FIRST_PROCESS+(j-topproc)*TEXT_HEIGHT;
|
|
ext.width=X_TO_END-LAY_LEFT_BORDER;
|
|
ext.height=TEXT_HEIGHT;
|
|
gInvObloid(&ext);
|
|
}
|
|
|
|
LOCAL_C VOID DrawLine(INT j)
|
|
{
|
|
P_RECT box;
|
|
INT len;
|
|
UWORD *base;
|
|
TEXT *fmt;
|
|
TEXT *buf;
|
|
INT margin;
|
|
TEXT out[20];
|
|
INT i;
|
|
INT val;
|
|
|
|
box.tl.x=LAY_LEFT_BORDER;
|
|
box.tl.y=Y_TO_FIRST_PROCESS+j*TEXT_HEIGHT;
|
|
box.br.y=box.tl.y+TEXT_HEIGHT;
|
|
j+=topproc;
|
|
if (j>=numproc)
|
|
{
|
|
box.br.x=X_TO_END;
|
|
gClrRect(&box,G_TRMODE_CLR);
|
|
return;
|
|
}
|
|
box.br.x=X_TO_FIRST_COLUMN;
|
|
buf=(&proc[j].name[0]);
|
|
len=p_slen(buf);
|
|
gPrintBoxText(&box,TEXT_ASCENT,G_TEXT_ALIGN_LEFT,
|
|
NAME_COLUMN_INDENT,buf,len);
|
|
base=(&proc[j].bytes_allocated)-1;
|
|
for (i=0; i<3; )
|
|
{
|
|
box.tl.x=box.br.x;
|
|
box.br.x=box.tl.x+cwid[i];
|
|
val=(*(base+col[++i]));
|
|
if (col[i]==DISPLAY_STATUS)
|
|
buf=statuses[val];
|
|
else
|
|
{
|
|
if (col[i]==DISPLAY_IOSEMCNT)
|
|
fmt="%d";
|
|
else if (using_decimal || col[i]>=DISPLAY_CELLS_ALLOCED)
|
|
fmt="%u";
|
|
else
|
|
fmt="%x";
|
|
p_atos(buf=(&out[0]),fmt,val);
|
|
}
|
|
margin=(i==3? TRAILING_INDENT: 0);
|
|
gPrintBoxText(&box,TEXT_ASCENT,G_TEXT_ALIGN_RIGHT,
|
|
margin,buf,p_slen(buf));
|
|
}
|
|
if (j==selproc)
|
|
InvertLine(j);
|
|
}
|
|
|
|
LOCAL_C VOID DrawList(VOID)
|
|
{
|
|
INT j;
|
|
|
|
for (j=0; j<6; j++)
|
|
DrawLine(j);
|
|
}
|
|
|
|
LOCAL_C VOID SetPriority(INT prio)
|
|
{
|
|
p_setpri(p_getpid(),prio);
|
|
}
|
|
|
|
LOCAL_C VOID PriorityHigh(VOID)
|
|
{
|
|
SetPriority(E_MAX_PRIORITY);
|
|
}
|
|
|
|
LOCAL_C VOID PriorityLow(VOID)
|
|
{
|
|
SetPriority(E_PRIORITY_BACK+1);
|
|
}
|
|
|
|
LOCAL_C INT SystemProcessName(TEXT *pname)
|
|
{
|
|
return(!p_bcmp(pname,4,"SYS$",4));
|
|
}
|
|
|
|
LOCAL_C VOID GetMblock(HANDLE pid,MBLOCK *ofs,MBLOCK *buf)
|
|
{
|
|
p_pcpyfr(pid,ofs,buf,SZMBLK);
|
|
}
|
|
|
|
LOCAL_C INT WalkHeap(HANDLE pid,UWORD *poffset,PROCESS_DATA *pdata,
|
|
MBLOCK *MemBasePtr)
|
|
{
|
|
MBLOCK *p1,*p2,*memhigh;
|
|
MBLOCK m1,m2;
|
|
|
|
memhigh=(MBLOCK *)pdata->seg_size;
|
|
p2=MemBasePtr;
|
|
p1=p2+1; /* first allocated cell starts at an mblock after memBasePtr */
|
|
FOREVER
|
|
{ /* walk every cell from memlow to memhigh */
|
|
GetMblock(pid,p2,&m2);
|
|
*poffset=(UWORD)p2;
|
|
p2=m2.mnext; /* next free cell */
|
|
if (!p2)
|
|
p2=memhigh; /* last free cell */
|
|
else
|
|
{
|
|
GetMblock(pid,p2,&m2);
|
|
if (p2>(memhigh-1))
|
|
return(ERR_FREECELL_BEYOND_MEMHIGH);
|
|
else if (m2.mnext && m2.mnext<p2+1)
|
|
{
|
|
*poffset=(UWORD)p2;
|
|
return(ERR_FREECELL_GOES_BACKWARDS);
|
|
}
|
|
}
|
|
while (p1!=p2)
|
|
{ /* walk cells until next free cell */
|
|
GetMblock(pid,p1,&m1);
|
|
*poffset=(UWORD)p1;
|
|
if (m1.mlen<SZMBLK)
|
|
return(ERR_CELL_LENGTH_TOO_SMALL);
|
|
if (m1.mlen&1)
|
|
return(ERR_CELL_LENGTH_ODD);
|
|
pdata->cells_allocated++;
|
|
pdata->bytes_allocated+=m1.mlen;
|
|
if (m1.mlen>((UBYTE *)p2-(UBYTE *)p1))
|
|
return(ERR_ALLOCED_CELLS_OVERRUN_FREE);
|
|
p1=(MBLOCK *)(((UBYTE *)p1)+m1.mlen);
|
|
}
|
|
if (p2==memhigh)
|
|
{
|
|
*poffset=0;
|
|
break;
|
|
}
|
|
p1=(MBLOCK *)(((UBYTE *)p2)+m2.mlen); /* next allocated cell */
|
|
pdata->cells_free++;
|
|
pdata->bytes_free+=m2.mlen;
|
|
pdata->last_free=m2.mlen;
|
|
}
|
|
if (pdata->seg_size!=(UINT)(MemBasePtr)+SZMBLK
|
|
+pdata->bytes_allocated+pdata->bytes_free)
|
|
return(ERR_TOTALS_DONT_MATCH);
|
|
return(0); /* all OK */
|
|
}
|
|
|
|
LOCAL_C VOID NotifyError(INT ret,UWORD offset,TEXT *pname)
|
|
{
|
|
TEXT buf[40];
|
|
|
|
p_atos(&buf[0],"%s: heap corrupt at %u",pname,offset);
|
|
p_notify(&buf[0],heap_errors[ret-1],0,0,0);
|
|
}
|
|
|
|
LOCAL_C VOID CollectProcessData(HANDLE pid,TEXT *pname)
|
|
{
|
|
PROCESS_DATA *pdata;
|
|
E_PROC epc;
|
|
UBYTE sbuf[STACK_READ_SIZE+2];
|
|
UBYTE *p;
|
|
UBYTE *pEnd;
|
|
UWORD segoffset;
|
|
WORD locked;
|
|
UWORD offset;
|
|
INT ret;
|
|
UWORD sem[3];
|
|
|
|
pdata=(&proc[numproc++]);
|
|
p_bfil(pdata,sizeof(PROCESS_DATA),0);
|
|
p_scpy(&pdata->name[0],pname);
|
|
pdata->pid=pid;
|
|
p_getosd(&epc,(VOID *)(E_PIDMASK&pid),sizeof(E_PROC));
|
|
pdata->seg_size=p_sgsize(epc.dataSeg)<<4;
|
|
pdata->stack_pointer=(UWORD)epc.saveSP;
|
|
pdata->status=epc.status-E_PROC_CURRENT;
|
|
pdata->priority=p_getpri(pid);
|
|
p_getosd(&sem[0],(VOID *)epc.semaphore,6);
|
|
pdata->iosemcnt=sem[2];
|
|
segoffset=0x80;
|
|
pEnd=(&sbuf[STACK_READ_SIZE]);
|
|
*pEnd=0;
|
|
do
|
|
{
|
|
p_pcpyfr(pid,(VOID *)segoffset,&sbuf[0],STACK_READ_SIZE);
|
|
p=(&sbuf[0]);
|
|
while (*p==255)
|
|
p++;
|
|
segoffset+=STACK_READ_SIZE;
|
|
} while (p==pEnd);
|
|
pdata->least_stack=segoffset-STACK_READ_SIZE+p-(&sbuf[0]);
|
|
if (epc.memBasePtr && !epc.isTask && pid!=failpid)
|
|
{
|
|
locked=0;
|
|
p_pcpyfr(pid,&DatHeapLocked,&locked,1);
|
|
if (!locked)
|
|
{
|
|
ret=WalkHeap(pid,&offset,pdata,(MBLOCK *)epc.memBasePtr);
|
|
if (ret)
|
|
{
|
|
NotifyError(ret,offset,pname);
|
|
failpid=pid;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LOCAL_C VOID BuildList(VOID)
|
|
{
|
|
HANDLE prchand;
|
|
TEXT name[E_MAX_NAME+2];
|
|
HANDLE pid;
|
|
INT first;
|
|
|
|
numproc=0;
|
|
first=TRUE;
|
|
prchand=NULL;
|
|
PriorityHigh();
|
|
while ((prchand=p_pfind(prchand,"*",&name[0]))!=E_FILE_NXIST)
|
|
{
|
|
if (first)
|
|
{
|
|
first=FALSE;
|
|
continue;
|
|
}
|
|
if (which_processes!=PROCESS_ALL)
|
|
{
|
|
if (SystemProcessName(&name[0]))
|
|
{
|
|
if (which_processes==PROCESS_APPLICATION)
|
|
continue;
|
|
}
|
|
else if (which_processes==PROCESS_SYSTEM)
|
|
continue;
|
|
}
|
|
if ((pid=p_pidfind(&name[0]))<0)
|
|
continue;
|
|
CollectProcessData(pid,&name[0]);
|
|
}
|
|
PriorityLow();
|
|
if (topproc>numproc-6)
|
|
topproc=numproc-6;
|
|
if (selproc>numproc-1)
|
|
selproc=numproc-1;
|
|
}
|
|
|
|
LOCAL_C VOID UpdateList(VOID)
|
|
{
|
|
BuildList();
|
|
DrawList();
|
|
}
|
|
|
|
LOCAL_C VOID ResetList(VOID)
|
|
{
|
|
CancelTimer();
|
|
UpdateList();
|
|
QueueTimer();
|
|
}
|
|
|
|
LOCAL_C VOID ChangeColumnsViewed(VOID)
|
|
{
|
|
UWORD copy[3];
|
|
INT j;
|
|
TEXT prompt[10];
|
|
TEXT *pb;
|
|
|
|
p_bcpy(©[0],&col[1],6);
|
|
pb=(&prompt[7]); /* points to '1' of "Column 1" */
|
|
FOREVER
|
|
{
|
|
p_scpy(&prompt[0],"Column 1");
|
|
if (uOpenDialog("Change display for each column"))
|
|
return;
|
|
for (j=0; j<3; j++)
|
|
{
|
|
if (uAddChoiceList(&prompt[0],©[j],"Bytes allocated",
|
|
"Bytes free","Segment size","Last free cell",
|
|
"Least stack","Process priority","Stack pointer",
|
|
"Process ID","Cells allocated","Cells free",
|
|
"IO semaphore count","Process status",NULL))
|
|
return;
|
|
(*pb)++;
|
|
}
|
|
if (uRunDialog()<=0)
|
|
return;
|
|
if (copy[0]!=copy[1] && copy[0]!=copy[2] && copy[1]!=copy[2])
|
|
break;
|
|
wInfoMsg("Duplicate columns");
|
|
}
|
|
p_bcpy(&col[1],©[0],6);
|
|
DrawTitles();
|
|
ResetList();
|
|
}
|
|
|
|
LOCAL_C VOID ChangeRefreshRate(VOID)
|
|
{
|
|
H_DI_NUMBER num;
|
|
|
|
if (uOpenDialog("Refresh rate"))
|
|
return;
|
|
num.value=(&timint);
|
|
num.low=5;
|
|
num.high=1000;
|
|
if (uAddDialogItem(H_DIALOG_NUMBER,"Tenths of seconds",&num))
|
|
return;
|
|
if (uRunDialog()<=0)
|
|
return;
|
|
CancelTimer();
|
|
QueueTimer();
|
|
}
|
|
|
|
LOCAL_C VOID ChangeProcessesViewed(VOID)
|
|
{
|
|
if (uOpenDialog(NULL))
|
|
return;
|
|
if (uAddChoiceList("View which processes",&which_processes,
|
|
"System","Application","All",NULL))
|
|
return;
|
|
if (uRunDialog()<=0)
|
|
return;
|
|
ResetList();
|
|
}
|
|
|
|
LOCAL_C VOID ToggleBaseUsed(VOID)
|
|
{
|
|
if (using_decimal^=TRUE)
|
|
{
|
|
wInfoMsg("Display now using decimal");
|
|
cmds[USE_ITEM]="hUse hex";
|
|
}
|
|
else
|
|
{
|
|
wInfoMsg("Display now using hexadecimal");
|
|
cmds[USE_ITEM]="hUse decimal";
|
|
}
|
|
ResetList();
|
|
}
|
|
|
|
LOCAL_C VOID ToggleTimer(VOID)
|
|
{
|
|
CancelTimer();
|
|
if (using_timer^=TRUE)
|
|
{
|
|
wInfoMsg("Timer re-enabled");
|
|
cmds[TIMER_ITEM]="tTimer off";
|
|
}
|
|
else
|
|
{
|
|
wInfoMsg("Timer suspended");
|
|
cmds[TIMER_ITEM]="tTimer on";
|
|
}
|
|
QueueTimer();
|
|
}
|
|
|
|
LOCAL_C VOID CompressAllHeaps(VOID)
|
|
{
|
|
p_sgcreate("t$t$",0x7FFF,E_SEGMENT_HIGH);
|
|
wInfoMsg("All heaps compressed");
|
|
ResetList();
|
|
}
|
|
|
|
LOCAL_C VOID WalkAllHeapsAgain(VOID)
|
|
{
|
|
if (!failpid)
|
|
wInfoMsg("No failed process");
|
|
else
|
|
{
|
|
failpid=NULL;
|
|
wInfoMsg("Now rewalking ALL processes");
|
|
ResetList();
|
|
}
|
|
}
|
|
|
|
LOCAL_C TEXT *CurrentTaskName(VOID)
|
|
{
|
|
return(&proc[selproc].name[0]);
|
|
}
|
|
|
|
LOCAL_C VOID NamedInfoMsg(TEXT *fmt)
|
|
{
|
|
TEXT buf[40];
|
|
|
|
p_atos(&buf[0],fmt,CurrentTaskName());
|
|
wInfoMsg(&buf[0]);
|
|
}
|
|
|
|
LOCAL_C VOID GotoCurrentProcess(VOID)
|
|
{
|
|
HANDLE pid;
|
|
|
|
pid=proc[selproc].pid;
|
|
if ((INT)wClientInfo(pid)>=0)
|
|
wClientPosition(0,pid);
|
|
else
|
|
NamedInfoMsg("Cannot go to %s");
|
|
}
|
|
|
|
LOCAL_C INT TryResetLeastStack(VOID)
|
|
{
|
|
HANDLE pid;
|
|
E_PROC epc;
|
|
UBYTE *offset;
|
|
TEXT buf[STACK_READ_SIZE];
|
|
|
|
PriorityHigh();
|
|
if (proc[selproc].priority>=E_MAX_PRIORITY)
|
|
{
|
|
PriorityLow();
|
|
NamedInfoMsg("Cannot reset stack of %s");
|
|
return;
|
|
}
|
|
p_bfil(&buf[0],STACK_READ_SIZE,0xFF);
|
|
pid=proc[selproc].pid;
|
|
p_getosd(&epc,(VOID *)(E_PIDMASK&pid),sizeof(E_PROC));
|
|
offset=(UBYTE *)0x80;
|
|
while (offset+STACK_READ_SIZE<epc.saveSP)
|
|
{
|
|
p_pcpyto(pid,offset,&buf[0],STACK_READ_SIZE);
|
|
offset+=STACK_READ_SIZE;
|
|
}
|
|
p_pcpyto(pid,offset,&buf[0],(UINT)(epc.saveSP-offset));
|
|
PriorityLow();
|
|
ResetList();
|
|
}
|
|
|
|
LOCAL_C INT AddTextItem(TEXT *msg,INT type)
|
|
{
|
|
TEXT buf[40];
|
|
H_DI_TEXT txt;
|
|
|
|
txt.type=type;
|
|
uZTStoBCS(txt.str=(&buf[0]),msg);
|
|
return(uAddDialogItem(H_DIALOG_TEXT,NULL,&txt));
|
|
}
|
|
|
|
LOCAL_C VOID TryKillCurrentProcess(VOID)
|
|
{
|
|
INT ret;
|
|
TEXT buf[40];
|
|
|
|
p_atos(&buf[0],"Kill %s",CurrentTaskName());
|
|
if (uOpenDialog(&buf[0]))
|
|
return;
|
|
if (AddTextItem("Are you sure?",H_DTEXT_ALIGN_CENTRE|H_DTEXT_BOLD))
|
|
return;
|
|
if (uAddButtonList("No",-'n',"Yes",'y',NULL))
|
|
return;
|
|
if (uRunDialog()!='y')
|
|
return;
|
|
ret=p_pterminate(proc[selproc].pid,0);
|
|
if (!ret)
|
|
ResetList();
|
|
else
|
|
NamedInfoMsg("Cannot kill %s");
|
|
}
|
|
|
|
LOCAL_C VOID ManageCommand(INT index)
|
|
{
|
|
switch (index)
|
|
{
|
|
case ITEMS_BEFORE_DISPLAY:
|
|
ChangeColumnsViewed();
|
|
break;
|
|
case ITEMS_BEFORE_DISPLAY+1:
|
|
ToggleBaseUsed();
|
|
break;
|
|
case ITEMS_BEFORE_DISPLAY+2:
|
|
ChangeProcessesViewed();
|
|
break;
|
|
case ITEMS_BEFORE_DISPLAY+3:
|
|
ResetList();
|
|
break;
|
|
case ITEMS_BEFORE_DISPLAY+4:
|
|
MonitorBandWidth();
|
|
break;
|
|
case ITEMS_BEFORE_TIMER:
|
|
ToggleTimer();
|
|
break;
|
|
case ITEMS_BEFORE_TIMER+1:
|
|
ChangeRefreshRate();
|
|
break;
|
|
case ITEMS_BEFORE_LOG:
|
|
wsReport(proc[selproc].pid);
|
|
break;
|
|
case ITEMS_BEFORE_LOG+1:
|
|
wsReport(0); /* Log all Window server clients */
|
|
break;
|
|
case ITEMS_BEFORE_SPECIAL:
|
|
CompressAllHeaps();
|
|
break;
|
|
case ITEMS_BEFORE_SPECIAL+1:
|
|
WalkAllHeapsAgain();
|
|
break;
|
|
case ITEMS_BEFORE_SPECIAL+2:
|
|
GotoCurrentProcess();
|
|
break;
|
|
case ITEMS_BEFORE_SPECIAL+3:
|
|
TryResetLeastStack();
|
|
break;
|
|
case ITEMS_BEFORE_SPECIAL+4:
|
|
TryKillCurrentProcess();
|
|
break;
|
|
case ITEMS_BEFORE_SPECIAL+5:
|
|
p_exit(0);
|
|
}
|
|
}
|
|
|
|
LOCAL_C VOID TryExecuteCommand(INT keycode)
|
|
{
|
|
keycode=uLocateCommand(keycode);
|
|
if (keycode>=0)
|
|
ManageCommand(keycode);
|
|
}
|
|
|
|
LOCAL_C VOID DoScroll(INT dely)
|
|
{
|
|
P_POINT offset;
|
|
P_RECT src;
|
|
|
|
offset.x=0;
|
|
offset.y=dely*TEXT_HEIGHT;
|
|
src.tl.x=LAY_LEFT_BORDER;
|
|
src.br.x=X_TO_END;
|
|
if (dely>0)
|
|
{
|
|
src.tl.y=Y_TO_FIRST_PROCESS;
|
|
src.br.y=Y_TO_FIRST_PROCESS+(6-dely)*TEXT_HEIGHT;
|
|
}
|
|
else
|
|
{
|
|
src.tl.y=Y_TO_FIRST_PROCESS-dely*TEXT_HEIGHT;
|
|
src.br.y=Y_TO_FIRST_PROCESS+6*TEXT_HEIGHT;
|
|
}
|
|
wScrollRect(MainWid,&src,&offset);
|
|
}
|
|
|
|
LOCAL_C VOID MakeHighlight(INT newselproc)
|
|
{
|
|
INT toscroll;
|
|
|
|
if (newselproc==selproc)
|
|
return;
|
|
InvertLine(selproc);
|
|
toscroll=topproc-newselproc;
|
|
if (toscroll>0)
|
|
{
|
|
topproc-=toscroll;
|
|
if (toscroll<6)
|
|
DoScroll(toscroll);
|
|
else
|
|
toscroll=6;
|
|
while (toscroll)
|
|
DrawLine(--toscroll);
|
|
}
|
|
else
|
|
{
|
|
toscroll=-5-toscroll;
|
|
if (toscroll>0)
|
|
{
|
|
topproc+=toscroll;
|
|
if (toscroll<6)
|
|
DoScroll(-toscroll);
|
|
else
|
|
toscroll=6;
|
|
while (toscroll)
|
|
DrawLine(6-toscroll--);
|
|
}
|
|
}
|
|
selproc=newselproc;
|
|
InvertLine(selproc);
|
|
}
|
|
|
|
LOCAL_C VOID ScrollPageBy(INT delta)
|
|
{
|
|
if (delta<(-5))
|
|
delta=(-5);
|
|
else if (delta>5)
|
|
delta=5;
|
|
topproc+=delta;
|
|
selproc+=delta;
|
|
DrawList();
|
|
}
|
|
|
|
LOCAL_C VOID TryMatchFirstLetter(INT upper)
|
|
{
|
|
INT k;
|
|
INT i;
|
|
|
|
k=numproc;
|
|
i=selproc;
|
|
while (k--)
|
|
{
|
|
if (++i==numproc)
|
|
i=0;
|
|
if (proc[i].name[0]==upper)
|
|
{
|
|
MakeHighlight(i);
|
|
return;
|
|
}
|
|
}
|
|
p_sound(-5,320);
|
|
}
|
|
|
|
LOCAL_C VOID CheckBorderArrows(VOID)
|
|
{
|
|
INT bflags;
|
|
|
|
if (topproc)
|
|
bflags=W_BORD_CORNER_4|W_BORD_TOP_ON;
|
|
else
|
|
bflags=W_BORD_CORNER_4|W_BORD_TOP_OFF;
|
|
if (topproc+6<numproc)
|
|
bflags|=W_BORD_BOT_ON;
|
|
else
|
|
bflags|=W_BORD_BOT_OFF;
|
|
if (bflags!=lastbflags)
|
|
gBorder(lastbflags=bflags);
|
|
}
|
|
|
|
LOCAL_C VOID SystemPauseLoop(VOID)
|
|
{
|
|
WS_EV event;
|
|
UINT key,oldPri,pid;
|
|
UWORD procBuf[WS_MAX_CLIENTS+1];
|
|
|
|
pid=p_getpid();
|
|
wGetProcessList(&procBuf[0]);
|
|
if (procBuf[0]==pid)
|
|
return;
|
|
oldPri=p_getpri(pid);
|
|
p_setpri(pid,E_PRIORITY_WSERV-1);
|
|
DisableReads(TRUE);
|
|
wGetEvent(&event);
|
|
FOREVER
|
|
{
|
|
if (event.type!=E_FILE_PENDING)
|
|
{
|
|
p_iowait();
|
|
if (event.type==WM_FOREGROUND || event.type==WM_BACKGROUND)
|
|
break;
|
|
if (event.type==WM_KEY)
|
|
{
|
|
key=p_tolower(event.p.key.keycode&(~W_SPECIAL_KEY));
|
|
if (key=='s' || key==W_KEY_ESCAPE)
|
|
break;
|
|
}
|
|
wGetEvent(&event);
|
|
}
|
|
}
|
|
DisableReads(FALSE);
|
|
p_setpri(pid,oldPri);
|
|
}
|
|
|
|
LOCAL_C VOID MainLoop(VOID)
|
|
{
|
|
INT ret;
|
|
WMSG_KEY key;
|
|
WORD keystat;
|
|
WORD keyactive;
|
|
|
|
keyactive=FALSE;
|
|
FOREVER
|
|
{
|
|
CheckBorderArrows();
|
|
if (keyactive)
|
|
wFlush();
|
|
else
|
|
{
|
|
uGetKeyA(&keystat,&key);
|
|
keyactive=TRUE;
|
|
}
|
|
p_iowait();
|
|
if (keystat==E_FILE_PENDING)
|
|
{
|
|
UpdateList();
|
|
QueueTimer();
|
|
continue;
|
|
}
|
|
keyactive=FALSE;
|
|
if (key.keycode&W_EVENT_KEY)
|
|
{
|
|
switch (key.keycode)
|
|
{
|
|
case CONS_EVENT_COMMAND:
|
|
p_exit(0);
|
|
case CONS_EVENT_FOREGROUND:
|
|
ResetList();
|
|
}
|
|
}
|
|
else if ((key.modifiers&W_CTRL_MODIFIER|W_PSION_MODIFIER)==
|
|
(W_CTRL_MODIFIER|W_PSION_MODIFIER) &&
|
|
key.keycode==(W_SPECIAL_KEY|'n'))
|
|
wsReport(-1); /* Report foreground client (no dialogs) */
|
|
else if ((key.modifiers&W_CTRL_MODIFIER|W_PSION_MODIFIER)==
|
|
(W_CTRL_MODIFIER|W_PSION_MODIFIER) &&
|
|
key.keycode==(W_SPECIAL_KEY|'p'))
|
|
wClientPosition(0,0);
|
|
else if ((key.modifiers&W_CTRL_MODIFIER|W_PSION_MODIFIER)==
|
|
(W_CTRL_MODIFIER|W_PSION_MODIFIER) &&
|
|
key.keycode==(W_SPECIAL_KEY|'s'))
|
|
SystemPauseLoop();
|
|
else if (key.keycode&W_SPECIAL_KEY)
|
|
TryExecuteCommand(key.keycode&(~W_SPECIAL_KEY));
|
|
else
|
|
{
|
|
switch (key.keycode)
|
|
{
|
|
case W_KEY_MENU:
|
|
if (!(key.modifiers&W_CTRL_MODIFIER))
|
|
{
|
|
ret=uPresentMenus();
|
|
if (ret>0)
|
|
TryExecuteCommand(ret);
|
|
}
|
|
break;
|
|
case W_KEY_UP:
|
|
if (selproc)
|
|
MakeHighlight(selproc-1);
|
|
break;
|
|
case W_KEY_DOWN:
|
|
if (selproc<numproc-1)
|
|
MakeHighlight(selproc+1);
|
|
break;
|
|
case W_KEY_PAGE_UP:
|
|
if (key.modifiers&W_CTRL_MODIFIER)
|
|
MakeHighlight(0);
|
|
else if (!topproc)
|
|
MakeHighlight(0);
|
|
else
|
|
ScrollPageBy(-topproc);
|
|
break;
|
|
case W_KEY_PAGE_DOWN:
|
|
if (key.modifiers&W_CTRL_MODIFIER)
|
|
MakeHighlight(numproc-1);
|
|
else if (topproc+6>=numproc)
|
|
MakeHighlight(numproc-1);
|
|
else
|
|
ScrollPageBy(numproc-topproc-6);
|
|
break;
|
|
default:
|
|
if (p_isprint(key.keycode))
|
|
TryMatchFirstLetter(p_toupper(key.keycode));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LOCAL_C VOID CreateGC(VOID)
|
|
{
|
|
INT hgc;
|
|
|
|
hgc=gCreateGC0(MainWid);
|
|
if (hgc<0)
|
|
p_exit(hgc);
|
|
}
|
|
|
|
LOCAL_C VOID SpecificInit(VOID)
|
|
{
|
|
MainWid=uFindMainWid();
|
|
CreateGC();
|
|
hCrackCommandLine();
|
|
p_unmarka();
|
|
DrawTitles();
|
|
UpdateList();
|
|
p_open(&timcb,"TIM:",-1);
|
|
QueueTimer();
|
|
if (wCaptureKey('n'|W_SPECIAL_KEY,W_CTRL_MODIFIER|W_PSION_MODIFIER,
|
|
W_CTRL_MODIFIER|W_PSION_MODIFIER)<0)
|
|
wInfoMsg("'n' key capture failed");
|
|
if (wCaptureKey('p'|W_SPECIAL_KEY,W_CTRL_MODIFIER|W_PSION_MODIFIER,
|
|
W_CTRL_MODIFIER|W_PSION_MODIFIER)<0)
|
|
wInfoMsg("'p' key capture failed");
|
|
if (wCaptureKey('s'|W_SPECIAL_KEY,W_CTRL_MODIFIER|W_PSION_MODIFIER,
|
|
W_CTRL_MODIFIER|W_PSION_MODIFIER)<0)
|
|
wInfoMsg("'s' key capture failed");
|
|
}
|
|
|
|
GLDEF_C VOID main(VOID)
|
|
{
|
|
uCommonInit();
|
|
SpecificInit();
|
|
MainLoop();
|
|
}
|