home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / comm / tcp / amitcp / src / l / inet-handler / args.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-19  |  5.7 KB  |  252 lines

  1. /*
  2.  * args.c
  3.  *
  4.  * Author: Tomi Ollila <too@ajk.tele.fi>
  5.  *
  6.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
  7.  *                    All rights reserved.
  8.  *
  9.  * Created: Mon Sep 27 08:33:42 1993 too
  10.  * Last modified: Wed Apr 13 16:02:04 1994 too
  11.  *
  12.  * $Id: args.c,v 1.4 1994/04/17 11:51:30 too Exp $
  13.  *
  14.  * HISTORY
  15.  * $Log: args.c,v $
  16.  * Revision 1.4  1994/04/17  11:51:30  too
  17.  * Changed some error messages to be a bit more descriptive
  18.  *
  19.  * Revision 1.3  1994/04/05  15:51:13  too
  20.  * Fixed wrong protocol string
  21.  *
  22.  * Revision 1.2  1993/11/17  12:06:50  too
  23.  * small fix + updates
  24.  *
  25.  * Revision 1.1  1993/10/24  12:50:39  too
  26.  * Initial revision
  27.  *
  28.  */
  29.  
  30. #include <exec/types.h>
  31. #include <exec/memory.h>
  32. #include <dos/dos.h>
  33.  
  34. #define BSDSOCKET_H /* defining BSDSOCKET_H inhibitis automatic inline incl. */
  35. #include <sys/types.h>
  36. #include <sys/socket.h>
  37. #include <netinet/in.h>
  38. #include <netdb.h>
  39.  
  40. #ifndef inline
  41. #define inline __inline
  42. #endif
  43.  
  44. #include "system_includes.h" /* overkill but who cares.. */
  45. #include "c.h"
  46. #include "args.h"
  47. #include "readargs.h"
  48.  
  49. extern const int one;
  50.  
  51. int getPort(struct Library * SocketBase, char * service)
  52. {
  53.   struct servent * srv;
  54.   int port;
  55.   
  56.   if (!isdigit(service[0])) {
  57.     if ((srv = getservbyname(service, "tcp")) == NULL)
  58.       port = -1;
  59.     else
  60.       port = srv->s_port;
  61.   }
  62.   else
  63.     port = atoi(service);
  64.  
  65.   return port;
  66. }
  67.  
  68. long getAddr(struct Library * SocketBase, char * host)
  69. {
  70.   struct hostent * h;
  71.   long retval;
  72.   
  73.   if ((h = gethostbyname(host)) == NULL)
  74.     return -1;
  75.  
  76.   CopyMem(h->h_addr_list[0], &retval, 4);
  77.   return retval;
  78. }
  79.  
  80. /****************************************************************************/
  81.  
  82. #define TEMPLATE "H=HOST,P=PORT,S=SERVICE/K,O=OBTAIN/K"
  83.                     
  84. enum { CI_HOST, CI_PORT, CI_SERVICE, CI_OBTAIN, CI_SIZE };
  85.  
  86. #define HOSTKW    "HOST"
  87. #define hostkw    "host"
  88. #define HKW    "H"
  89. #define isHostKw(z) (z == sizeof HOSTKW - 1 || z == sizeof HKW - 1)
  90.  
  91. #define Return(x) do { retval = x; goto End; } while (0)
  92.  
  93. inline UBYTE handleArgs(struct Library * SocketBase, ULONG * flags, LONG * sdp,
  94.             char * name, int namelen)
  95. {
  96.   struct readargs * rargs;
  97.   int shp = 0;
  98.   UBYTE retval = 0;
  99.  
  100.   {
  101.     int len;
  102.     char * zapbuf, * p, * z;
  103.  
  104.     /*
  105.      * skip handler name
  106.      */
  107.     for (p = name, len = namelen; len >0; p++, len--)
  108.       if (*p == ':') {
  109.     namelen = len;
  110.     p++;
  111.     name = p;
  112.     len--;      /* namelen is len + 1 since dos ReadArgs needs '\n' at end */
  113.     break;
  114.       }
  115.     if (len == 0) 
  116.       return ERROR_REQUIRED_ARG_MISSING;
  117.     
  118.     if ((zapbuf = AllocMem(namelen * sizeof (char), MEMF_PUBLIC)) == NULL)
  119.       return ERROR_NO_FREE_STORE;
  120.     z = zapbuf;
  121.     
  122.     /*
  123.      * scan 'args', change '/'s to ' 's. Check if H or HOST is given as
  124.      * a keyword.
  125.      */ 
  126.     for (; len > 0; p++, z++, len--) {
  127.       switch (*p) {
  128.       case '/':
  129.     *z = ' ';
  130.     if (isHostKw(shp))
  131.       goto skip;
  132.     else
  133.       shp = 0; /* start from beginning */
  134.     continue;
  135.       case '=':
  136.     if (isHostKw(shp))
  137.       goto skip;
  138.     else
  139.       shp = -1; /* dont start at all */
  140.     break;
  141.       default:
  142.     if (shp != -1)
  143.       if (*p == HOSTKW[shp] || *p == hostkw[shp])
  144.         shp++;
  145.       else
  146.         shp = -1;
  147.       }
  148.       *z = *p;
  149.     }
  150.   skip:
  151.     /*
  152.      * scan rest chars if H or HOST found as a keyword. (if previously
  153.      * skipped and there was hostkw and /, one write is done twice).
  154.      */
  155.     for (; len > 0; p++, z++, len--)
  156.       if (*p == '/')
  157.     *z = ' ';
  158.       else
  159.     *z = *p;
  160.  
  161.     *z = '\n';    /* sentinel */
  162.   
  163.     rargs = readargs(TEMPLATE, CI_SIZE, zapbuf, namelen);
  164.     FreeMem(zapbuf, namelen * sizeof (char));
  165.  
  166.     if (rargs == NULL)
  167.       return IoErr();
  168.   }
  169.  
  170.   {
  171.     char * port;
  172.     struct sockaddr_in addr = { 0 };
  173.     /*
  174.      */
  175.     if (rargs->ra_Args[CI_SERVICE]) {
  176.       if (rargs->ra_Args[CI_PORT])
  177.     Return(ERROR_TOO_MANY_ARGS); /* both port and service */
  178.       else
  179.     port = (char *)rargs->ra_Args[CI_SERVICE];
  180.     }
  181.     else {
  182.       port = (char *)rargs->ra_Args[CI_PORT];
  183.       if (rargs->ra_Args[CI_HOST] != NULL && port == NULL)
  184.     if (isHostKw(shp))
  185.       Return(ERROR_REQUIRED_ARG_MISSING); /* host and no port */
  186.     else {
  187.       port = (char *)rargs->ra_Args[CI_HOST];
  188.       rargs->ra_Args[CI_HOST] = NULL;
  189.     }
  190.     }
  191. #if 0    
  192.     if (rargs->ra_Args[CI_RLOGIND])
  193.       if (rargs->ar_Args[CI_HOST])
  194.     Return(ERROR_TOO_MANY_ARGS); /* host cannot be used w/ rlogind */
  195.       else
  196.     *flags |= APF_RLOGIND;
  197. #endif
  198.  
  199.     if (rargs->ra_Args[CI_OBTAIN]) {
  200.       if (rargs->ra_Args[CI_PORT])
  201.     Return(ERROR_TOO_MANY_ARGS); /* port and obtain at the same time */
  202.       else {
  203.     LONG id;
  204.     /*
  205.      * One can use service name as an id for ObtainSocket().
  206.      */
  207.     if ((id = getPort(SocketBase,
  208.               (char *)rargs->ra_Args[CI_OBTAIN])) == -1 ||
  209.         (*sdp = ObtainSocket(id, AF_INET, SOCK_STREAM, 0)) == -1)
  210.       Return(ERROR_OBJECT_NOT_FOUND);
  211.       }
  212.     }
  213.     /*
  214.      * drop here if only host and port or only port (rlogind possible if
  215.      * only port but it is not an issue here)
  216.      */
  217.  
  218.     addr.sin_family = AF_INET;
  219.     if ((addr.sin_port = getPort(SocketBase, port)) == (u_short)-1 ||
  220.     (*sdp = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  221.       Return(ERROR_BAD_NUMBER);
  222.     
  223.     if (rargs->ra_Args[CI_HOST]) {
  224.       /*
  225.        * connect
  226.        */
  227.       if ((addr.sin_addr.s_addr = getAddr(SocketBase,
  228.                 (char *)rargs->ra_Args[CI_HOST])) == -1 ||
  229.       connect(*sdp, (struct sockaddr *)&addr, sizeof addr) == -1) {
  230.     CloseSocket(*sdp);
  231.      Return(ERROR_OBJECT_NOT_FOUND);
  232.       }
  233.     }
  234.     else {
  235.       /*
  236.        * bind & listen
  237.        */
  238.       setsockopt(*sdp, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof one);
  239.       if (bind(*sdp, (struct sockaddr *)&addr, sizeof addr) == -1 ||
  240.       listen(*sdp, 1) == -1) {
  241.     CloseSocket(*sdp);
  242.     Return(ERROR_OBJECT_NOT_FOUND);
  243.       }
  244.       else
  245.     *flags |= APF_LISTENING; /* not connected yet */
  246.     }
  247.   }
  248.  End:
  249.   freeargs(rargs);
  250.   return retval;
  251. }
  252.