xref: /haiku/src/tools/fs_shell/external_commands_beos.cpp (revision b55a57da7173b9af0432bd3e148d03f06161d036)
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 
15 static port_id sReplyPort = -1;
16 
17 
18 static port_id
19 get_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 
33 bool
34 FSShell::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 
80 void
81 FSShell::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 
103 void
104 FSShell::external_command_cleanup()
105 {
106 	// The port will be deleted automatically when the team exits.
107 }
108