/*========================================================================
 * Written by D. Jason Penney, 1991.  Rights to this program are as follows:
 * you may not receive any compensation for distribution of this program
 * except for an optional fee for the distribution medium.  This program
 * must be accompanied by this source code.  This notice may not be removed.
 * Modifications to this program must be clearly noted and marked as such.
 * Since this program is provided free of charge, there is ABSOLUTELY NO
 * WARRANTY.
 *
 * Name - getservbyname.c
 *
 * Description - Program to verify presence of a given service, i.e.
 *               by the getservbyname(2) call.
 *
 * Compile with:
 *   cc -o getservbyname getservbyname.c
 *   chmod 555 getservbyname
 *
 *
 * $Id: getservbyname.c 19162 2008-06-03 20:59:32Z stever $
 *
 *========================================================================
 */

#if defined(__hpux)
#if !defined(_HPUX_SOURCE)
#define _HPUX_SOURCE
#endif /* !defined(_HPUX_SOURCE) */
#include <sys/stdsyms.h> /* Pick up the other related #defs */
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if defined(MSDOS)
#include <winsock.h>
#include <io.h>
#elif defined(macintosh) || defined(__MWERKS__)
#include "global.ht"
#include "tnetmac.hf"
#else
#include <netdb.h>
#endif
#include <ctype.h>
#include <errno.h>

#if defined(OS2)
#include <types.h> /* for u_long */
#endif

#if !defined(macintosh) && !defined(__MWERKS__)
#include <sys/types.h>
#endif

#if !defined(MSDOS) && !defined(macintosh) && !defined(__MWERKS__)
#include <netinet/in.h>
#endif

#if defined(__OS2__)
#include <utils.h>
#endif

#if defined(MSDOS)
#define MAKEWORD(a, b)      ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))

static void ShutdownNetwork(void)
{
  WSACleanup();
}

static void InitNetwork(void)
{
  WSADATA wsaData;
  WORD version = MAKEWORD(1,1);
  int err = WSAStartup(version, &wsaData);
  if( err == 0 )
    if( LOBYTE(wsaData.wVersion) != LOBYTE(version) ||
       HIBYTE(wsaData.wVersion) != HIBYTE(version) )
      {
        err = WSAVERNOTSUPPORTED;
        fprintf(stderr,
                "The lowest version supported by the DLL is = %d.%d\n",
                LOBYTE(wsaData.wVersion),
                HIBYTE(wsaData.wVersion) );
        fprintf(stderr,
                "The higest version supported by the DLL is = %d.%d\n",
                LOBYTE(wsaData.wHighVersion),
                HIBYTE(wsaData.wHighVersion) );
        WSACleanup();
        exit(1);
      }
  if( err != 0 )
    {
      switch(err)
        {   
        case WSASYSNOTREADY:
          fprintf(stderr, "Windows Socket subsystem not ready.\n");
          break;
        case WSAVERNOTSUPPORTED:
          fprintf(stderr, "Windows Socket API version %d.%d not supported\n",
                  LOBYTE(version), HIBYTE(version) );
          break;
        case WSAEINVAL:
          fprintf(stderr, "Windows Socket version %d.%d not supported\n",
                  LOBYTE(version), HIBYTE(version) );
          break;
        default:
          fprintf(stderr, "Could not find winsock.dll. error=%d\n", err);
          break;
        }   
      exit(1);
    }   
  atexit(ShutdownNetwork);
  return;
}
#endif /* MSDOS */

int main(int argc, char *argv[])
{
struct servent *thisOne;
char **thisAlias;
char s[BUFSIZ];

#if defined(MSDOS)
char *p;

/* When program terminates provide dialog box with program
   exit code and window exit choices. */
_wsetexit(_WINEXITPROMPT);

printf("Service name: ");
fflush(stdout);
if (fgets(s, sizeof(s), stdin) == NULL)
   exit(1);
if ( (p = strchr(s, '\n')) != NULL)
  *p = '\0';

InitNetwork();
#elif defined(macintosh) || defined(__MWERKS__)
char *p;

printf("Service name: ");
fflush(stdout);
if (fgets(s, sizeof(s), stdin) == NULL)
   exit(1);
if ( (p = strchr(s, '\n')) != NULL)
  *p = '\0';
TnetInitMacTCP();

#else
if (argc != 2) {
  printf("Usage: %s <service-name>\n", argv[0]);
  exit(1);
  }
strncpy(s, argv[1], sizeof(s));
#endif /* MSDOS */

#if defined(ultrix) || defined(sparcSolaris)
  /* Workaround an for ULTRIX bug which causes segmentation violation if
     the name specified by the first argument does not appear in the
     network services database and the second argument is NULL. 

     On Solaris NULL as second argument causes a NULL return
     even if the service exists, bug6445.
 */
  thisOne = getservbyname(s, "tcp");
#else
  thisOne = getservbyname(s, NULL);
#endif

if (thisOne == NULL) {
  printf("%s:  (no entry, errno = %d)\n", s, errno);
  exit(1);
  }
printf("s_name=%s s_port = %d s_proto = %s\n", thisOne->s_name, 
    ntohs(thisOne->s_port), thisOne->s_proto);
if (*thisOne->s_aliases != NULL) {
  printf("aliases: ");
  for (thisAlias = thisOne->s_aliases; *thisAlias != NULL; thisAlias ++)
    printf("%s ", *thisAlias);
  printf("\n");
  }

#if defined(macintosh) || defined(__MWERKS__)
TnetShutdownMacTCP();
#endif

return 0; /* for lint */
}

#if defined(__MWERKS__)
/* incestuous relationship between tnetmac and hostmac */
int HostGetEnv(const char inStr[], char outStr[], ArraySizeType outSize)
{
  return FALSE;
}
#endif
