#ifdef NEEDS_TYPES #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define FILE_HANDLE_TYPE FILE * char host[] = "UNIX"; #else struct files_t { FILE *in; FILE *out; }; struct files_t *popen2(char * program, char * args[]); int pclose2(struct files_t *fp); #define CLEANUP_PIPE(pipe) close((pipe)[0]); close((pipe)[1]) typedef struct files_t files_t; struct files_chain_t { files_t files; pid_t pid; struct files_chain_t *next; }; typedef struct files_chain_t files_chain_t; static files_chain_t *files_chain; static files_t * root_handle; static int _do_popen2(files_chain_t *link, char * program, char * args[]) { int child_in[2]; int child_out[2]; if (0 != pipe(child_in)) { return -1; } if (0 != pipe(child_out)) { CLEANUP_PIPE(child_in); return -1; } pid_t cpid = link->pid = fork(); if (0 > cpid) { CLEANUP_PIPE(child_in); CLEANUP_PIPE(child_out); return -1; } if (0 == cpid) { if (0 > dup2(child_in[0], 0) || 0 > dup2(child_out[1], 1)) { exit(1); } CLEANUP_PIPE(child_in); CLEANUP_PIPE(child_out); for (files_chain_t *p = files_chain; p; p = p->next) { int fd_in = fileno(p->files.in); if (fd_in != 0) { close(fd_in); } int fd_out = fileno(p->files.out); if (fd_out != 1) { close(fd_out); } } execv(program, args); exit(1); } close(child_in[0]); close(child_out[1]); link->files.in = fdopen(child_in[1], "w"); link->files.out = fdopen(child_out[0], "r"); return 0; } files_t *popen2(char * program, char * args[]) { files_chain_t *link = (files_chain_t *) malloc(sizeof (files_chain_t)); if (NULL == link) { return NULL; } if (0 > _do_popen2(link, program, args)) { free(link); return NULL; } link->next = files_chain; files_chain = link; return (files_t *) link; } int pclose2(files_t *fp) { files_chain_t **p = &files_chain; int found = 0; while (*p) { if (*p == (files_chain_t *) fp) { *p = (*p)->next; found = 1; break; } p = &(*p)->next; } if (!found) { return -1; } if (0 > fclose(fp->in) || 0 > fclose(fp->out)) { free((files_chain_t *) fp); return -1; } int status = -1; pid_t wait_pid; do { wait_pid = waitpid(((files_chain_t *) fp)->pid, &status, 0); } while (-1 == wait_pid && EINTR == errno); free((files_chain_t *) fp); if (wait_pid == -1) { return -1; } return status; } void write_be32(uint32_t value) { fputc(value >> 24, root_handle->in); fputc(value >> 16, root_handle->in); fputc(value >> 8, root_handle->in); fputc(value, root_handle->in); } uint32_t read_be32() { uint32_t value = fgetc(root_handle->out) << 24; value |= fgetc(root_handle->out) << 16; value |= fgetc(root_handle->out) << 8; value |= fgetc(root_handle->out); return value; } int main(int argc, char * argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s [args...]\n", argv[0]); exit(1); } if (!(root_handle = popen2(argv[1], argv + 2))) { fprintf(stderr, "Failed to run %s.\n", argv[1]); exit(1); } while(!feof(root_handle->out)) { int packet_code = fgetc(root_handle->out); switch(packet_code) { case 0x01: packet_0x01(); break; case 0x02: packet_0x02(); break; case 0x03: packet_0x03(); break; case 0x04: packet_0x04(); break; case 0x05: packet_0x05(); break; case 0x06: packet_0x06(); break; case 0x07: packet_0x07(); break; case 0x08: packet_0x08(); break; case 0x09: packet_0x09(); break; case 0x0A: packet_0x0A(); break; case 0x0B: packet_0x0B(); break; case 0x0C: packet_0x0C(); break; case 0x0D: packet_0x0D(); break; case 0x0E: packet_0x0E(); break; case 0x0F: packet_0x0F(); break; case 0x10: packet_0x10(); break; case 0x11: packet_0x11(); break; case 0x12: packet_0x12(); break; case 0x13: packet_0x13(); break; case 0x14: packet_0x14(); break; case 0x15: packet_0x15(); break; case 0x16: packet_0x16(); break; case 0x17: packet_0x17(); break; case 0x18: packet_0x18(); break; case 0x19: packet_0x19(); break; case 0x1A: packet_0x1A(); break; case 0x1B: packet_0x1B(); break; case 0x1C: packet_0x1C(); break; case 0x1D: packet_0x1D(); break; case 0x1E: packet_0x1E(); break; case 0x1F: packet_0x1F(); break; case 0x20: packet_0x20(); break; case 0x21: packet_0x21(); break; case 0x22: packet_0x22(); break; case 0x23: packet_0x23(); break; case 0x24: packet_0x24(); break; case 0x25: packet_0x25(); break; case 0x26: packet_0x26(); break; case 0x27: packet_0x27(); break; default: fprintf(stderr, "[IOBridge] Unknown packet code: 0x%02X\n", packet_code); exit(1); } } pclose2(root_handle); } void child_send(int c) { fputc(c, root_handle->in); } int child_recv() { int c = fgetc(root_handle->out); return c == EOF ? -1 : c; } void child_read(char ** buffer, uint32_t * size) { *buffer = (char *) malloc(*size); if (!*buffer) { fprintf(stderr, "Failed to allocate %u bytes.\n", *size); exit(1); } *size = fread(buffer, 1, *size, root_handle->out); } void stdin_read(char ** buffer, uint32_t * size) { *buffer = (char *) malloc(*size); if (!*buffer) { fprintf(stderr, "Failed to allocate %u bytes.\n", *size); exit(1); } *size = fread(buffer, 1, *size, stdin); } void child_write(uint8_t * buffer, uint32_t size) { fwrite(buffer, 1, size, root_handle->in); } ssize_t read_line(char ** buffer, size_t * size) { return getline(buffer, size, root_handle->out) != -1; } void write_output(uint8_t * buffer, size_t size) { fwrite(buffer, 1, size, stdout); } void write_error(uint8_t * buffer, size_t size) { fwrite(buffer, 1, size, stderr); } int get_key() { int x = fgetc(stdin); if (x == EOF) return -1; else return x; } void * io_malloc(size_t size) { return malloc(size); } void io_free(void * ptr) { free(ptr); } void * io_realloc(void * ptr, size_t size) { return realloc(ptr, size); } FILE *io_open(char *f, char *m) { return fopen(f, m); } void io_close(FILE *f) { fclose(f); } void io_read_file(FILE * f, uint8_t ** buf, uint32_t * len) { *buf = (uint8_t *) malloc(*len); *len = fread(*buf, 1, *len, f); } void io_write_file(FILE * f, uint8_t * buf, uint32_t len) { fwrite(buf, 1, len, f); } uint32_t io_get_file_size(FILE * f) { long pos = ftell(f); fseek(f, 0, SEEK_END); uint32_t size = ftell(f); fseek(f, pos, SEEK_SET); return size; } void io_seek_file(FILE_HANDLE_TYPE f, uint32_t off, uint8_t whence) { switch (whence) { case 0: fseek(f, off, SEEK_SET); break; case 1: fseek(f, off, SEEK_CUR); break; case 2: fseek(f, off, SEEK_END); break; } } void io_rename(char * src, char * dst) { rename(src, dst); } void io_delete(char * f) { unlink(f); } void io_mkdir(char * src) { mkdir(src, 0777); } void io_rmdir(char * src) { rmdir(src); } void io_chdir(char * src) { chdir(src); } void io_getcwd(char ** buffer) { uint32_t size = PATH_MAX; *buffer = (char *) malloc(size); if (!getcwd(*buffer, size)) { free(*buffer); *buffer = NULL; } } unsigned long io_time() { return time(NULL); } void io_localtime(uint32_t * year, uint8_t * month, uint8_t * day, uint8_t * hour, uint8_t * minute, uint8_t * second) { struct tm * timeinfo; time_t rawtime; time(&rawtime); timeinfo = localtime(&rawtime); *year = timeinfo->tm_year + 1900; *month = timeinfo->tm_mon + 1; *day = timeinfo->tm_mday; *hour = timeinfo->tm_hour; *minute = timeinfo->tm_min; *second = timeinfo->tm_sec; } void io_gmtime(uint32_t * year, uint8_t * month, uint8_t * day, uint8_t * hour, uint8_t * minute, uint8_t * second) { struct tm * timeinfo; time_t rawtime; time(&rawtime); timeinfo = gmtime(&rawtime); *year = timeinfo->tm_year + 1900; *month = timeinfo->tm_mon + 1; *day = timeinfo->tm_mday; *hour = timeinfo->tm_hour; *minute = timeinfo->tm_min; *second = timeinfo->tm_sec; } void io_sleep(uint32_t time) { usleep(time * 1000); } void term_cooked() { struct termios cooked; tcgetattr(STDIN_FILENO, &cooked); cooked.c_lflag |= (ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &cooked); } void term_raw() { struct termios raw; tcgetattr(STDIN_FILENO, &raw); raw.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &raw); } void term_bounds(uint32_t * width, uint32_t * height) { struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); *width = w.ws_col; *height = w.ws_row; } void term_flush() { fflush(stdout); } void io_flush(FILE_HANDLE_TYPE f) { fflush(f); } uint8_t get_errno() { return errno; } uint8_t file_exists(char * path) { struct stat st; return stat(path, &st) == 0; } void io_handle_packet_0x25() { uint32_t len = read_be32(); uint8_t * data; child_read((char **) &data, &len); if(data[len - 1] == 0) data[len - 1] = 0x00; DIR * dir = opendir((char *) data); if(dir == NULL) { child_send(0x25); write_be32(0); io_free(data); return; } struct dirent * ent; vector(uint8_t) buffer = NULL; while((ent = readdir(dir)) != NULL) { uint32_t len = strlen(ent->d_name) + 1; vector_push_back(buffer, (len >> 8) & 0xff); vector_push_back(buffer, len & 0xff); for (int i = 0; i < len; i++) { vector_push_back(buffer, ent->d_name[i]); } vector_push_back(buffer, ent->d_type); } closedir(dir); child_send(0x25); write_be32(vector_size(buffer)); child_write(buffer, vector_size(buffer)); vector_free(data); } #endif