diff options
author | Yukihiro Matsumoto <matz@ruby-lang.org> | 1995-04-10 18:36:06 +0900 |
---|---|---|
committer | Takashi Kokubun <takashikkbn@gmail.com> | 2019-08-17 22:09:32 +0900 |
commit | b2420d8ffa4d347a75efbbdc376f4ce65c0eb172 (patch) | |
tree | bd40c44d9155d9cb10232a0e962dc1cc221c2c8b /ext | |
parent | 11e21a36bc935088f88a7cd1548f8c74c3bf6099 (diff) |
version 0.73v0_73
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.73.tar.gz
Mon Apr 10 18:36:06 1995 Yukihiro Matsumoto (matz@ix-02)
* version 0.73
Fri Apr 7 13:51:08 1995 Yukihiro Matsumoto (matz@ix-02)
* cons.c->assoc.c: consの余計な機能は外してpairとしての機能だけを
残した.enumerableをincludeするのもやめた.
* string.c(esub): 文字列置換イテレータ.perlのs///eの相当する.
Diffstat (limited to 'ext')
-rw-r--r-- | ext/MANIFEST | 6 | ||||
-rw-r--r-- | ext/Makefile.in | 40 | ||||
-rw-r--r-- | ext/dbm.c | 441 | ||||
-rw-r--r-- | ext/dbm.doc | 107 | ||||
-rw-r--r-- | ext/socket.c | 761 | ||||
-rw-r--r-- | ext/socket.doc | 227 |
6 files changed, 1582 insertions, 0 deletions
diff --git a/ext/MANIFEST b/ext/MANIFEST new file mode 100644 index 0000000000..881a97c39e --- /dev/null +++ b/ext/MANIFEST @@ -0,0 +1,6 @@ +MANIFEST +Makefile.in +dbm.c +dbm.doc +socket.c +socket.doc diff --git a/ext/Makefile.in b/ext/Makefile.in new file mode 100644 index 0000000000..20d8c5c9c4 --- /dev/null +++ b/ext/Makefile.in @@ -0,0 +1,40 @@ +2SHELL = /bin/sh + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ + +CFLAGS = -I.. @CCDLFLAGS@ @CFLAGS@ +LIBS = @LIBS@ +EXT = @EXT@ + +prefix = @prefix@ +binprefix = +exec_prefix = @exec_prefix@ +bindir = $(exec_prefix)/bin + +#### End of system configuration section. #### + +.SUFFIXES: .so $(SUFFIXES) + +OBJS = dbm.$(EXT) \ + socket.$(EXT) + +all: $(OBJS) + +clean:; @rm -f *.o *.so + +realclean:; @rm -f *.o *.so + @rm -f core ruby *~ Makefile + +.o.so: + ld -o $*.so $*.o + +# Prevent GNU make v3 from overflowing arg limit on SysV. +.NOEXPORT: +### +dbm.o: dbm.c ../ruby.h ../config.h ../defines.h +socket.o: socket.c ../ruby.h ../config.h ../defines.h ../io.h diff --git a/ext/dbm.c b/ext/dbm.c new file mode 100644 index 0000000000..f3e8295d6a --- /dev/null +++ b/ext/dbm.c @@ -0,0 +1,441 @@ +/************************************************ + + dbm.c - + + $Author: matz $ + $Date: 1995/01/10 10:42:24 $ + created at: Mon Jan 24 15:59:52 JST 1994 + + Copyright (C) 1995 Yukihiro Matsumoto + +************************************************/ + +#include "ruby.h" + +#ifdef USE_DBM + +#include <ndbm.h> +#include <fcntl.h> +#include <errno.h> + +VALUE C_DBM; +static ID id_dbm; + +extern VALUE M_Enumerable; + +static void +closeddbm() +{ + Fail("closed DBM file"); +} + +#define GetDBM(obj, dbmp) {\ + DBM **_dbm;\ + Get_Data_Struct(obj, id_dbm, DBM*, _dbm);\ + dbmp = *_dbm;\ + if (dbmp == Qnil) closeddbm();\ +} + +static void +free_dbm(dbmp) + DBM **dbmp; +{ + if (*dbmp) dbm_close(*dbmp); +} + +#define MakeDBM(obj, dp) {\ + DBM **_dbm;\ + if (!id_dbm) id_dbm = rb_intern("dbm");\ + Make_Data_Struct(obj,id_dbm,DBM*,Qnil,free_dbm,_dbm);\ + *_dbm=dp;\ +} + +static VALUE +Sdbm_open(argc, argv, class) + int argc; + VALUE *argv; + VALUE class; +{ + VALUE file, vmode; + DBM *dbm, **dbm2; + int mode; + VALUE obj; + + if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) { + mode = 0666; /* default value */ + } + else if (NIL_P(vmode)) { + mode = -1; /* return nil if DB not exist */ + } + else { + mode = NUM2INT(vmode); + } + Check_Type(file, T_STRING); + + dbm = Qnil; + if (mode >= 0) + dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode); + if (!dbm) + dbm = dbm_open(RSTRING(file)->ptr, O_RDWR, mode); + if (!dbm) + dbm = dbm_open(RSTRING(file)->ptr, O_RDONLY, mode); + + if (!dbm) { + if (mode == -1) return Qnil; + rb_sys_fail(RSTRING(file)->ptr); + } + + obj = obj_alloc(class); + MakeDBM(obj, dbm); + + return obj; +} + +static VALUE +Fdbm_close(obj) + VALUE obj; +{ + DBM **dbmp; + + Get_Data_Struct(obj, id_dbm, DBM*, dbmp); + if (*dbmp == Qnil) Fail("already closed DBM file"); + dbm_close(*dbmp); + *dbmp = Qnil; + + return Qnil; +} + +static VALUE +Fdbm_fetch(obj, keystr) + VALUE obj, keystr; +{ + datum key, value; + DBM *dbm; + + Check_Type(keystr, T_STRING); + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + + GetDBM(obj, dbm); + value = dbm_fetch(dbm, key); + if (value.dptr == Qnil) { + return Qnil; + } + return str_new(value.dptr, value.dsize); +} + +static VALUE +Fdbm_indexes(obj, args) + VALUE obj; + struct RArray *args; +{ + VALUE *p, *pend; + struct RArray *new; + int i = 0; + + if (!args || args->len == 1 && TYPE(args->ptr) != T_ARRAY) { + args = (struct RArray*)rb_to_a(args->ptr[0]); + } + + new = (struct RArray*)ary_new2(args->len); + + p = args->ptr; pend = p + args->len; + while (p < pend) { + new->ptr[i++] = Fdbm_fetch(obj, *p++); + new->len = i; + } + return (VALUE)new; +} + +static VALUE +Fdbm_delete(obj, keystr) + VALUE obj, keystr; +{ + datum key; + DBM *dbm; + + Check_Type(keystr, T_STRING); + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + + GetDBM(obj, dbm); + if (dbm_delete(dbm, key)) { + Fail("dbm_delete failed"); + } + return obj; +} + +static VALUE +Fdbm_shift(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + VALUE keystr, valstr; + + GetDBM(obj, dbm); + + key = dbm_firstkey(dbm); + if (!key.dptr) return Qnil; + val = dbm_fetch(dbm, key); + dbm_delete(dbm, key); + + keystr = str_new(key.dptr, key.dsize); + valstr = str_new(val.dptr, val.dsize); + return assoc_new(keystr, valstr); +} + +static VALUE +Fdbm_delete_if(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + VALUE keystr, valstr; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + keystr = str_new(key.dptr, key.dsize); + valstr = str_new(val.dptr, val.dsize); + if (rb_yield(assoc_new(keystr, valstr)) + && dbm_delete(dbm, key)) { + Fail("dbm_delete failed"); + } + } + return obj; +} + +static VALUE +Fdbm_clear(obj) + VALUE obj; +{ + datum key; + DBM *dbm; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + if (dbm_delete(dbm, key)) { + Fail("dbm_delete failed"); + } + } + return obj; +} + +static VALUE +Fdbm_store(obj, keystr, valstr) + VALUE obj, keystr, valstr; +{ + datum key, val; + DBM *dbm; + + if (valstr == Qnil) { + Fdbm_delete(obj, keystr); + return Qnil; + } + + Check_Type(keystr, T_STRING); + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + Check_Type(valstr, T_STRING); + val.dptr = RSTRING(valstr)->ptr; + val.dsize = RSTRING(valstr)->len; + + GetDBM(obj, dbm); + if (dbm_store(dbm, key, val, DBM_REPLACE)) { + dbm_clearerr(dbm); + if (errno == EPERM) rb_sys_fail(Qnil); + Fail("dbm_store failed"); + } + return valstr; +} + +static VALUE +Fdbm_length(obj) + VALUE obj; +{ + datum key; + DBM *dbm; + int i = 0; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + i++; + } + return INT2FIX(i); +} + +static VALUE +Fdbm_each_value(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + rb_yield(str_new(val.dptr, val.dsize)); + } + return obj; +} + +static VALUE +Fdbm_each_key(obj) + VALUE obj; +{ + datum key; + DBM *dbm; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + rb_yield(str_new(key.dptr, key.dsize)); + } + return obj; +} + +static VALUE +Fdbm_each_pair(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + VALUE keystr, valstr; + + GetDBM(obj, dbm); + + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + keystr = str_new(key.dptr, key.dsize); + valstr = str_new(val.dptr, val.dsize); + rb_yield(assoc_new(keystr, valstr)); + } + + return obj; +} + +static VALUE +Fdbm_keys(obj) + VALUE obj; +{ + datum key; + DBM *dbm; + VALUE ary; + + ary = ary_new(); + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + ary_push(ary, str_new(key.dptr, key.dsize)); + } + + return ary; +} + +static VALUE +Fdbm_values(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + VALUE ary; + + ary = ary_new(); + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + ary_push(ary, str_new(val.dptr, val.dsize)); + } + + return ary; +} + +static VALUE +Fdbm_has_key(obj, keystr) + VALUE obj, keystr; +{ + datum key, val; + DBM *dbm; + + Check_Type(keystr, T_STRING); + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + + GetDBM(obj, dbm); + val = dbm_fetch(dbm, key); + if (val.dptr) return TRUE; + return FALSE; +} + +static VALUE +Fdbm_has_value(obj, valstr) + VALUE obj, valstr; +{ + datum key, val; + DBM *dbm; + + Check_Type(valstr, T_STRING); + val.dptr = RSTRING(valstr)->ptr; + val.dsize = RSTRING(valstr)->len; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + if (val.dsize == RSTRING(valstr)->len && + memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0) + return TRUE; + } + return FALSE; +} + +static VALUE +Fdbm_to_a(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + VALUE ary; + + GetDBM(obj, dbm); + + ary = ary_new(); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + ary_push(ary, assoc_new(str_new(key.dptr, key.dsize), + str_new(val.dptr, val.dsize))); + } + + return ary; +} + +Init_dbm() +{ +#ifdef HAVE_LIBDBM + dln_load_lib("libdbm.a"); +#endif + C_DBM = rb_define_class("DBM", C_Object); + rb_include_module(C_DBM, M_Enumerable); + + rb_define_single_method(C_DBM, "open", Sdbm_open, -1); + rb_define_method(C_DBM, "close", Fdbm_close, 0); + rb_define_method(C_DBM, "[]", Fdbm_fetch, 1); + rb_define_method(C_DBM, "[]=", Fdbm_store, 2); + rb_define_method(C_DBM, "indexes", Fdbm_indexes, -2); + rb_define_method(C_DBM, "length", Fdbm_length, 0); + rb_define_alias(C_DBM, "size", "length"); + rb_define_method(C_DBM, "each", Fdbm_each_pair, 0); + rb_define_method(C_DBM, "each_value", Fdbm_each_value, 0); + rb_define_method(C_DBM, "each_key", Fdbm_each_key, 0); + rb_define_method(C_DBM, "each_pair", Fdbm_each_pair, 0); + rb_define_method(C_DBM, "keys", Fdbm_keys, 0); + rb_define_method(C_DBM, "values", Fdbm_values, 0); + rb_define_method(C_DBM, "shift", Fdbm_shift, 1); + rb_define_method(C_DBM, "delete", Fdbm_delete, 1); + rb_define_method(C_DBM, "delete_if", Fdbm_delete_if, 0); + rb_define_method(C_DBM, "clear", Fdbm_clear, 0); + rb_define_method(C_DBM, "includes", Fdbm_has_key, 1); + rb_define_method(C_DBM, "has_key", Fdbm_has_key, 1); + rb_define_method(C_DBM, "has_value", Fdbm_has_value, 1); + + rb_define_method(C_DBM, "to_a", Fdbm_to_a, 0); +} +#endif /* USE_DBM */ diff --git a/ext/dbm.doc b/ext/dbm.doc new file mode 100644 index 0000000000..48c91a9157 --- /dev/null +++ b/ext/dbm.doc @@ -0,0 +1,107 @@ +.\" dbm.doc - -*- Indented-Text -*- created at: Thu Mar 23 20:28:31 JST 1995 + +** DBM(饹) + +NDBMե륯饹ǡȤʸǤʤФ +ʤȤ¤ȡǡե¸ȤƤ +Dict饹Ʊͤ˰ȤǤ롥NDBMƤʤƥǤ +Υ饹ʤ + +SuperClass: Object + +Included Modules: Enumerable + +Methods: + + self [key] + + keyȤ֤ͤ + + self [key]= value + + keyȤơvalueǼ롥valueȤnilꤹȡ + keyФܤκȤʤ롥 + + clear + + DBMեȤˤ롥 + + close + + DBMե롥ʸ㳰ȯ롥 + + delete(key) + + keyȤȤ롥 + + delete_if + + Ǥ륤ƥ졼key::valueȤڥͿơ֥ + ɾͤλܤ롥 + + each + each_pair + + key::valueʤڥͿ륤ƥ졼 + + each_key + + ƤkeyФƷ֤ƥ졼 + + each_value + + ƤvalueФƷ֤ƥ졼 + + has_key(key) + includes(key) + + keyǡ١¸ߤ֤ + + has_value(value) + + valueͤȤȤǡ١¸ߤ + ֤ + + indexes(ary) + indexes(key-1, ..., key-n) + + 1ܤηǤʸȤƼơǤ + ȤǤޤ֤2ܤηǤϳưͤ + Ǥޤ֤. + + keys + + ǡ١¸ߤ륭Ƥޤ֤ + + length + size + + ǡ١Ǥο֤(:ߤμ¸Ǥǿ + 뤿˥ǡ١Τǡ빽Ȥ⤤ + ĤƻȤ.) + + shift + + ǡ١ǤļФ(ǡ١) + key::valueȤڥ֤ + + to_a + + ǡ١key-valueڥǤȤ֤ + + values + + ǡ١¸ߤƤޤ֤ + +Single Methods: + + open(dbname[, mode]) + + dbnameǻꤷǡ١⡼ɤmodeꤷƥץ + 롥modeξάͤ0666Ǥ롥modeȤnilꤹȥǡ + ١¸ߤʤˤϿ˥ץnil֤ + +------------------------------------------------------- +Local variables: +fill-column: 70 +end: diff --git a/ext/socket.c b/ext/socket.c new file mode 100644 index 0000000000..ec992340a4 --- /dev/null +++ b/ext/socket.c @@ -0,0 +1,761 @@ +/************************************************ + + socket.c - + + $Author: matz $ + $Date: 1995/01/10 10:42:55 $ + created at: Thu Mar 31 12:21:29 JST 1994 + +************************************************/ + +#include "ruby.h" +#ifdef HAVE_SOCKET +#include "io.h" +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <errno.h> +#include <sys/un.h> + +extern VALUE C_IO; +VALUE C_BasicSocket; +VALUE C_TCPsocket; +VALUE C_TCPserver; +VALUE C_UNIXsocket; +VALUE C_UNIXserver; +VALUE C_Socket; + +FILE *rb_fdopen(); +char *strdup(); + +static VALUE +sock_new(class, fd) + VALUE class; + int fd; +{ + VALUE sock = obj_alloc(class); + OpenFile *fp; + + MakeOpenFile(sock, fp); + fp->f = rb_fdopen(fd, "r"); + setbuf(fp->f, NULL); + fp->f2 = rb_fdopen(fd, "w"); + fp->mode = FMODE_READWRITE|FMODE_SYNC; + + return sock; +} + +static VALUE +Fbsock_shutdown(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + VALUE howto; + int how; + OpenFile *fptr; + + rb_scan_args(argc, argv, "01", &howto); + if (howto == Qnil) + how = 2; + else { + how = NUM2INT(howto); + if (how < 0 && how > 2) how = 2; + } + GetOpenFile(sock, fptr); + if (shutdown(fileno(fptr->f), how) == -1) + rb_sys_fail(Qnil); + + return INT2FIX(0); +} + +static VALUE +Fbsock_setopt(sock, lev, optname, val) + VALUE sock, lev, optname; + struct RString *val; +{ + int level, option; + OpenFile *fptr; + + level = NUM2INT(lev); + option = NUM2INT(optname); + Check_Type(val, T_STRING); + + GetOpenFile(sock, fptr); + if (setsockopt(fileno(fptr->f), level, option, val->ptr, val->len) < 0) + rb_sys_fail(fptr->path); + + return INT2FIX(0); +} + +static VALUE +Fbsock_getopt(sock, lev, optname) + VALUE sock, lev, optname; +{ + int level, option, len; + struct RString *val; + OpenFile *fptr; + + level = NUM2INT(lev); + option = NUM2INT(optname); + len = 256; + val = (struct RString*)str_new(0, len); + Check_Type(val, T_STRING); + + GetOpenFile(sock, fptr); + if (getsockopt(fileno(fptr->f), level, option, val->ptr, &len) < 0) + rb_sys_fail(fptr->path); + val->len = len; + return (VALUE)val; +} + +static VALUE +Fbsock_getsockname(sock) + VALUE sock; +{ + char buf[1024]; + int len = sizeof buf; + OpenFile *fptr; + + GetOpenFile(sock, fptr); + if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0) + rb_sys_fail("getsockname(2)"); + return str_new(buf, len); +} + +static VALUE +Fbsock_getpeername(sock) + VALUE sock; +{ + char buf[1024]; + int len = sizeof buf; + OpenFile *fptr; + + GetOpenFile(sock, fptr); + if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0) + rb_sys_fail("getpeername(2)"); + return str_new(buf, len); +} + +static VALUE +open_inet(class, h, serv, server) + VALUE class, h, serv; + int server; +{ + char *host; + struct hostent *hostent, _hostent; + struct servent *servent, _servent; + struct protoent *protoent; + struct sockaddr_in sockaddr; + int fd, status; + int hostaddr, hostaddrPtr[2]; + int servport; + char *syscall; + VALUE sock; + + if (h) { + Check_Type(h, T_STRING); + host = RSTRING(h)->ptr; + hostent = gethostbyname(host); + if (hostent == NULL) { + hostaddr = inet_addr(host); + if (hostaddr == -1) { + if (server && !strlen(host)) + hostaddr = INADDR_ANY; + else + rb_sys_fail(host); + } + _hostent.h_addr_list = (char **)hostaddrPtr; + _hostent.h_addr_list[0] = (char *)&hostaddr; + _hostent.h_addr_list[1] = NULL; + _hostent.h_length = sizeof(hostaddr); + _hostent.h_addrtype = AF_INET; + hostent = &_hostent; + } + } + servent = NULL; + if (FIXNUM_P(serv)) { + servport = FIX2UINT(serv); + goto setup_servent; + } + Check_Type(serv, T_STRING); + servent = getservbyname(RSTRING(serv)->ptr, "tcp"); + if (servent == NULL) { + servport = strtoul(RSTRING(serv)->ptr, Qnil, 0); + if (servport == -1) Fail("no such servce %s", RSTRING(serv)->ptr); + setup_servent: + _servent.s_port = servport; + _servent.s_proto = "tcp"; + servent = &_servent; + } + protoent = getprotobyname(servent->s_proto); + if (protoent == NULL) Fail("no such proto %s", servent->s_proto); + + fd = socket(PF_INET, SOCK_STREAM, protoent->p_proto); + + sockaddr.sin_family = AF_INET; + if (h == Qnil) { + sockaddr.sin_addr.s_addr = INADDR_ANY; + } + else { + memcpy((char *)&(sockaddr.sin_addr.s_addr), + (char *) hostent->h_addr_list[0], + (size_t) hostent->h_length); + } + sockaddr.sin_port = servent->s_port; + + if (server) { + status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); + syscall = "bind(2)"; + } + else { + status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); + syscall = "connect(2)"; + } + + if (status < 0) { + close (fd); + rb_sys_fail(syscall); + } + if (server) listen(fd, 5); + + /* create new instance */ + sock = sock_new(class, fd); + + return sock; +} + +static VALUE +Stcp_sock_open(class, host, serv) + VALUE class, host, serv; +{ + Check_Type(host, T_STRING); + return open_inet(class, host, serv, 0); +} + +static VALUE +Stcp_svr_open(argc, argv, class) + int argc; + VALUE *argv; + VALUE class; +{ + VALUE arg1, arg2; + + if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) + return open_inet(class, arg1, arg2, 1); + else + return open_inet(class, Qnil, arg1, 1); +} + +static VALUE +sock_accept(class, fd, sockaddr, len) + VALUE class; + int fd; + struct sockaddr *sockaddr; + int *len; +{ + int fd2; + + retry: + fd2 = accept(fd, sockaddr, len); + if (fd2 < 0) { + if (errno == EINTR) goto retry; + rb_sys_fail(Qnil); + } + return sock_new(class, fd2); +} + +static VALUE +Ftcp_accept(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_in from; + int fromlen; + + GetOpenFile(sock, fptr); + fromlen = sizeof(struct sockaddr_in); + return sock_accept(C_TCPsocket, fileno(fptr->f), + (struct sockaddr*)&from, &fromlen); +} + +static VALUE +open_unix(class, path, server) + VALUE class; + struct RString *path; + int server; +{ + struct sockaddr_un sockaddr; + int fd, status; + char *syscall; + VALUE sock; + OpenFile *fptr; + + Check_Type(path, T_STRING); + fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) rb_sys_fail("socket(2)"); + + sockaddr.sun_family = AF_UNIX; + strncpy(sockaddr.sun_path, path->ptr, sizeof(sockaddr.sun_path)-1); + sockaddr.sun_path[sizeof(sockaddr.sun_path)-1] = '\0'; + + if (server) { + status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); + syscall = "bind(2)"; + } + else { + status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); + syscall = "connect(2)"; + } + + if (status < 0) { + close (fd); + rb_sys_fail(syscall); + } + + if (server) listen(fd, 5); + + sock = sock_new(class, fd); + GetOpenFile(sock, fptr); + fptr->path = strdup(path->ptr); + + return sock; +} + +static VALUE +tcp_addr(sockaddr) + struct sockaddr_in *sockaddr; +{ + VALUE family, port, addr; + VALUE ary; + struct hostent *hostent; + + family = str_new2("AF_INET"); + hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr, + sizeof(sockaddr->sin_addr), + AF_INET); + if (hostent) { + addr = str_new2(hostent->h_name); + } + else { + char buf[16]; + char *a = (char*)&sockaddr->sin_addr; + sprintf(buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); + addr = str_new2(buf); + } + port = INT2FIX(sockaddr->sin_port); + ary = ary_new3(3, family, port, addr); + + return ary; +} + +static VALUE +Ftcp_addr(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_in addr; + int len = sizeof addr; + + GetOpenFile(sock, fptr); + + if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + rb_sys_fail("getsockname(2)"); + return tcp_addr(&addr); +} + +static VALUE +Ftcp_peeraddr(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_in addr; + int len = sizeof addr; + + GetOpenFile(sock, fptr); + + if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + rb_sys_fail("getsockname(2)"); + return tcp_addr(&addr); +} + +static VALUE +Sunix_sock_open(sock, path) + VALUE sock, path; +{ + return open_unix(sock, path, 0); +} + +static VALUE +Funix_path(sock) + VALUE sock; +{ + OpenFile *fptr; + + GetOpenFile(sock, fptr); + if (fptr->path == Qnil) { + struct sockaddr_un addr; + int len = sizeof(addr); + if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + rb_sys_fail(Qnil); + fptr->path = strdup(addr.sun_path); + } + return str_new2(fptr->path); +} + +static VALUE +Sunix_svr_open(class, path) + VALUE class, path; +{ + return open_unix(class, path, 1); +} + +static VALUE +Funix_accept(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_un from; + int fromlen; + + GetOpenFile(sock, fptr); + fromlen = sizeof(struct sockaddr_un); + return sock_accept(C_UNIXsocket, fileno(fptr->f), + (struct sockaddr*)&from, &fromlen); +} + +static VALUE +unix_addr(sockaddr) + struct sockaddr_un *sockaddr; +{ + return assoc_new(str_new2("AF_UNIX"),str_new2(sockaddr->sun_path)); +} + +static VALUE +Funix_addr(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_un addr; + int len = sizeof addr; + + GetOpenFile(sock, fptr); + + if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + rb_sys_fail("getsockname(2)"); + return unix_addr(&addr); +} + +static VALUE +Funix_peeraddr(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_un addr; + int len = sizeof addr; + + GetOpenFile(sock, fptr); + + if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + rb_sys_fail("getsockname(2)"); + return unix_addr(&addr); +} + +static void +setup_domain_and_type(domain, dv, type, tv) + VALUE domain, type; + int *dv, *tv; +{ + char *ptr; + + if (TYPE(domain) == T_STRING) { + ptr = RSTRING(domain)->ptr; + if (strcmp(ptr, "PF_UNIX") == 0) + *dv = PF_UNIX; + else if (strcmp(ptr, "PF_INET") == 0) + *dv = PF_INET; +#ifdef PF_IMPLINK + else if (strcmp(ptr, "PF_IMPLINK") == 0) + *dv = PF_IMPLINK; +#endif +#ifdef PF_AX25 + else if (strcmp(ptr, "PF_AX25") == 0) + *dv = PF_AX25; +#endif +#ifdef PF_IPX + else if (strcmp(ptr, "PF_IPX") == 0) + *dv = PF_IPX; +#endif + else + Fail("Unknown socket domain %s", ptr); + } + else { + *dv = NUM2INT(domain); + } + if (TYPE(type) == T_STRING) { + ptr = RSTRING(type)->ptr; + if (strcmp(ptr, "SOCK_STREAM") == 0) + *tv = SOCK_STREAM; + else if (strcmp(ptr, "SOCK_DGRAM") == 0) + *tv = SOCK_DGRAM; +#ifdef SOCK_RAW + else if (strcmp(ptr, "SOCK_RAW") == 0) + *tv = SOCK_RAW; +#endif +#ifdef SOCK_SEQPACKET + else if (strcmp(ptr, "SOCK_SEQPACKET") == 0) + *tv = SOCK_SEQPACKET; +#endif +#ifdef SOCK_RDM + else if (strcmp(ptr, "SOCK_RDM") == 0) + *tv = SOCK_RDM; +#endif +#ifdef SOCK_PACKET + else if (strcmp(ptr, "SOCK_PACKET") == 0) + *tv = SOCK_PACKET; +#endif + else + Fail("Unknown socket type %s", ptr); + } + else { + *tv = NUM2INT(type); + } +} + +static VALUE +Ssock_open(class, domain, type, protocol) + VALUE class, domain, type, protocol; +{ + int fd; + int d, t; + + setup_domain_and_type(domain, &d, type, &t); + fd = socket(d, t, NUM2INT(protocol)); + if (fd < 0) rb_sys_fail("socke(2)"); + return sock_new(class, fd); +} + +static VALUE +Ssock_for_fd(class, fd) + VALUE class, fd; +{ + return sock_new(class, NUM2INT(fd)); +} + +static VALUE +Ssock_socketpair(class, domain, type, protocol) + VALUE class, domain, type, protocol; +{ + int fd; + int d, t, sp[2]; + + setup_domain_and_type(domain, &d, type, &t); + if (socketpair(d, t, NUM2INT(protocol), sp) < 0) + rb_sys_fail("socketpair(2)"); + + return assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1])); +} + +static VALUE +Fsock_connect(sock, addr) + VALUE sock; + struct RString *addr; +{ + OpenFile *fptr; + + Check_Type(addr, T_STRING); + str_modify(addr); + + GetOpenFile(sock, fptr); + if (connect(fileno(fptr->f), (struct sockaddr*)addr->ptr, addr->len) < 0) + rb_sys_fail("connect(2)"); + + return INT2FIX(0); +} + +static VALUE +Fsock_bind(sock, addr) + VALUE sock; + struct RString *addr; +{ + OpenFile *fptr; + + Check_Type(addr, T_STRING); + str_modify(addr); + + GetOpenFile(sock, fptr); + if (bind(fileno(fptr->f), (struct sockaddr*)addr->ptr, addr->len) < 0) + rb_sys_fail("bind(2)"); + + return INT2FIX(0); +} + +static VALUE +Fsock_listen(sock, log) + VALUE sock, log; +{ + OpenFile *fptr; + + GetOpenFile(sock, fptr); + if (listen(fileno(fptr->f), NUM2INT(log)) < 0) + rb_sys_fail("listen(2)"); + + return INT2FIX(0); +} + +static VALUE +Fsock_accept(sock) + VALUE sock; +{ + OpenFile *fptr; + VALUE addr, sock2; + char buf[1024]; + int len = sizeof buf; + + GetOpenFile(sock, fptr); + sock2 = sock_accept(C_Socket,fileno(fptr->f),(struct sockaddr*)buf,&len); + + return assoc_new(sock2, str_new(buf, len)); +} + +static VALUE +Fsock_send(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + struct RString *msg, *to; + VALUE flags; + OpenFile *fptr; + FILE *f; + int fd, n; + + rb_scan_args(argc, argv, "21", &msg, &flags, &to); + + Check_Type(msg, T_STRING); + + GetOpenFile(sock, fptr); + f = fptr->f2?fptr->f2:fptr->f; + fd = fileno(f); + if (to) { + Check_Type(to, T_STRING); + n = sendto(fd, msg->ptr, msg->len, NUM2INT(flags), + (struct sockaddr*)to->ptr, to->len); + } + else { + n = send(fd, msg->ptr, msg->len, NUM2INT(flags)); + } + if (n < 0) { + rb_sys_fail("send(2)"); + } + return INT2FIX(n); +} + +static VALUE +sock_recv(sock, argc, argv, from) + VALUE sock; + int argc; + VALUE *argv; + int from; +{ + OpenFile *fptr; + FILE f; + struct RString *str; + char buf[1024]; + int fd, alen = sizeof buf; + VALUE len, flg; + int flags; + + rb_scan_args(argc, argv, "11", &len, &flg); + + if (flg == Qnil) flags = 0; + else flags = NUM2INT(flg); + + str = (struct RString*)str_new(0, NUM2INT(len)); + + GetOpenFile(sock, fptr); + fd = fileno(fptr->f); + if ((str->len = recvfrom(fd, str->ptr, str->len, flags, + (struct sockaddr*)buf, &alen)) < 0) { + rb_sys_fail("recvfrom(2)"); + } + + if (from) + return assoc_new(str, str_new(buf, alen)); + else + return (VALUE)str; +} + +static VALUE +Fsock_recv(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + return sock_recv(sock, argc, argv, 0); +} + +static VALUE +Fsock_recvfrom(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + return sock_recv(sock, argc, argv, 1); +} + +Init_socket () +{ +#ifdef HAVE_LIBSOCKET + dln_load_lib("libsocket.a"); +#endif + C_BasicSocket = rb_define_class("BasicSocket", C_IO); + rb_undef_method(C_BasicSocket, "new"); + rb_define_method(C_BasicSocket, "shutdown", Fbsock_shutdown, -1); + rb_define_method(C_BasicSocket, "setopt", Fbsock_setopt, 3); + rb_define_method(C_BasicSocket, "getopt", Fbsock_getopt, 2); + rb_define_method(C_BasicSocket, "getsockname", Fbsock_getsockname, 0); + rb_define_method(C_BasicSocket, "getpeername", Fbsock_getpeername, 0); + + C_TCPsocket = rb_define_class("TCPsocket", C_BasicSocket); + rb_define_single_method(C_TCPsocket, "open", Stcp_sock_open, 2); + rb_define_single_method(C_TCPsocket, "new", Stcp_sock_open, 2); + rb_define_method(C_TCPsocket, "addr", Ftcp_addr, 0); + rb_define_method(C_TCPsocket, "peeraddr", Ftcp_peeraddr, 0); + + C_TCPserver = rb_define_class("TCPserver", C_TCPsocket); + rb_define_single_method(C_TCPserver, "open", Stcp_svr_open, -1); + rb_define_single_method(C_TCPserver, "new", Stcp_svr_open, -1); + rb_define_method(C_TCPserver, "accept", Ftcp_accept, 0); + + C_UNIXsocket = rb_define_class("UNIXsocket", C_BasicSocket); + rb_define_single_method(C_UNIXsocket, "open", Sunix_sock_open, 1); + rb_define_single_method(C_UNIXsocket, "new", Sunix_sock_open, 1); + rb_define_method(C_UNIXsocket, "path", Funix_path, 0); + rb_define_method(C_UNIXsocket, "addr", Funix_addr, 0); + rb_define_method(C_UNIXsocket, "peeraddr", Funix_peeraddr, 0); + + C_UNIXserver = rb_define_class("UNIXserver", C_UNIXsocket); + rb_define_single_method(C_UNIXserver, "open", Sunix_svr_open, 1); + rb_define_single_method(C_UNIXserver, "new", Sunix_svr_open, 1); + rb_define_method(C_UNIXserver, "accept", Funix_accept, 0); + + C_Socket = rb_define_class("Socket", C_BasicSocket); + rb_define_single_method(C_Socket, "open", Ssock_open, 3); + rb_define_single_method(C_Socket, "new", Ssock_open, 3); + rb_define_single_method(C_Socket, "for_fd", Ssock_for_fd, 1); + + rb_define_method(C_Socket, "connect", Fsock_connect, 1); + rb_define_method(C_Socket, "bind", Fsock_bind, 1); + rb_define_method(C_Socket, "listen", Fsock_listen, 1); + rb_define_method(C_Socket, "accept", Fsock_accept, 0); + + rb_define_method(C_Socket, "send", Fsock_send, -1); + rb_define_method(C_Socket, "recv", Fsock_recv, -1); + rb_define_method(C_Socket, "recvfrom", Fsock_recv, -1); + + rb_define_single_method(C_Socket, "socketpair", Ssock_socketpair, 3); +} +#endif /* HAVE_SOCKET */ diff --git a/ext/socket.doc b/ext/socket.doc new file mode 100644 index 0000000000..aa5bfedbff --- /dev/null +++ b/ext/socket.doc @@ -0,0 +1,227 @@ +.\" socket.doc - -*- Indented-Text -*- created at: Thu Mar 23 20:29:02 JST 1995 + +** Socket(饹) + +SuperClass: BasicSocket + +åȤΤΤФ륷ƥॳ٥Υ륯饹 +PerlΥåȤФ륢Ʊ٥εǽƤ롥Υ +Ǥϥåȥɥ쥹pack줿ʸǡꤹ롥UDPåȤϤ +Υ饹ȤäѤ롥 + +Methods: + + accept + + ³դơ³Ф륽åȤȥɥ쥹 + ڥ֤accept(2)ȡ + + bind(addr) + + bind(2)ƱƯ롥addrpack줿åȥɥ쥹¤ + ΤǤ롥 + + connect(addr) + + connect(2)ƱƯ롥addrpack줿åȥɥ쥹 + ¤ΤǤ롥 + + listen(backlog) + + listen(2)ƱƯ롥 + + recv(len[, flags]) + + åȤǡꡤʸȤ֤lenϼ + Ĺꤹ롥flagsˤĤƤrecv(2)ȡflagsΥ + եͤ0Ǥ롥 + + recvfrom(len[, flags]) + + recvƱͤ˥åȤǡ뤬ͤʸ + åȤΥɥ쥹ΥڥǤ롥ˤĤƤrecvƱ͡ + + send(mesg, flags[, to]) + + åȤ𤷤ƥǡ롥flags˴ؤƤsend(2)Ȥλ + connectƤʤåȤФƤǤtoꤹɬ + פ롥ºݤäǡĹ֤ + +Single Methods: + + open(domain, type, protocol) + new(domain, type, protocol) + + åȤ롥domaintypeprotocolϥ롼 + եƤͤǻꤹ롥domaintype˴ؤ + ϡʸǻǤ뤬٤ƤСƤݾڤϤʤ + + socketpair(domain, type, protocol) + + åȤΥڥ֤λ openƱǤ롥 + +** BasicSocket(饹) + +åȤɽݥ饹Ūʥåϥ֥饹롥 +㤨ХͥåȥɥᥤξTCPsocketѤ롥 + +SuperClass: IO + +Methods: + + getopt(level, optname) + + åȤΥץ롥getsockopt(2)ȤΤȡ + ץƤޤʸ֤ + + getpeername + + ³ΥåȤξ롥ѥå줿sockaddr¤ + ٥˥פʸ֤롥getpeername(2)ȤΤȡ + + getsockname + + åȤξ롥ѥå줿sockaddr¤Τ٥˥ + ʸ֤롥getsockname(2)ȤΤȡ + + setopt(level, optname, optval) + + åȤΥץꤹ롥setsockopt(2)ȤΤȡ + + shutdown(how) + + åȤΰʹߤ³λ롥how0Ǥʹߤμ + how1Ǥϡʹߤݤ롥how2λˤϡ + ʹߤȤ˵ݤ롥shutdown(2)ȡ + +** TCPserver(饹) + +TCP/IPȥ³Υ¦ΥåȤΥ饹Υ饹ˤä +ñ˥åȤѤФΥץߥǤ롥㤨echo +ФϰʲΤ褦ˤʤ롥 + + gs = TCPserver.open(4444) + socks = [gs] + + while TRUE + nsock = select(socks); + if nsock == nil; continue end + for s in nsock[0] + if s == gs + socks.push(s.accept) + else + if s.eof + s.close + socks.delete(s) + else + str = s.gets + s.write(str) + end + end + end + end + +SuperClass: TCPsocket + +Methods: + + accept + + 饤Ȥ³դ³TCPsocketΥ + ֤ + +Single Methods: + + new([host, ]service) + open([host, ]service) + + service/etc/services(ޤNIS)ϿƤ륵ӥ̾ + ݡֹǻꤹ롥hostꤷϻꤷۥȤ + ³դ롥άƤΥۥȤ³ + 롥 + +** TCPsocket + +ͥåȥɥᥤΥȥåȤΥ饹̾IO饹 +֥饹ƱͤϤǤ롥Υ饹ˤäƥåȤѤ +饤Ȥñ˵ҤǤ롥桼ϤΤޤޥФž +ϰʲΤ褦ˤʤ롥 + + s = TCPsocket("localhost", 4444) + while gets() + s.write($_) + print(s.read) + end + +SuperClass: BasicSocket + +Methods: + + addr + + åȤ³ɽ֤γǤ1 + ʸ "AF_INET"2Ǥportֹ桤3ǤۥȤɽʸ + Ǥ롥 + + peeraddr + + ³襽åȤξɽ֤γǤ + addråɤ֤ƱǤ롥 + +Single Methods: + + open(host, service) + new(host, service) + + hostǻꤷۥȤserviceǻꤷݡȤ³ + Ȥ֤hostϥۥ̾ޤϥͥåȥɥ쥹ʸ + service/etc/services(ޤNIS)ϿƤ륵 + ̾ݡֹǤ롥 + +** UNIXserver + +UNIXȥ³Υ¦ΥåȤΥ饹 + +SuperClass: UNIXsocket + +Methods: + + accept + + 饤Ȥ³դ³UNIXsocketΥ + ֤ + +** UNIXsocket + +UNIXɥᥤΥȥåȤΥ饹̾IO饹Υ֥饹 +ƱͤϤǤ롥 + +SuperClass: BasicSocket + +Methods: + + addr + + åȤ³ɽ֤γǤ1 + ʸ "AF_UNIX"2ǤpathǤ롥 + + path + + UNIXåȤΥѥ֤ + + peeraddr + + ³襽åȤξɽ֤γǤ + addråɤ֤ƱǤ롥 + +Single Methods: + + open(path) + new(path) + + pathǻꤷѥ̾Ѥ³åȤ֤ + +------------------------------------------------------- +Local variables: +fill-column: 70 +end: |