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