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