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) { 68ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich char *final_cmd = strdup("0 "); 69ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich if (final_cmd == NULL) { 70ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich perror("strdup"); 71ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich return errno; 72ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich } 73ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich 74d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int i; 75d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 76d18304287dbabc7835be771400b85d4ae8b63de6San Mehat for (i = 1; i < argc; i++) { 77ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich if (index(argv[i], '"')) { 78ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich perror("argument with embedded quotes not allowed"); 79ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich free(final_cmd); 80ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich return 1; 81ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich } 82ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich bool needs_quoting = index(argv[i], ' '); 83ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich const char *format = needs_quoting ? "%s\"%s\"%s" : "%s%s%s"; 84d18304287dbabc7835be771400b85d4ae8b63de6San Mehat char *cmp; 85d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 86ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich if (asprintf(&cmp, format, final_cmd, argv[i], 87ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich (i == (argc -1)) ? "" : " ") < 0) { 88ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich perror("malloc"); 89ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich free(final_cmd); 90ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich return errno; 91ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich } 92ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich free(final_cmd); 93ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich final_cmd = cmp; 94d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 95d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 96d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) { 97d18304287dbabc7835be771400b85d4ae8b63de6San Mehat perror("write"); 98ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich free(final_cmd); 99d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return errno; 100d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 101ad5b41fae92f20fa9fff334c459dd400de0b8285Nick Kralevich free(final_cmd); 102d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 103d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return do_monitor(sock, 1); 104d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 105d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 106d18304287dbabc7835be771400b85d4ae8b63de6San Mehatstatic int do_monitor(int sock, int stop_after_cmd) { 107d18304287dbabc7835be771400b85d4ae8b63de6San Mehat char *buffer = malloc(4096); 108d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 109d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (!stop_after_cmd) 110d18304287dbabc7835be771400b85d4ae8b63de6San Mehat printf("[Connected to Netd]\n"); 111d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 112d18304287dbabc7835be771400b85d4ae8b63de6San Mehat while(1) { 113d18304287dbabc7835be771400b85d4ae8b63de6San Mehat fd_set read_fds; 114d18304287dbabc7835be771400b85d4ae8b63de6San Mehat struct timeval to; 115d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int rc = 0; 116d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 117d18304287dbabc7835be771400b85d4ae8b63de6San Mehat to.tv_sec = 10; 118d18304287dbabc7835be771400b85d4ae8b63de6San Mehat to.tv_usec = 0; 119d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 120d18304287dbabc7835be771400b85d4ae8b63de6San Mehat FD_ZERO(&read_fds); 121d18304287dbabc7835be771400b85d4ae8b63de6San Mehat FD_SET(sock, &read_fds); 122d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 123d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) { 124d18304287dbabc7835be771400b85d4ae8b63de6San Mehat fprintf(stderr, "Error in select (%s)\n", strerror(errno)); 125d18304287dbabc7835be771400b85d4ae8b63de6San Mehat free(buffer); 126d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return errno; 127d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } else if (!rc) { 128d18304287dbabc7835be771400b85d4ae8b63de6San Mehat continue; 129d18304287dbabc7835be771400b85d4ae8b63de6San Mehat fprintf(stderr, "[TIMEOUT]\n"); 130d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return ETIMEDOUT; 131d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } else if (FD_ISSET(sock, &read_fds)) { 132d18304287dbabc7835be771400b85d4ae8b63de6San Mehat memset(buffer, 0, 4096); 133d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if ((rc = read(sock, buffer, 4096)) <= 0) { 134d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (rc == 0) 1359d10b341a0ba46f108cb96e46691197d778cbc06San Mehat fprintf(stderr, "Lost connection to Netd - did it crash?\n"); 136d18304287dbabc7835be771400b85d4ae8b63de6San Mehat else 137d18304287dbabc7835be771400b85d4ae8b63de6San Mehat fprintf(stderr, "Error reading data (%s)\n", strerror(errno)); 138d18304287dbabc7835be771400b85d4ae8b63de6San Mehat free(buffer); 139d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (rc == 0) 140d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return ECONNRESET; 141d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return errno; 142d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 14344ec9035d3821f17d185032ed64446cabae266bfDmitry Shmidt 144d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int offset = 0; 145d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int i = 0; 146d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 147d18304287dbabc7835be771400b85d4ae8b63de6San Mehat for (i = 0; i < rc; i++) { 148d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (buffer[i] == '\0') { 149d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int code; 150d18304287dbabc7835be771400b85d4ae8b63de6San Mehat char tmp[4]; 151d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 152d18304287dbabc7835be771400b85d4ae8b63de6San Mehat strncpy(tmp, buffer + offset, 3); 153d18304287dbabc7835be771400b85d4ae8b63de6San Mehat tmp[3] = '\0'; 154d18304287dbabc7835be771400b85d4ae8b63de6San Mehat code = atoi(tmp); 155d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 156d18304287dbabc7835be771400b85d4ae8b63de6San Mehat printf("%s\n", buffer + offset); 157d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (stop_after_cmd) { 158d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (code >= 200 && code < 600) 159d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return 0; 160d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 161d18304287dbabc7835be771400b85d4ae8b63de6San Mehat offset = i + 1; 162d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 163d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 164d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 165d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 166d18304287dbabc7835be771400b85d4ae8b63de6San Mehat free(buffer); 167d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return 0; 168d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 169d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 170d18304287dbabc7835be771400b85d4ae8b63de6San Mehatstatic void usage(char *progname) { 171745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt fprintf(stderr, "Usage: %s [sockname] <monitor>|<cmd> [arg1] [arg2...]\n", progname); 172d18304287dbabc7835be771400b85d4ae8b63de6San Mehat exit(1); 173d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 174