Changeset 306 for trunk/appswitch


Ignore:
Timestamp:
10/28/06 13:47:45 (17 years ago)
Author:
Nicholas Riley
Message:

VERSION: Updated for 1.1d1.

main.c: Mostly switch to Process Manager. Remove obsolete comments.

README: Updated for 1.1d1.

appswitch.xcodeproj: Upgraded Xcode project.

Location:
trunk/appswitch/appswitch
Files:
4 added
1 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/appswitch/appswitch/README

    r160 r306  
    1 appswitch 1.0.1 [16 May 2004]
     1appswitch 1.1d1 [unreleased]
    22===============
    33
     
    3333% sudo /usr/bin/install -c build/appswitch /usr/local/bin
    3434% sudo /usr/bin/install -c appswitch.1 /usr/local/man/man1
    35 % rehash
     35% rehash                                # if necessary
    3636
    3737Uninstallation:
     
    4242-----------
    4343
    44 An Xcode project, 'appswitch.xcode', is included.  A precompiled
    45 binary is also provided.  'appswitch' was developed and tested under
    46 Mac OS 10.3.3 with the April 2004 Developer Tools, and does not
    47 require any additional software to build.
     44An Xcode project, 'appswitch.xcodeproj', is included.  A precompiled
     45Universal binary is also provided.  'appswitch' was developed and
     46tested under Mac OS 10.4.8 with Xcode 2.4, and does not require any
     47additional software to build.
    4848
    4949USAGE
     
    5656other methods, this should give you some indication.
    5757
    58 appswitch -a Emacs          0.00s user 0.02s system 55% cpu 0.054 total
    59 appswitch -i com.gnu.Emacs  0.00s user 0.04s system 63% cpu 0.063 total
    60 open -a Emacs               0.32s user 0.12s system 50% cpu 0.876 total
    61 launch -a Emacs             0.00s user 0.03s system 35% cpu 0.085 total
     58appswitch -a Emacs          0.01s user 0.01s system 28% cpu 0.069 total
     59launch -a Emacs             0.01s user 0.01s system 35% cpu 0.076 total
     60open -a Emacs               0.04s user 0.02s system 52% cpu 0.115 total
    6261osascript -e 'tell application "Emacs" to activate'
    63                             0.41s user 0.23s system 67% cpu 0.949 total
     62                            0.13s user 0.06s system 59% cpu 0.326 total
    6463
    65 The above tests were performed on a PowerBook G4/800; slower systems
    66 should show more dramatic differences.
     64The above tests were performed on a Mac mini Core Duo 1.66 GHz; slower
     65systems show more dramatic differences.
    6766
    6867COMMENTS, SUGGESTIONS, BUG REPORTS, ETC.
     
    7473---------------
    7574
     751.1 - unreleased
     76 - switched to Process Manager instead of CPS (slower but more
     77   compatible)
     78 - fixed description of -k option: SIGTERM, not SIGINT
     79 - added -f option
     80 - Universal Binary, compatible with Intel Macs
    76811.0.1 - 16 May 2004
    7782 - fixed crash matching applications with no bundle identifier
  • trunk/appswitch/appswitch/VERSION

    r161 r306  
    1 1.0.1
     11.1d1
  • trunk/appswitch/appswitch/main.c

    r163 r306  
    33 Nicholas Riley <appswitch@sabi.net>
    44
    5  Copyright (c) 2003-04, Nicholas Riley
     5 Copyright (c) 2003-06, Nicholas Riley
    66 All rights reserved.
    77
     
    1919
    2020#include <unistd.h>
     21#include <signal.h>
    2122#include <sys/ioctl.h>
     23#include <ApplicationServices/ApplicationServices.h>
    2224#include "CPS.h"
    2325
    2426const char *APP_NAME;
    2527
    26 #define VERSION "1.0.1"
     28#define VERSION "1.1d1"
    2729
    2830struct {
    29     OSType creator;
     31    CFStringRef creator;
    3032    CFStringRef bundleID;
    31     char *name;
     33    CFStringRef name;
    3234    pid_t pid;
    33     char *path;
     35    CFStringRef path;
    3436    enum {
    3537        MATCH_UNKNOWN, MATCH_FRONT, MATCH_CREATOR, MATCH_BUNDLE_ID, MATCH_NAME, MATCH_PID, MATCH_PATH, MATCH_ALL
    3638    } matchType;
    3739    enum {
    38         APP_NONE, APP_SWITCH, APP_SHOW, APP_HIDE, APP_QUIT, APP_KILL, APP_KILL_HARD, APP_LIST, APP_PRINT_PID
     40        APP_NONE, APP_SWITCH, APP_SHOW, APP_HIDE, APP_QUIT, APP_KILL, APP_KILL_HARD, APP_LIST, APP_PRINT_PID, APP_FRONTMOST
    3941    } appAction;
    4042    Boolean longList;
     
    5759static errList ERRS = {
    5860    // Process Manager errors
    59     { appIsDaemon, "application is background-only\n", },
    60     { procNotFound, "unable to connect to system service.\nAre you logged in?" },
     61    { appIsDaemon, "application is background-only", },
     62    { procNotFound, "application not found" },
     63    { connectionInvalid, "application is not background-only", },
    6164    // CoreGraphics errors
    6265    { kCGErrorIllegalArgument, "window server error.\nAre you logged in?" },
    6366    { fnfErr, "file not found" },
     67    // (abused) errors
     68    { permErr, "no permission" },
    6469    { 0, NULL }
    6570};
    6671
    6772void usage() {
    68     fprintf(stderr, "usage: %s [-sShHqkFlLP] [-c creator] [-i bundleID] [-a name] [-p pid] [path]\n"
     73    fprintf(stderr, "usage: %s [-sShHqklLPfF] [-c creator] [-i bundleID] [-a name] [-p pid] [path]\n"
    6974            "  -s            show application, bring windows to front (do not switch)\n"
    7075            "  -S            show all applications\n"
     
    7277            "  -H            hide other applications\n"
    7378            "  -q            quit application\n"
    74             "  -k            kill application (SIGINT)\n"
     79            "  -k            kill application (SIGTERM)\n"
    7580            "  -K            kill application hard (SIGKILL)\n"
    7681            "  -l            list applications\n"
    7782            "  -L            list applications including full paths and bundle identifiers\n"
    7883            "  -P            print application process ID\n"
     84            "  -f            bring application's frontmost window to front\n"
    7985            "  -F            bring current application's windows to front\n"
    8086            "  -c creator    match application by four-character creator code ('ToyS')\n"
    81             "  -i bundle ID  match application by bundle identifier (com.apple.scripteditor)\n"
    82             "  -p pid        match application by process identifier [slower]\n"
     87            "  -i bundle ID  match application by bundle identifier (com.apple.ScriptEditor2)\n"
     88            "  -p pid        match application by process identifier\n"
    8389            "  -a name       match application by name\n"
    8490            , APP_NAME);
    85     fprintf(stderr, "appswitch "VERSION" (c) 2003-04 Nicholas Riley <http://web.sabi.net/nriley/software/>.\n"
     91    fprintf(stderr, "appswitch "VERSION" (c) 2003-06 Nicholas Riley <http://web.sabi.net/nriley/software/>.\n"
    8692            "Please send bugs, suggestions, etc. to <appswitch@sabi.net>.\n");
    8793
     
    101107            break;
    102108        }
    103             len = strlen(errDesc) + 10 * sizeof(char);
     109    len = strlen(errDesc) + 10 * sizeof(char);
    104110    str = (char *)malloc(len);
    105111    if (str != NULL)
     
    136142    if (argc == 1) usage();
    137143
    138     const char *opts = "c:i:p:a:sShHqkKlLPF";
     144    const char *opts = "c:i:p:a:sShHqkKlLPfF";
    139145
    140146    while ( (ch = getopt(argc, argv, opts)) != -1) {
     
    148154            case 'c':
    149155                if (OPTS.matchType != MATCH_UNKNOWN) errexit("choose only one of -c, -i, -p, -a options");
    150                 if (strlen(optarg) != 4) errexit("creator (argument of -c) must be four characters long");
    151                 OPTS.creator = *(OSTypePtr)optarg;
     156                OPTS.creator = CFStringCreateWithFileSystemRepresentation(NULL, optarg);
     157                if (OPTS.creator == NULL) errexit("invalid creator (wrong text encoding?)");
     158                if (CFStringGetLength(OPTS.creator) != 4) errexit("creator (argument of -c) must be four characters long");
    152159                OPTS.matchType = MATCH_CREATOR;
    153160                break;
    154161            case 'i':
    155162                if (OPTS.matchType != MATCH_UNKNOWN) errexit("choose only one of -c, -i, -p, -a options");
    156                 OPTS.bundleID = CFStringCreateWithCString(NULL, optarg, CFStringGetSystemEncoding());
     163                OPTS.bundleID = CFStringCreateWithFileSystemRepresentation(NULL, optarg);
     164                if (OPTS.bundleID == NULL) errexit("invalid bundle ID (wrong text encoding?)");
    157165                OPTS.matchType = MATCH_BUNDLE_ID;
    158166                break;
    159167            case 'a':
    160168                if (OPTS.matchType != MATCH_UNKNOWN) errexit("choose only one of -c, -i, -p, -a options");
    161                 OPTS.name = strdup(optarg);
     169                OPTS.name = CFStringCreateWithFileSystemRepresentation(NULL, optarg);
     170                if (OPTS.name == NULL) errexit("invalid application name (wrong text encoding?)");
    162171                OPTS.matchType = MATCH_NAME;
    163172                break;
    164173            case 's':
    165                 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options");
     174                if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P, -f options");
    166175                OPTS.appAction = APP_SHOW;
    167176                break;
    168177            case 'h':
    169                 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options");
     178                if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P, -f options");
    170179                OPTS.appAction = APP_HIDE;
    171180                break;
    172181            case 'q':
    173                 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options");
     182                if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P, -f options");
    174183                OPTS.appAction = APP_QUIT;
    175184                break;
    176185            case 'k':
    177                 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options");
     186                if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P, -f options");
    178187                OPTS.appAction = APP_KILL;
    179188                break;
    180189            case 'K':
    181                 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options");
     190                if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P, -f options");
    182191                OPTS.appAction = APP_KILL_HARD;
    183192                break;
    184193            case 'l':
    185                 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options");
     194                if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P, -f options");
    186195                OPTS.appAction = APP_LIST;
    187196                break;
    188197            case 'L':
    189                 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options");
     198                if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P, -f options");
    190199                OPTS.appAction = APP_LIST;
    191200                OPTS.longList = true;
    192201                break;
    193202            case 'P':
    194                 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -P options");
     203                if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P, -f options");
    195204                OPTS.appAction = APP_PRINT_PID;
     205                break;
     206            case 'f':
     207                if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P, -f options");
     208                OPTS.appAction = APP_FRONTMOST;
    196209                break;
    197210            case 'S':
     
    224237            } else usage();
    225238        } else if (argc == 1) {
    226             OPTS.path = argv[0];
     239            OPTS.path = CFStringCreateWithFileSystemRepresentation(NULL, argv[0]);
     240            if (OPTS.path == NULL) errexit("invalid path (wrong text encoding?)");
    227241            OPTS.matchType = MATCH_PATH;
    228242        } else usage();
     
    234248}
    235249
    236 CPSProcessSerNum frontApplication() {
    237     CPSProcessSerNum psn;
    238     OSStatus err = CPSGetFrontProcess(&psn);
     250ProcessSerialNumber frontApplication() {
     251    ProcessSerialNumber psn;
     252    OSStatus err = GetFrontProcess(&psn);
    239253    if (err != noErr) osstatusexit(err, "can't get frontmost process");
    240254#if DEBUG
    241     fprintf(stderr, "front application PSN %ld.%ld\n", psn.hi, psn.lo);
     255    fprintf(stderr, "front application PSN %ld.%ld\n", psn.lowLongOfPSN, psn.highLongOfPSN);
    242256#endif
    243257    return psn;
    244258}
    245259
    246 Boolean bundleIdentifierForApplication(CFStringRef *bundleID, char *path) {
    247     CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, path, strlen(path), false);
    248     if (url == NULL) return false;
    249     CFBundleRef bundle = CFBundleCreate(NULL, url);
    250     if (bundle != NULL) {
    251         *bundleID = CFBundleGetIdentifier(bundle);
    252         if (*bundleID != NULL) {
    253             CFRetain(*bundleID);
    254 #if DEBUG
    255             CFShow(*bundleID);
    256 #endif
    257         }
    258         CFRelease(bundle);
    259     } else {
    260         *bundleID = NULL;
    261     }
    262     CFRelease(url);
    263     return true;
    264 }
    265 
    266 OSStatus quitApplication(CPSProcessSerNum *psn) {
     260OSStatus quitApplication(ProcessSerialNumber *psn) {
    267261    AppleEvent event;
    268262    AEAddressDesc appDesc;
     
    273267    if (err != noErr) return err;
    274268
    275     // XXX AECreateAppleEvent is very slow in Mac OS X 10.2.4 and earlier.
    276     // XXX This is Apple's bug: <http://lists.apple.com/archives/applescript-implementors/2003/Feb/19/aecreateappleeventfromco.txt>
    277269    err = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &appDesc, kAutoGenerateReturnID, kAnyTransactionID, &event);
    278270    if (err != noErr) return err;
     
    288280}
    289281
    290 CPSProcessSerNum matchApplication(CPSProcessInfoRec *info) {
    291     long pathMaxLength = pathconf("/", _PC_PATH_MAX);
    292     long nameMaxLength = pathconf("/", _PC_NAME_MAX);
    293 
    294     char *path = (char *)malloc(pathMaxLength);
    295     char *name = (char *)malloc(nameMaxLength);;
    296 
    297     if (path == NULL || name == NULL) errexit("can't allocate memory for path or filename buffer");
    298 
     282pid_t getPID(const ProcessSerialNumber *psn) {
     283    pid_t pid;
     284    OSStatus err = GetProcessPID(psn, &pid);
     285    if (err != noErr) osstatusexit(err, "can't get process ID");
     286    return pid;
     287}
     288
     289bool infoStringMatches(CFDictionaryRef info, CFStringRef key, CFStringRef matchStr) {
     290    CFStringRef str = CFDictionaryGetValue(info, key);
     291    if (str == NULL)
     292        return false;
     293    /* note: this means we might match names/paths that are wrong, but works better in the common case */
     294    return CFStringCompare(str, matchStr, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
     295}
     296
     297char *getInfoCString(CFDictionaryRef info, CFStringRef key) {
     298    CFStringRef str = CFDictionaryGetValue(info, key);
     299    if (str == NULL)
     300        return "";
     301    static char *cStr = NULL;
     302    static bool wasDynamic = false;
     303    if (wasDynamic)
     304        free(cStr);
     305    cStr = (char *)CFStringGetCStringPtr(str, CFStringGetSystemEncoding());
     306    if (cStr != NULL) {
     307        wasDynamic = false;
     308    } else {
     309        CFIndex cStrLength = CFStringGetMaximumSizeOfFileSystemRepresentation(str);
     310        cStr = (char *)malloc(cStrLength * sizeof(char));
     311        if (!CFStringGetFileSystemRepresentation(str, cStr, cStrLength)) {
     312            CFShow(cStr);
     313            errexit("internal error: string encoding conversion failed");
     314        }
     315        wasDynamic = true;
     316    }
     317    return cStr;
     318}
     319
     320ProcessSerialNumber matchApplication(void) {
    299321    if (OPTS.matchType == MATCH_FRONT) return frontApplication();
    300322
    301323    OSStatus err;
    302     CPSProcessSerNum psn = {
     324    ProcessSerialNumber psn = {
    303325        kNoProcess, kNoProcess
    304326    };
    305     int len;
     327    pid_t pid;
    306328    char *format = NULL;
    307329    if (OPTS.appAction == APP_LIST) {
     
    314336             ioctl(STDIN_FILENO,  TIOCGWINSZ, (char *)&ws) != -1) ||
    315337            ws.ws_col != 0) termwidth = ws.ws_col;
    316         char *formatButPath = "%9ld.%ld %5ld %c%c%c%c %c%c%c%c %-19.19s";
     338        char *formatButPath = "%9ld.%ld %5ld %4s %4s %-19.19s";
    317339        int pathlen = termwidth - strlen(banner) - 1;
    318340        // XXX don't ever free 'format', should fix if we get called repeatedly
     
    328350    }
    329351   
    330     while ( (err = CPSGetNextProcess(&psn)) == noErr) {
    331         err = CPSGetProcessInfo(&psn, info, path, pathMaxLength, &len, name, nameMaxLength);
    332         if (err != noErr) osstatusexit(err, "can't get information for process PSN %ld.%ld", psn.hi, psn.lo);
    333 
    334 #if DEBUG
    335         fprintf(stderr, "%ld.%ld: %s : %s\n", psn.hi, psn.lo, name, path);
    336 #endif
     352    CFDictionaryRef info = NULL;
     353    while ( (err = GetNextProcess(&psn)) == noErr) {
     354        if (info != NULL) CFRelease(info);
     355        info = ProcessInformationCopyDictionary(&psn, kProcessDictionaryIncludeAllInformationMask);
     356        if (info == NULL) errexit("can't get information for process with PSN %ld.%ld",
     357                                  psn.lowLongOfPSN, psn.highLongOfPSN);
    337358
    338359        switch (OPTS.matchType) {
    339360            case MATCH_ALL:
    340361                break;
    341             case MATCH_CREATOR: if (OPTS.creator != info->ExecFileCreator) continue;
    342                 break;
    343             case MATCH_NAME: if (strcmp(name, OPTS.name) != 0) continue;
    344                 break;
    345             case MATCH_PID: if (OPTS.pid != info->UnixPID) continue;
    346                 break;
    347             case MATCH_PATH: if (strcmp(path, OPTS.path) != 0) continue;
    348                 break;
    349             case MATCH_BUNDLE_ID:
    350                {
    351                    CFStringRef bundleID;
    352                    if (!bundleIdentifierForApplication(&bundleID, path))
    353                        errexit("can't get bundle location for process '%s' (PSN %ld.%ld, pid %ld)", name, psn.hi, psn.lo, info->UnixPID);
    354                    if (bundleID != NULL) {
    355                        CFComparisonResult result = CFStringCompare(OPTS.bundleID, bundleID, kCFCompareCaseInsensitive);
    356                        if (result == kCFCompareEqualTo)
    357                            break;
    358                        CFRelease(bundleID);
    359                    }
    360                    continue;
    361                }
     362            case MATCH_CREATOR: if (!infoStringMatches(info, CFSTR("FileCreator"), OPTS.creator)) continue;
     363                break;
     364            case MATCH_NAME: if (!infoStringMatches(info, CFSTR("CFBundleName"), OPTS.name)) continue;
     365                break;
     366            case MATCH_PID: err = GetProcessPID(&psn, &pid); if (err != noErr || OPTS.pid != pid) continue;
     367                break;
     368            case MATCH_PATH: if (!infoStringMatches(info, CFSTR("BundlePath"), OPTS.path)) continue;
     369                break;
     370            case MATCH_BUNDLE_ID: if (!infoStringMatches(info, CFSTR("CFBundleIdentifier"), OPTS.bundleID)) continue;
     371                break;
    362372            default:
    363373                errexit("internal error: invalid match type");
    364374        }
    365375        if (OPTS.appAction == APP_LIST) {
    366             char *type = (char *)&(info->ExecFileType), *crea = (char *)&(info->ExecFileCreator);
    367 #define CXX(c) ( (c) < ' ' ? ' ' : (c) )
    368 #define OSTYPE_CHAR_ARGS(t) CXX(t[0]), CXX(t[1]), CXX(t[2]), CXX(t[3])
    369             printf(format, psn.hi, psn.lo, info->UnixPID,
    370                    OSTYPE_CHAR_ARGS(type), OSTYPE_CHAR_ARGS(crea),
    371                    name, path);
     376            if (GetProcessPID(&psn, &pid) != noErr)
     377                pid = -1;
     378            printf(format, psn.lowLongOfPSN, psn.highLongOfPSN, pid,
     379                   getInfoCString(info, CFSTR("FileType")), getInfoCString(info, CFSTR("FileCreator")),
     380                   getInfoCString(info, CFSTR("CFBundleName")), getInfoCString(info, CFSTR("BundlePath")));
    372381            if (OPTS.longList) {
    373                 CFStringRef bundleID = NULL;
    374                 if (!bundleIdentifierForApplication(&bundleID, path))
    375                     errexit("can't get bundle location for process '%s' (PSN %ld.%ld, pid %ld)", name, psn.hi, psn.lo, info->UnixPID);
    376                 if (bundleID != NULL) {
    377                     char *bundleIDStr = (char *)CFStringGetCStringPtr(bundleID, CFStringGetSystemEncoding());
    378                     if (bundleIDStr == NULL) {
    379                         CFIndex bundleIDLength = CFStringGetLength(bundleID) + 1;
    380                         bundleIDStr = (char *)malloc(bundleIDLength * sizeof(char));
    381                         if (!CFStringGetCString(bundleID, bundleIDStr, bundleIDLength, CFStringGetSystemEncoding())) {
    382                             CFShow(bundleIDStr);
    383                             errexit("internal error: string encoding conversion failed for bundle identifier");
    384                         }
    385                         printf(" (%s)", bundleIDStr);
    386                         free(bundleIDStr);
    387                     } else {
    388                         printf(" (%s)", bundleIDStr);
    389                     }
    390                     CFRelease(bundleID);
    391                 }
     382                char *bundleID = getInfoCString(info, CFSTR("CFBundleIdentifier"));
     383                if (bundleID[0] != '\0')
     384                    printf(" (%s)", bundleID);
    392385            }
    393386            putchar('\n');
     
    410403    getargs(argc, argv);
    411404
    412     // need to establish connection with window server
    413     InitCursor();
    414 
    415     CPSProcessInfoRec info;
    416     CPSProcessSerNum psn = matchApplication(&info);
     405    ProcessSerialNumber psn = matchApplication();
    417406
    418407    const char *verb = NULL;
     
    420409        case APP_NONE: break;
    421410        case APP_LIST: break; // already handled in matchApplication
    422         case APP_SWITCH: err = CPSSetFrontProcess(&psn); verb = "set front"; break;
    423         case APP_SHOW: err = CPSPostShowReq(&psn); verb = "show"; break;
    424         case APP_HIDE: err = CPSPostHideReq(&psn); verb = "hide"; break;
     411        case APP_SWITCH: err = SetFrontProcess(&psn); verb = "set front"; break;
     412        case APP_SHOW: err = ShowHideProcess(&psn, true); verb = "show"; break;
     413        case APP_HIDE: err = ShowHideProcess(&psn, false); verb = "hide"; break;
    425414        case APP_QUIT: err = quitApplication(&psn); verb = "quit"; break;
    426         case APP_KILL: err = CPSPostKillRequest(&psn, kNilOptions); verb = "kill"; break;
    427         case APP_KILL_HARD: err = CPSPostKillRequest(&psn, bfCPSKillHard); verb = "kill"; break;
    428         case APP_PRINT_PID:
    429             if (info.UnixPID <= 0) errexit("can't get process ID");
    430             printf("%lu\n", info.UnixPID); // pid_t is signed, but this field isn't
     415        case APP_KILL: err = KillProcess(&psn); verb = "send SIGTERM to"; break;
     416        case APP_KILL_HARD:
     417        {
     418            if (kill(getPID(&psn), SIGKILL) == -1)
     419                err = (errno == ESRCH) ? procNotFound : (errno == EPERM ? permErr : paramErr);
     420            verb = "send SIGKILL to";
    431421            break;
     422        }
     423        case APP_PRINT_PID: printf("%d\n", getPID(&psn)); break;
     424        case APP_FRONTMOST: err = SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly);
     425            verb = "bring frontmost window to front"; break;
    432426        default:
    433427            errexit("internal error: invalid application action");
     
    449443            psn = frontApplication();
    450444#if DEBUG
    451             fprintf(stderr, "posting show request for %ld.%ld\n", psn.hi, psn.lo);
     445            fprintf(stderr, "posting show request for %ld.%ld\n", psn.lowLongOfPSN, psn.highLongOfPSN);
    452446#endif
    453447            if (OPTS.action != ACTION_NONE) usleep(750000); // XXX
    454             err = CPSPostShowReq(&psn) || CPSSetFrontProcess(&psn);
     448            err = ShowHideProcess(&psn, true) || SetFrontProcess(&psn);
    455449            verb = "bring current application's windows to the front";
    456450            break;
Note: See TracChangeset for help on using the changeset viewer.