1f6233d23SIngo Weinhold/*
2f6233d23SIngo Weinhold * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
3f6233d23SIngo Weinhold * Distributed under the terms of the MIT License.
4f6233d23SIngo Weinhold */
5f6233d23SIngo Weinhold
6f6233d23SIngo Weinhold#include <stdio.h>
7f6233d23SIngo Weinhold#include <string.h>
8f6233d23SIngo Weinhold
9f6233d23SIngo Weinhold#include <OS.h>
10f6233d23SIngo Weinhold
11f6233d23SIngo Weinhold#include "external_commands.h"
12f6233d23SIngo Weinhold#include "fs_shell_command_beos.h"
13f6233d23SIngo Weinhold
146c19139dSIngo Weinhold
15f6233d23SIngo Weinholdstatic port_id sReplyPort = -1;
16f6233d23SIngo Weinhold
176c19139dSIngo Weinhold
18f6233d23SIngo Weinholdstatic port_id
19f6233d23SIngo Weinholdget_command_port()
20f6233d23SIngo Weinhold{
21f6233d23SIngo Weinhold	static port_id port = -1;
22f6233d23SIngo Weinhold	static bool initialized = false;
23f6233d23SIngo Weinhold
24f6233d23SIngo Weinhold	if (!initialized) {
25f6233d23SIngo Weinhold		port = create_port(10, kFSShellCommandPort);
26f6233d23SIngo Weinhold		initialized = true;
27f6233d23SIngo Weinhold	}
28f6233d23SIngo Weinhold
29f6233d23SIngo Weinhold	return port;
30f6233d23SIngo Weinhold}
31f6233d23SIngo Weinhold
32f6233d23SIngo Weinhold
33f6233d23SIngo Weinholdbool
346c19139dSIngo WeinholdFSShell::get_external_command(char *input, int len)
35f6233d23SIngo Weinhold{
36f6233d23SIngo Weinhold	// get/create the port
37f6233d23SIngo Weinhold	port_id port = get_command_port();
38f6233d23SIngo Weinhold	if (port < 0) {
396c19139dSIngo Weinhold		fprintf(stderr, "Error: Failed to create command port: %s\n",
406c19139dSIngo Weinhold			strerror(port));
41f6233d23SIngo Weinhold		return false;
42f6233d23SIngo Weinhold	}
43f6233d23SIngo Weinhold
44f6233d23SIngo Weinhold	while (true) {
45f6233d23SIngo Weinhold		// read a message
466c19139dSIngo Weinhold		char _message[sizeof(external_command_message) + kMaxCommandLength];
476c19139dSIngo Weinhold		external_command_message* message = (external_command_message*)_message;
48f6233d23SIngo Weinhold		ssize_t bytesRead;
49f6233d23SIngo Weinhold		do {
50f6233d23SIngo Weinhold			int32 code;
516c19139dSIngo Weinhold			bytesRead = read_port(port, &code, message, sizeof(_message));
52f6233d23SIngo Weinhold		} while (bytesRead == B_INTERRUPTED);
53f6233d23SIngo Weinhold
54f6233d23SIngo Weinhold		if (bytesRead < 0) {
556c19139dSIngo Weinhold			fprintf(stderr, "Error: Reading from port failed: %s\n",
56f6233d23SIngo Weinhold				strerror(bytesRead));
57f6233d23SIngo Weinhold			return false;
58f6233d23SIngo Weinhold		}
59f6233d23SIngo Weinhold
60f6233d23SIngo Weinhold		// get the len of the command
616c19139dSIngo Weinhold		int commandLen = _message + bytesRead - message->command;
62f6233d23SIngo Weinhold		if (commandLen <= 1) {
636c19139dSIngo Weinhold			fprintf(stderr, "Error: No command given.\n");
64f6233d23SIngo Weinhold			continue;
65f6233d23SIngo Weinhold		}
66f6233d23SIngo Weinhold		if (commandLen > len) {
676c19139dSIngo Weinhold			fprintf(stderr, "Error: Command too long. Ignored.\n");
68f6233d23SIngo Weinhold			continue;
69f6233d23SIngo Weinhold		}
70f6233d23SIngo Weinhold
71f6233d23SIngo Weinhold		// copy the command
726c19139dSIngo Weinhold		memcpy(input, message->command, commandLen);
73f6233d23SIngo Weinhold		input[len - 1] = '\0';	// always NULL-terminate
746c19139dSIngo Weinhold		sReplyPort = message->reply_port;
75f6233d23SIngo Weinhold		return true;
76f6233d23SIngo Weinhold	}
77f6233d23SIngo Weinhold}
78f6233d23SIngo Weinhold
79f6233d23SIngo Weinhold
80f6233d23SIngo Weinholdvoid
816c19139dSIngo WeinholdFSShell::reply_to_external_command(int result)
82f6233d23SIngo Weinhold{
83f6233d23SIngo Weinhold	if (sReplyPort >= 0) {
84f6233d23SIngo Weinhold		// prepare the message
85f6233d23SIngo Weinhold		external_command_reply reply;
86f6233d23SIngo Weinhold		reply.error = result;
87f6233d23SIngo Weinhold
88f6233d23SIngo Weinhold		// send the reply
89f6233d23SIngo Weinhold		status_t error;
90f6233d23SIngo Weinhold		do {
91f6233d23SIngo Weinhold			error = write_port(sReplyPort, 0, &reply, sizeof(reply));
92f6233d23SIngo Weinhold		} while (error == B_INTERRUPTED);
93f6233d23SIngo Weinhold		sReplyPort = -1;
94f6233d23SIngo Weinhold
95f6233d23SIngo Weinhold		if (error != B_OK) {
966c19139dSIngo Weinhold			fprintf(stderr, "Error: Failed to send command result to reply "
976c19139dSIngo Weinhold				"port: %s\n", strerror(error));
98f6233d23SIngo Weinhold		}
99f6233d23SIngo Weinhold	}
100f6233d23SIngo Weinhold}
101f6233d23SIngo Weinhold
102f6233d23SIngo Weinhold
103f6233d23SIngo Weinholdvoid
1046c19139dSIngo WeinholdFSShell::external_command_cleanup()
105f6233d23SIngo Weinhold{
106f6233d23SIngo Weinhold	// The port will be deleted automatically when the team exits.
107f6233d23SIngo Weinhold}