/* INET DGRAM talkto.c */

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>


static void printaddr (t)
char *t;
{
printf("addr %u.%u.%u.%u\n", t[0]&0xFF, t[1]&0xFF, t[2]&0xFF, t[3]&0xFF);
} /* printaddr */

/******************************************************************************/

static int scan_size (str)
char *str;
{
int nb;
int mul = 1;
char *s;

s = str;
while (*s)
  {
  if (isdigit(*s)) { s++; continue; }
  if ((*s == 'K') || (*s == 'k')) { mul = 1024; break; }
  if ((*s == 'M') || (*s == 'm')) { mul = 1024*1024; break; }
  }
nb=atoi(str);
return nb*mul;
} /* scan_size */


static int fill_buff (buff, size, value)
char *buff; int size; char *value;
{
char *q;
int count = 1;
q = value; buff[size-2] = '\n'; buff[size-1] = 0; size -= 2;
while (size--)
  { *buff++ = *q++; if (! *q) { count++; q=value; } }
return count;
} /* fill_buff */

/******************************************************************************/

int main (argc, argv)
int argc;
char **argv;
{
int size;			/* number of bytes to send */
char *value = "Hello world, backslash N...";
char *message;
int f_repeat = 0;		/* flag for -r option */
int sd;				/* Socket descriptor */
int snd;			/* send() return status */
int f_no_port = 1;		/* flag for -p option presence */
char *port_name;		
int f_no_host = 1;		/* flag for -h option presence */
char *peername;			/* peer name */
struct sockaddr_in name;
struct hostent *hp, *gethostbyname();
int ch;				/* for getopt() */
extern char *optarg;		/* for getopt() */

while ((ch = getopt(argc, argv, "h:p:r:m:")) != EOF)
  switch (ch)
    {
    case 'h': peername = optarg; f_no_host = 0; break;
    case 'p': port_name = optarg; f_no_port = 0; break;
    case 'r': f_repeat = 1; size=scan_size(optarg); break;
    case 'm': value = optarg; break;
    }

if (f_no_host || f_no_port) goto usage;

fprintf(stderr, "Process %d will try to send \"%s\"", getpid(), value);
if (f_repeat)
  {
  if (! (message = malloc(size)))
    {
    fprintf(stderr, "No space.\n");
    exit(2);
    }
  printf(" repeated %d times.\n", fill_buff(message, size, value));
  }
else
  {
  size = strlen(value)+1;
  message = value;
  printf(".\n");
  }

/*  */
/* Create socket on which to send */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == -1)
  {
  perror("opening datagram socket");
  exit(1);
  }
else
  printf("socket %d created\n", sd);

/* Construct name of socket to send to */
    hp = gethostbyname(peername);
    if (hp == 0)
      { fprintf(stderr, "%s : unknown host", peername); exit(2); }
    name.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
name.sin_family = AF_INET;
name.sin_port = htons(atoi(port_name));

  {
  printf("%d bytes to send to ", size);
  printaddr(&name.sin_addr);
  /*  */
  /* Send message */
  if ((snd=sendto(sd, message, size, 0,
	(struct sockaddr *) (&name), sizeof(name))) == -1)
    {
    printf("Error ******** : %d bytes sent\n", snd);
    perror("sending packet");
    exit(1);
    }
  printf("%d bytes sent\n", snd);
  }

close(sd);
exit(0);

usage:
fprintf(stderr, "%s [-r size] [-m message] -h peername -p portnumber\n", argv[0]);
fprintf(stderr, "<size> could be in bytes with no suffix,\n");
fprintf(stderr, "       or in kilobytes with <k> suffix,\n");
fprintf(stderr, "       or in megabytes with <m> suffix.\n");
exit(1);
} /* main */