home *** CD-ROM | disk | FTP | other *** search
- /*
- * args.c
- *
- * Author: Tomi Ollila <too@ajk.tele.fi>
- *
- * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
- * All rights reserved.
- *
- * Created: Mon Sep 27 08:33:42 1993 too
- * Last modified: Wed Apr 13 16:02:04 1994 too
- *
- * $Id: args.c,v 1.4 1994/04/17 11:51:30 too Exp $
- *
- * HISTORY
- * $Log: args.c,v $
- * Revision 1.4 1994/04/17 11:51:30 too
- * Changed some error messages to be a bit more descriptive
- *
- * Revision 1.3 1994/04/05 15:51:13 too
- * Fixed wrong protocol string
- *
- * Revision 1.2 1993/11/17 12:06:50 too
- * small fix + updates
- *
- * Revision 1.1 1993/10/24 12:50:39 too
- * Initial revision
- *
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <dos/dos.h>
-
- #define BSDSOCKET_H /* defining BSDSOCKET_H inhibitis automatic inline incl. */
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
-
- #ifndef inline
- #define inline __inline
- #endif
-
- #include "system_includes.h" /* overkill but who cares.. */
- #include "c.h"
- #include "args.h"
- #include "readargs.h"
-
- extern const int one;
-
- int getPort(struct Library * SocketBase, char * service)
- {
- struct servent * srv;
- int port;
-
- if (!isdigit(service[0])) {
- if ((srv = getservbyname(service, "tcp")) == NULL)
- port = -1;
- else
- port = srv->s_port;
- }
- else
- port = atoi(service);
-
- return port;
- }
-
- long getAddr(struct Library * SocketBase, char * host)
- {
- struct hostent * h;
- long retval;
-
- if ((h = gethostbyname(host)) == NULL)
- return -1;
-
- CopyMem(h->h_addr_list[0], &retval, 4);
- return retval;
- }
-
- /****************************************************************************/
-
- #define TEMPLATE "H=HOST,P=PORT,S=SERVICE/K,O=OBTAIN/K"
-
- enum { CI_HOST, CI_PORT, CI_SERVICE, CI_OBTAIN, CI_SIZE };
-
- #define HOSTKW "HOST"
- #define hostkw "host"
- #define HKW "H"
- #define isHostKw(z) (z == sizeof HOSTKW - 1 || z == sizeof HKW - 1)
-
- #define Return(x) do { retval = x; goto End; } while (0)
-
- inline UBYTE handleArgs(struct Library * SocketBase, ULONG * flags, LONG * sdp,
- char * name, int namelen)
- {
- struct readargs * rargs;
- int shp = 0;
- UBYTE retval = 0;
-
- {
- int len;
- char * zapbuf, * p, * z;
-
- /*
- * skip handler name
- */
- for (p = name, len = namelen; len >0; p++, len--)
- if (*p == ':') {
- namelen = len;
- p++;
- name = p;
- len--; /* namelen is len + 1 since dos ReadArgs needs '\n' at end */
- break;
- }
- if (len == 0)
- return ERROR_REQUIRED_ARG_MISSING;
-
- if ((zapbuf = AllocMem(namelen * sizeof (char), MEMF_PUBLIC)) == NULL)
- return ERROR_NO_FREE_STORE;
- z = zapbuf;
-
- /*
- * scan 'args', change '/'s to ' 's. Check if H or HOST is given as
- * a keyword.
- */
- for (; len > 0; p++, z++, len--) {
- switch (*p) {
- case '/':
- *z = ' ';
- if (isHostKw(shp))
- goto skip;
- else
- shp = 0; /* start from beginning */
- continue;
- case '=':
- if (isHostKw(shp))
- goto skip;
- else
- shp = -1; /* dont start at all */
- break;
- default:
- if (shp != -1)
- if (*p == HOSTKW[shp] || *p == hostkw[shp])
- shp++;
- else
- shp = -1;
- }
- *z = *p;
- }
- skip:
- /*
- * scan rest chars if H or HOST found as a keyword. (if previously
- * skipped and there was hostkw and /, one write is done twice).
- */
- for (; len > 0; p++, z++, len--)
- if (*p == '/')
- *z = ' ';
- else
- *z = *p;
-
- *z = '\n'; /* sentinel */
-
- rargs = readargs(TEMPLATE, CI_SIZE, zapbuf, namelen);
- FreeMem(zapbuf, namelen * sizeof (char));
-
- if (rargs == NULL)
- return IoErr();
- }
-
- {
- char * port;
- struct sockaddr_in addr = { 0 };
- /*
- */
- if (rargs->ra_Args[CI_SERVICE]) {
- if (rargs->ra_Args[CI_PORT])
- Return(ERROR_TOO_MANY_ARGS); /* both port and service */
- else
- port = (char *)rargs->ra_Args[CI_SERVICE];
- }
- else {
- port = (char *)rargs->ra_Args[CI_PORT];
- if (rargs->ra_Args[CI_HOST] != NULL && port == NULL)
- if (isHostKw(shp))
- Return(ERROR_REQUIRED_ARG_MISSING); /* host and no port */
- else {
- port = (char *)rargs->ra_Args[CI_HOST];
- rargs->ra_Args[CI_HOST] = NULL;
- }
- }
- #if 0
- if (rargs->ra_Args[CI_RLOGIND])
- if (rargs->ar_Args[CI_HOST])
- Return(ERROR_TOO_MANY_ARGS); /* host cannot be used w/ rlogind */
- else
- *flags |= APF_RLOGIND;
- #endif
-
- if (rargs->ra_Args[CI_OBTAIN]) {
- if (rargs->ra_Args[CI_PORT])
- Return(ERROR_TOO_MANY_ARGS); /* port and obtain at the same time */
- else {
- LONG id;
- /*
- * One can use service name as an id for ObtainSocket().
- */
- if ((id = getPort(SocketBase,
- (char *)rargs->ra_Args[CI_OBTAIN])) == -1 ||
- (*sdp = ObtainSocket(id, AF_INET, SOCK_STREAM, 0)) == -1)
- Return(ERROR_OBJECT_NOT_FOUND);
- }
- }
- /*
- * drop here if only host and port or only port (rlogind possible if
- * only port but it is not an issue here)
- */
-
- addr.sin_family = AF_INET;
- if ((addr.sin_port = getPort(SocketBase, port)) == (u_short)-1 ||
- (*sdp = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- Return(ERROR_BAD_NUMBER);
-
- if (rargs->ra_Args[CI_HOST]) {
- /*
- * connect
- */
- if ((addr.sin_addr.s_addr = getAddr(SocketBase,
- (char *)rargs->ra_Args[CI_HOST])) == -1 ||
- connect(*sdp, (struct sockaddr *)&addr, sizeof addr) == -1) {
- CloseSocket(*sdp);
- Return(ERROR_OBJECT_NOT_FOUND);
- }
- }
- else {
- /*
- * bind & listen
- */
- setsockopt(*sdp, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof one);
- if (bind(*sdp, (struct sockaddr *)&addr, sizeof addr) == -1 ||
- listen(*sdp, 1) == -1) {
- CloseSocket(*sdp);
- Return(ERROR_OBJECT_NOT_FOUND);
- }
- else
- *flags |= APF_LISTENING; /* not connected yet */
- }
- }
- End:
- freeargs(rargs);
- return retval;
- }
-