/*
** identsucks-inetd
** Version 1.0
** Written by Neill Corlett because whoever wrote RFC1413 should be shot.
**
** I don't even know or care what license this should be under.  I think I
** stole the timed_read and write functions from somewhere but I'll be damned
** if I can remember where and it's been ages since I touched this code.
**
** To install, just put it somewhere like /usr/local/sbin and add this line
** to your inetd.conf:
**
** 113 stream tcp nowait nobody /usr/local/sbin/identsucks-inetd identsucks-inetd
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <time.h>
#include <syslog.h>
#include <ctype.h>
#include <poll.h>

static ssize_t timed_read(
  int     fd,
  void   *buf,
  size_t  siz,
  time_t  timeout
) {
  int tot = 0;
  char *p = buf;
  struct timeval tv, start, after, duration, tmp;
  tv.tv_sec = timeout;
  tv.tv_usec = 0;
  for(;;) {
    struct pollfd rfd;
    int i, r, error;
    if(tot >= siz) return siz;
    rfd.fd = fd;
    rfd.events = POLLIN;
    rfd.revents = 0;
    gettimeofday(&start, NULL);
    error = poll(
      &rfd,
      1,
      tv.tv_sec * 1000 + tv.tv_usec / 1000
    );
    if(error <= 0) return error;
    r = read(fd, p, siz - tot);
    if(r <= 0) return r;
    for(i = 0; i < r; i++) {
      if(p[i] == '\r' || p[i] == '\n') {
	tot += i;
        return tot;
      }
    }
    gettimeofday(&after, NULL);
    timersub(&start, &after, &duration);
    timersub(&tv, &duration, &tmp);
    tv = tmp;
    if(
      (tv.tv_sec < 0) ||
      (!timerisset(&tv))
    ) return tot;
    tot += r;
    p += r;
  }
}

static ssize_t timed_write(
  int         fd,
  const void *buf,
  size_t      siz,
  time_t      timeout
) {
  int error;
  fd_set writeds;
  struct timeval tv;
  FD_ZERO(&writeds);
  FD_SET(fd, &writeds);
  tv.tv_sec = timeout;
  tv.tv_usec = 0;
  error = select(fd + 1, NULL, &writeds, NULL, &tv);
  switch(error) { case -1: case 0: return error; }
  return(write(fd, buf, siz));
}

int main(void) {
  int seconds = 5;
  char buf[100];
  int n = timed_read(0, buf, 20, seconds);
  if(n <= 0 || n > 20) return 0;
  strcpy(buf + n, " : USERID : UNIX :identsucks\r\n");
  timed_write(1, buf, strlen(buf), seconds);
  return 0;
}
