- Timestamp:
- 05/11/08 22:47:36 (17 years ago)
- Location:
- trunk/launch/launch
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/launch/launch/README
r314 r477 63 63 An Xcode project, 'launch.xcodeproj', is included. A precompiled 64 64 Universal binary is also provided. 'launch' was developed and tested 65 under Mac OS X 10. 4.8 with Xcode 2.4, and does not require any65 under Mac OS X 10.5.2 with Xcode 3.1, and does not require any 66 66 additional software to build. 67 67 … … 225 225 1.1.1 - unreleased 226 226 - updated error codes for Mac OS X 10.4 227 - read Info.plists embedded in all Mach-O binaries (e.g. hdiutil) 227 228 1.1 - 30 October 2006 228 229 - -L: send "launch" (ascr/noop) event to app, bypasses automatic -
trunk/launch/launch/VERSION
r314 r477 1 1.1.1d 11 1.1.1d2 -
trunk/launch/launch/launch.xcodeproj/project.pbxproj
r308 r477 106 106 isa = PBXProject; 107 107 buildConfigurationList = E194195609C40AD400266191 /* Build configuration list for PBXProject "launch" */; 108 compatibilityVersion = "Xcode 2.4"; 108 109 hasScannedForEncodings = 1; 109 110 mainGroup = 08FB7794FE84155DC02AAC07 /* launch */; 110 111 projectDirPath = ""; 112 projectRoot = ""; 111 113 targets = ( 112 114 E194196209C40AFB00266191 /* launch */, -
trunk/launch/launch/main.c
r314 r477 3 3 Nicholas Riley <launchsw@sabi.net> 4 4 5 Copyright (c) 2001-0 6, Nicholas Riley5 Copyright (c) 2001-08, Nicholas Riley 6 6 All rights reserved. 7 7 … … 37 37 const char *APP_NAME; 38 38 39 #define VERSION "1.1 "39 #define VERSION "1.1.1d2" 40 40 41 41 #define STRBUF_LEN 1024 … … 99 99 { kCGErrorApplicationRequiresNewerSystem, "application requires a newer Mac OS X version" }, 100 100 { fnfErr, "file not found" }, 101 { eofErr, "data not found" }, 101 102 { 0, NULL } 102 103 }; … … 755 756 check(url != NULL && context == NULL); 756 757 757 if (stringFromURLIsRemote(url, strBuffer)) 758 if (stringFromURLIsRemote(url, strBuffer)) { 758 759 printf("<%s>: URL\n", strBuffer); 759 else { 760 static LSItemInfoRecord info; 761 CFStringRef version = NULL; 762 UInt32 intVersion = 0; 763 OSStatus err = LSCopyItemInfoForURL(url, kLSRequestAllInfo, &info); 764 Boolean haveFSRef; 765 FSRef fsr; 766 if (err != noErr) osstatusexit(err, "unable to get information about '%s'", strBuffer); 767 haveFSRef = CFURLGetFSRef(url, &fsr); 768 769 printf("%s: ", strBuffer); 770 771 // modifiers 772 if (info.flags & kLSItemInfoIsInvisible) printf("invisible "); 773 if (info.flags & kLSItemInfoAppIsScriptable) printf("scriptable "); 774 if (info.flags & kLSItemInfoIsNativeApp) printf("Mac OS X "); 775 if (info.flags & kLSItemInfoIsClassicApp) printf("Classic "); 776 777 // kind 778 if (info.flags & kLSItemInfoIsVolume) printf("volume"); 779 else if (info.flags & kLSItemInfoIsApplication) printf("application "); 780 else if (info.flags & kLSItemInfoIsPackage) printf("non-application "); 781 else if (info.flags & kLSItemInfoIsContainer) printf("folder"); 782 else if (info.flags & kLSItemInfoIsAliasFile) printf("alias"); 783 else if (info.flags & kLSItemInfoIsSymlink) printf("symbolic link"); 784 else if (info.flags & kLSItemInfoIsPlainFile) printf("document"); 785 else printf("unknown file system entity"); 786 787 if (info.flags & kLSItemInfoIsPackage) printf("package "); 788 789 if (info.flags & kLSItemInfoAppPrefersNative) printf("[Carbon, prefers native OS X]"); 790 else if (info.flags & kLSItemInfoAppPrefersClassic) printf("[Carbon, prefers Classic]"); 791 792 printf("\n"); 793 if (!(info.flags & kLSItemInfoIsContainer) || info.flags & kLSItemInfoIsPackage) { 794 printf("\ttype: '%s'", utf8StringFromOSType(info.filetype)); 795 printf("\tcreator: '%s'\n", utf8StringFromOSType(info.creator)); 796 } 797 if (info.flags & kLSItemInfoIsPackage || info.flags & kLSItemInfoIsApplication) { 798 // a package, or possibly a native app with a 'plst' resource 799 CFBundleRef bundle = CFBundleCreate(NULL, url); 800 CFStringRef bundleID = NULL; 801 if (bundle == NULL && (info.flags & kLSItemInfoIsApplication)) { 802 if (info.flags & kLSItemInfoIsPackage || !haveFSRef) { 803 printf("\t[can't access CFBundle for application]\n"); 804 } else { // OS X bug causes this to fail when it shouldn't, so fake it 805 SInt16 resFork = FSOpenResFile(&fsr, fsRdPerm); 806 OSStatus err = ResError(); 807 if (err != noErr) { 808 printf("\t[can't open resource fork: %s]\n", osstatusstr(err)); 809 } else { 810 Handle h = Get1Resource('plst', 0); 811 if ( (err = ResError()) != noErr || h == NULL) { 812 if (err != noErr && err != resNotFound) osstatusexit(err, "unable to read 'plst' 0 resource"); 813 } else { 814 CFDataRef plstData = CFDataCreate(NULL, (UInt8 *)*h, GetHandleSize(h)); 815 CFStringRef error; 816 CFPropertyListRef infoPlist = CFPropertyListCreateFromXMLData(NULL, plstData, kCFPropertyListImmutable, &error); 817 if (plstData != NULL) { 818 CFRelease(plstData); 819 plstData = NULL; 820 } else { 821 // this function should handle the 'plst' 0 case too, but it doesn't provide error messages; however, it handles the case of an unbundled Mach-O binary, so it is useful as a fallback 822 infoPlist = CFBundleCopyInfoDictionaryForURL(url); 823 } 824 if (infoPlist == NULL) { 825 printf("\t['plst' 0 resource invalid: %s]\n", utf8StringFromCFStringRef(error)); 826 CFRelease(error); 827 } else { 828 // mimic CFBundle logic below 829 bundleID = CFDictionaryGetValue(infoPlist, kCFBundleIdentifierKey); 830 if (bundleID != NULL) CFRetain(bundleID); 831 version = CFDictionaryGetValue(infoPlist, CFSTR("CFBundleShortVersionString")); 832 if (version == NULL) 833 version = CFDictionaryGetValue(infoPlist, kCFBundleVersionKey); 834 if (version != NULL) CFRetain(version); 835 CFRelease(infoPlist); 836 } 837 } 838 VersRecHndl vers = (VersRecHndl)Get1Resource('vers', 1); 839 if ( (err = ResError()) != noErr || vers == NULL) { 840 if (err != noErr && err != resNotFound) osstatusexit(err, "unable to read 'vers' 1 resource"); 841 } else { 842 if (version == NULL) { // prefer 'plst' version 843 version = CFStringCreateWithPascalString(NULL, vers[0]->shortVersion, CFStringGetSystemEncoding()); // XXX use country code instead? 844 } 845 intVersion = ((NumVersionVariant)vers[0]->numericVersion).whole; 846 } 847 CloseResFile(resFork); 848 } 849 } 850 } else { 851 bundleID = CFBundleGetIdentifier(bundle); 852 if (bundleID != NULL) CFRetain(bundleID); 853 // prefer a short version string, e.g. "1.0 Beta" instead of "51" for Safari 854 version = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("CFBundleShortVersionString")); 855 if (version == NULL) 856 version = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey); 857 if (version != NULL) { 858 CFRetain(version); 859 intVersion = CFBundleGetVersionNumber(bundle); 860 } 861 CFURLRef executable = CFBundleCopyExecutableURL(bundle); 862 if (executable != NULL) { 863 printExecutableArchitectures(executable, true); 864 CFRelease(executable); 865 } 866 CFRelease(bundle); 867 } 868 if (bundleID != NULL) { 869 printf("\tbundle ID: %s\n", utf8StringFromCFStringRef(bundleID)); 870 CFRelease(bundleID); 871 } 872 } else { 873 printExecutableArchitectures(url, false); 874 if (haveFSRef) { 875 // try to get a version if we can, but don't complain if we can't 876 SInt16 resFork = FSOpenResFile(&fsr, fsRdPerm); 877 if (ResError() == noErr) { 878 VersRecHndl vers = (VersRecHndl)Get1Resource('vers', 1); 879 if (ResError() == noErr && vers != NULL) { 880 version = CFStringCreateWithPascalString(NULL, vers[0]->shortVersion, CFStringGetSystemEncoding()); // XXX use country code instead? 881 intVersion = ((NumVersionVariant)vers[0]->numericVersion).whole; 882 } 883 } 884 CloseResFile(resFork); 885 } 886 } 887 760 return; 761 } 762 763 static LSItemInfoRecord info; 764 OSStatus err; 765 if ( (err = LSCopyItemInfoForURL(url, kLSRequestAllInfo, &info)) != noErr) 766 osstatusexit(err, "unable to get information about '%s'", strBuffer); 767 768 printf("%s: ", strBuffer); 769 770 // modifiers 771 if (info.flags & kLSItemInfoIsInvisible) printf("invisible "); 772 if (info.flags & kLSItemInfoAppIsScriptable) printf("scriptable "); 773 if (info.flags & kLSItemInfoIsNativeApp) printf("Mac OS X "); 774 if (info.flags & kLSItemInfoIsClassicApp) printf("Classic "); 775 776 // kind 777 if (info.flags & kLSItemInfoIsVolume) printf("volume"); 778 else if (info.flags & kLSItemInfoIsApplication) printf("application "); 779 else if (info.flags & kLSItemInfoIsPackage) printf("non-application "); 780 else if (info.flags & kLSItemInfoIsContainer) printf("folder"); 781 else if (info.flags & kLSItemInfoIsAliasFile) printf("alias"); 782 else if (info.flags & kLSItemInfoIsSymlink) printf("symbolic link"); 783 else if (info.flags & kLSItemInfoIsPlainFile) printf("document"); 784 else printf("unknown file system entity"); 785 786 if (info.flags & kLSItemInfoIsPackage) printf("package "); 787 788 if (info.flags & kLSItemInfoAppPrefersNative) printf("[Carbon, prefers native OS X]"); 789 else if (info.flags & kLSItemInfoAppPrefersClassic) printf("[Carbon, prefers Classic]"); 790 791 printf("\n"); 792 if (!(info.flags & kLSItemInfoIsContainer) || info.flags & kLSItemInfoIsPackage) { 793 printf("\ttype: '%s'", utf8StringFromOSType(info.filetype)); 794 printf("\tcreator: '%s'\n", utf8StringFromOSType(info.creator)); 795 } 796 797 CFStringRef bundleID = NULL; 798 CFStringRef version = NULL; 799 UInt32 intVersion = 0; 800 FSRef fsr; 801 Boolean haveFSRef = CFURLGetFSRef(url, &fsr); 802 CFBundleRef bundle = NULL; 803 804 if ((info.flags & kLSItemInfoIsPackage || info.flags & kLSItemInfoIsApplication) && 805 ( (bundle = CFBundleCreate(NULL, url)) != NULL)) { 806 bundleID = CFBundleGetIdentifier(bundle); 807 if (bundleID != NULL) CFRetain(bundleID); 808 // prefer a short version string, e.g. "1.0 Beta" instead of "51" for Safari 809 version = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("CFBundleShortVersionString")); 810 if (version == NULL) 811 version = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey); 888 812 if (version != NULL) { 889 printf("\tversion: %s", utf8StringFromCFStringRef(version)); 890 if (intVersion != 0) printf(" [0x%lx = %lu]", intVersion, intVersion); 891 putchar('\n'); 892 CFRelease(version); 893 } 894 895 // kind string 896 err = LSCopyKindStringForURL(url, &kind); 897 if (err != noErr) osstatusexit(err, "unable to get kind of '%s'", strBuffer); 898 printf("\tkind: %s\n", utf8StringFromCFStringRef(kind)); 899 CFRelease(kind); 900 901 if (haveFSRef) { 902 // content type identifier (UTI) 903 err = LSCopyItemAttribute(&fsr, kLSRolesAll, kLSItemContentType, (CFTypeRef *)&kind); 904 if (err == noErr) { 905 printf("\tcontent type ID: %s\n", utf8StringFromCFStringRef(kind)); 906 CFRelease(kind); 907 } 908 printMoreInfoForRef(fsr); 909 } 813 CFRetain(version); 814 intVersion = CFBundleGetVersionNumber(bundle); 815 } 816 CFURLRef executable = CFBundleCopyExecutableURL(bundle); 817 if (executable != NULL) { 818 printExecutableArchitectures(executable, true); 819 CFRelease(executable); 820 } 821 CFRelease(bundle); 822 } else if (info.flags & kLSItemInfoIsPackage || !haveFSRef) { 823 printf("\t[can't access package contents]\n"); 824 } else if (haveFSRef) { 825 SInt16 resFork = FSOpenResFile(&fsr, fsRdPerm); 826 CFPropertyListRef infoPlist = NULL; 827 if ( (err = ResError()) == noErr) { 828 Handle h = Get1Resource('plst', 0); 829 if (h == NULL) { 830 err = ResError(); 831 if (err != noErr && err != resNotFound) 832 osstatusexit(err, "unable to read 'plst' 0 resource"); 833 } else { 834 CFDataRef plstData = CFDataCreate(NULL, (UInt8 *)*h, GetHandleSize(h)); 835 CFStringRef error = NULL; 836 infoPlist = CFPropertyListCreateFromXMLData(NULL, plstData, kCFPropertyListImmutable, &error); 837 if (plstData != NULL) CFRelease(plstData); 838 if (infoPlist == NULL) { 839 printf("\t['plst' 0 resource invalid: %s]\n", utf8StringFromCFStringRef(error)); 840 CFRelease(error); 841 } 842 } 843 } 844 if (infoPlist == NULL) { 845 // this function should handle the 'plst' 0 case too, but it doesn't provide error messages; however, it handles the case of an unbundled Mach-O binary, so it is useful as a fallback 846 infoPlist = CFBundleCopyInfoDictionaryForURL(url); 847 if (infoPlist == NULL && info.flags & kLSItemInfoIsApplication && resFork == -1) 848 printf("\t[can't open resource fork: %s]\n", osstatusstr(err)); 849 } 850 if (infoPlist != NULL) { 851 // mimic CFBundle logic above 852 bundleID = CFDictionaryGetValue(infoPlist, kCFBundleIdentifierKey); 853 if (bundleID != NULL) CFRetain(bundleID); 854 version = CFDictionaryGetValue(infoPlist, CFSTR("CFBundleShortVersionString")); 855 if (version == NULL) 856 version = CFDictionaryGetValue(infoPlist, kCFBundleVersionKey); 857 if (version != NULL) CFRetain(version); 858 CFRelease(infoPlist); 859 } 860 if (resFork != -1) { 861 VersRecHndl vers = (VersRecHndl)Get1Resource('vers', 1); 862 if (vers == NULL) { 863 err = ResError(); 864 if (err != noErr && err != resNotFound) 865 osstatusexit(err, "unable to read 'vers' 1 resource"); 866 } else { 867 if (version == NULL) { // prefer 'plst' version 868 version = CFStringCreateWithPascalString(NULL, vers[0]->shortVersion, CFStringGetSystemEncoding()); // XXX use country code instead? 869 } 870 intVersion = ((NumVersionVariant)vers[0]->numericVersion).whole; 871 } 872 CloseResFile(resFork); 873 } 874 printExecutableArchitectures(url, false); 875 } 876 877 if (bundleID != NULL) { 878 printf("\tbundle ID: %s\n", utf8StringFromCFStringRef(bundleID)); 879 CFRelease(bundleID); 880 } 881 if (version != NULL) { 882 printf("\tversion: %s", utf8StringFromCFStringRef(version)); 883 if (intVersion != 0) printf(" [0x%lx = %lu]", intVersion, intVersion); 884 putchar('\n'); 885 CFRelease(version); 886 } 887 888 // kind string 889 err = LSCopyKindStringForURL(url, &kind); 890 if (err != noErr) osstatusexit(err, "unable to get kind of '%s'", strBuffer); 891 printf("\tkind: %s\n", utf8StringFromCFStringRef(kind)); 892 CFRelease(kind); 893 894 if (haveFSRef) { 895 // content type identifier (UTI) 896 err = LSCopyItemAttribute(&fsr, kLSRolesAll, kLSItemContentType, (CFTypeRef *)&kind); 897 if (err == noErr) { 898 printf("\tcontent type ID: %s\n", utf8StringFromCFStringRef(kind)); 899 CFRelease(kind); 900 } 901 printMoreInfoForRef(fsr); 910 902 } 911 903 }
Note:
See TracChangeset
for help on using the changeset viewer.