#include #include #include #include #include #include #include #include #include #define ANSI_FG_RED "\033[0;31m" #define ANSI_FG_DEFAULT "\033[0;39m" int main(int argc, char **argv) { for (int i = 1; i < argc; i++) { struct stat fileinfo; if (stat(argv[i], &fileinfo)) err(-1, "couldn't stat " ANSI_FG_RED "%s" ANSI_FG_DEFAULT, argv[i]); if (!S_ISREG(fileinfo.st_mode)) errx(-1, ANSI_FG_RED "%s" ANSI_FG_DEFAULT " is not a regular file.", argv[i]); if (fileinfo.st_size > UINT32_MAX) errx(-1, ANSI_FG_RED "%s" ANSI_FG_DEFAULT " is too big.", argv[i]); uint32_t file_size = fileinfo.st_size; uint32_t name_size = strlen(argv[i]); if (fwrite(&name_size, 4, 1, stdout) != 1) errx(-1, "error writing to stdout"); if (printf("%s", argv[i]) != name_size) errx(-1, "error writing to stdout"); for (int j = 0; (j + (name_size & 0b11)) & 0b11; j++) if (putchar('\0')) errx(-1, "error writing to stdout"); if (fwrite(&file_size, 4, 1, stdout) != 1) errx(-1, "error writing to stdout"); if (fflush(stdout)) err(-1, "couldn't flush stdout"); pid_t pid; int wstatus; switch (pid = fork()) { case -1: err(-1, "couldn't fork"); case 0: if (execlp("cat", "cat", argv[i], NULL)) err(-1, "couldn't execute cat"); default: if (wait(&wstatus) == -1) err(-1, "error waiting for child"); if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) exit(-1); } for (int j = 0; (j + (file_size & 0b11)) & 0b11; j++) if (putchar('\0')) errx(-1, "error writing to stdout"); } return 0; }