1 /* 2 * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2005-2007, François Revol, revol@free.fr. 4 * All rights reserved. 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 <Mime.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 " 61 "signature> ...\n", progName); 62 } 63 64 while (*++argv) { 65 status_t status = B_OK; 66 argc--; 67 68 BEntry entry(*argv); 69 if ((status = entry.InitCheck()) == B_OK && entry.Exists()) { 70 status = open_file(openWith, entry); 71 } else if (!strncasecmp("application/", *argv, 12)) { 72 // maybe it's an application-mimetype? 73 74 // subsequent files are open with that app 75 openWith = *argv; 76 77 // in the case the app is already started, 78 // don't start it twice if we have other args 79 BList teams; 80 if (argc > 1) 81 be_roster->GetAppList(*argv, &teams); 82 83 if (teams.IsEmpty()) 84 status = be_roster->Launch(*argv); 85 else 86 status = B_OK; 87 } else if (strchr(*argv, ':')) { 88 // try to open it as an URI 89 BString mimeType = "application/x-vnd.Be.URL."; 90 BString arg(*argv); 91 mimeType.Append(arg, arg.FindFirst(":")); 92 93 // the protocol should be alphanum 94 // we just check if it's registered 95 // if not there is likely no supporting app anyway 96 if (BMimeType::IsValid(mimeType.String())) { 97 char *args[2] = { *argv, NULL }; 98 status = be_roster->Launch(openWith ? openWith 99 : mimeType.String(), 1, args); 100 if (status == B_OK) 101 continue; 102 } 103 104 // maybe it's "file:line" or "file:line:col" 105 int line = 0, col = 0, i; 106 status = B_ENTRY_NOT_FOUND; 107 // remove gcc error's last : 108 if (arg[arg.Length() - 1] == ':') 109 arg.Truncate(arg.Length() - 1); 110 111 i = arg.FindLast(':'); 112 if (i > 0) { 113 line = atoi(arg.String() + i + 1); 114 arg.Truncate(i); 115 116 status = entry.SetTo(arg.String()); 117 if (status == B_OK && entry.Exists()) 118 status = open_file(openWith, entry, line); 119 if (status == B_OK) 120 continue; 121 122 // get the column 123 col = line; 124 i = arg.FindLast(':'); 125 line = atoi(arg.String() + i + 1); 126 arg.Truncate(i); 127 128 status = entry.SetTo(arg.String()); 129 if (status == B_OK && entry.Exists()) 130 status = open_file(openWith, entry, line, col); 131 } 132 } else 133 status = B_ENTRY_NOT_FOUND; 134 135 if (status != B_OK && status != B_ALREADY_RUNNING) { 136 fprintf(stderr, "%s: \"%s\": %s\n", progName, *argv, 137 strerror(status)); 138 // make sure the shell knows this 139 exitcode = EXIT_FAILURE; 140 } 141 } 142 143 return exitcode; 144 } 145