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