blob: 3e7b0cd55bb2314a369fe10fbddc2fb1c96f6e51 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* POSIX module implementation */
26
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000027#include <signal.h>
28#include <string.h>
29#include <setjmp.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <sys/time.h>
33#ifdef SYSV
34#include <dirent.h>
35#define direct dirent
36#else
37#include <sys/dir.h>
38#endif
39
Guido van Rossum3f5da241990-12-20 15:06:42 +000040#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000041#include "modsupport.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000042
Guido van Rossum7f77e2d1990-10-30 13:34:38 +000043extern char *strerror PROTO((int));
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000044
45#ifdef AMOEBA
46#define NO_LSTAT
47#endif
48
49
50/* Return a dictionary corresponding to the POSIX environment table */
51
52extern char **environ;
53
54static object *
55convertenviron()
56{
57 object *d;
58 char **e;
59 d = newdictobject();
60 if (d == NULL)
61 return NULL;
62 if (environ == NULL)
63 return d;
64 /* XXX This part ignores errors */
65 for (e = environ; *e != NULL; e++) {
66 object *v;
67 char *p = strchr(*e, '=');
68 if (p == NULL)
69 continue;
70 v = newstringobject(p+1);
71 if (v == NULL)
72 continue;
73 *p = '\0';
74 (void) dictinsert(d, *e, v);
75 *p = '=';
76 DECREF(v);
77 }
78 return d;
79}
80
81
82static object *PosixError; /* Exception posix.error */
83
84/* Set a POSIX-specific error from errno, and return NULL */
85
Guido van Rossum9a1581c1990-10-21 13:12:47 +000086static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000087posix_error()
88{
Guido van Rossume8f305a1990-10-14 20:04:28 +000089 return err_errno(PosixError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000090}
91
92
93/* POSIX generic methods */
94
95static object *
96posix_1str(args, func)
97 object *args;
98 int (*func) FPROTO((const char *));
99{
100 object *path1;
101 if (!getstrarg(args, &path1))
102 return NULL;
103 if ((*func)(getstringvalue(path1)) < 0)
104 return posix_error();
105 INCREF(None);
106 return None;
107}
108
109static object *
110posix_2str(args, func)
111 object *args;
112 int (*func) FPROTO((const char *, const char *));
113{
114 object *path1, *path2;
115 if (!getstrstrarg(args, &path1, &path2))
116 return NULL;
117 if ((*func)(getstringvalue(path1), getstringvalue(path2)) < 0)
118 return posix_error();
119 INCREF(None);
120 return None;
121}
122
123static object *
124posix_strint(args, func)
125 object *args;
126 int (*func) FPROTO((const char *, int));
127{
128 object *path1;
129 int i;
130 if (!getstrintarg(args, &path1, &i))
131 return NULL;
132 if ((*func)(getstringvalue(path1), i) < 0)
133 return posix_error();
134 INCREF(None);
135 return None;
136}
137
138static object *
139posix_do_stat(self, args, statfunc)
140 object *self;
141 object *args;
142 int (*statfunc) FPROTO((const char *, struct stat *));
143{
144 struct stat st;
145 object *path;
146 object *v;
147 if (!getstrarg(args, &path))
148 return NULL;
149 if ((*statfunc)(getstringvalue(path), &st) != 0)
150 return posix_error();
151 v = newtupleobject(10);
152 if (v == NULL)
153 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000154#define SET(i, st_member) settupleitem(v, i, newintobject((long)st.st_member))
155 SET(0, st_mode);
156 SET(1, st_ino);
157 SET(2, st_dev);
158 SET(3, st_nlink);
159 SET(4, st_uid);
160 SET(5, st_gid);
161 SET(6, st_size);
162 SET(7, st_atime);
163 SET(8, st_mtime);
164 SET(9, st_ctime);
165#undef SET
Guido van Rossum3f5da241990-12-20 15:06:42 +0000166 if (err_occurred()) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000167 DECREF(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000168 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000169 }
170 return v;
171}
172
173
174/* POSIX methods */
175
176static object *
177posix_chdir(self, args)
178 object *self;
179 object *args;
180{
181 extern int chdir PROTO((const char *));
182 return posix_1str(args, chdir);
183}
184
185static object *
186posix_chmod(self, args)
187 object *self;
188 object *args;
189{
190 extern int chmod PROTO((const char *, mode_t));
191 return posix_strint(args, chmod);
192}
193
194static object *
195posix_getcwd(self, args)
196 object *self;
197 object *args;
198{
199 char buf[1026];
200 extern char *getcwd PROTO((char *, int));
201 if (!getnoarg(args))
202 return NULL;
203 if (getcwd(buf, sizeof buf) == NULL)
204 return posix_error();
205 return newstringobject(buf);
206}
207
208static object *
209posix_link(self, args)
210 object *self;
211 object *args;
212{
213 extern int link PROTO((const char *, const char *));
214 return posix_2str(args, link);
215}
216
217static object *
218posix_listdir(self, args)
219 object *self;
220 object *args;
221{
222 object *name, *d, *v;
223 DIR *dirp;
224 struct direct *ep;
225 if (!getstrarg(args, &name))
226 return NULL;
227 if ((dirp = opendir(getstringvalue(name))) == NULL)
228 return posix_error();
229 if ((d = newlistobject(0)) == NULL) {
230 closedir(dirp);
231 return NULL;
232 }
233 while ((ep = readdir(dirp)) != NULL) {
234 v = newstringobject(ep->d_name);
235 if (v == NULL) {
236 DECREF(d);
237 d = NULL;
238 break;
239 }
240 if (addlistitem(d, v) != 0) {
241 DECREF(v);
242 DECREF(d);
243 d = NULL;
244 break;
245 }
246 DECREF(v);
247 }
248 closedir(dirp);
249 return d;
250}
251
252static object *
253posix_mkdir(self, args)
254 object *self;
255 object *args;
256{
257 extern int mkdir PROTO((const char *, mode_t));
258 return posix_strint(args, mkdir);
259}
260
261static object *
262posix_rename(self, args)
263 object *self;
264 object *args;
265{
266 extern int rename PROTO((const char *, const char *));
267 return posix_2str(args, rename);
268}
269
270static object *
271posix_rmdir(self, args)
272 object *self;
273 object *args;
274{
275 extern int rmdir PROTO((const char *));
276 return posix_1str(args, rmdir);
277}
278
279static object *
280posix_stat(self, args)
281 object *self;
282 object *args;
283{
284 extern int stat PROTO((const char *, struct stat *));
285 return posix_do_stat(self, args, stat);
286}
287
288static object *
289posix_system(self, args)
290 object *self;
291 object *args;
292{
293 object *command;
294 int sts;
295 if (!getstrarg(args, &command))
296 return NULL;
297 sts = system(getstringvalue(command));
298 return newintobject((long)sts);
299}
300
301static object *
302posix_umask(self, args)
303 object *self;
304 object *args;
305{
306 int i;
307 if (!getintarg(args, &i))
308 return NULL;
309 i = umask(i);
310 if (i < 0)
311 return posix_error();
312 return newintobject((long)i);
313}
314
315static object *
316posix_unlink(self, args)
317 object *self;
318 object *args;
319{
320 extern int unlink PROTO((const char *));
321 return posix_1str(args, unlink);
322}
323
324static object *
325posix_utimes(self, args)
326 object *self;
327 object *args;
328{
329 object *path;
330 struct timeval tv[2];
331 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
332 err_badarg();
333 return NULL;
334 }
335 if (!getstrarg(gettupleitem(args, 0), &path) ||
336 !getlonglongargs(gettupleitem(args, 1),
337 &tv[0].tv_sec, &tv[1].tv_sec))
338 return NULL;
339 tv[0].tv_usec = tv[1].tv_usec = 0;
340 if (utimes(getstringvalue(path), tv) < 0)
341 return posix_error();
342 INCREF(None);
343 return None;
344}
345
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000346
347#ifndef NO_LSTAT
348
349static object *
350posix_lstat(self, args)
351 object *self;
352 object *args;
353{
354 extern int lstat PROTO((const char *, struct stat *));
355 return posix_do_stat(self, args, lstat);
356}
357
358static object *
359posix_readlink(self, args)
360 object *self;
361 object *args;
362{
363 char buf[1024]; /* XXX Should use MAXPATHLEN */
364 object *path;
365 int n;
366 if (!getstrarg(args, &path))
367 return NULL;
368 n = readlink(getstringvalue(path), buf, sizeof buf);
369 if (n < 0)
370 return posix_error();
371 return newsizedstringobject(buf, n);
372}
373
374static object *
375posix_symlink(self, args)
376 object *self;
377 object *args;
378{
379 extern int symlink PROTO((const char *, const char *));
380 return posix_2str(args, symlink);
381}
382
383#endif /* NO_LSTAT */
384
385
386static struct methodlist posix_methods[] = {
387 {"chdir", posix_chdir},
388 {"chmod", posix_chmod},
389 {"getcwd", posix_getcwd},
390 {"link", posix_link},
391 {"listdir", posix_listdir},
392 {"mkdir", posix_mkdir},
393 {"rename", posix_rename},
394 {"rmdir", posix_rmdir},
395 {"stat", posix_stat},
396 {"system", posix_system},
397 {"umask", posix_umask},
398 {"unlink", posix_unlink},
399 {"utimes", posix_utimes},
400#ifndef NO_LSTAT
401 {"lstat", posix_lstat},
402 {"readlink", posix_readlink},
403 {"symlink", posix_symlink},
404#endif
405 {NULL, NULL} /* Sentinel */
406};
407
408
409void
410initposix()
411{
412 object *m, *d, *v;
413
414 m = initmodule("posix", posix_methods);
415 d = getmoduledict(m);
416
417 /* Initialize posix.environ dictionary */
418 v = convertenviron();
419 if (v == NULL || dictinsert(d, "environ", v) != 0)
420 fatal("can't define posix.environ");
421 DECREF(v);
422
423 /* Initialize posix.error exception */
424 PosixError = newstringobject("posix.error");
425 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
426 fatal("can't define posix.error");
427}