103 lines
2.8 KiB
C
103 lines
2.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <ctype.h> // isprint
|
|
|
|
#define BUF_SIZE 4096
|
|
|
|
// Hexdump 헬퍼 함수
|
|
// offset_base: 전체 스트림에서의 현재 위치 (0x0000, 0x0010 ...)
|
|
void print_hexdump(const unsigned char *buf, ssize_t len, size_t offset_base) {
|
|
for (size_t i = 0; i < len; i += 16) {
|
|
// 1. 오프셋 출력
|
|
fprintf(stderr, "%08zx: ", offset_base + i);
|
|
|
|
// 2. 16진수 출력
|
|
for (size_t j = 0; j < 16; j++) {
|
|
if (i + j < len)
|
|
fprintf(stderr, "%02x ", buf[i + j]);
|
|
else
|
|
fprintf(stderr, " "); // 패딩
|
|
}
|
|
|
|
fprintf(stderr, " |");
|
|
|
|
// 3. ASCII 출력
|
|
for (size_t j = 0; j < 16; j++) {
|
|
if (i + j < len) {
|
|
unsigned char c = buf[i + j];
|
|
// 출력 가능한 문자면 출력, 아니면 점(.)
|
|
fprintf(stderr, "%c", isprint(c) ? c : '.');
|
|
}
|
|
}
|
|
fprintf(stderr, "|\n");
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int *fds = (int *)malloc(sizeof(int) * argc);
|
|
int fd_count = 0;
|
|
|
|
// 모드 플래그
|
|
int mode_stderr = 0; // --stderr (Raw 출력)
|
|
int mode_hexdump = 0; // --hexdump (Hex 출력)
|
|
|
|
// 1. 인자 파싱
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "--stderr") == 0) {
|
|
mode_stderr = 1;
|
|
continue;
|
|
}
|
|
if (strcmp(argv[i], "--hexdump") == 0) {
|
|
mode_hexdump = 1;
|
|
continue;
|
|
}
|
|
|
|
// 일반 파일 열기
|
|
int fd = open(argv[i], O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
|
if (fd < 0) {
|
|
perror(argv[i]);
|
|
continue;
|
|
}
|
|
fds[fd_count++] = fd;
|
|
}
|
|
|
|
// 2. 데이터 처리 루프
|
|
unsigned char buf[BUF_SIZE]; // unsigned로 변경
|
|
ssize_t n;
|
|
size_t total_bytes = 0; // 전체 스트림 오프셋 추적용
|
|
|
|
while ((n = read(STDIN_FILENO, buf, BUF_SIZE)) > 0) {
|
|
// (A) STDOUT 출력 (필수: 파이프 연결 유지)
|
|
if (write(STDOUT_FILENO, buf, n) != n) {
|
|
perror("write stdout");
|
|
break;
|
|
}
|
|
|
|
// (B) STDERR 처리 (디버깅용)
|
|
if (mode_hexdump) {
|
|
// Hexdump 모드면 예쁘게 포맷팅해서 stderr로
|
|
print_hexdump(buf, n, total_bytes);
|
|
} else if (mode_stderr) {
|
|
// 그냥 stderr 모드면 Raw 데이터를 stderr로
|
|
if (write(STDERR_FILENO, buf, n) != n) { /* ignore */ }
|
|
}
|
|
|
|
// (C) 파일 출력
|
|
for (int i = 0; i < fd_count; i++) {
|
|
if (write(fds[i], buf, n) != n) {
|
|
perror("write file");
|
|
}
|
|
}
|
|
|
|
total_bytes += n;
|
|
}
|
|
|
|
for (int i = 0; i < fd_count; i++) {
|
|
close(fds[i]);
|
|
}
|
|
free(fds);
|
|
return 0;
|
|
} |