#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sysexits.h>
#include <errno.h>
#include <err.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netgraph.h>
#define DEFAULT_HOOKNAME "debug"
#define NG_SOCK_HOOK_NAME "hook"
#define BUF_SIZE (64 * 1024)
static void WriteAscii(u_char * buf, int len);
static void Usage(void);
int
main(int ac, char *av[])
{
struct ngm_connect ngc;
const char *path = NULL, *hook = DEFAULT_HOOKNAME;
int csock, dsock;
int asciiFlag = 0;
int ch;
while ((ch = getopt(ac, av, "da")) != -1) {
switch (ch) {
case 'd':
NgSetDebug(NgSetDebug(-1) + 1);
break;
case 'a':
asciiFlag = 1;
break;
case '?':
default:
Usage();
}
}
ac -= optind;
av += optind;
switch (ac) {
case 2:
hook = av[1];
case 1:
path = av[0];
break;
default:
Usage();
}
if (NgMkSockNode(NULL, &csock, &dsock) < 0)
errx(EX_OSERR, "can't get sockets");
snprintf(ngc.path, sizeof(ngc.path), "%s", path);
snprintf(ngc.ourhook, sizeof(ngc.ourhook), NG_SOCK_HOOK_NAME);
snprintf(ngc.peerhook, sizeof(ngc.peerhook), "%s", hook);
if (NgSendMsg(csock, ".",
NGM_GENERIC_COOKIE, NGM_CONNECT, &ngc, sizeof(ngc)) < 0)
errx(EX_OSERR, "can't connect to node");
while (1) {
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(0, &rfds);
FD_SET(dsock, &rfds);
if (select(FD_SETSIZE, &rfds, NULL, NULL, NULL) < 0)
err(EX_OSERR, "select");
if (FD_ISSET(dsock, &rfds)) {
char buf[BUF_SIZE];
int rl, wl;
if ((rl = NgRecvData(dsock,
buf, sizeof(buf), NULL)) < 0)
err(EX_OSERR, "read(hook)");
if (rl == 0)
errx(EX_OSERR, "read EOF from hook?!");
if (asciiFlag)
WriteAscii((u_char *) buf, rl);
else if ((wl = write(1, buf, rl)) != rl) {
if (wl < 0) {
err(EX_OSERR, "write(stdout)");
} else {
errx(EX_OSERR,
"stdout: read %d, wrote %d",
rl, wl);
}
}
}
if (FD_ISSET(0, &rfds)) {
char buf[BUF_SIZE];
int rl;
if ((rl = read(0, buf, sizeof(buf))) < 0)
err(EX_OSERR, "read(stdin)");
if (rl == 0)
errx(EX_OSERR, "EOF(stdin)");
if (NgSendData(dsock, NG_SOCK_HOOK_NAME, buf, rl) < 0)
err(EX_OSERR, "write(hook)");
}
}
}
static void
WriteAscii(u_char *buf, int len)
{
char ch, sbuf[100];
int k, count;
for (count = 0; count < len; count += 16) {
snprintf(sbuf, sizeof(sbuf), "%04x: ", count);
for (k = 0; k < 16; k++)
if (count + k < len)
snprintf(sbuf + strlen(sbuf),
sizeof(sbuf) - strlen(sbuf),
"%02x ", buf[count + k]);
else
snprintf(sbuf + strlen(sbuf),
sizeof(sbuf) - strlen(sbuf), " ");
snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " ");
for (k = 0; k < 16; k++)
if (count + k < len) {
ch = isprint(buf[count + k]) ?
buf[count + k] : '.';
snprintf(sbuf + strlen(sbuf),
sizeof(sbuf) - strlen(sbuf), "%c", ch);
} else
snprintf(sbuf + strlen(sbuf),
sizeof(sbuf) - strlen(sbuf), " ");
snprintf(sbuf + strlen(sbuf),
sizeof(sbuf) - strlen(sbuf), "\n");
write(1, sbuf, strlen(sbuf));
}
ch = '\n';
write(1, &ch, 1);
}
static void
Usage(void)
{
errx(EX_USAGE, "usage: nghook [-da] path [hookname]");
}