/*

restart-nos < -a ip-addr> < -k pwd> < -p port#> hostname <e | k | r>

Issues UDP "remote" packets to NOS in order to restart it. See help() at 
the end of the source for details.

Tom Jennings
20 Aug 91

*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

/* Remote reset/restart server definitions (From NOS' "REMOTE.H") */

#define IPPORT_REMOTE 1234	/* NOS' picked-from-the-air "REMOTE" port
				   number. (See REMOTE.H in the NOS source.) */
#define	SYS_RESET 1
#define	SYS_EXIT 2
#define	KICK_ME 3

char data[80];		/* packet data -- big enough for anything we'll send,
			   plus it's zero'd for us. */

#define ADDR_SIZE 4	/* 8-bit bytes per IP address */
#define NULLCHAR '\0'

extern int errno;
extern int optind,opterr;
extern char *optarg;

int resolve();

int
main(argc,argv)
int argc;
char *argv[];
{
	struct sockaddr_in fsock;
	int s = -1;
	int port,len;
	char *key = NULLCHAR;
	int klen;
	int addr = 0;
	char cmd,*host,c;

	port = IPPORT_REMOTE;	/* Set default */
	optind = 1;		/* reinit getopt() */
	while((c = getopt(argc,argv,"a:p:k:")) != -1){
		switch(c){
		case 'a':
			if((addr = resolve(optarg)) == 0){
				printf("Host %s unknown\n",optarg);
				exit(1);
			}
			break;

		case 'p':
			port = atoi(optarg);
			break;

		case 'k':
			key = optarg;
			klen = strlen(key);
			break;
		}
	}

	if(optind > argc - 1) {			/* we require at least */
		help();				/* the hostname */
		exit(1);
	}
	host = argv[optind++];			/* remember ptr to hostname */
	cmd= 'e'; 				/* default command is EXIT */
	if (optind < argc) cmd= *argv[optind];	/* unless specified otherwise*/
	len = 1;				/* packet len = 1 char so far*/

	fsock.sin_family = AF_INET;		/* cvt hostname to address */
	if((fsock.sin_addr.s_addr = resolve(host)) == 0){
	        printf("Ain't no such host \"%s\"\n",host);
		exit(1);			/* oops */
	}

	fsock.sin_port = port;
	if((s = socket(AF_INET,SOCK_DGRAM,0)) == -1){ /* open socket to addr */
		printf("socket() failed\n");
		exit(1);			/* oops */
	}

	switch(cmd) {				/* various REMOTE commands */
	case 'r':
		data[0] = SYS_RESET;		/* remote command */
		strncpy(&data[1],key,klen);	/* the password */
		len += klen;			/* password length */
		break;

	case 'e':
		data[0] = SYS_EXIT;
		strncpy(&data[1],key,klen);
		len += klen;
		break;

	case 'k':
		data[0] = KICK_ME;
		if (addr == 0) {
			printf("KICK command requires an address\n");
			goto cleanup;
		}
		len += ADDR_SIZE;		/* account for addr size */
		* ((int *) &data[1])= htonl(addr); /* use network byteorder */
		break;

	default:
		printf("Unknown command %c\n",cmd);
		goto cleanup;
	}

	/* Form the command packet and send it */
	if(sendto(s,data,len,0,(char *)&fsock,sizeof(fsock)) == -1){
		printf("sendto failed (errno= %d)\n",errno);
	}

cleanup:
	if (s != -1) close(s);
	return 0;
}

/* Look up the host name, return it's address. */

int
resolve(name)
char *name;
{
	struct hostent *h,*gethostbyname();
	int addr;

	h= gethostbyname(name);			/* look up the name, */
	if (h == 0) return(0);			/* not found */

	bcopy((char *) h-> h_addr_list[0],(char *) &addr,h-> h_length); /*  */
	if (h-> h_length != ADDR_SIZE) { 	/* OOPS! */
		printf("OOPS! host address size isn't %d bytes... (I wonder what will happen)\n",ADDR_SIZE);
	}	
	return(addr);
}

/* Print program usage. */

help() {

printf("restart-nos [-a ip-addr] [-k pwd] [-p port#] hostname [e | k | r]\n\n");
printf("Examples:\n\n");
printf("restart-nos -k password gw e		Issue an EXIT command to gw\n");
printf("restart-nos -k password gw 		Ditto -- command defaults to EXIT\n");
printf("restart-nos -a 140.174.9.1 -k pwd gw k	Kick specified socket\n");

printf("restart-nos issues a \"REMOTE\" UDP packet to the MSDOS NOS.EXE program,\n");
printf("in order to restart or reboot NOS, or to kick a specified process. (We can\n");
printf("only assume that hostname is on a NOS box.)\n\n");

printf("There are three possible commands; e (EXIT), k (KICK), or r (RESET). (The last\n");
printf("argument on the command line.) If no command is specified (2nd example above)\n");
printf("restart-nos assumes EXIT.\n\n");

printf("-- KICK requires an ip-address specified with -a.\n");
printf("-- EXIT causes NOS to terminate normally (where a properly-installed\n");
printf("   DOS batch file will restart NOS).\n");
printf("-- RESET causes the remote NOS computer to reboot.\n\n");

printf("Both RESET and EXIT re-start NOS. EXIT is faster, as it simply makes NOS\n");
printf("exit and reload. Both cause NOS to re-read it's control file, AUTOEXEC.NOS.\n");

printf("Tom Jennings -- 20 Aug 91\n");
}

