Ignore:
Timestamp:
10/23/03 21:06:33 (21 years ago)
Author:
Nicholas Riley
Message:

VERSION: Updated for 1.0 (at long last!)

main.c: Dealt with -b/-h issue through documentation in man page,
removed from to do list. Dealt with -X issue through testing and
adding kLSNoClassicEnvironmentErr. Added kLSNoExecutableErr and
kCGErrorApplicationRequiresNewerSystem. Removed
BROKEN_LAUNCHNEWINSTANCE because it's fixed in Panther. Updated for
1.0. Fixed a couple of minor memory leaks. Output errors to stderr
instead of stdout. Work around bug in LSOpenFromURLSpec in Panther
(filed bug already). Don't make '????' look like a trigraph to GCC.

launch.pbproj: Updated for Xcode.

launch.1: Manual page, finally. Documents several known Mac OS X bugs
which interfere with launch's functioning.

README: Updated for 1.0. Added man page installation/removal
instructions, just like appswitch. s/Chimera/Camino/. Added my zsh
e() function as an example. Updated examples to reflect current
software versions and usage. Updated stationery discussion to mention
that Omni apps handle stationery too.

package-launch.sh: Set type/creator of files (not that it matters
since we're not doing a dmg distribution any more). Changes for man
page packaging.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/launch/launch/main.c

    r138 r146  
    1818/* To do/think about:
    1919
    20 - Do we need to assume -b if -h?  Hiding the foreground app just makes
    21 it flash (only if Cocoa?)
    22 
    23 - Does -X work at all?  What does it return if it fails?
    24 
    2520- Launching as root: use authentication framework - doesn't work.
    2621
     
    3732*/
    3833
    39 #define DEBUG 1
     34/* #define DEBUG 1 */
    4035#define BROKEN_AUTHORIZATION 1
    41 #define BROKEN_LAUNCHNEWINSTANCE 1
     36#define BROKEN_LSOPENFROMURLSPEC 1
    4237#define kComponentSignatureString "launch"
    4338
     
    5651const char *APP_NAME;
    5752
    58 #define VERSION "1.0b3"
     53#define VERSION "1.0"
    5954
    6055#define STRBUF_LEN 1024
     
    9085    { kLSLaunchInProgressErr, "application is being opened; please try again after the application is open" },
    9186    { kLSNotRegisteredErr, "application not registered in Launch Services database" },
     87    { kLSNoExecutableErr, "application package contains no executable, or an unusable executable" },
     88    { kLSNoClassicEnvironmentErr, "Classic environment required but not available" },
    9289#ifndef BROKEN_AUTHORIZATION
    9390    // Security framework errors
     
    10299    { procNotFound, "unable to connect to system service.\nAre you logged in?" },
    103100    { kCGErrorIllegalArgument, "window server error.\nAre you logged in?" },
     101    { kCGErrorApplicationRequiresNewerSystem, "application requires a newer Mac OS X version" },
    104102    { fnfErr, "file not found" },
    105103    { 0, NULL }
     
    119117        "  -w            wait for application to finish opening before exiting\n"
    120118        "  -b            launch application in the background\n"
    121 #ifndef BROKEN_LAUNCHNEWINSTANCE
    122119        "  -m            launch application again, even if already running\n"
    123 #endif
    124120        "  -h            hide application once it's finished opening\n"
    125121        "  -C            force CFM/PEF Carbon application to launch in Classic\n"
     
    254250                CFRelease(url);
    255251                url = NULL;
    256             }
     252            } else {
     253                CFRelease(scheme);
     254            }
    257255        }
    258256    }
     
    382380        case 'w': LSPEC.launchFlags ^= kLSLaunchAsync; break;      // synchronous
    383381        case 'b': LSPEC.launchFlags |= kLSLaunchDontSwitch; break; // open in background
    384 #ifdef BROKEN_LAUNCHNEWINSTANCE
    385         case 'm': errexit("-m option not functional (LaunchServices bug?), sorry");
    386 #else
    387382        case 'm': LSPEC.launchFlags |= kLSLaunchNewInstance; break;// open multiple
    388 #endif
    389383        case 'h': LSPEC.launchFlags |= kLSLaunchAndHide; break;    // hide once launched
    390384        case 'C': LSPEC.launchFlags |= kLSLaunchInClassic; break;  // force Classic
     
    419413                    if (scheme == NULL || !CFEqual(scheme, CFSTR("file")))
    420414                        errexit("invalid file:// URL (argument of -u)");
     415                    CFRelease(scheme);
    421416                }
    422417            }
     
    501496}
    502497
    503 // 'context' is to match prototype for CFArrayApplierFunction, it's unused
    504 void printPathFromURL(CFURLRef url, void *context) {
     498void printPathFromURL(CFURLRef url, FILE *stream) {
    505499    CFStringRef scheme, pathOrURL;
    506500    static char strBuffer[STRBUF_LEN];
    507501   
    508     check(url != NULL && context == NULL);
     502    check(url != NULL && stream != NULL);
    509503
    510504    scheme = CFURLCopyScheme(url);
     
    517511    strBuffer[0] = '\0';
    518512    CFStringGetCString(pathOrURL, strBuffer, STRBUF_LEN, CFStringGetSystemEncoding()); // XXX buffer size issues?
    519     printf("%s\n", strBuffer);
     513    fprintf(stream, "%s\n", strBuffer);
    520514    CFRelease(scheme);
    521515    CFRelease(pathOrURL);
     
    700694                                bundleID = CFDictionaryGetValue(infoPlist, kCFBundleIdentifierKey);
    701695                                if (bundleID != NULL) CFRetain(bundleID);
    702                                 CFStringRef appVersion = CFDictionaryGetValue(infoPlist, CFSTR("CFBundleShortVersionString"));
     696                                appVersion = CFDictionaryGetValue(infoPlist, CFSTR("CFBundleShortVersionString"));
    703697                                if (appVersion == NULL)
    704698                                    appVersion = CFDictionaryGetValue(infoPlist, kCFBundleVersionKey);
     
    723717                if (bundleID != NULL) CFRetain(bundleID);
    724718                // prefer a short version string, e.g. "1.0 Beta" instead of "51" for Safari
    725                 CFStringRef appVersion = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("CFBundleShortVersionString"));
     719                appVersion = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("CFBundleShortVersionString"));
    726720                if (appVersion == NULL)
    727721                    appVersion = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey);
    728                 if (appVersion != NULL)
     722                if (appVersion != NULL) {
     723                    CFRetain(appVersion);
    729724                    intVersion = CFBundleGetVersionNumber(bundle);
     725                }
    730726                CFRelease(bundle);
    731727            }
     
    749745        CFStringGetCString(kind, tmpBuffer, STRBUF_LEN, CFStringGetSystemEncoding());
    750746        printf("\tkind: %s\n", tmpBuffer);
     747        CFRelease(kind);
    751748        printMoreInfoFromURL(url);
    752749    }
     
    772769   
    773770    CFRelease(urlStr);
     771}
     772
     773OSStatus openFromURLSpec() {
     774#ifndef BROKEN_LSOPENFROMURLSPEC
     775    return LSOpenFromURLSpec(&LSPEC, NULL);
     776#else
     777    LSLaunchFSRefSpec spec = {NULL, 0, NULL, LSPEC.passThruParams,
     778                              LSPEC.launchFlags, LSPEC.asyncRefCon};
     779    CFIndex urlIndex, urlCount = LSPEC.itemURLs ? CFArrayGetCount(LSPEC.itemURLs) : 0;
     780    FSRef *itemRefs = malloc(urlCount * sizeof(FSRef));
     781    CFURLRef url;
     782    CFStringRef scheme, fileScheme = CFSTR("file");
     783    int itemIndex = 0;
     784    OSStatus err;
     785
     786    for (urlIndex = 0 ; urlIndex < urlCount ; urlIndex++) {
     787        url = CFArrayGetValueAtIndex(LSPEC.itemURLs, urlIndex);
     788        scheme = CFURLCopyScheme(url);
     789        if (CFEqual(scheme, fileScheme)) {
     790            if (CFURLGetFSRef(url, &itemRefs[itemIndex])) {
     791                itemIndex++;
     792                CFArrayRemoveValueAtIndex((CFMutableArrayRef)LSPEC.itemURLs, urlIndex);
     793                urlIndex--;
     794                urlCount--;
     795            } else {
     796                fprintf(stderr, "%s: unable to locate: ", APP_NAME);
     797                printPathFromURL(url, stderr);
     798            }
     799        }
     800        CFRelease(scheme);
     801    }
     802
     803    if (urlCount > 0 || itemIndex == 0) { /* URLs, or no items */
     804        err = LSOpenFromURLSpec(&LSPEC, NULL);
     805        if (err != noErr)
     806            return err;
     807    }
     808    if (itemIndex > 0) {
     809        FSRef appRef;
     810        spec.numDocs = itemIndex;
     811        spec.itemRefs = itemRefs;
     812        if (LSPEC.appURL != NULL) {
     813            if (!CFURLGetFSRef(LSPEC.appURL, &appRef)) {
     814                errexit("can't find application");
     815            }
     816            spec.appRef = &appRef;
     817        }
     818        return LSOpenFromRefSpec(&spec, NULL);
     819    }
     820    return noErr;
     821#endif
    774822}
    775823
     
    798846    switch (OPTS.action) {
    799847    case ACTION_FIND:
    800         printPathFromURL(LSPEC.appURL, NULL);
     848        printPathFromURL(LSPEC.appURL, stdout);
    801849        break;
    802850    case ACTION_OPEN:
    803         err = LSOpenFromURLSpec(&LSPEC, NULL);
     851        err = openFromURLSpec();
    804852        if (err != noErr) osstatusexit(err, "can't open application", argv[1]);
    805853        break;
    806854    case ACTION_FIND_ITEMS:
    807855        CFArrayApplyFunction(LSPEC.itemURLs, CFRangeMake(0, CFArrayGetCount(LSPEC.itemURLs)),
    808                              (CFArrayApplierFunction) printPathFromURL, NULL);
     856                             (CFArrayApplierFunction) printPathFromURL, stdout);
    809857        break;
    810858    case ACTION_OPEN_ITEMS:
    811         err = LSOpenFromURLSpec(&LSPEC, NULL);
     859        err = openFromURLSpec();
    812860        if (err != noErr) osstatusexit(err, "can't open items", argv[1]);
    813861        break;
     
    819867    {
    820868        ICInstance icInst;
    821         err = ICStart(&icInst, '????');
     869        err = ICStart(&icInst, '\?\?\?\?'); // in case GCC trigraph handling is enabled
    822870        if (err != noErr) osstatusexit(err, "can't initialize Internet Config", argv[1]);
    823871        CFArrayApplyFunction(LSPEC.itemURLs, CFRangeMake(0, CFArrayGetCount(LSPEC.itemURLs)),
Note: See TracChangeset for help on using the changeset viewer.