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