symbian-qemu-0.9.1-12/python-2.6.1/Demo/pysvr/pysvr.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /* A multi-threaded telnet-like server that gives a Python prompt.
       
     2 
       
     3 Usage: pysvr [port]
       
     4 
       
     5 For security reasons, it only accepts requests from the current host.
       
     6 This can still be insecure, but restricts violations from people who
       
     7 can log in on your machine.  Use with caution!
       
     8 
       
     9 */
       
    10 
       
    11 #include <stdio.h>
       
    12 #include <stdlib.h>
       
    13 #include <string.h>
       
    14 #include <ctype.h>
       
    15 #include <errno.h>
       
    16 
       
    17 #include <sys/types.h>
       
    18 #include <sys/socket.h>
       
    19 #include <netinet/in.h>
       
    20 
       
    21 #include <pthread.h>
       
    22 #include <getopt.h>
       
    23 
       
    24 /* XXX Umpfh.
       
    25    Python.h defines a typedef destructor, which conflicts with pthread.h.
       
    26    So Python.h must be included after pthread.h. */
       
    27 
       
    28 #include "Python.h"
       
    29 
       
    30 extern int Py_VerboseFlag;
       
    31 
       
    32 #ifndef PORT
       
    33 #define PORT 4000
       
    34 #endif
       
    35 
       
    36 struct workorder {
       
    37 	int conn;
       
    38 	struct sockaddr_in addr;
       
    39 };
       
    40 
       
    41 /* Forward */
       
    42 static void init_python(void);
       
    43 static void usage(void);
       
    44 static void oprogname(void);
       
    45 static void main_thread(int);
       
    46 static void create_thread(int, struct sockaddr_in *);
       
    47 static void *service_thread(struct workorder *);
       
    48 static void run_interpreter(FILE *, FILE *);
       
    49 static int run_command(char *, PyObject *);
       
    50 static void ps(void);
       
    51 
       
    52 static char *progname = "pysvr";
       
    53 
       
    54 static PyThreadState *gtstate;
       
    55 
       
    56 main(int argc, char **argv)
       
    57 {
       
    58 	int port = PORT;
       
    59 	int c;
       
    60 
       
    61 	if (argc > 0 && argv[0] != NULL && argv[0][0] != '\0')
       
    62 		progname = argv[0];
       
    63 
       
    64 	while ((c = getopt(argc, argv, "v")) != EOF) {
       
    65 		switch (c) {
       
    66 		case 'v':
       
    67 			Py_VerboseFlag++;
       
    68 			break;
       
    69 		default:
       
    70 			usage();
       
    71 		}
       
    72 	}
       
    73 
       
    74 	if (optind < argc) {
       
    75 		if (optind+1 < argc) {
       
    76 			oprogname();
       
    77 			fprintf(stderr, "too many arguments\n");
       
    78 			usage();
       
    79 		}
       
    80 		port = atoi(argv[optind]);
       
    81 		if (port <= 0) {
       
    82 			fprintf(stderr, "bad port (%s)\n", argv[optind]);
       
    83 			usage();
       
    84 		}
       
    85 	}
       
    86 
       
    87 	main_thread(port);
       
    88 
       
    89 	fprintf(stderr, "Bye.\n");
       
    90 
       
    91 	exit(0);
       
    92 }
       
    93 
       
    94 static char usage_line[] = "usage: %s [port]\n";
       
    95 
       
    96 static void
       
    97 usage(void)
       
    98 {
       
    99 	fprintf(stderr, usage_line, progname);
       
   100 	exit(2);
       
   101 }
       
   102 
       
   103 static void
       
   104 main_thread(int port)
       
   105 {
       
   106 	int sock, conn, size, i;
       
   107 	struct sockaddr_in addr, clientaddr;
       
   108 
       
   109 	sock = socket(PF_INET, SOCK_STREAM, 0);
       
   110 	if (sock < 0) {
       
   111 		oprogname();
       
   112 		perror("can't create socket");
       
   113 		exit(1);
       
   114 	}
       
   115 
       
   116 #ifdef SO_REUSEADDR
       
   117 	i = 1;
       
   118 	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof i);
       
   119 #endif
       
   120 
       
   121 	memset((char *)&addr, '\0', sizeof addr);
       
   122 	addr.sin_family = AF_INET;
       
   123 	addr.sin_port = htons(port);
       
   124 	addr.sin_addr.s_addr = 0L;
       
   125 	if (bind(sock, (struct sockaddr *)&addr, sizeof addr) < 0) {
       
   126 		oprogname();
       
   127 		perror("can't bind socket to address");
       
   128 		exit(1);
       
   129 	}
       
   130 
       
   131 	if (listen(sock, 5) < 0) {
       
   132 		oprogname();
       
   133 		perror("can't listen on socket");
       
   134 		exit(1);
       
   135 	}
       
   136 
       
   137 	fprintf(stderr, "Listening on port %d...\n", port);
       
   138 
       
   139 	for (i = 0; ; i++) {
       
   140 		size = sizeof clientaddr;
       
   141 		memset((char *) &clientaddr, '\0', size);
       
   142 		conn = accept(sock, (struct sockaddr *) &clientaddr, &size);
       
   143 		if (conn < 0) {
       
   144 			oprogname();
       
   145 			perror("can't accept connection from socket");
       
   146 			exit(1);
       
   147 		}
       
   148 
       
   149 		size = sizeof addr;
       
   150 		memset((char *) &addr, '\0', size);
       
   151 		if (getsockname(conn, (struct sockaddr *)&addr, &size) < 0) {
       
   152 			oprogname();
       
   153 			perror("can't get socket name of connection");
       
   154 			exit(1);
       
   155 		}
       
   156 		if (clientaddr.sin_addr.s_addr != addr.sin_addr.s_addr) {
       
   157 			oprogname();
       
   158 			perror("connection from non-local host refused");
       
   159 			fprintf(stderr, "(addr=%lx, clientaddr=%lx)\n",
       
   160 				ntohl(addr.sin_addr.s_addr),
       
   161 				ntohl(clientaddr.sin_addr.s_addr));
       
   162 			close(conn);
       
   163 			continue;
       
   164 		}
       
   165 		if (i == 4) {
       
   166 			close(conn);
       
   167 			break;
       
   168 		}
       
   169 		create_thread(conn, &clientaddr);
       
   170 	}
       
   171 
       
   172 	close(sock);
       
   173 
       
   174 	if (gtstate) {
       
   175 		PyEval_AcquireThread(gtstate);
       
   176 		gtstate = NULL;
       
   177 		Py_Finalize();
       
   178 		/* And a second time, just because we can. */
       
   179 		Py_Finalize(); /* This should be harmless. */
       
   180 	}
       
   181 	exit(0);
       
   182 }
       
   183 
       
   184 static void
       
   185 create_thread(int conn, struct sockaddr_in *addr)
       
   186 {
       
   187 	struct workorder *work;
       
   188 	pthread_t tdata;
       
   189 
       
   190 	work = malloc(sizeof(struct workorder));
       
   191 	if (work == NULL) {
       
   192 		oprogname();
       
   193 		fprintf(stderr, "out of memory for thread.\n");
       
   194 		close(conn);
       
   195 		return;
       
   196 	}
       
   197 	work->conn = conn;
       
   198 	work->addr = *addr;
       
   199 
       
   200 	init_python();
       
   201 
       
   202 	if (pthread_create(&tdata, NULL, (void *)service_thread, work) < 0) {
       
   203 		oprogname();
       
   204 		perror("can't create new thread");
       
   205 		close(conn);
       
   206 		return;
       
   207 	}
       
   208 
       
   209 	if (pthread_detach(tdata) < 0) {
       
   210 		oprogname();
       
   211 		perror("can't detach from thread");
       
   212 	}
       
   213 }
       
   214 
       
   215 static PyThreadState *the_tstate;
       
   216 static PyInterpreterState *the_interp;
       
   217 static PyObject *the_builtins;
       
   218 
       
   219 static void
       
   220 init_python(void)
       
   221 {
       
   222 	if (gtstate)
       
   223 		return;
       
   224 	Py_Initialize(); /* Initialize the interpreter */
       
   225 	PyEval_InitThreads(); /* Create (and acquire) the interpreter lock */
       
   226 	gtstate = PyEval_SaveThread(); /* Release the thread state */
       
   227 }
       
   228 
       
   229 static void *
       
   230 service_thread(struct workorder *work)
       
   231 {
       
   232 	FILE *input, *output;
       
   233 
       
   234 	fprintf(stderr, "Start thread for connection %d.\n", work->conn);
       
   235 
       
   236 	ps();
       
   237 
       
   238 	input = fdopen(work->conn, "r");
       
   239 	if (input == NULL) {
       
   240 		oprogname();
       
   241 		perror("can't create input stream");
       
   242 		goto done;
       
   243 	}
       
   244 
       
   245 	output = fdopen(work->conn, "w");
       
   246 	if (output == NULL) {
       
   247 		oprogname();
       
   248 		perror("can't create output stream");
       
   249 		fclose(input);
       
   250 		goto done;
       
   251 	}
       
   252 
       
   253 	setvbuf(input, NULL, _IONBF, 0);
       
   254 	setvbuf(output, NULL, _IONBF, 0);
       
   255 
       
   256 	run_interpreter(input, output);
       
   257 
       
   258 	fclose(input);
       
   259 	fclose(output);
       
   260 
       
   261   done:
       
   262 	fprintf(stderr, "End thread for connection %d.\n", work->conn);
       
   263 	close(work->conn);
       
   264 	free(work);
       
   265 }
       
   266 
       
   267 static void
       
   268 oprogname(void)
       
   269 {
       
   270 	int save = errno;
       
   271 	fprintf(stderr, "%s: ", progname);
       
   272 	errno = save;
       
   273 }
       
   274 
       
   275 static void
       
   276 run_interpreter(FILE *input, FILE *output)
       
   277 {
       
   278 	PyThreadState *tstate;
       
   279 	PyObject *new_stdin, *new_stdout;
       
   280 	PyObject *mainmod, *globals;
       
   281 	char buffer[1000];
       
   282 	char *p, *q;
       
   283 	int n, end;
       
   284 
       
   285 	PyEval_AcquireLock();
       
   286 	tstate = Py_NewInterpreter();
       
   287 	if (tstate == NULL) {
       
   288 		fprintf(output, "Sorry -- can't create an interpreter\n");
       
   289 		return;
       
   290 	}
       
   291 
       
   292 	mainmod = PyImport_AddModule("__main__");
       
   293 	globals = PyModule_GetDict(mainmod);
       
   294 	Py_INCREF(globals);
       
   295 
       
   296 	new_stdin = PyFile_FromFile(input, "<socket-in>", "r", NULL);
       
   297 	new_stdout = PyFile_FromFile(output, "<socket-out>", "w", NULL);
       
   298 
       
   299 	PySys_SetObject("stdin", new_stdin);
       
   300 	PySys_SetObject("stdout", new_stdout);
       
   301 	PySys_SetObject("stderr", new_stdout);
       
   302 
       
   303 	for (n = 1; !PyErr_Occurred(); n++) {
       
   304 		Py_BEGIN_ALLOW_THREADS
       
   305 		fprintf(output, "%d> ", n);
       
   306 		p = fgets(buffer, sizeof buffer, input);
       
   307 		Py_END_ALLOW_THREADS
       
   308 
       
   309 		if (p == NULL)
       
   310 			break;
       
   311 		if (p[0] == '\377' && p[1] == '\354')
       
   312 			break;
       
   313 
       
   314 		q = strrchr(p, '\r');
       
   315 		if (q && q[1] == '\n' && q[2] == '\0') {
       
   316 			*q++ = '\n';
       
   317 			*q++ = '\0';
       
   318 		}
       
   319 
       
   320 		while (*p && isspace(*p))
       
   321 			p++;
       
   322 		if (p[0] == '#' || p[0] == '\0')
       
   323 			continue;
       
   324 
       
   325 		end = run_command(buffer, globals);
       
   326 		if (end < 0)
       
   327 			PyErr_Print();
       
   328 
       
   329 		if (end)
       
   330 			break;
       
   331 	}
       
   332 
       
   333 	Py_XDECREF(globals);
       
   334 	Py_XDECREF(new_stdin);
       
   335 	Py_XDECREF(new_stdout);
       
   336 
       
   337 	Py_EndInterpreter(tstate);
       
   338 	PyEval_ReleaseLock();
       
   339 
       
   340 	fprintf(output, "Goodbye!\n");
       
   341 }
       
   342 
       
   343 static int
       
   344 run_command(char *buffer, PyObject *globals)
       
   345 {
       
   346 	PyObject *m, *d, *v;
       
   347 	fprintf(stderr, "run_command: %s", buffer);
       
   348 	if (strchr(buffer, '\n') == NULL)
       
   349 		fprintf(stderr, "\n");
       
   350 	v = PyRun_String(buffer, Py_single_input, globals, globals);
       
   351 	if (v == NULL) {
       
   352 		if (PyErr_Occurred() == PyExc_SystemExit) {
       
   353 			PyErr_Clear();
       
   354 			return 1;
       
   355 		}
       
   356 		PyErr_Print();
       
   357 		return 0;
       
   358 	}
       
   359 	Py_DECREF(v);
       
   360 	return 0;
       
   361 }
       
   362 
       
   363 static void
       
   364 ps(void)
       
   365 {
       
   366 	char buffer[100];
       
   367 	PyOS_snprintf(buffer, sizeof(buffer),
       
   368 		      "ps -l -p %d </dev/null | sed 1d\n", getpid());
       
   369 	system(buffer);
       
   370 }