home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff224.lzh / Who / Who.c < prev    next >
C/C++ Source or Header  |  1989-06-20  |  12KB  |  384 lines

  1. /* ROOM TO GROW:   Attempt to see what processes are waiting for?  (node->
  2.    pr_Task.tc_SigWait?)  Workbench version paginate?  Always paginate?
  3.    Display the mort field?  It's just the ID plus sizeof(struct Task), which
  4.    is 92 decimal or 5c hex.
  5.  */
  6.  
  7. /*
  8.  * WHO
  9.  * by George Musser Jr.
  10.  * 16 November 1986
  11.  *
  12.  * 21 January 1987 - added task id, CLI process numbers
  13.  *
  14.  * Lists tasks on the Ready and Wait queues.
  15.  *
  16.  */
  17.  
  18.  
  19. /* ============================================================================
  20.    Modified by Paul Kienitz 10/88 for prettier sorted output, Cli command name,
  21.    other additional useful data, and single Disable/Enable snapshot.  Manxed
  22.    for smallness (should still be Lattice compatible), no more large arrays on
  23.    stack.  It crashed sometimes before. Also workbench runnable with
  24.    "WINDOW=CON:0/nn/640/nnn/Press any key to exit" tooltype in the icon, but
  25.    it's not really a workbench program.
  26.    -- 12/88 added Cli script file name, improved "for" display, added crude
  27.    unit number detection for some driver tasks, flag for Cli interactiveness.
  28.    -- 2/9/89 discovered that trackdisk.device plugs the task MsgPort pointer
  29.    directly into the io_Unit field, instead of in the first field of the struct
  30.    Unit (or struct TDU_PublicUnit?) that's supposed to be pointed to by that.
  31.    Reduced Disabled time with tap array.  Decided that trying to find unit
  32.    numbers for any device other than trackdisk is too dangerous, as well as
  33.    unlikely to accomplish anything, since you have no way of knowing what
  34.    some chumps will put in the io_Unit field.
  35.    -- 4/13/89 removed limit of at most 99 tasks displayed, made sorting by
  36.    name use cli command name instead of task name when present, fixed failure
  37.    to handle out-of-memory condition.
  38.    -- 4/14/89 made it create standard 640×200 window under Workbench without
  39.    consulting any tooltypes -- this makes it start faster.
  40.  */
  41.  
  42.  
  43. #include <exec/types.h>
  44. #include <exec/nodes.h>
  45. #include <exec/lists.h>
  46. #include <exec/ports.h>
  47. #include <exec/devices.h>
  48. #include <exec/execbase.h>
  49. #include <devices/trackdisk.h>
  50. #include <libraries/dosextens.h>
  51. #include <libraries/filehandler.h>
  52. #ifdef AZTEC_C
  53. #include <functions.h>
  54. #endif
  55.  
  56. #define Maxks    999   /* Maximum handleable number of tasks */
  57. #define NAME_LEN  40   /* Number of characters in task names */
  58. #define CLIp      40   /* Length to truncate Cli command strings to */
  59. #define dimwit    30   /* how many devices we can recognize */
  60.  
  61. #define min(a,b) (a > b ? b : a)
  62. #define bip(T, B) ((T *) (B << 2))
  63. #define gbip(B) bip(void, B)
  64.  
  65. extern struct ExecBase *SysBase;
  66. extern struct DosLibrary *DOSBase;
  67.  
  68. extern int Enable_Abort;
  69.  
  70. char *strncpy();
  71. void *malloc();
  72.  
  73. /* lame excess incomplete Unix compatible Manx 3.4a bullshit */
  74. char *hex6(), *hex8();
  75. /* even lamer English weenie-ism */
  76. void Beast();
  77.  
  78. typedef struct Task *task;
  79. typedef struct Process *process;
  80. typedef struct MsgPort *port;
  81.  
  82. typedef struct {
  83.    task id;            /* struct Task address */
  84.    task stout;            /* standard output handler process */
  85.    port mort;            /* message port address (for processes) */
  86.    short pri, clinum, nype;    /* priority, Cli number, strange node type */
  87.    BOOL dosproc, foreskin;    /* it's a process, it's an interactive Cli */
  88.    char name[NAME_LEN],        /* task name */
  89.       command[CLIp],        /* Cli command string (truncated) */
  90.       xeq[CLIp];        /* Execute source file name (truncated) */
  91. } vitals;
  92. typedef vitals *vitalp;
  93.  
  94. typedef struct {
  95.    char dame[31];        /* name of device (e.g. DF1) */
  96.    char drivel[31];        /* name of device driver (e.g trackdisk.device) */
  97.    task hand;            /* id of dos handler process */
  98. } dist;
  99. typedef dist *dip;
  100.  
  101.  
  102. task     tap[Maxks];        /* all the task pointers from the lists */
  103. vitalp   tasx;            /* all the data on those tasks */
  104.  
  105.  
  106.  
  107. main(argc) int argc;
  108. {
  109.    short reds, weights;         /* how many ready, how many waiting */
  110.    dip devz[dimwit];            /* data on devices */
  111.    short numbed;                /* how many devices in devz */
  112.    process me;
  113.    void PrintList(), DigestList();
  114.    int rank();
  115.    short EatList(), EatDevices();
  116.  
  117.    Forbid();
  118.    numbed = EatDevices(devz);
  119.    Disable();  /* Here we mustn't let the list get reordered */
  120.    reds = EatList (&SysBase->TaskReady, tap, Maxks);
  121.    weights = EatList (&SysBase->TaskWait, tap + reds, Maxks - reds);
  122.    /* running tasks have dibs on array slots; waiting tasks have to sit in the
  123.       back of the bus */
  124.    Enable();
  125.    /* That was probably longer than 250 microseconds, but I've disabled for
  126.       several seconds at a time with no harm, even during disk activity */
  127.    /* Here it's okay if they're reordered, just make sure none of them exit */
  128.    if (!(tasx = malloc((reds + weights) * sizeof(vitals)))) {
  129.       Permit();
  130.       printf("\nGaaah!  Insufficient memory!\n");
  131.       exit(10);
  132.    }
  133.    DigestList(tap, reds, tasx);
  134.    DigestList(tap + reds, weights, tasx + reds);
  135.    Permit();
  136.  
  137.    qsort(tasx + reds, weights, sizeof(vitals), rank);
  138.    PrintList(tasx + reds, weights, "Waiting", -reds, devz, numbed);
  139.    qsort(tasx, reds, sizeof(vitals), rank);
  140.    PrintList(tasx, reds, "Ready to run", weights, devz, numbed);
  141.  
  142.    me = (process) FindTask(0L);
  143.    printf("Running: this WHO process ");
  144.    if (me->pr_TaskNum) printf("(CLI %ld) ", me->pr_TaskNum);
  145.    printf("is id %s, priority %d.",
  146.           hex6(me), (int) me->pr_Task.tc_Node.ln_Pri);
  147.    if (!argc) {
  148.        printf("   ");
  149.        set_raw();
  150.        getchar();     /* wait for keystroke if workbench */
  151.    }
  152.    else putchar('\n');
  153. }
  154.  
  155.  
  156.  
  157. short EatDevices(devz) dip devz[dimwit];
  158. {  short numbed = 0;
  159.    struct FileSysStartupMsg *fart;
  160.    struct DeviceNode *devlist = bip(struct DeviceNode, bip(struct DosInfo,
  161.                      ((struct RootNode *) DOSBase->dl_Root)
  162.                    ->rn_Info)->di_DevInfo);
  163.    for ( ; devlist ; devlist = gbip(devlist->dn_Next)) {
  164.       if (!devlist->dn_Type) {
  165.          if (!(devz[numbed] = malloc(sizeof(dist)))) return (numbed - 1);
  166.          Beast(devlist->dn_Name, devz[numbed]->dame, 30);
  167.      if (devlist->dn_Task)
  168.         devz[numbed]->hand = devlist->dn_Task->mp_SigTask;
  169.      else
  170.         devz[numbed]->hand = NULL;
  171.      if (devz[numbed]->hand && (fart = gbip(devlist->dn_Startup)))
  172.         Beast(fart->fssm_Device, devz[numbed]->drivel, 30);
  173.      else
  174.         devz[numbed]->drivel[0] = '\0';
  175.      if (++numbed >= dimwit) break;
  176.       }
  177.    }
  178.    return (numbed);
  179. }
  180.  
  181.  
  182.  
  183. short EatList(header, tap, limit)
  184. struct List *header; task tap[]; short limit;
  185. {
  186.    struct Node *node;
  187.    short i;
  188.  
  189.    if (limit < 0) limit = 0;
  190.    for (node = header->lh_Head, i = 0;
  191.           node->ln_Succ && i < limit;
  192.           node = node->ln_Succ, i++)
  193.       tap[i] = (task) node;
  194.    return (i);
  195. }
  196.  
  197.  
  198.  
  199. void DigestList(tap, count, ray) task tap[]; short count; vitalp ray;
  200. {
  201.    short i;
  202.    struct Node *node;
  203.    process pode;
  204.    struct FileHandle *ss;
  205.    port sss;
  206.    struct CommandLineInterface *kwy;
  207.    BPTR mandy;
  208.    vitalp this;
  209.  
  210.    for (i = 0; i < count; i++) {
  211.       node = (struct Node *) tap[i];
  212.       this = ray + i;
  213.       this->nype = node->ln_Type;
  214.       strncpy (this->name, node->ln_Name, NAME_LEN);
  215.       this->id = (task) node;
  216.       this->pri = node->ln_Pri;
  217.       if (this->dosproc = node->ln_Type == NT_PROCESS) {
  218.          pode = (process) node;
  219.      this->mort = &pode->pr_MsgPort;
  220.          if (this->clinum = (short) (pode->pr_TaskNum)) {
  221.         kwy = gbip(pode->pr_CLI);
  222.         mandy = kwy->cli_CommandName;
  223.         /* The only thing in the universe that's stupider than a BPTR is a
  224.            BSTR.  Why should a *string* pointer to be longword aligned??? */
  225.             Beast(mandy, this->command, CLIp);
  226.         this->foreskin = kwy->cli_Interactive;
  227.         mandy = kwy->cli_CommandFile;
  228.         if (mandy) Beast(mandy, this->xeq, CLIp);
  229.         else this->xeq[0] = '\0';
  230.      }
  231.      ss = bip(struct FileHandle, pode->pr_COS);
  232.      sss = ((long) ss ? ss->fh_Type : (port) NULL);
  233.      this->stout = ((long) sss ? sss->mp_SigTask : (task) NULL);
  234.       } else {
  235.          this->clinum = 0;
  236.      this->stout = NULL;
  237.      this->mort = NULL;
  238.       }
  239.    }
  240. }
  241.  
  242.  
  243.  
  244. void Beast(from, to, limit) BPTR from; char *to; short limit;
  245. {
  246.    int j;
  247.    char *fro = gbip(from);
  248.    j = min(fro[0], limit);
  249.    strncpy(to, fro + 1, j);
  250.    to[j] = '\0';
  251. }
  252.  
  253.  
  254.  
  255. /*
  256.  * PrintList()
  257.  *
  258.  * Prints the names, pointers, priorities, and types of items in a list.
  259.  *
  260.  */
  261.  
  262. void PrintList(list, count, label, stench, devz, numbed)
  263. vitalp list; char *label; dip devz[]; short count, stench, numbed;
  264. {
  265.    short j, k, lo, hi;
  266.    char *lab;
  267.    task mycon = bip(struct FileHandle, (BPTR) Output())->fh_Type->mp_SigTask;
  268.    vitalp this;
  269.    struct IOExtTD quest;
  270.    task trask[4];
  271.  
  272.    setmem(&quest, sizeof(struct IOExtTD), 0);
  273.    for (j = 0; j < 4; j++)
  274.       if (!OpenDevice(TD_NAME, (long) j, &quest, 0L)) {
  275.      trask[j] = ((port) quest.iotd_Req.io_Unit)->mp_SigTask;
  276.      CloseDevice(&quest);
  277.       } else trask[j] = NULL;
  278.    if (!count) printf("%s:  none.\n", label);
  279.    else printf ("%s:\n", label);
  280.    for (j = 0; j < count; j++) {
  281.       this = list + j;
  282.       if (this->dosproc)
  283.          if (this->clinum)
  284.         printf("CLI %d%c%c ", this->clinum,
  285.                (this->foreskin ? '>' : ' '),
  286.            (this->clinum < 10 ? ' ' : '\0'));
  287.      else printf("Process ");
  288.       else printf(" task   ");
  289.       printf ("ID %s, pri%4d, ", hex6(this->id), this->pri);
  290.       if (this->clinum)
  291.          if (this->command[0]) {
  292.         printf("cmd. \"%s\"", this->command);
  293.         if (this->xeq[0]) printf(" script \"%s\"", this->xeq);
  294.      } else
  295.         printf("(no command)");
  296.       else
  297.      printf("name \"%s\"", this->name);
  298.       lab = "for";
  299.       for (k = 0; k < numbed; k++)
  300.          if (this->id == devz[k]->hand) {
  301.         printf(" %s %s:", lab, devz[k]->dame);
  302.         lab = "&";
  303.      }
  304.       if (this->id == mycon) {
  305.          printf(" %s this output", lab);
  306.      lab = "&";
  307.       }
  308.       for (k = 0; k < 4; k++)
  309.      if (this->id == trask[k])
  310.             printf(" unit %d", k);
  311.       lo = 0; hi = count;    /* look in both parts of the array */
  312.       if (stench < 0) lo = stench; else hi += stench;
  313.       for (k = lo; k < hi; k++)
  314.          if (list[k].stout == this->id) {
  315.         if (list[k].clinum) printf(" %s CLI %d", lab, list[k].clinum);
  316.         else printf(" %s ID %s", lab, hex6(list[k].id));
  317.         lab = "&";
  318.      }
  319.       if (this->nype != NT_TASK & this->nype != NT_PROCESS)
  320.      printf(" NODE TYPE %d", this->nype);   /* example:  PerfMon */
  321.       putchar('\n');
  322.    }
  323. }
  324.  
  325.  
  326.  
  327. int rank(a, b) vitalp a, b;        /* called by qsort */
  328. {
  329.    int tp = a->dosproc - b->dosproc;
  330.    int pr = b->pri - a->pri;
  331.    char *na = a->name, *nb = b->name;
  332.    char ca, cb;
  333.    if (tp) return (tp);
  334.    if (pr) return (pr);
  335.    if (a->clinum) na = a->command;
  336.    if (b->clinum) nb = b->command;
  337.    for (ca = toupper(*na), cb = toupper(*nb); ca && ca == cb;
  338.               ca = toupper(*++na), cb = toupper(*++nb)) ;
  339.    return (ca - cb);
  340. }
  341.  
  342.  
  343.  
  344. char *hex8(l) unsigned long l;  /* convert long to UPPERCASE hexadecimal */
  345. {
  346.    static char result[9];
  347.    int hid, nyb;
  348.    for (hid = 0; hid <= 7; hid++) {
  349.       nyb = (l >> (4*hid)) & 15L;
  350.       result[7 - hid] = (nyb >= 10 ? (char) nyb + 'A' - 10 : (char) nyb + '0');
  351.    }
  352.    for (hid = 0; hid <= 7; hid++)
  353.       if (result[hid] == '0') result[hid] = ' ';
  354.       else break;
  355.    result[8] = '\0';
  356.    return (result);
  357. }
  358.  
  359.  
  360.  
  361. char *hex6(l) unsigned long l;  /* for 24 bit addresses */
  362. {  return (hex8(l) + 2); }
  363.  
  364.  
  365.  
  366. #ifdef AZTEC_C
  367.  
  368. extern int _argc;
  369. void _cli_parse()
  370. {  _argc = 1; }        /* don't bother to parse arguments */
  371.  
  372. void _wb_parse(me) struct Process *me;  /* don't bother with ToolType */
  373. {
  374.    BPTR wind = Open("CON:0/0/640/200/ Who - press any key to clear ",
  375.             MODE_OLDFILE);
  376.    if (!wind) exit(10);
  377.    me->pr_ConsoleTask = (adr) bip(struct FileHandle, wind)->fh_Type;
  378.    me->pr_CIS = wind;
  379.    me->pr_COS = Open("*", MODE_OLDFILE);
  380. }
  381.  
  382. #endif
  383.  
  384.