ndc.c revision 44ec9035d3821f17d185032ed64446cabae266bf
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <unistd.h> 20#include <string.h> 21#include <signal.h> 22#include <errno.h> 23#include <fcntl.h> 24 25#include <sys/socket.h> 26#include <sys/select.h> 27#include <sys/time.h> 28#include <sys/types.h> 29#include <sys/un.h> 30 31#include <cutils/sockets.h> 32#include <private/android_filesystem_config.h> 33 34static void usage(char *progname); 35static int do_monitor(int sock, int stop_after_cmd); 36static int do_cmd(int sock, int argc, char **argv); 37 38int main(int argc, char **argv) { 39 int sock; 40 41 if (argc < 2) 42 usage(argv[0]); 43 44 if ((sock = socket_local_client("netd", 45 ANDROID_SOCKET_NAMESPACE_RESERVED, 46 SOCK_STREAM)) < 0) { 47 fprintf(stderr, "Error connecting (%s)\n", strerror(errno)); 48 exit(4); 49 } 50 51 if (!strcmp(argv[1], "monitor")) 52 exit(do_monitor(sock, 0)); 53 exit(do_cmd(sock, argc, argv)); 54} 55 56static int do_cmd(int sock, int argc, char **argv) { 57 char final_cmd[255] = { '0', ' ', '\0' }; 58 int i; 59 60 for (i = 1; i < argc; i++) { 61 char *cmp; 62 63 if (!index(argv[i], ' ')) 64 asprintf(&cmp, "%s%s", argv[i], (i == (argc -1)) ? "" : " "); 65 else 66 asprintf(&cmp, "\"%s\"%s", argv[i], (i == (argc -1)) ? "" : " "); 67 68 strcat(final_cmd, cmp); 69 free(cmp); 70 } 71 72 if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) { 73 perror("write"); 74 return errno; 75 } 76 77 return do_monitor(sock, 1); 78} 79 80static int do_monitor(int sock, int stop_after_cmd) { 81 char *buffer = malloc(4096); 82 83 if (!stop_after_cmd) 84 printf("[Connected to Netd]\n"); 85 86 while(1) { 87 fd_set read_fds; 88 struct timeval to; 89 int rc = 0; 90 91 to.tv_sec = 10; 92 to.tv_usec = 0; 93 94 FD_ZERO(&read_fds); 95 FD_SET(sock, &read_fds); 96 97 if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) { 98 fprintf(stderr, "Error in select (%s)\n", strerror(errno)); 99 free(buffer); 100 return errno; 101 } else if (!rc) { 102 continue; 103 fprintf(stderr, "[TIMEOUT]\n"); 104 return ETIMEDOUT; 105 } else if (FD_ISSET(sock, &read_fds)) { 106 memset(buffer, 0, 4096); 107 if ((rc = read(sock, buffer, 4096)) <= 0) { 108 if (rc == 0) 109 fprintf(stderr, "Lost connection to Netd - did it crash?\n"); 110 else 111 fprintf(stderr, "Error reading data (%s)\n", strerror(errno)); 112 free(buffer); 113 if (rc == 0) 114 return ECONNRESET; 115 return errno; 116 } 117 118 int offset = 0; 119 int i = 0; 120 121 for (i = 0; i < rc; i++) { 122 if (buffer[i] == '\0') { 123 int code; 124 char tmp[4]; 125 126 strncpy(tmp, buffer + offset, 3); 127 tmp[3] = '\0'; 128 code = atoi(tmp); 129 130 printf("%s\n", buffer + offset); 131 if (stop_after_cmd) { 132 if (code >= 200 && code < 600) 133 return 0; 134 } 135 offset = i + 1; 136 } 137 } 138 } 139 } 140 free(buffer); 141 return 0; 142} 143 144static void usage(char *progname) { 145 fprintf(stderr, "Usage: %s <monitor>|<cmd> [arg1] [arg2...]\n", progname); 146 exit(1); 147} 148 149