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