/* This program emulates the KA9Q NOS remote function
   The syntax was kept as close as possible to the one in
   NOS. 

   The command argument selection code fragments were modeled after
   KA9Q NOS to keep them similar. (Thanks Phil! How many ways
   can you use getopt & switch's :-) )

   You need to add a line to /etc/services as follows:
      remote      1234/udp                # ka9q reboot socket

   Or you can just specify the port via the -p option.

   Tested on my HP9000/360 HP-UX 7.0   Should work on any sys
   with Berkely sockets & getopts.

   Written by Alan Barrow KM4BA 1/8/92

   A little cleanup of warnings by Brian A. Lantz/KO4KS 6-24-95

   Use however you wish!

 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <signal.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#ifdef linux
#include <unistd.h>
#endif

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: nos_remote.c,v 1.5 1996/08/29 12:11:16 root Exp $";
#endif

extern int errno;

int s;				/* socket descriptor */
int port;			/* port number */
char *datagram; 		/* datagram */
char const *key = "mymindisgoing";	/* password key */
int len,c ;
extern char *optarg;
extern int optind;
char *cmd, *host;

struct hostent *hp;		/* pointer to host info for nameserver host */
struct servent *sp;		/* pointer to service information */

struct sockaddr_in myaddr_in;	/* for local socket address */
struct sockaddr_in servaddr_in;	/* for server socket address */

#define ADDRNOTFOUND	0xffffffff	/* value returned for unknown host */
#define RETRIES	5		/* number of times to retry before givin up */


int
main(int argc, char *argv[])
{

	port = 0; 
	while((c = getopt(argc, argv, "p:k:" )) != EOF ){
		switch(c){
		case 'p':
			port = atoi( optarg );
			break;
		case 'k':
			key = (char *) optarg;
			break;
		}
	}
	if (optind > argc - 2) {
		fprintf(stderr, "Usage:  %s [-p port#] [-k key] hostname reset|exit|kick\n", argv[0]);
		exit(1);
	}

	host = argv[ optind++ ];
	cmd = argv[ optind ];

		/* clear out address structures */
	memset ((char *)&myaddr_in, 0, sizeof(struct sockaddr_in));
	memset ((char *)&servaddr_in, 0, sizeof(struct sockaddr_in));

		/* Set up the server address. */
	servaddr_in.sin_family = AF_INET;

		/* Get the host information for the server's hostname that the
		 * user passed in.
		 */
	hp = gethostbyname (host);
	if (hp == NULL) {
		fprintf(stderr, "%s: Unable to resolve %s \n",
				argv[0], host);
		exit(1);
	}
	servaddr_in.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;

	/* If we did not specify a port */
	if (port == 0) {

		/* Find the information for the "remote" server
		 * in order to get the needed port number.
		 */
		sp = getservbyname ("remote", "udp");
		if (sp == NULL) {
			fprintf(stderr,"%s: remote not found in /etc/services\n",
					argv[0]);
			exit(1);
		}
		servaddr_in.sin_port = sp->s_port;
	}else{
		/* use the port from the cmd line */
		servaddr_in.sin_port = htons(port);
	}

		/* Create the socket. */
	s = socket (AF_INET, SOCK_DGRAM, 0);
	if (s == -1) {
		perror(argv[0]);
		fprintf(stderr, "%s: unable to create socket\n", argv[0]);
		exit(1);
	}

#define NOS_RESET 1
#define NOS_EXIT 2
#define NOS_KICK 3

#define      NULLCHAR        (char *)0

	/* create a buffer to hold the cmd flag & the key string */
	len = strlen(key) + 1;
	datagram = (char *) malloc(len);

	/* stuff the cmd flag into the buffer */
	switch(cmd[0]){
	case 'r':
		datagram[0] = NOS_RESET;
		break;
	
	case 'e':
		datagram[0] = NOS_EXIT;
		break;

	case 'k':
		datagram[0] = NOS_KICK;
		break;
		
	default:
		fprintf(stderr,"%s: Unknown command %s\n",argv[0],cmd);
		exit(1);
	}

		

	/* stuff the string into the buffer */
	if(key != NULLCHAR){
                        strcpy(&datagram[1],key);
	}
	else{
		fprintf(stderr,"%s: key must not be null string\n",cmd);
		exit(1);
	}

		/* Send the request to the target. */

	if (sendto (s, datagram, strlen(datagram), 0,
				(const struct sockaddr *)&servaddr_in,
				sizeof(struct sockaddr_in)) == -1) {
		perror(argv[0]);
		fprintf(stderr, "%s: unable to send request\n", argv[0]);
		exit(1);
	}
	return 0;
}
