xref: /haiku/src/tools/fs_shell/fs_shell_command_unix.cpp (revision b30304acc8c37e678a1bf66976d15bdab103f931)
1 /*
2  * Copyright 2005-2007, Ingo Weinhold, bonefish@cs.tu-berlin.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "fs_shell_command_unix.h"
7 
8 #include <errno.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <sys/socket.h>
13 #include <sys/un.h>
14 
15 #include "fs_shell_command.h"
16 
17 
18 static bool
19 write_data(int fd, const void* _buffer, size_t toWrite)
20 {
21 	const char* buffer = (const char*)_buffer;
22 
23 	ssize_t bytesWritten;
24 	do {
25 		bytesWritten = write(fd, buffer, toWrite);
26 		if (bytesWritten > 0) {
27 			buffer += bytesWritten;
28 			toWrite -= bytesWritten;
29 		}
30 	} while (toWrite > 0 && !(bytesWritten < 0 && errno != EINTR));
31 
32 	return (bytesWritten >= 0);
33 }
34 
35 
36 bool
37 send_external_command(const char *command, int *result)
38 {
39 	external_command_message message;
40 	message.command_length = strlen(command);
41 
42 	// create a socket
43 	int fd = socket(AF_UNIX, SOCK_STREAM, 0);
44 	if (fd < 0) {
45 		fprintf(stderr, "Error: Failed to open unix socket: %s\n",
46 			strerror(errno));
47 		return false;
48 	}
49 
50 	// connect to the fs_shell
51 	sockaddr_un addr;
52 	addr.sun_family = AF_UNIX;
53 	strcpy(addr.sun_path, kFSShellCommandSocketAddress);
54 	int addrLen = addr.sun_path + strlen(addr.sun_path) + 1 - (char*)&addr;
55 	if (connect(fd, (sockaddr*)&addr, addrLen) < 0) {
56 		fprintf(stderr, "Error: Failed to open connection to FS shell: %s\n",
57 			strerror(errno));
58 		close(fd);
59 		return false;
60 	}
61 
62 	// send the command message and the command
63 	if (!write_data(fd, &message, sizeof(message))
64 		|| !write_data(fd, command, message.command_length)) {
65 		fprintf(stderr, "Error: Writing to fs_shell failed: %s\n",
66 			strerror(errno));
67 		close(fd);
68 		return false;
69 	}
70 
71 	// read the reply
72 	external_command_reply reply;
73 	int toRead = sizeof(reply);
74 	char *replyBuffer = (char*)&reply;
75 	while (toRead > 0) {
76 		int bytesRead = read(fd, replyBuffer, toRead);
77 		if (bytesRead < 0) {
78 			if (errno == EINTR) {
79 				continue;
80 			} else {
81 				fprintf(stderr, "Error: Failed to read reply from fs_shell: "
82 					"%s\n", strerror(errno));
83 				close(fd);
84 				return false;
85 			}
86 		}
87 
88 		if (bytesRead == 0) {
89 			fprintf(stderr, "Error: Unexpected end of fs_shell reply. Was "
90 				"still expecting %d bytes\n", toRead);
91 			close(fd);
92 			return false;
93 		}
94 
95 		replyBuffer += bytesRead;
96 		toRead -= bytesRead;
97 	}
98 	close(fd);
99 
100 	*result = reply.error;
101 	return true;
102 }
103 
104