blob: ea0ac6c577e35f7ff7c290d99e87d098b6ab5147 [file] [log] [blame]
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001/* POSIX module implementation */
2
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00003#include <signal.h>
4#include <string.h>
5#include <setjmp.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <sys/time.h>
9#ifdef SYSV
10#include <dirent.h>
11#define direct dirent
12#else
13#include <sys/dir.h>
14#endif
15
Guido van Rossum3f5da241990-12-20 15:06:42 +000016#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000017#include "modsupport.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000018
Guido van Rossum7f77e2d1990-10-30 13:34:38 +000019extern char *strerror PROTO((int));
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000020
21#ifdef AMOEBA
22#define NO_LSTAT
23#endif
24
25
26/* Return a dictionary corresponding to the POSIX environment table */
27
28extern char **environ;
29
30static object *
31convertenviron()
32{
33 object *d;
34 char **e;
35 d = newdictobject();
36 if (d == NULL)
37 return NULL;
38 if (environ == NULL)
39 return d;
40 /* XXX This part ignores errors */
41 for (e = environ; *e != NULL; e++) {
42 object *v;
43 char *p = strchr(*e, '=');
44 if (p == NULL)
45 continue;
46 v = newstringobject(p+1);
47 if (v == NULL)
48 continue;
49 *p = '\0';
50 (void) dictinsert(d, *e, v);
51 *p = '=';
52 DECREF(v);
53 }
54 return d;
55}
56
57
58static object *PosixError; /* Exception posix.error */
59
60/* Set a POSIX-specific error from errno, and return NULL */
61
Guido van Rossum9a1581c1990-10-21 13:12:47 +000062static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000063posix_error()
64{
Guido van Rossume8f305a1990-10-14 20:04:28 +000065 return err_errno(PosixError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000066}
67
68
69/* POSIX generic methods */
70
71static object *
72posix_1str(args, func)
73 object *args;
74 int (*func) FPROTO((const char *));
75{
76 object *path1;
77 if (!getstrarg(args, &path1))
78 return NULL;
79 if ((*func)(getstringvalue(path1)) < 0)
80 return posix_error();
81 INCREF(None);
82 return None;
83}
84
85static object *
86posix_2str(args, func)
87 object *args;
88 int (*func) FPROTO((const char *, const char *));
89{
90 object *path1, *path2;
91 if (!getstrstrarg(args, &path1, &path2))
92 return NULL;
93 if ((*func)(getstringvalue(path1), getstringvalue(path2)) < 0)
94 return posix_error();
95 INCREF(None);
96 return None;
97}
98
99static object *
100posix_strint(args, func)
101 object *args;
102 int (*func) FPROTO((const char *, int));
103{
104 object *path1;
105 int i;
106 if (!getstrintarg(args, &path1, &i))
107 return NULL;
108 if ((*func)(getstringvalue(path1), i) < 0)
109 return posix_error();
110 INCREF(None);
111 return None;
112}
113
114static object *
115posix_do_stat(self, args, statfunc)
116 object *self;
117 object *args;
118 int (*statfunc) FPROTO((const char *, struct stat *));
119{
120 struct stat st;
121 object *path;
122 object *v;
123 if (!getstrarg(args, &path))
124 return NULL;
125 if ((*statfunc)(getstringvalue(path), &st) != 0)
126 return posix_error();
127 v = newtupleobject(10);
128 if (v == NULL)
129 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000130#define SET(i, st_member) settupleitem(v, i, newintobject((long)st.st_member))
131 SET(0, st_mode);
132 SET(1, st_ino);
133 SET(2, st_dev);
134 SET(3, st_nlink);
135 SET(4, st_uid);
136 SET(5, st_gid);
137 SET(6, st_size);
138 SET(7, st_atime);
139 SET(8, st_mtime);
140 SET(9, st_ctime);
141#undef SET
Guido van Rossum3f5da241990-12-20 15:06:42 +0000142 if (err_occurred()) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000143 DECREF(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000144 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000145 }
146 return v;
147}
148
149
150/* POSIX methods */
151
152static object *
153posix_chdir(self, args)
154 object *self;
155 object *args;
156{
157 extern int chdir PROTO((const char *));
158 return posix_1str(args, chdir);
159}
160
161static object *
162posix_chmod(self, args)
163 object *self;
164 object *args;
165{
166 extern int chmod PROTO((const char *, mode_t));
167 return posix_strint(args, chmod);
168}
169
170static object *
171posix_getcwd(self, args)
172 object *self;
173 object *args;
174{
175 char buf[1026];
176 extern char *getcwd PROTO((char *, int));
177 if (!getnoarg(args))
178 return NULL;
179 if (getcwd(buf, sizeof buf) == NULL)
180 return posix_error();
181 return newstringobject(buf);
182}
183
184static object *
185posix_link(self, args)
186 object *self;
187 object *args;
188{
189 extern int link PROTO((const char *, const char *));
190 return posix_2str(args, link);
191}
192
193static object *
194posix_listdir(self, args)
195 object *self;
196 object *args;
197{
198 object *name, *d, *v;
199 DIR *dirp;
200 struct direct *ep;
201 if (!getstrarg(args, &name))
202 return NULL;
203 if ((dirp = opendir(getstringvalue(name))) == NULL)
204 return posix_error();
205 if ((d = newlistobject(0)) == NULL) {
206 closedir(dirp);
207 return NULL;
208 }
209 while ((ep = readdir(dirp)) != NULL) {
210 v = newstringobject(ep->d_name);
211 if (v == NULL) {
212 DECREF(d);
213 d = NULL;
214 break;
215 }
216 if (addlistitem(d, v) != 0) {
217 DECREF(v);
218 DECREF(d);
219 d = NULL;
220 break;
221 }
222 DECREF(v);
223 }
224 closedir(dirp);
225 return d;
226}
227
228static object *
229posix_mkdir(self, args)
230 object *self;
231 object *args;
232{
233 extern int mkdir PROTO((const char *, mode_t));
234 return posix_strint(args, mkdir);
235}
236
237static object *
238posix_rename(self, args)
239 object *self;
240 object *args;
241{
242 extern int rename PROTO((const char *, const char *));
243 return posix_2str(args, rename);
244}
245
246static object *
247posix_rmdir(self, args)
248 object *self;
249 object *args;
250{
251 extern int rmdir PROTO((const char *));
252 return posix_1str(args, rmdir);
253}
254
255static object *
256posix_stat(self, args)
257 object *self;
258 object *args;
259{
260 extern int stat PROTO((const char *, struct stat *));
261 return posix_do_stat(self, args, stat);
262}
263
264static object *
265posix_system(self, args)
266 object *self;
267 object *args;
268{
269 object *command;
270 int sts;
271 if (!getstrarg(args, &command))
272 return NULL;
273 sts = system(getstringvalue(command));
274 return newintobject((long)sts);
275}
276
277static object *
278posix_umask(self, args)
279 object *self;
280 object *args;
281{
282 int i;
283 if (!getintarg(args, &i))
284 return NULL;
285 i = umask(i);
286 if (i < 0)
287 return posix_error();
288 return newintobject((long)i);
289}
290
291static object *
292posix_unlink(self, args)
293 object *self;
294 object *args;
295{
296 extern int unlink PROTO((const char *));
297 return posix_1str(args, unlink);
298}
299
300static object *
301posix_utimes(self, args)
302 object *self;
303 object *args;
304{
305 object *path;
306 struct timeval tv[2];
307 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
308 err_badarg();
309 return NULL;
310 }
311 if (!getstrarg(gettupleitem(args, 0), &path) ||
312 !getlonglongargs(gettupleitem(args, 1),
313 &tv[0].tv_sec, &tv[1].tv_sec))
314 return NULL;
315 tv[0].tv_usec = tv[1].tv_usec = 0;
316 if (utimes(getstringvalue(path), tv) < 0)
317 return posix_error();
318 INCREF(None);
319 return None;
320}
321
322#ifdef NO_GETCWD
323
Guido van Rossum3f5da241990-12-20 15:06:42 +0000324#include "errno.h"
325
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000326/* Quick hack to get posix.getcwd() working for pure BSD 4.3 */
327/* XXX This assumes MAXPATHLEN = 1024 !!! */
328
329static char *
330getcwd(buf, size)
331 char *buf;
332 int size;
333{
334 extern char *getwd PROTO((char *));
335 register char *ret = getwd(buf);
336 if (ret == NULL)
337 errno = EACCES; /* Most likely error */
338 return ret;
339}
340
341#endif /* NO_GETCWD */
342
343
344#ifndef NO_LSTAT
345
346static object *
347posix_lstat(self, args)
348 object *self;
349 object *args;
350{
351 extern int lstat PROTO((const char *, struct stat *));
352 return posix_do_stat(self, args, lstat);
353}
354
355static object *
356posix_readlink(self, args)
357 object *self;
358 object *args;
359{
360 char buf[1024]; /* XXX Should use MAXPATHLEN */
361 object *path;
362 int n;
363 if (!getstrarg(args, &path))
364 return NULL;
365 n = readlink(getstringvalue(path), buf, sizeof buf);
366 if (n < 0)
367 return posix_error();
368 return newsizedstringobject(buf, n);
369}
370
371static object *
372posix_symlink(self, args)
373 object *self;
374 object *args;
375{
376 extern int symlink PROTO((const char *, const char *));
377 return posix_2str(args, symlink);
378}
379
380#endif /* NO_LSTAT */
381
382
383static struct methodlist posix_methods[] = {
384 {"chdir", posix_chdir},
385 {"chmod", posix_chmod},
386 {"getcwd", posix_getcwd},
387 {"link", posix_link},
388 {"listdir", posix_listdir},
389 {"mkdir", posix_mkdir},
390 {"rename", posix_rename},
391 {"rmdir", posix_rmdir},
392 {"stat", posix_stat},
393 {"system", posix_system},
394 {"umask", posix_umask},
395 {"unlink", posix_unlink},
396 {"utimes", posix_utimes},
397#ifndef NO_LSTAT
398 {"lstat", posix_lstat},
399 {"readlink", posix_readlink},
400 {"symlink", posix_symlink},
401#endif
402 {NULL, NULL} /* Sentinel */
403};
404
405
406void
407initposix()
408{
409 object *m, *d, *v;
410
411 m = initmodule("posix", posix_methods);
412 d = getmoduledict(m);
413
414 /* Initialize posix.environ dictionary */
415 v = convertenviron();
416 if (v == NULL || dictinsert(d, "environ", v) != 0)
417 fatal("can't define posix.environ");
418 DECREF(v);
419
420 /* Initialize posix.error exception */
421 PosixError = newstringobject("posix.error");
422 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
423 fatal("can't define posix.error");
424}