1 /* 2 * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Copyright 2005-2006, François Revol, revol@free.fr. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 /* Launches an application/document from the shell */ 8 9 10 #include <Roster.h> 11 #include <Entry.h> 12 #include <String.h> 13 #include <List.h> 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <errno.h> 19 20 21 const char *kTrackerSignature = "application/x-vnd.Be-TRAK"; 22 23 const char *openWith = kTrackerSignature; 24 25 26 status_t OpenFile(BEntry &entry, int32 line=-1, int32 col=-1) 27 { 28 status_t status; 29 entry_ref ref; 30 entry.GetRef(&ref); 31 32 BMessenger target(openWith); 33 if (target.IsValid()) { 34 BMessage message(B_REFS_RECEIVED); 35 message.AddRef("refs", &ref); 36 if (line > -1) 37 message.AddInt32("be:line", line); 38 if (col > -1) 39 message.AddInt32("be:column", col); 40 // tell the app to open the file 41 status = target.SendMessage(&message); 42 } else 43 status = be_roster->Launch(&ref); 44 return status; 45 } 46 47 int 48 main(int argc, char **argv) 49 { 50 int exitcode = EXIT_SUCCESS; 51 52 char *progName = argv[0]; 53 if (strrchr(progName, '/')) 54 progName = strrchr(progName, '/') + 1; 55 56 if (argc < 2) 57 fprintf(stderr,"usage: %s <file[:line[:column]] or url or application signature> ...\n", progName); 58 59 while (*++argv) { 60 status_t status = B_OK; 61 argc--; 62 63 BEntry entry(*argv); 64 if ((status = entry.InitCheck()) == B_OK && entry.Exists()) { 65 status = OpenFile(entry); 66 } else if (!strncasecmp("application/", *argv, 12)) { 67 // maybe it's an application-mimetype? 68 69 // subsequent files are open with that app 70 openWith = *argv; 71 // clear possible ENOENT from above 72 status = B_OK; 73 74 // in the case the app is already started, 75 // don't start it twice if we have other args 76 BList teams; 77 if (argc > 1) 78 be_roster->GetAppList(*argv, &teams); 79 80 if (teams.IsEmpty()) 81 status = be_roster->Launch(*argv); 82 } else if (strchr(*argv, ':')) { 83 // try to open it as an URI 84 BString mimeType = "application/x-vnd.Be.URL."; 85 BString arg(*argv); 86 if (arg.FindFirst("://") >= 0) 87 mimeType.Append(arg, arg.FindFirst("://")); 88 else 89 mimeType.Append(arg, arg.FindFirst(":")); 90 91 char *args[2] = { *argv, NULL }; 92 status = be_roster->Launch(mimeType.String(), 1, args); 93 if (status == B_OK) 94 continue; 95 96 // maybe it's "file:line" or "file:line:col" 97 int line = 0, col = 0, i; 98 status = B_ENTRY_NOT_FOUND; 99 // remove gcc error's last : 100 if (arg[arg.Length()-1] == ':') 101 arg.Truncate(arg.Length()-1); 102 i = arg.FindLast(':'); 103 if (i > 0) { 104 line = atoi(arg.String()+i+1); 105 arg.Truncate(i); 106 entry.SetTo(arg.String()); 107 if (entry.Exists()) 108 status = OpenFile(entry, line-1, col-1); 109 if (status == B_OK) 110 continue; 111 // get the col 112 col = line; 113 i = arg.FindLast(':'); 114 line = atoi(arg.String()+i+1); 115 arg.Truncate(i); 116 entry.SetTo(arg.String()); 117 if (entry.Exists()) 118 status = OpenFile(entry, line-1, col-1); 119 } 120 } else { 121 status = B_ENTRY_NOT_FOUND; 122 } 123 124 if (status != B_OK && status != B_ALREADY_RUNNING) { 125 fprintf(stderr, "%s: \"%s\": %s\n", progName, *argv, strerror(status)); 126 // make sure the shell knows this 127 exitcode = EXIT_FAILURE; 128 } 129 } 130 131 return exitcode; 132 } 133