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 #include <stdlib.h> 25 26 #include <sys/socket.h> 27 #include <sys/select.h> 28 #include <sys/time.h> 29 #include <sys/types.h> 30 #include <sys/un.h> 31 32 #include <cutils/sockets.h> 33 #include <private/android_filesystem_config.h> 34 35 static void usage(char *progname); 36 static int do_monitor(int sock, int stop_after_cmd); 37 static int do_cmd(int sock, int argc, char **argv); 38 39 int main(int argc, char **argv) { 40 int sock; 41 int wait_for_socket; 42 char *progname; 43 44 progname = argv[0]; 45 46 wait_for_socket = argc > 1 && strcmp(argv[1], "--wait") == 0; 47 if(wait_for_socket) { 48 argv++; 49 argc--; 50 } 51 52 if(argc < 2) { 53 usage(progname); 54 exit(5); 55 } 56 57 while ((sock = socket_local_client("vold", 58 ANDROID_SOCKET_NAMESPACE_RESERVED, 59 SOCK_STREAM)) < 0) { 60 if(!wait_for_socket) { 61 fprintf(stderr, "Error connecting (%s)\n", strerror(errno)); 62 exit(4); 63 } else { 64 sleep(1); 65 } 66 } 67 68 if (!strcmp(argv[1], "monitor")) { 69 exit(do_monitor(sock, 0)); 70 } else { 71 exit(do_cmd(sock, argc, argv)); 72 } 73 } 74 75 static int do_cmd(int sock, int argc, char **argv) { 76 char final_cmd[255] = "0 "; /* 0 is a (now required) sequence number */ 77 int i; 78 size_t ret; 79 80 for (i = 1; i < argc; i++) { 81 char *cmp; 82 83 if (!strchr(argv[i], ' ')) 84 asprintf(&cmp, "%s%s", argv[i], (i == (argc -1)) ? "" : " "); 85 else 86 asprintf(&cmp, "\"%s\"%s", argv[i], (i == (argc -1)) ? "" : " "); 87 88 ret = strlcat(final_cmd, cmp, sizeof(final_cmd)); 89 if (ret >= sizeof(final_cmd)) 90 abort(); 91 free(cmp); 92 } 93 94 if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) { 95 perror("write"); 96 return errno; 97 } 98 99 return do_monitor(sock, 1); 100 } 101 102 static int do_monitor(int sock, int stop_after_cmd) { 103 char *buffer = malloc(4096); 104 105 if (!stop_after_cmd) 106 printf("[Connected to Vold]\n"); 107 108 while(1) { 109 fd_set read_fds; 110 struct timeval to; 111 int rc = 0; 112 113 to.tv_sec = 10; 114 to.tv_usec = 0; 115 116 FD_ZERO(&read_fds); 117 FD_SET(sock, &read_fds); 118 119 if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) { 120 fprintf(stderr, "Error in select (%s)\n", strerror(errno)); 121 free(buffer); 122 return errno; 123 } else if (!rc) { 124 continue; 125 fprintf(stderr, "[TIMEOUT]\n"); 126 return ETIMEDOUT; 127 } else if (FD_ISSET(sock, &read_fds)) { 128 memset(buffer, 0, 4096); 129 if ((rc = read(sock, buffer, 4096)) <= 0) { 130 if (rc == 0) 131 fprintf(stderr, "Lost connection to Vold - did it crash?\n"); 132 else 133 fprintf(stderr, "Error reading data (%s)\n", strerror(errno)); 134 free(buffer); 135 if (rc == 0) 136 return ECONNRESET; 137 return errno; 138 } 139 140 int offset = 0; 141 int i = 0; 142 143 for (i = 0; i < rc; i++) { 144 if (buffer[i] == '\0') { 145 int code; 146 char tmp[4]; 147 148 strncpy(tmp, buffer + offset, 3); 149 tmp[3] = '\0'; 150 code = atoi(tmp); 151 152 printf("%s\n", buffer + offset); 153 if (stop_after_cmd) { 154 if (code >= 200 && code < 600) 155 return 0; 156 } 157 offset = i + 1; 158 } 159 } 160 } 161 } 162 free(buffer); 163 return 0; 164 } 165 166 static void usage(char *progname) { 167 fprintf(stderr, 168 "Usage: %s [--wait] <monitor>|<cmd> [arg1] [arg2...]\n", progname); 169 } 170 171