/* wrapsock.c provides access to socket related system calls. Copyright (C) 2008-2022 Free Software Foundation, Inc. Contributed by Gaius Mulley . This file is part of GNU Modula-2. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ #include "config.h" #include #define EXPORT(FUNC) m2iso ## _wrapsock_ ## FUNC #define IMPORT(MODULE,FUNC) m2iso ## _ ## MODULE ## _ ## FUNC #define M2EXPORT(FUNC) m2iso ## _M2_wrapsock_ ## FUNC #define M2LIBNAME "m2iso" /* This module should be rewritten to use C++. */ typedef void (*proc_con) (int, char **, char **); typedef void (*proc_dep) (void); extern void m2iso_M2RTS_RequestDependant (const char *modulename, const char *libname, const char *dependancy); extern void m2iso_M2RTS_RegisterModule (const char *modulename, const char *libname, proc_con init, proc_con fini, proc_dep dependencies); #if defined(HAVE_SYS_TYPES_H) #include "sys/types.h" #endif #if defined(HAVE_SYS_SOCKET_H) #include "sys/socket.h" #endif #if defined(HAVE_NETINET_IN_H) #include "netinet/in.h" #endif #if defined(HAVE_NETDB_H) #include "netdb.h" #endif #if defined(HAVE_UNISTD_H) #include "unistd.h" #endif #if defined(HAVE_SIGNAL_H) #include "signal.h" #endif #if defined(HAVE_SYS_ERRNO_H) #include "sys/errno.h" #endif #if defined(HAVE_ERRNO_H) #include "errno.h" #endif #if defined(HAVE_MALLOC_H) #include "malloc.h" #endif #if defined(HAVE_MALLOC_H) #include "signal.h" #endif #if defined(HAVE_STRING_H) #include "string.h" #endif #if defined(HAVE_STDLIB_H) #include "stdlib.h" #endif #include "ChanConsts.h" #define MAXHOSTNAME 1024 #define MAXPBBUF 1024 #if defined(HAVE_NETINET_IN_H) typedef struct { char hostname[MAXHOSTNAME]; struct hostent *hp; struct sockaddr_in sa; int sockFd; int portNo; int hasChar; char pbChar[MAXPBBUF]; } clientInfo; static openResults clientConnect (clientInfo *c); /* clientOpen - returns an ISO Modula-2 OpenResult. It attempts to connect to: hostname:portNo. If successful then the data structure, c, will have its fields initialized. */ openResults EXPORT(clientOpen) (clientInfo *c, char *hostname, unsigned int length, int portNo) { /* remove SIGPIPE which is raised on the server if the client is killed. */ signal (SIGPIPE, SIG_IGN); c->hp = gethostbyname (hostname); if (c->hp == NULL) return noSuchFile; memset ((void *)&c->sa, 0, sizeof (c->sa)); c->sa.sin_family = AF_INET; memcpy ((void *)&c->sa.sin_addr, (void *)c->hp->h_addr, c->hp->h_length); c->portNo = portNo; c->sa.sin_port = htons (portNo); c->hasChar = 0; /* Open a TCP socket (an Internet stream socket) */ c->sockFd = socket (c->hp->h_addrtype, SOCK_STREAM, 0); return clientConnect (c); } /* clientOpenIP - returns an ISO Modula-2 OpenResult. It attempts to connect to: ipaddress:portNo. If successful then the data structure, c, will have its fields initialized. */ openResults EXPORT(clientOpenIP) (clientInfo *c, unsigned int ip, int portNo) { /* remove SIGPIPE which is raised on the server if the client is killed. */ signal (SIGPIPE, SIG_IGN); memset ((void *)&c->sa, 0, sizeof (c->sa)); c->sa.sin_family = AF_INET; memcpy ((void *)&c->sa.sin_addr, (void *)&ip, sizeof (ip)); c->portNo = portNo; c->sa.sin_port = htons (portNo); /* Open a TCP socket (an Internet stream socket) */ c->sockFd = socket (PF_INET, SOCK_STREAM, 0); return clientConnect (c); } /* clientConnect - returns an ISO Modula-2 OpenResult once a connect has been performed. If successful the clientInfo will include the file descriptor ready for read/write operations. */ static openResults clientConnect (clientInfo *c) { if (connect (c->sockFd, (struct sockaddr *)&c->sa, sizeof (c->sa)) < 0) return noSuchFile; return opened; } /* getClientPortNo - returns the portNo from structure, c. */ int EXPORT(getClientPortNo) (clientInfo *c) { return c->portNo; } /* getClientHostname - fills in the hostname of the server the to which the client is connecting. */ void EXPORT(getClientHostname) (clientInfo *c, char *hostname, unsigned int high) { strncpy (hostname, c->hostname, high + 1); } /* getClientSocketFd - returns the sockFd from structure, c. */ int EXPORT(getClientSocketFd) (clientInfo *c) { return c->sockFd; } /* getClientIP - returns the sockFd from structure, s. */ unsigned int EXPORT(getClientIP) (clientInfo *c) { #if 0 printf("client ip = %s\n", inet_ntoa (c->sa.sin_addr.s_addr)); #endif return c->sa.sin_addr.s_addr; } /* getPushBackChar returns true if a pushed back character is available. */ bool EXPORT(getPushBackChar) (clientInfo *c, char *ch) { if (c->hasChar > 0) { c->hasChar--; *ch = c->pbChar[c->hasChar]; return true; } return false; } /* setPushBackChar returns true if it is able to push back a character. */ bool EXPORT(setPushBackChar) (clientInfo *c, char ch) { if (c->hasChar == MAXPBBUF) return false; c->pbChar[c->hasChar] = ch; c->hasChar++; return true; } /* getSizeOfClientInfo - returns the sizeof (opaque data type). */ unsigned int EXPORT(getSizeOfClientInfo) (void) { return sizeof (clientInfo); } #endif /* GNU Modula-2 linking hooks. */ void M2EXPORT(init) (int, char **, char **) { } void M2EXPORT(fini) (int, char **, char **) { } void M2EXPORT(dep) (void) { } void __attribute__((__constructor__)) M2EXPORT(ctor) (void) { m2iso_M2RTS_RegisterModule ("wrapsock", M2LIBNAME, M2EXPORT(init), M2EXPORT(fini), M2EXPORT(dep)); }