Skip to content

Instantly share code, notes, and snippets.

@qguv
Forked from syntactician/ls.c
Last active February 7, 2017 09:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qguv/eead5492f41e239a19f25fca57e3a538 to your computer and use it in GitHub Desktop.
Save qguv/eead5492f41e239a19f25fca57e3a538 to your computer and use it in GitHub Desktop.
#include <stdio.h> /* printf, puts, putchar */
#include <unistd.h> /* fork, execv */
#include <sys/ioctl.h> /* get username */
#include <sys/wait.h> /* join processes */
#include <sys/types.h> /* pid_t */
#include <string.h> /* strcpy, strncpy, memcpy */
#define MAX_WIDTH 80
#define MAX_CMD 64
#define SYSPATH "/usr/bin/"
#define FILEPATH "/home/f85/qguv/safety_warned"
#define INVERT "\033[7m"
#define REVERT "\033[0m"
#define HEADER "WARNING!"
#define MESSAGE "You have put my binary directory ahead of the system's in your $PATH. This will execute my binaries rather than the system's in the case of name collisions. While flattering, this is considered harmful. Please append my binary directory to the end of your $PATH, not the beginning. This incident will be reported."
/* add extra parens to be SUUUPER macro-safe */
#define ALEN(X) ((((((((((((((((((((sizeof(X) / sizeof(*(X))))))))))))))))))))))
static void print_wrap(size_t width, const char *msg, size_t msg_len)
{
size_t i, last_space;
size_t line_remaining = 0, msg_printed = 0;
char buf[MAX_WIDTH + 1];
while (msg_printed < msg_len) {
strncpy(buf + line_remaining,
msg + msg_printed,
width - line_remaining);
msg_printed += width - line_remaining;
last_space = 0;
for (i = 0; i < width; i++) {
if (!buf[i]) {
puts(buf);
return;
} else if (buf[i] == ' ') {
last_space = i;
} else if (buf[i] == '\n') {
last_space = i;
break;
}
}
line_remaining = width - last_space - 1;
buf[last_space] = '\0';
puts(buf);
memmove(buf, buf + last_space + 1, line_remaining);
}
}
int main(const int argc, char *const *argv)
{
FILE *fp;
struct winsize size;
int i, padding, width;
int status = 1;
pid_t pid;
char cmd[MAX_CMD];
(void) argc;
/* report user so I can make sure everyone's not ignoring these warnings */
if ((fp = fopen(FILEPATH, "a"))) {
fprintf(fp, "%s\n", getlogin());
fclose(fp);
}
/* run the 'real' command */
strncpy(cmd, SYSPATH, MAX_CMD);
strncpy(cmd + ALEN(SYSPATH) - 1, argv[0], MAX_CMD - ALEN(SYSPATH) - 1);
if (!(pid = fork()))
execv(cmd, argv);
waitpid(pid, &status, 0);
/* get terminal width */
ioctl(STDOUT_FILENO, TIOCGWINSZ, &size);
width = size.ws_col > MAX_WIDTH || size.ws_col < ALEN(HEADER) ?
MAX_WIDTH : size.ws_col;
padding = (width - (signed) ALEN(HEADER)) / 2;
/* print header */
printf("\n%s", INVERT);
for (i = 0; i < padding; i++)
putchar(' ');
printf("%s", HEADER);
for (i = 0; i < padding; i++)
putchar(' ');
printf("%s", REVERT);
putchar('\n');
print_wrap(width, MESSAGE, ALEN(MESSAGE) - 1);
return WEXITSTATUS(status);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment