⛏️ index : haiku.git

// RosterShell.cpp

#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;

		// get a list of team IDs
		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;
		}

		// activate the team
		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)
	{
		// check args
		if (args.size() != 2) {
			printf("launch: requires exactly one argument\n");
			return;
		}

		string program = args[1];

		// get an app ref
		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;
		}

		// launch the app
		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;

		// get a list of team IDs
		BList teamList;
		if (args.size() > 1)
			ParseTeamList(args, &teamList);
		else
			roster.GetAppList(&teamList);

		// print an info for each team
		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;

		// get a list of team IDs
		BList teamList;
		if (args.size() > 1)
			ParseTeamList(args, &teamList);
		else
			roster.GetAppList(&teamList);

		// print an info for each team
		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;
		// get a list of team IDs
		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;
		}

		// send a B_QUIT_REQUESTED message to each team
		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;
};


// read_line
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;
}

// main
int
main()
{
	Shell shell;

	// main input loop
	char line[10240];
	while (!shell.IsTerminating() && read_line(line, sizeof(line))) {
		// parse args
		std::istringstream in(line);
		vector<string> args;
		string arg;
		while (in >> arg)
			args.push_back(arg);
		// invoke command
		shell.DoCommand(args);
	}

	return 0;
}