blob: c4f77c8a71fc3d74dd7b8f1e473a96a9bfca714d [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
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000322
323#ifndef NO_LSTAT
324
325static object *
326posix_lstat(self, args)
327 object *self;
328 object *args;
329{
330 extern int lstat PROTO((const char *, struct stat *));
331 return posix_do_stat(self, args, lstat);
332}
333
334static object *
335posix_readlink(self, args)
336 object *self;
337 object *args;
338{
339 char buf[1024]; /* XXX Should use MAXPATHLEN */
340 object *path;
341 int n;
342 if (!getstrarg(args, &path))
343 return NULL;
344 n = readlink(getstringvalue(path), buf, sizeof buf);
345 if (n < 0)
346 return posix_error();
347 return newsizedstringobject(buf, n);
348}
349
350static object *
351posix_symlink(self, args)
352 object *self;
353 object *args;
354{
355 extern int symlink PROTO((const char *, const char *));
356 return posix_2str(args, symlink);
357}
358
359#endif /* NO_LSTAT */
360
361
362static struct methodlist posix_methods[] = {
363 {"chdir", posix_chdir},
364 {"chmod", posix_chmod},
365 {"getcwd", posix_getcwd},
366 {"link", posix_link},
367 {"listdir", posix_listdir},
368 {"mkdir", posix_mkdir},
369 {"rename", posix_rename},
370 {"rmdir", posix_rmdir},
371 {"stat", posix_stat},
372 {"system", posix_system},
373 {"umask", posix_umask},
374 {"unlink", posix_unlink},
375 {"utimes", posix_utimes},
376#ifndef NO_LSTAT
377 {"lstat", posix_lstat},
378 {"readlink", posix_readlink},
379 {"symlink", posix_symlink},
380#endif
381 {NULL, NULL} /* Sentinel */
382};
383
384
385void
386initposix()
387{
388 object *m, *d, *v;
389
390 m = initmodule("posix", posix_methods);
391 d = getmoduledict(m);
392
393 /* Initialize posix.environ dictionary */
394 v = convertenviron();
395 if (v == NULL || dictinsert(d, "environ", v) != 0)
396 fatal("can't define posix.environ");
397 DECREF(v);
398
399 /* Initialize posix.error exception */
400 PosixError = newstringobject("posix.error");
401 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
402 fatal("can't define posix.error");
403}