home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Utilities / ctxt-util-1.0 / ABAppInfo.m < prev    next >
Encoding:
Text File  |  1998-04-01  |  14.4 KB  |  640 lines

  1. /**********************************************************************
  2.   ABAppInfo.m
  3.  
  4.   Copyright (c) 1998, David C. Lambert.  All Rights Reserved.
  5. **********************************************************************/
  6. #import <time.h>
  7. #import "table.h"
  8. #import "ABWraps.h"
  9. #import "ABAppInfo.h"
  10.  
  11. static id            processTable;
  12. static id            pidUidTable;
  13. static id            pidMenuTable;
  14. static id            pidIconTable;
  15. static id            pidMinisTable;
  16. static id            pidCtxtTable;
  17. static id            ctxtPidTable;
  18. static NXSize        screenSize;
  19. static DPSContext    myContext;
  20.  
  21. static int
  22. safeGetCtxtIconPidAndMenu(int context, int *icon, int *pid, int *menu)
  23. {
  24.     int        status = 0;
  25.  
  26.     if (context < 0) return -1;
  27.  
  28.     DPSTraceContext(myContext, NO);
  29.     NX_DURING
  30.         PSWGetCtxtIconPidAndMenu(context, icon, pid, menu);
  31.         NXPing();
  32.     NX_HANDLER
  33.         NXReportError(&NXLocalHandler);
  34.         switch (NXLocalHandler.code) {
  35.           case dps_err_ps:
  36.             status = -1;
  37.             break;
  38.           default:
  39.             NX_RERAISE();
  40.         }
  41.     NX_ENDHANDLER
  42.     if (*menu == 100000) *menu = -1;
  43.     return status;
  44. }
  45.  
  46. static int
  47. safeGetWindowList(int *windows)
  48. {
  49.     int        count;
  50.  
  51.     if (!windows) return -1;
  52.  
  53.     NX_DURING
  54.         PScountwindowlist(0, &count);
  55.         PSwindowlist(0, count, windows);
  56.         NXPing();
  57.     NX_HANDLER
  58.         NXReportError(&NXLocalHandler);
  59.            switch (NXLocalHandler.code) {
  60.           case dps_err_ps:
  61.             PScountwindowlist(0, &count);
  62.             break;
  63.           default:
  64.             NX_RERAISE();
  65.            }
  66.     NX_ENDHANDLER
  67.     return count;
  68. }
  69.  
  70. static int
  71. safeGetCurrrentOwner(int windowNum, int *owner)
  72. {
  73.     int        status = 0;
  74.  
  75.     if (windowNum <= 0) return -1;
  76.  
  77.     NX_DURING
  78.         PSWGetCurrentOwner(windowNum, owner);
  79.         NXPing();
  80.     NX_HANDLER
  81.         NXReportError(&NXLocalHandler);
  82.         switch (NXLocalHandler.code) {
  83.           case dps_err_ps:
  84.             status = -1;
  85.             break;
  86.           default:
  87.             NX_RERAISE();
  88.         }
  89.     NX_ENDHANDLER
  90.     return status; 
  91. }
  92.  
  93. static int
  94. safeUnhideContext(int appCtxt, int raiseFlag, int activateFlag, int hideFlag)
  95. {
  96.     int        status = 0;
  97.  
  98.     if (appCtxt <= 0) return -1;
  99.  
  100.     DPSTraceContext(myContext, NO);
  101.     NX_DURING
  102.         PSWUnhideContext(appCtxt, raiseFlag, activateFlag, hideFlag);
  103.         NXPing();
  104.     NX_HANDLER
  105.         NXReportError(&NXLocalHandler);
  106.         switch (NXLocalHandler.code) {
  107.           case dps_err_ps:
  108.             status = -1;
  109.             NXLogError("PS error in PSWUnhideContext: %d, %d, %d, %d",
  110.                        appCtxt, raiseFlag, activateFlag, hideFlag);
  111.             break;
  112.           default:
  113.             NX_RERAISE();
  114.         }
  115.     NX_ENDHANDLER
  116.  
  117.     return status;
  118. }
  119.  
  120. static int
  121. safeGetMiniWindows(int appCtxt, int *minis)
  122. {
  123.     int        miniCount;
  124.     int        screenCount;
  125.  
  126.     if (appCtxt <= 0) return -1;
  127.  
  128.     DPSTraceContext(myContext, NO);
  129.     NX_DURING
  130.         PScountscreenlist(appCtxt, &screenCount);
  131.         PSWGetMiniWindows(appCtxt, screenCount, &miniCount, minis);
  132.     NX_HANDLER
  133.         NXReportError(&NXLocalHandler);
  134.         switch (NXLocalHandler.code) {
  135.           case dps_err_ps:
  136.             miniCount = 0;
  137.             NXLogError("PS error in PSWGetMiniWindows: %d, %d, %d",
  138.                        appCtxt, screenCount, miniCount);
  139.             break;
  140.           default:
  141.             NX_RERAISE();
  142.         }
  143.     NX_ENDHANDLER
  144.     return miniCount;
  145. }
  146.  
  147. @implementation ABAppInfo : Object
  148.  
  149. + initialize
  150. {
  151.     static BOOL done = NO;
  152.  
  153.     if (!done)    {
  154.         done = YES;
  155.  
  156.         processTable = [[HashTable allocFromZone:[self zone]] initKeyDesc:"%" valueDesc:"i"];
  157.  
  158.         pidUidTable = [[HashTable allocFromZone:[self zone]] initKeyDesc:"i" valueDesc:"i"];
  159.         pidIconTable = [[HashTable allocFromZone:[self zone]] initKeyDesc:"i" valueDesc:"i"];
  160.         pidMenuTable = [[HashTable allocFromZone:[self zone]] initKeyDesc:"i" valueDesc:"i"];
  161.         pidCtxtTable = [[HashTable allocFromZone:[self zone]] initKeyDesc:"i" valueDesc:"i"];
  162.         ctxtPidTable = [[HashTable allocFromZone:[self zone]] initKeyDesc:"i" valueDesc:"i"];
  163.         pidMinisTable = [[HashTable allocFromZone:[self zone]] initKeyDesc:"i" valueDesc:"@"];
  164.  
  165.         [NXApp getScreenSize:&screenSize];
  166.         myContext = DPSGetCurrentContext();
  167.         [self reset];
  168.     }
  169.     return self;
  170. }
  171.  
  172. + reset
  173. {
  174.     id            miniStore;
  175.     int            i;
  176.     int            j;
  177.     int            pid;
  178.     int            icon;
  179.     int            menu;
  180.     int            count;
  181.     int            owner;
  182.     int            miniCount;
  183.     int            screenCount;
  184.     int            *minis;
  185.     int            *windows;
  186.     int            table();
  187.     char        nameUidString[40];
  188.     struct tbl_procinfo pi;
  189.     NXZone        *theZone = [self zone];
  190.  
  191.     [pidUidTable empty];
  192.     [pidMenuTable empty];
  193.     [pidIconTable empty];
  194.     [pidCtxtTable empty];
  195.     [ctxtPidTable empty];
  196.     [processTable empty];
  197.     [pidMinisTable freeObjects];
  198.  
  199.     PScountwindowlist(0, &count);
  200.     windows = (int *)NXZoneMalloc(theZone, count*sizeof(int)+ARRBUF);
  201.     count = safeGetWindowList(windows);
  202.  
  203.     minis = (int *)NXZoneMalloc(theZone, count*sizeof(int)+ARRBUF);
  204.  
  205.     for(i = 0; i < count; i++)    {
  206.         if (safeGetCurrrentOwner(windows[i], &owner) < 0)
  207.             continue;
  208.         if (safeGetCtxtIconPidAndMenu(owner, &icon, &pid, &menu) < 0)
  209.             continue;
  210.         if (![pidIconTable isKey:(const void *)pid])    {
  211.             miniCount = safeGetMiniWindows(owner, minis);
  212.             if (pid > 0 && miniCount > 0)    {
  213.                 if (icon < 0) icon = minis[--miniCount];
  214.                 miniStore = [[Storage allocFromZone:theZone]
  215.                                           initCount:miniCount
  216.                                         elementSize:sizeof(int)
  217.                                         description:"i"];
  218.                 for(j = 0; j < miniCount; j++)
  219.                     [miniStore replaceElementAt:j with:(void *)(minis+j)];
  220.                 [pidMinisTable insertKey:(const void *)pid value:(void *)miniStore];
  221.             }
  222.             [pidMenuTable insertKey:(const void *)pid value:(void *)menu];
  223.             [pidIconTable insertKey:(const void *)pid value:(void *)icon];
  224.             [pidCtxtTable insertKey:(const void *)pid value:(void *)owner];
  225.             [ctxtPidTable insertKey:(const void *)owner value:(void *)pid];
  226.             if ((int)table(TBL_PROCINFO, pid, (char *)&pi, 1, sizeof pi) == 1 && pi.pi_status==PI_ACTIVE)    {
  227.                 [pidUidTable insertKey:(const void *)pid value:(void *)pi.pi_uid];
  228.                 sprintf(nameUidString, "%s::%d", pi.pi_comm, pi.pi_uid);
  229.                 [processTable insertKey:(const void *)NXUniqueString(nameUidString) value:(void *)pid];
  230.             }
  231.         }
  232.     }
  233.     NXZoneFree(theZone, minis);
  234.     NXZoneFree(theZone, windows);
  235.     return self;
  236. }
  237.  
  238. + unhideCtxt:(int)ctxt raise:(BOOL)raiseFlag activate:(BOOL)activateFlag hideOthers:(BOOL)hideFlag
  239. {
  240.     if (safeUnhideContext(ctxt, (int)raiseFlag, (int)activateFlag, (int)hideFlag) == 0)
  241.         return self;
  242.     else
  243.         return nil;
  244. }
  245.  
  246. + unhidePid:(int)pid raise:(BOOL)raiseFlag activate:(BOOL)activateFlag hideOthers:(BOOL)hideFlag
  247. {
  248.     int        ctxt = [self getAppCtxtForPid:pid];
  249.  
  250.     if (safeUnhideContext(ctxt, (int)raiseFlag, (int)activateFlag, (int)hideFlag) == 0)
  251.         return self;
  252.     else
  253.         return nil;
  254. }
  255.  
  256. + vanishIconForCtxt:(int)ctxt
  257. {
  258.     return [self vanishIconForPid:[self getPidForAppCtxt:ctxt]];
  259. }
  260.  
  261. + vanishIconForPid:(int)pid
  262. {
  263.     int        appIcon = [self getAppIconForPid:pid];
  264.  
  265.     if (appIcon > 0)    {
  266.         DPSTraceContext(myContext, NO);
  267.         PSWMove(NOWHERE, NOWHERE, appIcon);
  268.         NXPing();
  269.         return self;
  270.     }
  271.     else
  272.         return nil;
  273. }
  274.  
  275. + unvanishIconForCtxt:(int)ctxt
  276. {
  277.     return [self unvanishIconForPid:[self getPidForAppCtxt:ctxt]];
  278. }
  279.  
  280. + unvanishIconForPid:(int)pid
  281. {
  282.     int        appIcon = [self getAppIconForPid:pid];
  283.  
  284.     if (appIcon > 0)    {
  285.         DPSTraceContext(myContext, NO);
  286.         PSWReplaceIcon(appIcon, (int)(screenSize.width)-64);
  287.         NXPing();
  288.         return self;
  289.     }
  290.     else
  291.         return nil;
  292. }
  293.  
  294. + getShortName:(char *)shortName from:(const char *)theAppFileName
  295. {
  296.     char    *theAppName;
  297.  
  298.     if (!shortName || !theAppFileName)
  299.         return self;
  300.  
  301.     shortName[0] = '\0';
  302.     theAppName = strrchr(theAppFileName, '/');
  303.  
  304.     if (!theAppName)    {
  305.         strcpy(shortName, theAppFileName);
  306.         return self;
  307.     }
  308.     else
  309.         theAppName++;
  310.  
  311.     if (!strcmp(theAppName+strlen(theAppName)-4, ".app"))    {
  312.         strncpy(shortName, theAppName, strlen(theAppName)-4);
  313.         shortName[strlen(theAppName)-4] = '\0';
  314.     }
  315.     else if (!strcmp(theAppName+strlen(theAppName)-6, ".debug"))    {
  316.         strncpy(shortName, theAppName, strlen(theAppName)-6);
  317.         shortName[strlen(theAppName)-6] = '\0';
  318.     }
  319.     else if (!strcmp(theAppName+strlen(theAppName)-8, ".profile"))    {
  320.         strncpy(shortName, theAppName, strlen(theAppName)-8);
  321.         shortName[strlen(theAppName)-6] = '\0';
  322.     }
  323.     else
  324.         strcpy(shortName, theAppName);
  325.     shortName[16]=0;
  326.  
  327.     return self;
  328. }
  329.  
  330. + (int)getPidFor:(char *)aName
  331. {
  332.     NXAtom    atom = NXUniqueString(aName);
  333.  
  334.     if ([processTable isKey:atom])
  335.         return (int)[processTable valueForKey:atom];
  336.     else
  337.         return -1;
  338. }
  339.  
  340. + (int)getUidForPid:(int)aPid
  341. {
  342.     if ([pidUidTable isKey:(void *)aPid])
  343.         return (int)[pidUidTable valueForKey:(void *)aPid];
  344.     else
  345.         return -1;
  346. }
  347.  
  348. + (int)getAppIconForPid:(int)aPid
  349. {
  350.     if ([pidIconTable isKey:(void *)aPid])
  351.         return (int)[pidIconTable valueForKey:(void *)aPid];
  352.     else
  353.         return -1;
  354. }
  355.  
  356. + (int)getAppMenuForPid:(int)aPid
  357. {
  358.     if ([pidMenuTable isKey:(void *)aPid])
  359.         return (int)[pidMenuTable valueForKey:(void *)aPid];
  360.     else
  361.         return -1;
  362. }
  363.  
  364. + (int)getAppCtxtForPid:(int)aPid
  365. {
  366.     if ([pidCtxtTable isKey:(void *)aPid])
  367.         return (int)[pidCtxtTable valueForKey:(void *)aPid];
  368.     else
  369.         return -1;
  370. }
  371.  
  372. + getAppMiniWinsForPid:(int)aPid
  373. {
  374.     if ([pidMinisTable isKey:(void *)aPid])
  375.         return [pidMinisTable valueForKey:(void *)aPid];
  376.     else
  377.         return nil;
  378. }
  379.  
  380. + (int)getPidForAppCtxt:(int)aCtxt
  381. {
  382.     if ([ctxtPidTable isKey:(void *)aCtxt])
  383.         return (int)[ctxtPidTable valueForKey:(void *)aCtxt];
  384.     else
  385.         return -1;
  386. }
  387.  
  388. + (BOOL)pidExists:(int)aPid
  389. {
  390.     return [pidUidTable isKey:(void *)aPid];
  391. }
  392.  
  393. - initForFile:(char *)theAppFileName 
  394. {
  395.     char        theShortName[100];
  396.  
  397.     [super init];
  398.     [[self class] getShortName:theShortName from:theAppFileName];
  399.  
  400.     appFileName = NXUniqueString(theAppFileName);
  401.     appShortName = NXUniqueString(theShortName);
  402.  
  403.     [self update];
  404.  
  405.     return self;
  406. }
  407.  
  408. - update
  409. {
  410.     isLaunched = ((appPid = [[self class] getPidFor:(char *)appShortName]) != -1);
  411.  
  412.     if (isLaunched)    {
  413.         appUid = (int)[pidUidTable valueForKey:(const void *)appPid];
  414.         appCtxt = (int)[pidCtxtTable valueForKey:(const void *)appPid];
  415.         appIconWin = (int)[pidIconTable valueForKey:(const void *)appPid];
  416.         appMainMenu = (int)[pidMenuTable valueForKey:(const void *)appPid];
  417.         appMiniWins = [pidMinisTable valueForKey:(const void *)appPid];
  418.     }
  419.     else    {
  420.         appUid = appCtxt = appIconWin = appMainMenu = -1;
  421.         appMiniWins = nil;
  422.     }
  423.  
  424.     return self;
  425. }
  426.  
  427. - activateApp:(BOOL)activateFlag raise:(BOOL)raiseFlag hideOthers:(BOOL)hideFlag
  428. {
  429.     return [[self class] unhideCtxt:appCtxt raise:raiseFlag activate:activateFlag hideOthers:hideFlag];
  430. }
  431.  
  432. - vanishIcon
  433. {
  434.     if (appIconWin > 0)
  435.         PSWMove(NOWHERE, NOWHERE, appIconWin);
  436.     return self;
  437. }
  438.  
  439. - unvanishIcon
  440. {
  441.     if (appIconWin > 0)    {
  442.         DPSTraceContext(myContext, NO);
  443.         PSWReplaceIcon(appIconWin, (int)(screenSize.width)-64);
  444.     }
  445.     return self;
  446. }
  447.  
  448. - free
  449. {
  450.     return [super free];
  451. }
  452.  
  453. - (BOOL)isLaunched
  454. {
  455.     return isLaunched;
  456. }
  457.  
  458. - (int)appPid
  459. {
  460.     return appPid;
  461. }
  462.  
  463. - (int)appUid
  464. {
  465.     return appUid;
  466. }
  467.  
  468. - (int)appCtxt
  469. {
  470.     return appCtxt;
  471. }
  472.  
  473. - (int)appIconWin
  474. {
  475.     return appIconWin;
  476. }
  477.  
  478. - (int)appMainMenu
  479. {
  480.     return appMainMenu;
  481. }
  482.  
  483. - appMiniWins
  484. {
  485.     return appMiniWins;
  486. }
  487.  
  488. - (NXAtom)appFileName
  489. {
  490.     return appFileName;
  491. }
  492.  
  493. - (NXAtom)appShortName
  494. {
  495.     return appShortName;
  496. }
  497.  
  498. @end
  499.  
  500. #ifdef ABTEST
  501. #include <libc.h>
  502. #include <string.h>
  503. #include <stdlib.h>
  504.  
  505. void
  506. listApps()
  507. {
  508.     id        appMinis;
  509.     int        i;
  510.     int        count;
  511.     int        appPid;
  512.     int        appUid;
  513.     int        appCtxt;
  514.     int        appMenu;
  515.     int        appIcon;
  516.     char    theName[30];
  517.     char    *shortName;
  518.     NXHashState    state = [processTable initState];
  519.  
  520.     printf("%-17s%7s%7s%12s%7s%7s%10s\n", "SHORTNAME", "PID", "UID", "CTXT", "ICON", "MENU", "MINIWINS");
  521.     while ([processTable nextState:&state key:(void *)&shortName value:(void *)&appPid])    {
  522.         if (strstr(shortName, "kernel idle")) continue;
  523.         strcpy(theName, shortName);
  524.         *strstr(theName, "::") = '\0';
  525.         appUid = (int)[pidUidTable valueForKey:(void *)appPid];
  526.         appCtxt = (int)[pidCtxtTable valueForKey:(void *)appPid];
  527.         appIcon = (int)[pidIconTable valueForKey:(void *)appPid];
  528.         appMenu = (int)[pidMenuTable valueForKey:(void *)appPid];
  529.         appMinis = [pidMinisTable valueForKey:(void *)appPid];
  530.         printf("%-17s%7d%7d%12d%7d%7d  ", theName, appPid, appUid, appCtxt, appIcon, appMenu);
  531.         if (appMinis != nil)    {
  532.             count = [appMinis count];
  533.             for(i = 0; i < count; i++)
  534.                 printf("%d ", *(int *)[appMinis elementAt:i]);
  535.         }
  536.         printf("\n");
  537.     }
  538. }
  539.  
  540. main(int argc, char **argv)
  541. {
  542.     id            miniWins;
  543.     int            c;
  544.     int            i;
  545.     int            count;
  546.     char        *theName;
  547.     int            pid = -1;
  548.     int            ctxt = -1;
  549.     int            appUid = -1;
  550.     int            action = 0;
  551.     BOOL        list = NO;
  552.     BOOL        raise = NO;
  553.     BOOL        activate = NO;
  554.     BOOL        hideOthers = NO;
  555.     BOOL        vanishIcon = NO;
  556.     BOOL        unvanishIcon = NO;
  557.     ABAppInfo    *info;
  558.     extern char    *optarg;
  559.  
  560.     [Application new];
  561.     while((c = getopt(argc, argv, "ac:hHp:ruvN:")) != -1)    {
  562.         switch(c)    {
  563.           case 'a': activate = YES; break;
  564.           case 'c': ctxt = atoi(optarg); break;
  565.           case 'H': hideOthers = YES; break;
  566.           case 'p': pid = atoi(optarg); break;
  567.           case 'r': raise = YES; break;
  568.           case 'u': unvanishIcon = YES; action++; break;
  569.           case 'v': vanishIcon = YES; action++; break;
  570.           case 'N':
  571.             info = [[ABAppInfo alloc] initForFile:optarg];
  572.             printf("%-17s%7s%7s%12s%7s%7s%10s\n",
  573.                    "SHORTNAME", "PID", "UID", "CTXT", "ICON", "MENU", "MINIWINS");
  574.             sscanf([info appShortName], "%[^:]::%d", theName, &appUid);
  575.             printf("%-17s%7d%7d%12d%7d%7d  ", theName, [info appPid], appUid,
  576.                    [info appCtxt], [info appIconWin], [info appMainMenu]);
  577.             miniWins = [info appMiniWins];
  578.             if (miniWins != nil)    {
  579.                 count = [miniWins count];
  580.                 for(i = 0; i < count; i++)
  581.                     printf("%d ", *(int *)[miniWins elementAt:i]);
  582.             }
  583.             printf("\n");
  584.             exit(0);
  585.             break;
  586.           case 'h':
  587.           case '?':
  588.             fprintf(stderr, "Usage: ctxt-util [[-h] | [-N appName::uid] | [[-p pid|-c ctxt] -arHvu]\n");
  589.             fprintf(stderr, "       with no args, lists all active contexts\n");
  590.             fprintf(stderr, "       -h: show this message\n");
  591.             fprintf(stderr, "       -N: list info for a single app name::uid (eg, 'Edit::0')\n");
  592.             fprintf(stderr, "       In conjunction with -p or -c:\n");
  593.             fprintf(stderr, "           -a: activate (hides if not present)\n");
  594.             fprintf(stderr, "           -r: raise windows\n");
  595.             fprintf(stderr, "           -H: hide other apps\n");
  596.             fprintf(stderr, "           -v: vanish app icon\n");
  597.             fprintf(stderr, "           -u: restore app icon\n");
  598.             exit(c!='h');
  599.         }
  600.     }
  601.  
  602.     if (action != 1) list = YES;
  603.  
  604.     if (unvanishIcon && vanishIcon)    {
  605.         fprintf(stderr, "Can only replace OR vanish an icon, not both!\n");
  606.         exit(1);
  607.     }
  608.  
  609.     if ((raise || activate || hideOthers || vanishIcon || unvanishIcon) && !(pid>0 || ctxt>0))    {
  610.         fprintf(stderr, "You need a process or context id to do that!\n");
  611.         exit(1);
  612.     }
  613.  
  614.     [ABAppInfo initialize];
  615.  
  616.     if (raise || activate || hideOthers)    {
  617.         if (pid > 0)
  618.             [ABAppInfo unhidePid:pid raise:raise activate:activate hideOthers:hideOthers];
  619.         else
  620.             [ABAppInfo unhideCtxt:ctxt raise:raise activate:activate hideOthers:hideOthers];
  621.     }
  622.     else if (unvanishIcon)    {
  623.         if (pid > 0)
  624.             [ABAppInfo unvanishIconForPid:pid];
  625.         else
  626.             [ABAppInfo unvanishIconForCtxt:ctxt];
  627.     }
  628.     else if (vanishIcon)    {
  629.         if (pid > 0)
  630.             [ABAppInfo vanishIconForPid:pid];
  631.         else
  632.             [ABAppInfo vanishIconForCtxt:ctxt];
  633.     }
  634.     else
  635.         listApps();
  636.     exit(0);
  637. }
  638.  
  639. #endif
  640.