int ancil_send_fd(int sock, int fd) { ANCIL_FD_BUFFER(1) buffer; return(ancil_send_fds_with_buffer(sock, &fd, 1, &buffer)); }
int ancil_send_fds(int sock, const int *fds, unsigned n_fds) { ANCIL_FD_BUFFER(ANCIL_MAX_N_FDS) buffer; assert(n_fds <= ANCIL_MAX_N_FDS); return(ancil_send_fds_with_buffer(sock, fds, n_fds, &buffer)); }
int main(int argc, char *argv[]) { // connect to supplied address and send the greeting message to server int sock = Bootstrap(argv[1]); // process requests infinitely (we will be killed when done) int* nameLength; char status[3]; while(1) { int nameLength; if (scanf("%d", &nameLength) != 1) DieWithError("reading a filename length failed"); __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Length is %d", nameLength); char* filename; if ((filename = (char*) calloc(nameLength + 1, 1)) == NULL) DieWithError("calloc() failed"); __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Allocated %d - sized buffer", nameLength + 1); if (fgets(filename, nameLength + 1, stdin) == NULL) DieWithError("reading filename failed"); __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Attempting to open %s", filename); int mode; if (scanf("%d", &mode) != 1) DieWithError("reading a mode failed"); // freaking MIPS... if (mode&0x400) { mode ^= 0x400; mode |= O_APPEND; } if (mode&0x40) { mode ^= 0x40; mode |= O_CREAT; } __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Mode is %d", mode); int targetFd = open(filename, mode, S_IRWXU|S_IRWXG); if (targetFd > 0) { if (ancil_send_fds_with_buffer(sock, targetFd)) DieWithError("sending file descriptor failed"); } else { fprintf(stderr, "Error: failed to open a file - %s\n", strerror(errno)); } free(filename); close(targetFd); } return -1; }
// Perform initial greeting dance with server over socket with supplied name. // The procedure ends with "READY" and tty file descriptor are sent over the socket // and "GO" being received in response, which means, that the server process has acquired // file descriptor on the controlling terminal static int Bootstrap(char *socket_name) { int tty, sock; tty = GetTTY(sock); if ((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) DieWithError("socket() failed"); struct sockaddr_un echoServAddr; memset(&echoServAddr, 0, sizeof(echoServAddr)); echoServAddr.sun_family = AF_LOCAL; strncpy(echoServAddr.sun_path + 1, socket_name, sizeof(echoServAddr.sun_path) - 2); int size = sizeof(echoServAddr) - sizeof(echoServAddr.sun_path) + strlen(echoServAddr.sun_path+1) + 1; if (connect(sock, (struct sockaddr *) &echoServAddr, size) < 0) DieWithError("connect() failed"); dup2(sock, 1); dup2(sock, 2); if (ancil_send_fds_with_buffer(sock, tty)) DieWithError("sending tty descriptor failed"); if (scanf("GO") == 0) { if (close(tty)) DieWithError("failed to close controlling tty"); __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "The controlling tty is closed"); } else DieWithError("incomplete confirmation message"); return sock; }