1// RosterShell.cpp
2
3#include <iostream>
4#include <sstream>
5#include <stdio.h>
6#include <string>
7#include <string.h>
8#include <vector>
9#include <iostream>
10
11#include <List.h>
12#include <Path.h>
13#include <Roster.h>
14
15using std::string;
16using std::vector;
17
18const char kShellUsage[] =
19"Commands       Parameters     Description\n"
20"---------------------------------------------------------------------------\n"
21"activate, a    [ <team> ]     activates the application specified by <team>\n"
22"exit, e                       exits the roster shell\n"
23"help, h                       prints this help\n"
24"launch         [ <program> ]  Executes <program> via BRoster::Launch()\n"
25"list, l        [ <teams> ]    lists the applications specified by <teams>\n"
26"                              or all registered applications\n"
27"list-long, ll  [ <teams> ]    lists the applications specified by <teams>\n"
28"                              or all registered applications (long format)\n"
29"quit, q        [ <teams> ]    quits the applications specified by <teams>\n"
30"\n"
31;
32
33class Shell {
34public:
35	Shell()
36		:
37		fTerminating(false)
38	{
39	}
40
41	bool IsTerminating() const { return fTerminating; }
42
43	void
44	DoCommand(vector<string>& cmdLine)
45	{
46		if (cmdLine.size() > 0) {
47			string command = cmdLine[0];
48			if (command == "activate" || command == "a")
49				CmdActivate(cmdLine);
50			else if (command == "exit" || command == "e")
51				CmdExit(cmdLine);
52			else if (command == "help" || command == "h")
53				Usage(string(" "));
54			else if (command == "launch")
55				CmdLaunch(cmdLine);
56			else if (command == "list" || command == "l")
57				CmdList(cmdLine);
58			else if (command == "list-long" || command == "ll")
59				CmdListLong(cmdLine);
60			else if (command == "quit" || command == "q")
61				CmdQuit(cmdLine);
62			else
63				Usage(string("Unknown command `") + command + "'");
64		}
65	}
66
67	void
68	Usage(string error)
69	{
70		if (error.length() > 0)
71			std::cout << error << std::endl;
72		std::cout << kShellUsage;
73	}
74
75	void
76	CmdActivate(vector<string>& args)
77	{
78		BRoster roster;
79
80		// get a list of team IDs
81		BList teamList;
82		if (args.size() <= 1) {
83			printf("activate: requires exactly one argument\n");
84			return;
85		}
86
87		ParseTeamList(args, &teamList);
88		int32 count = teamList.CountItems();
89		if (count != 1) {
90			printf("activate: requires exactly one argument\n");
91			return;
92		}
93
94		// activate the team
95		team_id team = (team_id)(uintptr_t)teamList.ItemAt(0);
96		status_t error = roster.ActivateApp(team);
97		if (error != B_OK) {
98			printf("activate: failed to activate application %" B_PRId32
99				": %s\n", team, strerror(error));
100		}
101	}
102
103	void
104	CmdExit(vector<string>&)
105	{
106		fTerminating = true;
107	}
108
109	void
110	CmdLaunch(vector<string>& args)
111	{
112		// check args
113		if (args.size() != 2) {
114			printf("launch: requires exactly one argument\n");
115			return;
116		}
117
118		string program = args[1];
119
120		// get an app ref
121		entry_ref ref;
122		status_t error = get_ref_for_path(program.c_str(), &ref);
123		if (error != B_OK) {
124			printf("launch: Failed to get entry ref for \"%s\": %s\n",
125				program.c_str(), strerror(error));
126			return;
127		}
128
129		// launch the app
130		BRoster roster;
131		team_id teamID;
132		error = roster.Launch(&ref, (const BMessage*)NULL, &teamID);
133		if (error == B_OK) {
134			printf("launched \"%s\", team id: %" B_PRId32 "\n", program.c_str(),
135				teamID);
136		} else {
137			printf("launch: Failed to launch \"%s\": %s\n",
138				program.c_str(), strerror(error));
139		}
140	}
141
142	static void
143	ParseTeamList(vector<string>& args, BList* teamList)
144	{
145		for (int32 i = 1; i < (int32)args.size(); i++) {
146			string arg = args[i];
147			team_id team = -1;
148			if (sscanf(arg.c_str(), "%" B_PRId32, &team) > 0)
149				teamList->AddItem((void*)(addr_t)team);
150		}
151	}
152
153	void
154	CmdList(vector<string>& args)
155	{
156		BRoster roster;
157
158		// get a list of team IDs
159		BList teamList;
160		if (args.size() > 1)
161			ParseTeamList(args, &teamList);
162		else
163			roster.GetAppList(&teamList);
164
165		// print an info for each team
166		int32 count = teamList.CountItems();
167		printf("%-8s%-40s\n", "team", "signature");
168		printf("---------------------------------------------------------\n");
169		for (int32 i = 0; i < count; i++) {
170			team_id team = (team_id)(uintptr_t)teamList.ItemAt(i);
171			app_info info;
172			status_t error = roster.GetRunningAppInfo(team, &info);
173			if (error == B_OK)
174				printf("%-8" B_PRId32 "%-40s\n", team, info.signature);
175			else {
176				printf("%-8" B_PRId32 "failed to get the app_info: %s\n", team,
177					   strerror(error));
178			}
179		}
180		printf("\n");
181	}
182
183	void
184	CmdListLong(vector<string>& args)
185	{
186		BRoster roster;
187
188		// get a list of team IDs
189		BList teamList;
190		if (args.size() > 1)
191			ParseTeamList(args, &teamList);
192		else
193			roster.GetAppList(&teamList);
194
195		// print an info for each team
196		int32 count = teamList.CountItems();
197		for (int32 i = 0; i < count; i++) {
198			team_id team = (team_id)(uintptr_t)teamList.ItemAt(i);
199			printf("team %8" B_PRId32 "\n", team);
200			printf("-------------\n");
201			app_info info;
202			status_t error = roster.GetRunningAppInfo(team, &info);
203			if (error == B_OK) {
204				printf("signature: %s\n", info.signature);
205				printf("thread:    %" B_PRId32 "\n", info.thread);
206				printf("port:      %" B_PRId32 "\n", info.port);
207				printf("flags:     0x%" B_PRIx32 "\n", info.flags);
208				printf("file:      %s\n", BPath(&info.ref).Path());
209			} else
210				printf("failed to get the app_info: %s\n", strerror(error));
211			printf("\n");
212		}
213	}
214
215	void
216	CmdQuit(vector<string>& args)
217	{
218		BRoster roster;
219		// get a list of team IDs
220		BList teamList;
221		if (args.size() <= 1) {
222			printf("quit: requires at least one argument\n");
223			return;
224		}
225
226		ParseTeamList(args, &teamList);
227		int32 count = teamList.CountItems();
228		if (count < 1) {
229			printf("quit: requires at least one argument\n");
230			return;
231		}
232
233		// send a B_QUIT_REQUESTED message to each team
234		for (int32 i = 0; i < count; i++) {
235			team_id team = (team_id)(uintptr_t)teamList.ItemAt(i);
236			status_t error = B_OK;
237			BMessenger messenger(NULL, team, &error);
238			if (messenger.IsValid()) {
239				error = messenger.SendMessage(B_QUIT_REQUESTED);
240				if (error != B_OK) {
241					printf("quit: failed to deliver the B_QUIT_REQUESTED "
242						   "message to team %" B_PRId32 "\n", team);
243					printf("      %s\n", strerror(error));
244				}
245			} else {
246				printf("quit: failed to create a messenger for team %" B_PRId32
247					"\n", team);
248				printf("      %s\n", strerror(error));
249			}
250		}
251	}
252
253private:
254	bool	fTerminating;
255};
256
257
258// read_line
259bool
260read_line(char* line, size_t size)
261{
262	std::cout << "roster> ";
263	std::cout.flush();
264
265	try {
266		std::cin.getline(line, size);
267	} catch (const std::exception &ex) {
268		return false;
269	}
270
271	return true;
272}
273
274// main
275int
276main()
277{
278	Shell shell;
279
280	// main input loop
281	char line[10240];
282	while (!shell.IsTerminating() && read_line(line, sizeof(line))) {
283		// parse args
284		std::istringstream in(line);
285		vector<string> args;
286		string arg;
287		while (in >> arg)
288			args.push_back(arg);
289		// invoke command
290		shell.DoCommand(args);
291	}
292
293	return 0;
294}
295
296