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 if (url.OpenWithPreferredApplication() == B_OK) { 101 result = B_OK; 102 continue; 103 } 104 105 // maybe it's "file:line" or "file:line:col" 106 int line = 0, col = 0, i; 107 result = B_ENTRY_NOT_FOUND; 108 // remove gcc error's last : 109 BString arg(*argv); 110 if (arg[arg.Length() - 1] == ':') 111 arg.Truncate(arg.Length() - 1); 112 113 i = arg.FindLast(':'); 114 if (i > 0) { 115 line = atoi(arg.String() + i + 1); 116 arg.Truncate(i); 117 118 result = entry.SetTo(arg.String()); 119 if (result == B_OK && entry.Exists()) { 120 result = open_file(openWith, entry, line); 121 if (result == B_OK) 122 continue; 123 } 124 125 // get the column 126 col = line; 127 i = arg.FindLast(':'); 128 line = atoi(arg.String() + i + 1); 129 arg.Truncate(i); 130 131 result = entry.SetTo(arg.String()); 132 if (result == B_OK && entry.Exists()) 133 result = open_file(openWith, entry, line, col); 134 } 135 } else 136 result = B_ENTRY_NOT_FOUND; 137 138 if (result != B_OK && result != B_ALREADY_RUNNING) { 139 fprintf(stderr, "%s: \"%s\": %s\n", progName, *argv, 140 strerror(result)); 141 // make sure the shell knows this 142 exitCode = EXIT_FAILURE; 143 } 144 } 145 146 return exitCode; 147 } 148