Changeset 99 for trunk/appswitch/appswitch/main.c
- Timestamp:
- 02/20/03 02:08:05 (22 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/appswitch/appswitch/main.c
r97 r99 24 24 const char *APP_NAME; 25 25 26 #define VERSION "1.0 b2"26 #define VERSION "1.0" 27 27 28 28 struct { … … 36 36 } matchType; 37 37 enum { 38 APP_NONE, APP_SWITCH, APP_SHOW, APP_HIDE, APP_ KILL, APP_LIST, APP_PRINT_PID38 APP_NONE, APP_SWITCH, APP_SHOW, APP_HIDE, APP_QUIT, APP_KILL, APP_KILL_HARD, APP_LIST, APP_PRINT_PID 39 39 } appAction; 40 Boolean longList; 40 41 enum { 41 42 ACTION_NONE, ACTION_SHOW_ALL, ACTION_HIDE_OTHERS … … 46 47 } OPTS = 47 48 { 48 kLSUnknownCreator, NULL, NULL, -1, NULL, MATCH_UNKNOWN, APP_NONE, ACTION_NONE, FINAL_NONE 49 kLSUnknownCreator, NULL, NULL, -1, NULL, MATCH_UNKNOWN, APP_NONE, ACTION_NONE, FINAL_NONE, false 49 50 }; 50 51 … … 70 71 " -h hide application\n" 71 72 " -H hide other applications\n" 72 " -k kill application\n" 73 " -q quit application\n" 74 " -k kill application (SIGINT)\n" 75 " -K kill application hard (SIGKILL)\n" 73 76 " -l list applications\n" 77 " -L list applications including full paths and bundle identifiers\n" 74 78 " -P print application process ID\n" 75 79 " -F bring current application's windows to front\n" … … 132 136 if (argc == 1) usage(); 133 137 134 const char *opts = "c:i:p:a:sShH klPF";138 const char *opts = "c:i:p:a:sShHqkKlLPF"; 135 139 136 140 while ( (ch = getopt(argc, argv, opts)) != -1) { … … 159 163 break; 160 164 case 's': 161 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, - k, -l, -P options");165 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options"); 162 166 OPTS.appAction = APP_SHOW; 163 167 break; 164 168 case 'h': 165 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, - k, -l, -P options");169 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options"); 166 170 OPTS.appAction = APP_HIDE; 167 171 break; 172 case 'q': 173 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options"); 174 OPTS.appAction = APP_QUIT; 175 break; 168 176 case 'k': 169 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, - k, -l, -P options");177 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options"); 170 178 OPTS.appAction = APP_KILL; 171 179 break; 180 case 'K': 181 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options"); 182 OPTS.appAction = APP_KILL_HARD; 183 break; 172 184 case 'l': 173 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, - k, -l, -P options");185 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options"); 174 186 OPTS.appAction = APP_LIST; 175 187 break; 188 case 'L': 189 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -L, -P options"); 190 OPTS.appAction = APP_LIST; 191 OPTS.longList = true; 192 break; 176 193 case 'P': 177 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, - k, -l, -P options");194 if (OPTS.appAction != APP_NONE) errexit("choose only one of -s, -h, -q, -k, -K, -l, -P options"); 178 195 OPTS.appAction = APP_PRINT_PID; 179 196 break; … … 227 244 } 228 245 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 DEBUG 253 CFShow(*bundleID); 254 #endif 255 } 256 CFRelease(url); 257 return true; 258 } 259 260 OSStatus quitApplication(CPSProcessSerNum *psn) { 261 AppleEvent event; 262 AEAddressDesc appDesc; 263 OSStatus err; 264 265 AEInitializeDesc(&appDesc); 266 err = AECreateDesc(typeProcessSerialNumber, psn, sizeof(*psn), &appDesc); 267 if (err != noErr) return err; 268 269 // XXX AECreateAppleEvent is very slow in Mac OS X 10.2.4 and earlier. 270 // XXX This is Apple's bug: <http://lists.apple.com/archives/applescript-implementors/2003/Feb/19/aecreateappleeventfromco.txt> 271 err = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &appDesc, kAutoGenerateReturnID, kAnyTransactionID, &event); 272 if (err != noErr) return err; 273 274 AppleEvent nullReply = {typeNull, nil}; 275 err = AESendMessage(&event, &nullReply, kAENoReply, kNoTimeOut); 276 (void)AEDisposeDesc(&event); 277 if (err != noErr) return err; 278 279 (void)AEDisposeDesc(&nullReply); // according to docs, don't call unless AESend returned successfully 280 281 return noErr; 282 } 283 229 284 CPSProcessSerNum matchApplication(CPSProcessInfoRec *info) { 230 285 long pathMaxLength = pathconf("/", _PC_PATH_MAX); … … 249 304 char *banner = " PSN PID TYPE CREA NAME "; 250 305 // 12345678.0 12345 1234 1234 12345678901234567890 251 printf("%s PATH\n", banner);252 306 if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&ws) != -1 || 253 307 ioctl(STDERR_FILENO, TIOCGWINSZ, (char *)&ws) != -1 || 254 308 ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&ws) != -1) || 255 309 ws.ws_col != 0) termwidth = ws.ws_col; 310 char *formatButPath = "%8ld.%ld %5ld %c%c%c%c %c%c%c%c %-20.20s"; 256 311 int pathlen = termwidth - strlen(banner) - 1; 257 asprintf(&format, "%%8ld.%%ld %%5ld %%c%%c%%c%%c %%c%%c%%c%%c %%-20.20s %%-%d.%ds\n", pathlen, pathlen); 312 // XXX don't ever free 'format', should fix if we get called repeatedly 313 if (OPTS.longList) { 314 printf("%s PATH (bundle identifier)\n", banner); 315 asprintf(&format, "%s %%s", formatButPath); 316 } else if (pathlen >= 4) { 317 printf("%s PATH\n", banner); 318 asprintf(&format, "%s %%-%d.%ds", formatButPath, pathlen, pathlen); 319 } else { 320 format = formatButPath; 321 } 258 322 } 259 323 … … 279 343 case MATCH_BUNDLE_ID: 280 344 { 281 CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, path, strlen(path), false); 282 if (url == NULL) errexit("can't get bundle location for process '%s' (PSN %ld.%ld, pid %ld)", name, psn.hi, psn.lo, info->UnixPID); 283 CFBundleRef bundle = CFBundleCreate(NULL, url); 284 if (bundle != NULL) { 285 CFStringRef bundleID = CFBundleGetIdentifier(bundle); 286 #if DEBUG 287 CFShow(bundleID); 288 #endif 289 if (bundleID != NULL && CFStringCompare(OPTS.bundleID, bundleID, kCFCompareCaseInsensitive) == kCFCompareEqualTo) 290 break; 291 } 292 CFRelease(url); 345 CFStringRef bundleID; 346 if (!bundleIdentifierForApplication(&bundleID, path)) 347 errexit("can't get bundle location for process '%s' (PSN %ld.%ld, pid %ld)", name, psn.hi, psn.lo, info->UnixPID); 348 if (bundleID != NULL && CFStringCompare(OPTS.bundleID, bundleID, kCFCompareCaseInsensitive) == kCFCompareEqualTo) 349 break; 293 350 continue; 294 351 } … … 298 355 if (OPTS.appAction == APP_LIST) { 299 356 char *type = (char *)&(info->ExecFileType), *crea = (char *)&(info->ExecFileCreator); 300 #define CXX(c) ( (c) < ' ' ? ' ?' : (c) )357 #define CXX(c) ( (c) < ' ' ? ' ' : (c) ) 301 358 #define OSTYPE_CHAR_ARGS(t) CXX(t[0]), CXX(t[1]), CXX(t[2]), CXX(t[3]) 302 359 printf(format, psn.hi, psn.lo, info->UnixPID, 303 360 OSTYPE_CHAR_ARGS(type), OSTYPE_CHAR_ARGS(crea), 304 361 name, path); 362 if (OPTS.longList) { 363 CFStringRef bundleID = NULL; 364 if (!bundleIdentifierForApplication(&bundleID, path)) 365 errexit("can't get bundle location for process '%s' (PSN %ld.%ld, pid %ld)", name, psn.hi, psn.lo, info->UnixPID); 366 if (bundleID != NULL) { 367 char *bundleIDStr = (char *)CFStringGetCStringPtr(bundleID, CFStringGetSystemEncoding()); 368 if (bundleIDStr == NULL) { 369 CFIndex bundleIDLength = CFStringGetLength(bundleID) + 1; 370 bundleIDStr = (char *)malloc(bundleIDLength * sizeof(char)); 371 if (!CFStringGetCString(bundleID, bundleIDStr, bundleIDLength, CFStringGetSystemEncoding())) { 372 CFShow(bundleIDStr); 373 errexit("internal error: string encoding conversion failed for bundle identifier"); 374 } 375 printf(" (%s)", bundleIDStr); 376 free(bundleIDStr); 377 } else { 378 printf(" (%s)", bundleIDStr); 379 } 380 CFRelease(bundleID); 381 } 382 } 383 putchar('\n'); 305 384 continue; 306 385 } … … 334 413 case APP_SHOW: err = CPSPostShowReq(&psn); verb = "show"; break; 335 414 case APP_HIDE: err = CPSPostHideReq(&psn); verb = "hide"; break; 415 case APP_QUIT: err = quitApplication(&psn); verb = "quit"; break; 336 416 case APP_KILL: err = CPSPostKillRequest(&psn, kNilOptions); verb = "kill"; break; 417 case APP_KILL_HARD: err = CPSPostKillRequest(&psn, bfCPSKillHard); verb = "kill"; break; 337 418 case APP_PRINT_PID: 338 419 if (info.UnixPID <= 0) errexit("can't get process ID");
Note:
See TracChangeset
for help on using the changeset viewer.