1d18304287dbabc7835be771400b85d4ae8b63de6San Mehat/* 2d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Copyright (C) 2008 The Android Open Source Project 3d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * 4d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * you may not use this file except in compliance with the License. 6d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * You may obtain a copy of the License at 7d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * 8d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * 10d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Unless required by applicable law or agreed to in writing, software 11d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * See the License for the specific language governing permissions and 14d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * limitations under the License. 15d18304287dbabc7835be771400b85d4ae8b63de6San Mehat */ 16d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 17d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <stdio.h> 18d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <stdlib.h> 19d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <unistd.h> 20d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <string.h> 21d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <signal.h> 22d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <errno.h> 23d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <fcntl.h> 24d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 25d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/socket.h> 26d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/select.h> 27d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/time.h> 28d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/types.h> 29d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/un.h> 30d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 31d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <cutils/sockets.h> 32d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <private/android_filesystem_config.h> 33d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 34d18304287dbabc7835be771400b85d4ae8b63de6San Mehatstatic void usage(char *progname); 35d18304287dbabc7835be771400b85d4ae8b63de6San Mehatstatic int do_monitor(int sock, int stop_after_cmd); 36d18304287dbabc7835be771400b85d4ae8b63de6San Mehatstatic int do_cmd(int sock, int argc, char **argv); 37d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 38d18304287dbabc7835be771400b85d4ae8b63de6San Mehatint main(int argc, char **argv) { 39d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int sock; 40745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int cmdOffset = 0; 41d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 42d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (argc < 2) 43d18304287dbabc7835be771400b85d4ae8b63de6San Mehat usage(argv[0]); 44d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 45745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt // try interpreting the first arg as the socket name - if it fails go back to netd 46745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 47745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if ((sock = socket_local_client(argv[1], 48d18304287dbabc7835be771400b85d4ae8b63de6San Mehat ANDROID_SOCKET_NAMESPACE_RESERVED, 49d18304287dbabc7835be771400b85d4ae8b63de6San Mehat SOCK_STREAM)) < 0) { 50745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if ((sock = socket_local_client("netd", 51745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ANDROID_SOCKET_NAMESPACE_RESERVED, 52745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt SOCK_STREAM)) < 0) { 53745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt fprintf(stderr, "Error connecting (%s)\n", strerror(errno)); 54745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt exit(4); 55745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 56745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 57745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc < 3) usage(argv[0]); 58745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt printf("Using alt socket %s\n", argv[1]); 59745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cmdOffset = 1; 60d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 61d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 62745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (!strcmp(argv[1+cmdOffset], "monitor")) 63d18304287dbabc7835be771400b85d4ae8b63de6San Mehat exit(do_monitor(sock, 0)); 64745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt exit(do_cmd(sock, argc-cmdOffset, &(argv[cmdOffset]))); 65d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 66d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 67d18304287dbabc7835be771400b85d4ae8b63de6San Mehatstatic int do_cmd(int sock, int argc, char **argv) { 68be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall char *final_cmd; 69be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall char *conv_ptr; 70be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall int i; 71be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall 72be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall /* Check if 1st arg is cmd sequence number */ 73be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall strtol(argv[1], &conv_ptr, 10); 74be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall if (conv_ptr == argv[1]) { 75be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall final_cmd = strdup("0 "); 76be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall } else { 77be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall final_cmd = strdup(""); 78be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall } 79ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich if (final_cmd == NULL) { 80be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall int res = errno; 81be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall perror("strdup failed"); 82be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall return res; 83ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich } 84ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich 85d18304287dbabc7835be771400b85d4ae8b63de6San Mehat for (i = 1; i < argc; i++) { 86602b80d628692efc2ce020800a8fc8cd82834ad7Dan Albert if (strchr(argv[i], '"')) { 87ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich perror("argument with embedded quotes not allowed"); 88ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich free(final_cmd); 89ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich return 1; 90ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich } 91602b80d628692efc2ce020800a8fc8cd82834ad7Dan Albert bool needs_quoting = strchr(argv[i], ' '); 92ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich const char *format = needs_quoting ? "%s\"%s\"%s" : "%s%s%s"; 93be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall char *tmp_final_cmd; 94d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 95be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall if (asprintf(&tmp_final_cmd, format, final_cmd, argv[i], 96be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall (i == (argc - 1)) ? "" : " ") < 0) { 97be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall int res = errno; 98be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall perror("failed asprintf"); 99ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich free(final_cmd); 100be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall return res; 101ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich } 102ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich free(final_cmd); 103be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall final_cmd = tmp_final_cmd; 104d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 105d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 106d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) { 107be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall int res = errno; 108d18304287dbabc7835be771400b85d4ae8b63de6San Mehat perror("write"); 109ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich free(final_cmd); 110be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall return res; 111d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 112ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich free(final_cmd); 113d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 114d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return do_monitor(sock, 1); 115d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 116d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 117d18304287dbabc7835be771400b85d4ae8b63de6San Mehatstatic int do_monitor(int sock, int stop_after_cmd) { 118d18304287dbabc7835be771400b85d4ae8b63de6San Mehat char *buffer = malloc(4096); 119d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 120d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (!stop_after_cmd) 121d18304287dbabc7835be771400b85d4ae8b63de6San Mehat printf("[Connected to Netd]\n"); 122d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 123d18304287dbabc7835be771400b85d4ae8b63de6San Mehat while(1) { 124d18304287dbabc7835be771400b85d4ae8b63de6San Mehat fd_set read_fds; 125d18304287dbabc7835be771400b85d4ae8b63de6San Mehat struct timeval to; 126d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int rc = 0; 127d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 128d18304287dbabc7835be771400b85d4ae8b63de6San Mehat to.tv_sec = 10; 129d18304287dbabc7835be771400b85d4ae8b63de6San Mehat to.tv_usec = 0; 130d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 131d18304287dbabc7835be771400b85d4ae8b63de6San Mehat FD_ZERO(&read_fds); 132d18304287dbabc7835be771400b85d4ae8b63de6San Mehat FD_SET(sock, &read_fds); 133d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 134d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) { 135be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall int res = errno; 136d18304287dbabc7835be771400b85d4ae8b63de6San Mehat fprintf(stderr, "Error in select (%s)\n", strerror(errno)); 137d18304287dbabc7835be771400b85d4ae8b63de6San Mehat free(buffer); 138be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall return res; 139d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } else if (!rc) { 140d18304287dbabc7835be771400b85d4ae8b63de6San Mehat continue; 141d18304287dbabc7835be771400b85d4ae8b63de6San Mehat fprintf(stderr, "[TIMEOUT]\n"); 142d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return ETIMEDOUT; 143d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } else if (FD_ISSET(sock, &read_fds)) { 144d18304287dbabc7835be771400b85d4ae8b63de6San Mehat memset(buffer, 0, 4096); 145d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if ((rc = read(sock, buffer, 4096)) <= 0) { 146be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall int res = errno; 147d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (rc == 0) 1489d10b341a0ba46f108cb96e46691197d778cbc06San Mehat fprintf(stderr, "Lost connection to Netd - did it crash?\n"); 149d18304287dbabc7835be771400b85d4ae8b63de6San Mehat else 150d18304287dbabc7835be771400b85d4ae8b63de6San Mehat fprintf(stderr, "Error reading data (%s)\n", strerror(errno)); 151d18304287dbabc7835be771400b85d4ae8b63de6San Mehat free(buffer); 152d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (rc == 0) 153d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return ECONNRESET; 154be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall return res; 155d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 15644ec9035d3821f17d185032ed64446cabae266bfDmitry Shmidt 157d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int offset = 0; 158d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int i = 0; 159d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 160d18304287dbabc7835be771400b85d4ae8b63de6San Mehat for (i = 0; i < rc; i++) { 161d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (buffer[i] == '\0') { 162d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int code; 163d18304287dbabc7835be771400b85d4ae8b63de6San Mehat char tmp[4]; 164d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 165d18304287dbabc7835be771400b85d4ae8b63de6San Mehat strncpy(tmp, buffer + offset, 3); 166d18304287dbabc7835be771400b85d4ae8b63de6San Mehat tmp[3] = '\0'; 167d18304287dbabc7835be771400b85d4ae8b63de6San Mehat code = atoi(tmp); 168d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 169d18304287dbabc7835be771400b85d4ae8b63de6San Mehat printf("%s\n", buffer + offset); 170d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (stop_after_cmd) { 171d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (code >= 200 && code < 600) 172d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return 0; 173d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 174d18304287dbabc7835be771400b85d4ae8b63de6San Mehat offset = i + 1; 175d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 176d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 177d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 178d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 179d18304287dbabc7835be771400b85d4ae8b63de6San Mehat free(buffer); 180d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return 0; 181d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 182d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 183d18304287dbabc7835be771400b85d4ae8b63de6San Mehatstatic void usage(char *progname) { 184be746818fc7964e5d52d17d07fe173b40a474465JP Abgrall fprintf(stderr, "Usage: %s [<sockname>] ([monitor] | ([<cmd_seq_num>] <cmd> [arg ...]))\n", progname); 185d18304287dbabc7835be771400b85d4ae8b63de6San Mehat exit(1); 186d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 187