00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 /*************************************************************************** 00009 * RCS INFORMATION: 00010 * 00011 * $RCSfile: macosxvmdstart.C,v $ 00012 * $Author: johns $ $Locker: $ $State: Exp $ 00013 * $Revision: 1.29 $ $Date: 2020年12月13日 07:41:55 $ 00014 * 00015 ***************************************************************************/ 00021 // only compile this file if we're building on MacOS X 00022 // and when the target build is meant for an application bundle install 00023 // rather than a traditional X11/Unix style VMD install 00024 #if !defined(VMDNOMACBUNDLE) && (defined(ARCH_MACOSX) || defined(ARCH_MACOSXARM64) || defined(ARCH_MACOSXX86) || defined(ARCH_MACOSXX86_64)) 00025 #include <Carbon/Carbon.h> /* Carbon APIs for process management */ 00026 #include <stdlib.h> 00027 #include <stdio.h> 00028 #include "utilities.h" /* string/filename manipulation routines */ 00029 00030 #if !(defined(ARCH_MACOSXARM64) || defined(ARCH_MACOSXX86_64)) 00031 00032 // 00033 // Application bundle query APIs for Carbon-based 32-bit builds 00034 // 00035 OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr) { 00036 OSErr err; 00037 ProcessSerialNumber psn; 00038 err = GetCurrentProcess(&psn); 00039 if (err != noErr) return err; 00040 00041 FSRef location; 00042 err = GetProcessBundleLocation(&psn, &location); 00043 if (err != noErr) return err; 00044 00045 return FSGetCatalogInfo(&location, kFSCatInfoNone, 00046 NULL, NULL, theFSSpecPtr, NULL); 00047 } 00048 00049 OSErr GetApplicationPackageFSSpecFromBundle(FSSpecPtr theFSSpecPtr) { 00050 OSErr err = fnfErr; 00051 CFBundleRef myAppsBundle = CFBundleGetMainBundle(); 00052 if (myAppsBundle == NULL) return err; 00053 CFURLRef myBundleURL = CFBundleCopyBundleURL(myAppsBundle); 00054 if (myBundleURL == NULL) return err; 00055 00056 FSRef myBundleRef; 00057 Boolean ok = CFURLGetFSRef(myBundleURL, &myBundleRef); 00058 CFRelease(myBundleURL); 00059 if (!ok) return err; 00060 00061 return FSGetCatalogInfo(&myBundleRef, kFSCatInfoNone, 00062 NULL, NULL, theFSSpecPtr, NULL); 00063 } 00064 00065 #endif 00066 00067 00068 static char * vmd_get_vmddir(void) { 00069 OSErr rc = 0; 00070 FSSpec spec; 00071 FSRef ref; 00072 UInt8 *path = NULL; 00073 char *bundledir = NULL; 00074 char *vmddir = NULL; 00075 char *tmp = NULL; 00076 00077 bundledir = (char *) malloc(2048 * sizeof(UInt8)); 00078 memset(bundledir, 0, 2048 * sizeof(UInt8)); 00079 00080 #if defined(ARCH_MACOSXARM64) || defined(ARCH_MACOSXX86_64) 00081 // 00082 // CoreFoundation/Cocoa-based application bundle path query code 00083 // 00084 CFBundleRef mainbundle = CFBundleGetMainBundle(); 00085 if (mainbundle != NULL) { 00086 #if 1 00087 CFURLRef appurl = CFBundleCopyBundleURL(mainbundle); 00088 #else 00089 CFURLRef appurl = CFBundleCopyExecutableURL(mainbundle); 00090 #endif 00091 CFStringRef cfpath = CFURLCopyFileSystemPath(appurl, kCFURLPOSIXPathStyle); 00092 if (CFStringGetFileSystemRepresentation(cfpath, bundledir, 2048 * sizeof(UInt8) - 1) == true) { 00093 // printf("MacOS X Bundle path: %s\n", bundledir); 00094 00095 // Truncate bundle path to parent bundle directory, 00096 // if needed, when the executable is launched by double clicking 00097 // the application bundle in the GUI. When the application 00098 // is launched directly via scripts etc, the main bundle path 00099 // returned from the previous calls already points to the parent 00100 // directory of the VMD executable. 00101 if (strstr(bundledir, "/Contents/Resources/VMD.app")) { 00102 if ((tmp = strrchr(bundledir, '/')) != NULL) { 00103 tmp[0] = '0円'; 00104 } 00105 if ((tmp = strrchr(bundledir, '/')) != NULL) { 00106 tmp[0] = '0円'; 00107 } 00108 if ((tmp = strrchr(bundledir, '/')) != NULL) { 00109 tmp[0] = '0円'; 00110 } 00111 00112 // add path to main VMD directory from the outermost bundle container 00113 strcat(bundledir, "/Contents/vmd"); 00114 } 00115 00116 00117 vmddir = (char *) malloc(strlen(bundledir) + 1 + strlen("/vmd")); 00118 strcpy(vmddir, bundledir); 00119 } 00120 00121 free(bundledir); 00122 CFRelease(appurl); 00123 CFRelease(cfpath); 00124 } 00125 00126 if (!vmddir) { 00127 printf("WARNING: Failed to get path for main VMD application bundle...\n"); 00128 vmddir = getenv("VMDDIR"); 00129 } 00130 00131 #else 00132 00133 // 00134 // Carbon-based application bundle path query code 00135 // 00136 #if 0 00137 if (!(rc = GetApplicationPackageFSSpecFromBundle(&spec))) { 00138 #else 00139 if (!(rc = GetApplicationBundleFSSpec(&spec))) { 00140 #endif 00141 rc = FSpMakeFSRef(&spec, &ref); 00142 if (rc) printf("makefsref OSErr: %d\n", rc); 00143 00144 rc = FSRefMakePath(&ref,(UInt8 *) bundledir, 2048); 00145 if (rc) printf("makepath OSErr: %d\n", rc); 00146 } else { 00147 printf("getappbundlepath OSErr: %d\n", rc); 00148 } 00149 00150 if (rc) { 00151 free(bundledir); 00152 return NULL; 00153 } 00154 00155 // truncate bundle path to parent bundle directory 00156 if ((tmp = strrchr(bundledir, '/')) != NULL) { 00157 tmp[0] = '0円'; 00158 } 00159 if ((tmp = strrchr(bundledir, '/')) != NULL) { 00160 tmp[0] = '0円'; 00161 } 00162 00163 // add "/vmd" to parent bundle directory 00164 vmddir = (char *) malloc(strlen(bundledir) + 1 + strlen("/vmd")); 00165 strcpy(vmddir, bundledir); 00166 strcat(vmddir, "/vmd"); 00167 00168 free(bundledir); 00169 #endif 00170 00171 return (char *) vmddir; 00172 } 00173 00174 00175 #if 1 00176 int macosxvmdstart(int argc, char **argv) { 00177 #else 00178 int main(int argc, char **argv) { 00179 #endif 00180 char tmp[8192]; 00181 char * vmddir; 00182 int i; 00183 00184 vmddir = vmd_get_vmddir(); 00185 if (vmddir == NULL) { 00186 return -1; // fail and exit 00187 } 00188 00189 #if 0 00190 if (!getenv("MACOSXVMDSTARTUP")) { 00191 int startterminal=1; // be default, we start one... 00192 00193 setenv("MACOSXVMDSTARTUP", "1", 1); 00194 // check for -dispdev text, in which case we don't start a terminal... 00195 for (i=0; i < argc; i++) { 00196 if (!strupcmp(argv[i], "-dispdev")) { 00197 if (argc > i+1) { 00198 if (!strupcmp(argv[i+1], "text")) { 00199 startterminal=0; 00200 } 00201 } 00202 } 00203 } 00204 00205 if (startterminal) { 00206 char cmdbuf[16384]; 00207 sprintf(cmdbuf, "\"%s/vmd_MACOSX\"", vmddir); 00208 if (argc > 1) { 00209 for (i=1; i < argc; i++) { 00210 strcat(cmdbuf, " "); 00211 strcat(cmdbuf, argv[i]); 00212 } 00213 } 00214 strcat(cmdbuf, " &"); 00215 00216 printf("Executing VMD startup command: %s\n", cmdbuf); 00217 exit(system(cmdbuf)); 00218 } 00219 } 00220 #endif 00221 00222 if (!getenv("VMDDIR")) { 00223 setenv("VMDDIR", vmddir, 1); 00224 } 00225 00226 if (!getenv("TCL_LIBRARY")) { 00227 strcpy(tmp, vmddir); 00228 strcat(tmp, "/scripts/tcl"); 00229 setenv("TCL_LIBRARY", tmp, 1); 00230 } 00231 00232 if (!getenv("TK_LIBRARY")) { 00233 strcpy(tmp, vmddir); 00234 strcat(tmp, "/scripts/tk"); 00235 setenv("TK_LIBRARY", tmp, 1); 00236 } 00237 00238 if (!getenv("PYTHONPATH")) { 00239 strcpy(tmp, vmddir); 00240 strcat(tmp, "/scripts/python"); 00241 setenv("PYTHONPATH", tmp, 1); 00242 } else { 00243 strcpy(tmp, getenv("PYTHONPATH")); 00244 strcat(tmp, ":"); 00245 strcat(tmp, vmddir); 00246 strcat(tmp, "/scripts/python"); 00247 setenv("PYTHONPATH", tmp, 1); 00248 } 00249 00250 if (!getenv("STRIDE_BIN")) { 00251 strcpy(tmp, vmddir); 00252 #if defined(ARCH_MACOSXARM64) 00253 strcat(tmp, "/stride_MACOSXARM64"); 00254 #elif defined(ARCH_MACOSXX86_64) 00255 strcat(tmp, "/stride_MACOSXX86_64"); 00256 #elif defined(ARCH_MACOSXX86) 00257 strcat(tmp, "/stride_MACOSXX86"); 00258 #else 00259 strcat(tmp, "/stride_MACOSX"); 00260 #endif 00261 setenv("STRIDE_BIN", tmp, 1); 00262 } 00263 00264 if (!getenv("SURF_BIN")) { 00265 strcpy(tmp, vmddir); 00266 #if defined(ARCH_MACOSXARM64) 00267 strcat(tmp, "/surf_MACOSXARM64"); 00268 #elif defined(ARCH_MACOSXX86_64) 00269 strcat(tmp, "/surf_MACOSXX86_64"); 00270 #elif defined(ARCH_MACOSXX86) 00271 strcat(tmp, "/surf_MACOSXX86"); 00272 #else 00273 strcat(tmp, "/surf_MACOSX"); 00274 #endif 00275 setenv("SURF_BIN", tmp, 1); 00276 } 00277 00278 if (!getenv("TACHYON_BIN")) { 00279 strcpy(tmp, vmddir); 00280 #if defined(ARCH_MACOSXARM64) 00281 strcat(tmp, "/tachyon_MACOSXARM64"); 00282 #elif defined(ARCH_MACOSXX86_64) 00283 strcat(tmp, "/tachyon_MACOSXX86_64"); 00284 #elif defined(ARCH_MACOSXX86) 00285 strcat(tmp, "/tachyon_MACOSXX86"); 00286 #else 00287 strcat(tmp, "/tachyon_MACOSX"); 00288 #endif 00289 setenv("TACHYON_BIN", tmp, 1); 00290 } 00291 00292 return 0; 00293 } 00294 00295 00296 #endif 00297