/*
 * getinfo - retrieve and display Internet status information.
 *
 * Programming Assignment #6, Part 1 of 3
 *
 * CSc 645  Spring 1995  Jim Warhol
 *
 * getinfo retrieves and prints the following Internet information:
 *
 * 1) The host name of the executing computer;
 * 2) The IP address of the current host, displayed both in octal 
 *    and in the dotted-decimal notation; 
 * 3) the network ID and host ID, extracted from the IP address; and
 * 4) the port number of the UPD and TCP echo servers.
 *
 * Compile with:  cc -o getinfo getinfo.c
 *
 * Execute with:  getinfo
 *
 */

#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/param.h>

/* define compile-time constants (necessary due to NeXT header anomalies) */

#define stdoutx	1		/* standard output file ordinal */
#define stderrx	2		/* standard error file ordinal */

/* data definitions */

char hostname[MAXHOSTNAMELEN];	/* current internal host name */
char *dotted_decimal;		/* dotted decimal IP address notation */
int net, local;			/* network ID & local host ID */

struct hostent *hp;		/* result of host name lookup */
struct servent *sp;		/* result of service lookup */
struct in_addr ipaddr;		/* host IP address */

/* function prototypes */

void error(char errmsg[]);
void printn(char msg[], u_long n); /* write line with integer to std. output */
void prints(char msg[], char str[]); /* write line with string to std. output */

/* main program */

void main()
{

   /* determine current host name and print it */

   if (gethostname(hostname, MAXHOSTNAMELEN) != 0)
      error("An error occurred when calling gethostname().");

   prints("The current host name is %s.\n", hostname);

   /* determine IP address of host */

   hp = gethostbyname(hostname);
   if (hp == NULL) error("An error occured when calling gethostbyname().");
   bcopy((char *)hp->h_addr_list[0], (char *)&ipaddr, hp->h_length);

   /* print out IP address in octal and in dotted decimal forms */

   dotted_decimal = inet_ntoa(ipaddr);
   printn("The ip address is %o (octal).\n", ipaddr.s_addr);
   prints("The ip address (in dotted decimal notation) is %s.\n", 
      dotted_decimal);

   /* extract network ID and host ID from IP address, and print them */

   net = inet_netof(ipaddr);
   local = inet_lnaof(ipaddr);
   printn("The network ID is %o (octal).\n", net);
   printn("The local host ID is %o (octal).\n", local);

   /* determine port numbers for UDP and TCP echo servers, and print them */

   sp = getservbyname("echo", "udp");
   if (sp == NULL) error("An error occured when calling getservbyname().");
   printn("The port number of the UDP echo server is %d.\n", sp->s_port);

   sp = getservbyname("echo", "tcp");
   if (sp == NULL) error("An error occured when calling getservbyname().");
   printn("The port number of the TCP echo server is %d.\n", sp->s_port);

   /* terminate program */

   exit(0);

}

/*
 * error(char errmsg[]);
 *
 * error prints out an error message followed by a new line character, and 
 * then aborts program execution.
 *
 */

void error(char errmsg[])
{
   write(stderrx, errmsg, strlen(errmsg));
   write(stderrx, "\n", 2);
   exit(-1);
}

/*
 * void printn(char msg[], u_long n);
 *
 * printn writes a format string containing an integer to standard output.
 * NOTE: stdoutx is used instead of stdout because of NeXT system header 
 * file anomalies.
 *
 */

void printn(char msg[], u_long n)
{
   char printbuf[100];

   if (strlen(msg) > 100 - 10)	/* ensure room for msg and integer */
      error("printn: Message too long to fit in print buffer.");

   sprintf(printbuf, msg, n);
   write(stdoutx, printbuf, strlen(printbuf));
   return;
}

/*
 * void prints(char msg[], char str[]);
 *
 * printn writes a format string containing an integer to standard output.
 * NOTE: stdoutx is used instead of stdout because of NeXT system header 
 * file anomalies.
 *
 */

void prints(char msg[], char str[])
{
   char printbuf[100];

   if (strlen(msg) + strlen(str) > sizeof(printbuf)) /* ensure room */
      error("printn: Message too long to fit in print buffer.");

   sprintf(printbuf, msg, str);
   write(stdoutx, printbuf, strlen(printbuf));
   return;
}

