xref: /haiku/src/bin/open.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
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