#include #include #include #include #include #include #define HEX(v) ((v) > 9 ? (v) + 'a' - 0xa : (v) + '0' - 0x0) int main(int argc, char** argv) { int i, j, ret, digit, val, state, to_hex; char c; unsigned char ibuf[4096], obuf[8192]; struct pollfd pollfd = {0, POLLIN}; /* Scan command-line arguments. */ if (argc == 1) { to_hex = 1; } else if (argc == 2 && strcmp(argv[1], "-r") == 0) { to_hex = state = val = 0; } else { fprintf(stderr, "Usage: hex [-r] < data\n"); return EXIT_FAILURE; } /* We need nonblocking mode. */ fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK); while (1) { /* Wait for incoming data. */ ret = poll(&pollfd, 1, -1); if (ret == -1) { perror("poll"); return EXIT_FAILURE; } else if (ret == 0) { continue; } else { /* Fall through. */ } /* Read incoming data. */ ret = read(0, ibuf, 4096); if (ret == -1) { perror("read"); return EXIT_FAILURE; } else if (ret == 0) { return EXIT_SUCCESS; } else { /* Fall through. */ } if (to_hex) { /* Convert from binary to hexadecimal. */ for (i = j = 0; i < ret; ++i) { obuf[j] = HEX(ibuf[i] / 16); ++j; obuf[j] = HEX(ibuf[i] % 16); ++j; } } else { /* Convert from hexadecimal to binary. */ j = 0; for (i = 0; i < ret; ++i) { switch (c = ibuf[i]) { default: continue; /* Skip this character. */ case 'a' ... 'f': digit = c - 'a' + 10; break; case 'A' ... 'F': digit = c - 'A' + 10; break; case '0' ... '9': digit = c - '0' + 0; break; } val = (val * 16) | (digit); ++state; if (state == 2) { obuf[j] = val; ++j; state = val = 0; } } } /* Attempt to flush the output buffer. */ ret = write(1, obuf, j); if (ret == -1) { perror("write"); return EXIT_FAILURE; } else if (ret < j) { fprintf(stderr, "Failed to flush output buffer. :^(\n"); return EXIT_FAILURE; } else { /* Fall through to loop again. */ } } return EXIT_SUCCESS; } /* vim: set ts=4 sts=4 sw=4 tw=80 et: */