#include <iostream>
#include <sstream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <vector>
#include <iostream>
#include <List.h>
#include <Path.h>
#include <Roster.h>
using std::string;
using std::vector;
const char kShellUsage[] =
"Commands Parameters Description\n"
"---------------------------------------------------------------------------\n"
"activate, a [ <team> ] activates the application specified by <team>\n"
"exit, e exits the roster shell\n"
"help, h prints this help\n"
"launch [ <program> ] Executes <program> via BRoster::Launch()\n"
"list, l [ <teams> ] lists the applications specified by <teams>\n"
" or all registered applications\n"
"list-long, ll [ <teams> ] lists the applications specified by <teams>\n"
" or all registered applications (long format)\n"
"quit, q [ <teams> ] quits the applications specified by <teams>\n"
"\n"
;
class Shell {
public:
Shell()
:
fTerminating(false)
{
}
bool IsTerminating() const { return fTerminating; }
void
DoCommand(vector<string>& cmdLine)
{
if (cmdLine.size() > 0) {
string command = cmdLine[0];
if (command == "activate" || command == "a")
CmdActivate(cmdLine);
else if (command == "exit" || command == "e")
CmdExit(cmdLine);
else if (command == "help" || command == "h")
Usage(string(" "));
else if (command == "launch")
CmdLaunch(cmdLine);
else if (command == "list" || command == "l")
CmdList(cmdLine);
else if (command == "list-long" || command == "ll")
CmdListLong(cmdLine);
else if (command == "quit" || command == "q")
CmdQuit(cmdLine);
else
Usage(string("Unknown command `") + command + "'");
}
}
void
Usage(string error)
{
if (error.length() > 0)
std::cout << error << std::endl;
std::cout << kShellUsage;
}
void
CmdActivate(vector<string>& args)
{
BRoster roster;
BList teamList;
if (args.size() <= 1) {
printf("activate: requires exactly one argument\n");
return;
}
ParseTeamList(args, &teamList);
int32 count = teamList.CountItems();
if (count != 1) {
printf("activate: requires exactly one argument\n");
return;
}
team_id team = (team_id)(uintptr_t)teamList.ItemAt(0);
status_t error = roster.ActivateApp(team);
if (error != B_OK) {
printf("activate: failed to activate application %" B_PRId32
": %s\n", team, strerror(error));
}
}
void
CmdExit(vector<string>&)
{
fTerminating = true;
}
void
CmdLaunch(vector<string>& args)
{
if (args.size() != 2) {
printf("launch: requires exactly one argument\n");
return;
}
string program = args[1];
entry_ref ref;
status_t error = get_ref_for_path(program.c_str(), &ref);
if (error != B_OK) {
printf("launch: Failed to get entry ref for \"%s\": %s\n",
program.c_str(), strerror(error));
return;
}
BRoster roster;
team_id teamID;
error = roster.Launch(&ref, (const BMessage*)NULL, &teamID);
if (error == B_OK) {
printf("launched \"%s\", team id: %" B_PRId32 "\n", program.c_str(),
teamID);
} else {
printf("launch: Failed to launch \"%s\": %s\n",
program.c_str(), strerror(error));
}
}
static void
ParseTeamList(vector<string>& args, BList* teamList)
{
for (int32 i = 1; i < (int32)args.size(); i++) {
string arg = args[i];
team_id team = -1;
if (sscanf(arg.c_str(), "%" B_PRId32, &team) > 0)
teamList->AddItem((void*)(addr_t)team);
}
}
void
CmdList(vector<string>& args)
{
BRoster roster;
BList teamList;
if (args.size() > 1)
ParseTeamList(args, &teamList);
else
roster.GetAppList(&teamList);
int32 count = teamList.CountItems();
printf("%-8s%-40s\n", "team", "signature");
printf("---------------------------------------------------------\n");
for (int32 i = 0; i < count; i++) {
team_id team = (team_id)(uintptr_t)teamList.ItemAt(i);
app_info info;
status_t error = roster.GetRunningAppInfo(team, &info);
if (error == B_OK)
printf("%-8" B_PRId32 "%-40s\n", team, info.signature);
else {
printf("%-8" B_PRId32 "failed to get the app_info: %s\n", team,
strerror(error));
}
}
printf("\n");
}
void
CmdListLong(vector<string>& args)
{
BRoster roster;
BList teamList;
if (args.size() > 1)
ParseTeamList(args, &teamList);
else
roster.GetAppList(&teamList);
int32 count = teamList.CountItems();
for (int32 i = 0; i < count; i++) {
team_id team = (team_id)(uintptr_t)teamList.ItemAt(i);
printf("team %8" B_PRId32 "\n", team);
printf("-------------\n");
app_info info;
status_t error = roster.GetRunningAppInfo(team, &info);
if (error == B_OK) {
printf("signature: %s\n", info.signature);
printf("thread: %" B_PRId32 "\n", info.thread);
printf("port: %" B_PRId32 "\n", info.port);
printf("flags: 0x%" B_PRIx32 "\n", info.flags);
printf("file: %s\n", BPath(&info.ref).Path());
} else
printf("failed to get the app_info: %s\n", strerror(error));
printf("\n");
}
}
void
CmdQuit(vector<string>& args)
{
BRoster roster;
BList teamList;
if (args.size() <= 1) {
printf("quit: requires at least one argument\n");
return;
}
ParseTeamList(args, &teamList);
int32 count = teamList.CountItems();
if (count < 1) {
printf("quit: requires at least one argument\n");
return;
}
for (int32 i = 0; i < count; i++) {
team_id team = (team_id)(uintptr_t)teamList.ItemAt(i);
status_t error = B_OK;
BMessenger messenger(NULL, team, &error);
if (messenger.IsValid()) {
error = messenger.SendMessage(B_QUIT_REQUESTED);
if (error != B_OK) {
printf("quit: failed to deliver the B_QUIT_REQUESTED "
"message to team %" B_PRId32 "\n", team);
printf(" %s\n", strerror(error));
}
} else {
printf("quit: failed to create a messenger for team %" B_PRId32
"\n", team);
printf(" %s\n", strerror(error));
}
}
}
private:
bool fTerminating;
};
bool
read_line(char* line, size_t size)
{
std::cout << "roster> ";
std::cout.flush();
try {
std::cin.getline(line, size);
} catch (const std::exception &ex) {
return false;
}
return true;
}
int
main()
{
Shell shell;
char line[10240];
while (!shell.IsTerminating() && read_line(line, sizeof(line))) {
std::istringstream in(line);
vector<string> args;
string arg;
while (in >> arg)
args.push_back(arg);
shell.DoCommand(args);
}
return 0;
}