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