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