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