home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************/
- /* Program : SocketFS */
- /* Purpose : Treat Internet sockets as file streams */
- /* File : Nameproc.c */
- /* Author : R G Gammans */
- /* Date Created : 04-07-97 */
- /* Last Edited : 07-09-97 */
- /* */
- /* Copyright Date: July 1997 (C) R G Gammans */
- /* */
- /***************************************************************************/
- /*
- * SocketFS - BSD sockets filing system for RISC-OS.
- * Copyright (C) 1997 Roger G Gammans
- *
- * This program 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 2 of the License, or
- * (at your option) any later version.
- *
- *
- * This program 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: R Gammans <rgammans@compsurg,demon.co.uk>
- * Snailmail : 20 Trenches Rd, Crowborough, E Sussex, TN6 1ES UK.
- */
-
-
- #include <stdio.h>
- #include <sys/param.h>
- #include <sys/file.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <sys/un.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <pwd.h>
- #include <sys/syslog.h>
- #include <sys/wait.h>
- #include <sgtty.h>
- #include <ctype.h>
- #include <errnum.h>
- #include <string.h>
-
- #ifndef FIOMODE
- #define FIOMODE FIOSLEEPTW
- #endif
-
- #ifdef DEBUG
- #include "trackerlib.h"
- #endif
-
-
- /*
- * Most the code in here is pretty naff but it works.
- *
- * At some point this lot may as well be re-written in asm,
- * which will remove our dependendcy on stubs/sharedclib.
- *
- * Also the exceutable will drop in size considerably
- */
- typedef
- struct {
- int addr_family;
- int proto_family;
-
- char* special_field;
- int (*makesocket)(char* fname);
-
- } Thandler_struct;
-
-
- typedef
- struct TS_hand {
- Thandler_struct *data;
- struct TS_hand *next;
- } Thandler_list;
-
- Thandler_list *handler_list_root;
- char* errstr;
-
- Thandler_struct IPhandler,fdhandler;
- Thandler_list IPouter,fdouter;
-
-
-
- int makeInetStream(char* filename);
- int sock2fd(char* filename);
-
- void inithandlerlist()
- {
- IPhandler.special_field="IPv4";
- IPhandler.makesocket=makeInetStream;
- fdhandler.special_field="s2fd";
- fdhandler.makesocket=sock2fd;
- IPouter.data=&IPhandler;
- IPouter.next=&fdouter;
- fdouter.data=&fdhandler;
- fdouter.next=NULL;
- handler_list_root=&IPouter;
- }
-
- int makeSocket(char* specialfield,char* filename)
- {
- int a_socket;
- Thandler_list *traversee;
- int found;
-
- if (!specialfield)
- {
- /*Default AF_INET*/
- specialfield="IPv4";
-
- #ifdef DEBUG
- tracker_simple(" - special reset to \"IPv4\" (or is it)\n");
- #endif
- };
-
- traversee=handler_list_root;
- found=0;
- while ((traversee!=NULL) && !found) {
- found=!strcmp(specialfield,traversee->data->special_field);
- if (traversee!=NULL && !found) {
- traversee=traversee->next;
- }
- }
-
- if (!found)
- {
- /*File not found.. */
- a_socket=-1;
- }
- else
- {
- #ifdef DEBUG
- tracker_simple("About the call makesocket for af..\n");
- #endif
- a_socket=traversee->data->makesocket(filename);
- }
-
- return a_socket;
- }
-
-
- int makeInetStream(char* filename)
- {
- /* The aim here is two extract protocol over which where opening the
- * connection. (assuming ICMP/TCP/UDP.)
- * We also need to extract the host:port designation of both ends.
- *
- * We do this by processing each directory in turn.
- * eg. socket#IPv4::Tcp.$.www/demon/co/uk\80 -Talk to a Httpd - from any port.
- * socket#IPv4::Tcp.$.192/168/0/3\515.auto\768 -Talk to my lpd server.. from a resvered port
- */
-
- char *section,*divisor,*serv,*tmpptr;
- char proto[99],lcl_host[255],lcl_serv[255],rem_host[255],rem_serv[255];
- struct hostent *hp;
- struct servent *sp;
- struct sockaddr_in sin,sout;
- int s;
- char olddiv;
- int one =1;
-
- section=strstr(filename,":"); /*Should be 1st char */
- divisor=strstr(filename,".$.");
- if (!divisor)
- return -1;
-
- *divisor='\0';
- strcpy(proto,section+1);
- #ifdef DEBUG
- tracker_printf("Protocol = %s\n",proto);
- #endif
- *divisor='.';
- section=divisor+3;
-
- serv=strstr(section,"\\");
- divisor=strstr(section,".");
-
- if ((divisor) && (divisor<serv) || !serv)
- {
- /*
- * We must have both a port and a host at the
- * remote end.
- */
-
- return -1;
- }
- else
- {
- /* '\' in the remote part*/
-
- if (divisor) {
- olddiv= *divisor;
- *divisor='\0';
- }
- strcpy(rem_serv,serv+1);
- if (divisor)
- *divisor=olddiv;
- #ifdef DEBUG
- tracker_printf("Remote port name = %s\n",rem_serv);
- #endif
- olddiv=*serv;
- *serv='\0';
- strcpy(rem_host,section);
- *serv=olddiv;
- #ifdef DEBUG
- tracker_printf("Remote host part = %s\n",rem_host);
- #endif
- /* Do '.' and '/' replacement. */
-
- tmpptr=rem_host;
- while (*tmpptr!='\0') {
- if (*tmpptr=='/')
- {
- *tmpptr='.';
- }
- tmpptr++;
- }
- #ifdef DEBUG
- tracker_printf("Remote host = %s\n",rem_host);
- #endif
- hp=gethostbyname(rem_host);
- if (hp == NULL) {
- errstr="Can't find remote interface\n";
- return -1;
- }
-
- bzero((char *)&sin, sizeof(sin));
- bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
- sin.sin_family= hp->h_addrtype;
- sin.sin_port=htons(atoi(rem_serv));
-
- /* There is an implicit assumation here that our hosts */
- /* and network representations of 0 are the same */
- /* This will be true for all big & little endian */
- /* machines, which use 2's complement */
- if (sin.sin_port==0) {
- sp=getservbyname(rem_serv,proto);
- if (sp == NULL) {
- errstr="Can't resolve remote service\n";
- return -1;
- }
- sin.sin_port = sp->s_port;
- }
- #ifdef DEBUG
- tracker_printf("Remote port no = %d\n",ntohs(sin.sin_port));
- #endif
- }
-
- if (*divisor=='\0')
- {
- #ifdef DEBUG
- tracker_simple("Creating socket... ");
- #endif
- s=socket(AF_INET,SOCK_STREAM,0);
- #ifdef DEBUG
- tracker_simple("done\n");
- #endif
- if (s==-1) return s;
- }
- else
- {
- section=divisor+1;
- serv=strstr(section,"\\");
-
- if (!serv)
- {
- /*
- * No '\' in local part....
- * Currently we ignore all then!
- */
-
- s=socket(AF_INET,SOCK_STREAM,0);
- }
-
- else
- {
- /* '\' in the local part */
- #ifdef DEBUG
- tracker_printf("local port specified - %s\n",section);
- #endif
-
- *divisor='\0';
- strcpy(lcl_serv,serv+1);
-
- #ifdef DEBUG
- tracker_printf("Local port name = %s\n",lcl_serv);
- #endif
- *serv='\0';
- strcpy(lcl_host,section);
-
- #ifdef DEBUG
- tracker_printf("Local Host part = %s\n",lcl_host);
- #endif
- /*Do '.' and '/' replacement.*/
- tmpptr=lcl_host;
- while (*tmpptr=='\0') {
- if (*tmpptr=='/')
- {
- *tmpptr='.';
- }
- }
-
- #ifdef DEBUG
- tracker_printf("Local host = %s\n",lcl_host);
- #endif
- if (!strcmp(lcl_host,"auto")) {
- gethostname(lcl_host,sizeof(lcl_host));
- lcl_host[sizeof(lcl_host)-1]='\0';
- }
-
- hp=gethostbyname(lcl_host);
- if (hp == NULL) {
- errstr="Can't find local interface\n";
- return -1;
- }
-
- s=socket(AF_INET,SOCK_STREAM,0);
- if (s==-1) return s;
-
- bzero((char *)&sout, sizeof(sout));
- bcopy(hp->h_addr, (caddr_t)&sout.sin_addr, hp->h_length);
- sout.sin_family= hp->h_addrtype;
- #ifdef DEBUG
- tracker_printf("Local i/f = %s\n",lcl_host);
- #endif
-
- if (strcmp(lcl_serv,"auto")) {
- sout.sin_port=htons(atoi(lcl_serv));
-
- /* There is an implicit assumation here that our hosts */
- /* and the network representations of 0 are the same */
- /* This will be true for all big & little endian */
- /* machines, which use 2's complement. */
- if (sout.sin_port==0) {
- sp=getservbyname(lcl_serv,proto);
- if (sp == NULL) {
- errstr="Can't resolve local service\n";
- return -1;
- }
- sout.sin_port = sp->s_port;
- }
- }
- #ifdef DEBUG
- tracker_printf("Remote port no = %d\n",ntohs(sin.sin_port));
- #endif
-
- #ifdef DEBUG
- tracker_simple("trying to bind socket .... ");
- #endif
- if (bind(s,&sout,sizeof(sout))==-1) return -1;
- #ifdef DEBUG
- tracker_simple("done\n");
- #endif
-
-
- }
- }
- ioctl(s,FIOMODE,&one);
- #ifdef DEBUG
- tracker_simple("trying to connect .... ");
- #endif
- if (connect(s,&sin,sizeof(sin))==-1) return -1;
- #ifdef DEBUG
- tracker_simple("done\n");
- #endif
- return s;
- }
-
-
- int sock2fd(char* filename)
- {
- char *flags,*desc;
-
- flags=strstr(filename,":"); /*Should be 1st char */
- desc=strstr(filename,".$.");
- if (!desc)
- return -1;
- if isdigit(desc[3])
- {
- return atoi(desc[3]);
- }
-
- return -1;
- /*We ignore the meaning of the flags section currently */
- }
-