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