r = mkdir("/tmp/bash", 0700); if(r != 0) { NSLog(@"Failed to create /tmp/bash: %s", strerror(errno)); goto out; } pid_t pid = fork(); if(pid == -1) { NSLog(@"fork: %s", strerror(errno)); goto out; } else if(pid == 0) { r = setenv("SHELL", "/tmp/bootstrap/bin/bash", 1); if(r == 0) { r = setenv("TERM", "xterm-256color", 1); if(r == 0) { r = setenv("USER", "root", 1); if(r == 0) { r = setenv("LOGNAME", "root", 1); if(r == 0) { r = setenv("HOME", "/tmp/bash", 1); if(r == 0) { r = setenv("PATH", "/tmp/bootstrap/bin:/tmp/bootstrap/sbin:/usr/bin:/bin:/usr/sbin:/sbin", 1); if(r == 0) { r = setenv("PS1", "\\h:\\W \\u\\$ ", 1); } } } } } } if(r != 0) { NSLog(@"setenv: %s", strerror(errno)); exit(-1); } int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock == -1) { NSLog(@"socket: %s", strerror(errno)); exit(-1); } int one = 1; r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if(r != 0) { NSLog(@"setsockopt: %s", strerror(errno)); exit(-1); } struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = htons(44), .sin_addr = { .s_addr = INADDR_ANY, }, }; r = bind(sock, (struct sockaddr*)&addr, sizeof(addr)); if(r != 0) { NSLog(@"bind: %s", strerror(errno)); exit(-1); } r = listen(sock, 0); if(r != 0) { NSLog(@"listen: %s", strerror(errno)); exit(-1); } while(1) { int conn = accept(sock, NULL, NULL); pid = fork(); if(pid == -1) { NSLog(@"fork: %s", strerror(errno)); exit(-1); } else if(pid == 0) { int master = -1; pid = forkpty(&master, NULL, NULL, NULL); if(pid == -1) { NSLog(@"forkpty: %s", strerror(errno)); exit(-1); } else if(pid == 0) { execve("/tmp/bootstrap/bin/bash", (char *const[]){ "/tmp/bootstrap/bin/bash", "--noprofile", "--norc", "-i", NULL }, environ); } else { // XXX struct termios tio; tcgetattr(master, &tio); NSLog(@"c_iflag: %016lx", tio.c_iflag); NSLog(@"c_oflag: %016lx", tio.c_oflag); NSLog(@"c_cflag: %016lx", tio.c_cflag); NSLog(@"c_lflag: %016lx", tio.c_lflag); for(size_t i = 0; i < NCCS; ++i) { NSLog(@"c_cc[%lu]: %02x", i, tio.c_cc[i]); } NSLog(@"c_ispeed: %016lx", tio.c_ispeed); NSLog(@"c_ospeed: %016lx", tio.c_ospeed); // XXX fd_conn_t rarg = { .from = master, .to = conn, }; fd_conn_t warg = { .from = conn, .to = master, }; pthread_t rthrd, wthrd; r = pthread_create(&rthrd, NULL, fd_conn, &rarg); if(r != 0) { NSLog(@"pthread_create: %s", strerror(r)); exit(-1); } r = pthread_create(&wthrd, NULL, fd_conn, &warg); if(r != 0) { NSLog(@"pthread_create: %s", strerror(r)); exit(-1); } waitpid(pid, NULL, 0); exit(0); } } else { close(conn); } } } typedef struct { int from; int to; } fd_conn_t; void* fd_conn(void *arg) { const fd_conn_t *desc = arg; int from = desc->from, to = desc->to; while(1) { char buf[1024]; ssize_t num = read(from, buf, sizeof(buf)); if(num < 0) { NSLog(@"read: %s", strerror(errno)); exit(-1); } if(num == 0) { exit(0); } ssize_t n = 0; while(n < num) { n += write(to, buf + n, num - n); } } }