/*
 *  udpprobe.c  - send data over an UDP socket and look for response
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>

static char RCSID[]= "$Id: udpprobe.c,v 1.1 1994/01/31 22:46:30 olaf Exp $";

void usage(void)
{
  fputs("Usage: udpprobe [-w timeout] host port [text]\n",stderr);
  exit(9);
}

void checkarg(int arg, int ind)
{
  if (arg<=ind)
    usage();
}

extern char *optarg;
extern int optind;

void main(int argc, char *argv[])
{
  int s, len, timeout=1;
  struct sockaddr_in sa;
  struct hostent *hp;
  struct servent *sp;
  struct timeval tm;
  long addr;
  char buf[1024];
  char *rw;
  fd_set lfd;

  /* Look for timeout argument */
  switch (getopt(argc,argv,"w:")) {
  case 'w': timeout = atoi(optarg);
  case EOF: break;
  default: usage();
  }
  checkarg(argc, optind);

  /* Figure out the address to send to */
  bzero(&sa, sizeof(sa)) ;
  if ((addr = inet_addr(argv[optind])) != -1) {
    bcopy(&addr, &sa.sin_addr, sizeof(addr)) ;
    sa.sin_family=AF_INET ;
  } else {
    if ((hp = gethostbyname(argv[optind])) == NULL) {
      herror("gethostbyname");
      exit(2); }
    bcopy(hp->h_addr, &sa.sin_addr, hp->h_length) ;
    sa.sin_family=hp->h_addrtype ; }
  checkarg(argc, ++optind);

  /* ditto for the port */
  if ((s = atoi(argv[optind]))==0) {
    if ((sp = getservbyname(argv[optind], "udp"))==NULL) {
      perror("getservbyname");
      exit(2); }
    sa.sin_port = sp->s_port; }
  else
    sa.sin_port = s;
  ++optind;

  if ((s=socket(AF_INET, SOCK_DGRAM, 0))<0) {
    perror("socket");
    exit(2); }
  
  if (connect(s, (struct sockaddr *) &sa, sizeof(sa))<0) {
    perror("connect");
    exit(2); }

  bzero(buf, sizeof(buf));
  if (argc==optind) {
    read(0, buf, sizeof(buf)-1); 
    rw = buf; }
  else {
    rw = argv[optind]; } 
  /* If message empty, send just one \0 char */
  len = strlen(rw);
  if (len==0)
    len = 1;
  
  if (send(s, rw, len, 0)<0) {
    perror("send");
    exit(2); }

  if (timeout==0)
    exit(0);

  /* Now collect response */
  bzero(buf, sizeof(buf));
  FD_ZERO(&lfd);
  FD_SET(s, &lfd);
  tm.tv_sec = timeout;
  tm.tv_usec = 0;
  if (select(s+1, &lfd, NULL, NULL, &tm)<0) {
    perror("select");
    exit(2);}
  if (FD_ISSET(s, &lfd)) {
    if ((recv(s, buf, sizeof(buf)-1, 0)<0)) {
      perror("recv");
      exit(2); }
    else {
      printf("%s", buf); 
      exit(0); } }
  else
    exit(1);
}
