Made struct a standard built-in module; added string args to {set,get}sockopt;
added gl.gversion().
diff --git a/Modules/config.c.in b/Modules/config.c.in
index 4103075..ef1cb58 100644
--- a/Modules/config.c.in
+++ b/Modules/config.c.in
@@ -27,12 +27,13 @@
 /* These modules are normally always included, but *may* be taken out */
 #define USE_GRP		1	/* Use together with pwd */
 #define USE_MARSHAL	1	/* This is linked anyway */
+#define USE_MATH	1
 #define USE_PWD		1	/* Use together with grp */
 #define USE_POSIX	1
 #define USE_SELECT	1
 #define USE_SOCKET	1
+#define USE_STRUCT	1
 #define USE_TIME	1
-#define USE_MATH	1
 
 #include "PROTO.h"
 #include "mymalloc.h"
@@ -318,7 +319,7 @@
 	{"stdwin",	initstdwin},
 #endif
 
-#ifdef USE_STRUCT
+#ifdef USE_STROP
 	{"strop",	initstrop},
 #endif
 
diff --git a/Modules/cstubs b/Modules/cstubs
index 76feb6a..6ff8f54 100644
--- a/Modules/cstubs
+++ b/Modules/cstubs
@@ -801,6 +801,18 @@
 	return unpacked;
 }
 
+% gversion
+static object *
+gl_gversion(self, args)
+	object *self;
+	object *args;
+{
+	char buf[20];
+	gversion(buf);
+	return newstringobject(buf);
+}
+
+
 /* End of manually written stubs */
 
 %%
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index ab8c6b5..b1ab96d 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -384,8 +384,10 @@
 }
 
 
-/* s.setsockopt() method */
-/* XXX this works for integer flags only */
+/* s.setsockopt() method.
+   With an integer third argument, sets an integer option.
+   With a string third argument, sets an option from a buffer;
+   use optional built-in module 'struct' to encode the string. */
 
 static object *
 sock_setsockopt(s, args)
@@ -394,12 +396,21 @@
 {
 	int level;
 	int optname;
-	int flag;
 	int res;
+	char *buf;
+	int buflen;
+	int flag;
 
-	if (!getargs(args, "(iii)", &level, &optname, &flag))
-		return NULL;
-	res = setsockopt(s->sock_fd, level, optname, &flag, sizeof flag);
+	if (getargs(args, "(iii)", &level, &optname, &flag)) {
+		buf = (char *) &flag;
+		buflen = sizeof flag;
+	}
+	else {
+		err_clear();
+		if (!getargs(args, "(iis#)", &level, &optname, &buf, &buflen))
+			return NULL;
+	}
+	res = setsockopt(s->sock_fd, level, optname, buf, buflen);
 	if (res < 0)
 		return socket_error();
 	INCREF(None);
@@ -407,8 +418,10 @@
 }
 
 
-/* s.getsockopt() method */
-/* XXX this works for integer flags only */
+/* s.getsockopt() method.
+   With two arguments, retrieves an integer option.
+   With a third integer argument, retrieves a string buffer of that size;
+   use optional built-in module 'struct' to decode the string. */
 
 static object *
 sock_getsockopt(s, args)
@@ -417,18 +430,37 @@
 {
 	int level;
 	int optname;
-	int flag;
-	int flagsize;
 	int res;
+	object *buf;
+	int buflen;
+	int flag;
 
-	if (!getargs(args, "(ii)", &level, &optname))
+	if (getargs(args, "(ii)", &level, &optname)) {
+		int flag = 0;
+		int flagsize = sizeof flag;
+		res = getsockopt(s->sock_fd, level, optname, &flag, &flagsize);
+		if (res < 0)
+			return socket_error();
+		return newintobject(flag);
+	}
+	err_clear();
+	if (!getargs(args, "(iii)", &level, &optname, &buflen))
 		return NULL;
-	flagsize = sizeof flag;
-	flag = 0;
-	res = getsockopt(s->sock_fd, level, optname, &flag, &flagsize);
-	if (res < 0)
+	if (buflen <= 0 || buflen > 1024) {
+		err_setstr(SocketError, "getsockopt buflen out of range");
+		return NULL;
+	}
+	buf = newsizedstringobject((char *)NULL, buflen);
+	if (buf == NULL)
+		return NULL;
+	res = getsockopt(s->sock_fd, level, optname, getstringvalue(buf),
+			 &buflen);
+	if (res < 0) {
+		DECREF(buf);
 		return socket_error();
-	return newintobject(flag);
+	}
+	resizestring(&buf, buflen);
+	return buf;
 }