9b3271803aab7d9024e6ec14164337830050af7a
[gnome.seed] / modules / os / seed-os.c
1 /* -*- mode: C; indent-tabs-mode: t; tab-width: 8; c-basic-offset: 2; -*- */
2
3 /*
4  * This file is part of Seed, the GObject Introspection<->Javascript bindings.
5  *
6  * Seed is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation, either version 3 of
9  * the License, or (at your option) any later version.
10  * Seed is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with Seed.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Copyright (C) Robert Carr 2009 <carrr@rpi.edu>
18  */
19
20 #define _GNU_SOURCE
21
22 #include "../../config.h"
23
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <sys/stat.h>
31 #include <sys/utsname.h>
32
33 #include <sys/types.h>
34
35 #include <fcntl.h>
36
37 #ifdef HAVE_PTY_H
38 #include <pty.h>
39 #endif
40
41 #include <seed.h>
42
43 SeedObject os_namespace;
44
45 #define EXPECTED_EXCEPTION(name, argnum)                                \
46   seed_make_exception (ctx, exception, "ArgumentError", name " expected " argnum " got %Zd", argument_count); \
47   return seed_make_undefined (ctx);
48
49 SeedValue
50 seed_os_realpath (SeedContext ctx,
51                   SeedObject function,
52                   SeedObject this_object,
53                   size_t argument_count,
54                   const SeedValue arguments[],
55                   SeedException * exception)
56 {
57   gchar *arg;
58   gchar *ret;
59
60   if (argument_count != 1)
61     {
62       EXPECTED_EXCEPTION("os.realpath", "1 argument");
63     }
64   arg = seed_value_to_string (ctx, arguments[0], exception);
65   ret = realpath(arg, NULL);
66   g_free (arg);
67
68   return seed_value_from_string (ctx, ret, exception);
69 }
70
71 SeedValue
72 seed_os_chdir (SeedContext ctx,
73                SeedObject function,
74                SeedObject this_object,
75                size_t argument_count,
76                const SeedValue arguments[],
77                SeedException * exception)
78 {
79   gchar *arg;
80   gint ret;
81
82   if (argument_count != 1)
83     {
84       EXPECTED_EXCEPTION("os.chdir", "1 argument");
85     }
86   arg = seed_value_to_string (ctx, arguments[0], exception);
87   ret = chdir (arg);
88   g_free (arg);
89
90   return seed_value_from_int (ctx, ret, exception);
91 }
92
93 SeedValue
94 seed_os_fchdir (SeedContext ctx,
95                SeedObject function,
96                SeedObject this_object,
97                size_t argument_count,
98                const SeedValue arguments[],
99                SeedException * exception)
100 {
101   gint ret, arg;
102
103   if (argument_count != 1)
104     {
105       EXPECTED_EXCEPTION("os.fchdir", "1 argument");
106     }
107   arg = seed_value_to_int (ctx, arguments[0], exception);
108   ret = fchdir (arg);
109
110   return seed_value_from_int (ctx, ret, exception);
111 }
112
113 SeedValue
114 seed_os_getcwd (SeedContext ctx,
115                 SeedObject function,
116                 SeedObject this_object,
117                 size_t argument_count,
118                 const SeedValue arguments[],
119                 SeedException * exception)
120 {
121   SeedValue seed_ret;
122   gchar *ret;
123
124   if (argument_count != 0)
125     {
126       EXPECTED_EXCEPTION("os.getcwd", "no arguments");
127     }
128   ret = getcwd (NULL, 0);
129   seed_ret = seed_value_from_string (ctx, ret, exception);
130   g_free (ret);
131
132   return seed_ret;
133 }
134
135 SeedValue
136 seed_os_ctermid (SeedContext ctx,
137                  SeedObject function,
138                  SeedObject this_object,
139                  size_t argument_count,
140                  const SeedValue arguments[],
141                  SeedException * exception)
142 {
143   SeedValue seed_ret;
144   gchar *ret;
145
146   if (argument_count != 0)
147     {
148       EXPECTED_EXCEPTION("os.getcwd", "no arguments");
149     }
150   // ctermid returns a static buffer
151   ret = ctermid (NULL);
152   seed_ret = seed_value_from_string (ctx, ret, exception);
153
154   return seed_ret;
155 }
156
157 SeedValue
158 seed_os_getegid (SeedContext ctx,
159                  SeedObject function,
160                  SeedObject this_object,
161                  size_t argument_count,
162                  const SeedValue arguments[],
163                  SeedException * exception)
164 {
165   gid_t ret;
166
167   if (argument_count != 0)
168     {
169       EXPECTED_EXCEPTION("os.getegid", "no arguments");
170     }
171   ret = getegid ();
172
173   return seed_value_from_long (ctx, (glong) ret, exception);
174 }
175
176 SeedValue
177 seed_os_geteuid (SeedContext ctx,
178                  SeedObject function,
179                  SeedObject this_object,
180                  size_t argument_count,
181                  const SeedValue arguments[],
182                  SeedException * exception)
183 {
184   uid_t ret;
185
186   if (argument_count != 0)
187     {
188       EXPECTED_EXCEPTION("os.geteuid", "no arguments");
189     }
190   ret = geteuid ();
191
192   return seed_value_from_long (ctx, (glong) ret, exception);
193 }
194
195 SeedValue
196 seed_os_getgid (SeedContext ctx,
197                  SeedObject function,
198                  SeedObject this_object,
199                  size_t argument_count,
200                  const SeedValue arguments[],
201                  SeedException * exception)
202 {
203   gid_t ret;
204
205   if (argument_count != 0)
206     {
207       EXPECTED_EXCEPTION("os.getgid", "no arguments");
208     }
209   ret = getgid ();
210
211   return seed_value_from_long (ctx, (glong) ret, exception);
212 }
213
214 SeedValue
215 seed_os_getuid (SeedContext ctx,
216                 SeedObject function,
217                 SeedObject this_object,
218                 size_t argument_count,
219                 const SeedValue arguments[],
220                 SeedException * exception)
221 {
222   uid_t ret;
223
224   if (argument_count != 0)
225     {
226       EXPECTED_EXCEPTION("os.getuid", "no arguments");
227     }
228   ret = getuid ();
229
230   return seed_value_from_long (ctx, (glong) ret, exception);
231 }
232
233 SeedValue
234 seed_os_getgroups (SeedContext ctx,
235                    SeedObject function,
236                    SeedObject this_object,
237                    size_t argument_count,
238                    const SeedValue arguments[],
239                    SeedException * exception)
240 {
241   SeedValue ret;
242   SeedValue *groups;
243   gid_t *group_list;
244   guint num_groups, i;
245
246   if (argument_count != 0)
247     {
248       EXPECTED_EXCEPTION("os.getgroups", "no arguments");
249     }
250   num_groups = getgroups(0, NULL);
251   group_list = g_alloca (num_groups * sizeof(gid_t));
252   groups = g_alloca (num_groups * sizeof(SeedValue));
253   if (getgroups (num_groups, group_list) < 0)
254     {
255       // TODO: Decide on how to handle exceptions for things like this...
256       // Investigate python
257       return seed_make_null (ctx);
258     }
259
260   for (i = 0; i < num_groups; i++)
261     {
262       groups[i] = seed_value_from_long (ctx, (glong) group_list[i], exception);
263     }
264   ret = seed_make_array (ctx, groups, num_groups, exception);
265
266   return ret;
267 }
268
269 SeedValue
270 seed_os_getlogin (SeedContext ctx,
271                   SeedObject function,
272                   SeedObject this_object,
273                   size_t argument_count,
274                   const SeedValue arguments[],
275                   SeedException * exception)
276 {
277   if (argument_count != 0)
278     {
279       EXPECTED_EXCEPTION("os.getlogin", "no arguments");
280     }
281
282   return seed_value_from_string (ctx, getlogin(), exception);
283 }
284
285 SeedValue
286 seed_os_getpgid (SeedContext ctx,
287                  SeedObject function,
288                  SeedObject this_object,
289                  size_t argument_count,
290                  const SeedValue arguments[],
291                  SeedException * exception)
292 {
293   pid_t pid;
294   if (argument_count != 1)
295     {
296       EXPECTED_EXCEPTION("os.getpgid", "1 argument");
297     }
298   pid = (pid_t) seed_value_to_long (ctx, arguments[0], exception);
299
300   return seed_value_from_long (ctx, (glong) getpgid(pid), exception);
301 }
302
303 SeedValue
304 seed_os_getpgrp (SeedContext ctx,
305                  SeedObject function,
306                  SeedObject this_object,
307                  size_t argument_count,
308                  const SeedValue arguments[],
309                  SeedException * exception)
310 {
311   if (argument_count != 0)
312     {
313       EXPECTED_EXCEPTION("os.getpgrp", "no arguments");
314     }
315
316   return seed_value_from_long (ctx, (glong) getpgrp(), exception);
317 }
318
319 SeedValue
320 seed_os_getpid (SeedContext ctx,
321                 SeedObject function,
322                 SeedObject this_object,
323                 size_t argument_count,
324                 const SeedValue arguments[],
325                 SeedException * exception)
326 {
327   if (argument_count != 0)
328     {
329       EXPECTED_EXCEPTION("os.getpid", "no arguments");
330     }
331
332   return seed_value_from_long (ctx, (glong) getpid(), exception);
333 }
334
335 SeedValue
336 seed_os_getppid (SeedContext ctx,
337                 SeedObject function,
338                 SeedObject this_object,
339                 size_t argument_count,
340                 const SeedValue arguments[],
341                 SeedException * exception)
342 {
343   if (argument_count != 0)
344     {
345       EXPECTED_EXCEPTION("os.getppid", "no arguments");
346     }
347
348   return seed_value_from_long (ctx, (glong) getppid(), exception);
349 }
350
351 SeedValue
352 seed_os_getenv (SeedContext ctx,
353                 SeedObject function,
354                 SeedObject this_object,
355                 size_t argument_count,
356                 const SeedValue arguments[],
357                 SeedException * exception)
358 {
359   SeedValue ret;
360   gchar *name, *value;
361   if (argument_count != 1)
362     {
363       EXPECTED_EXCEPTION("os.getenv", "1 arguments");
364     }
365   name = seed_value_to_string (ctx, arguments[0], exception);
366   value = getenv (name);
367   ret = seed_value_from_string (ctx, value, exception);
368   g_free (name);
369
370   return ret;
371 }
372
373 SeedValue
374 seed_os_putenv (SeedContext ctx,
375                 SeedObject function,
376                 SeedObject this_object,
377                 size_t argument_count,
378                 const SeedValue arguments[],
379                 SeedException * exception)
380 {
381   gint ret;
382   gchar *name, *value, *arg;
383
384   if (argument_count != 2)
385     {
386       EXPECTED_EXCEPTION("os.putenv", "2 arguments");
387     }
388   name = seed_value_to_string (ctx, arguments[0], exception);
389   value = seed_value_to_string (ctx, arguments[1], exception);
390   arg = g_strconcat (name, "=", value, NULL);
391
392   ret = putenv (arg);
393
394   g_free (name);
395   g_free (value);
396
397   return seed_value_from_int (ctx, ret, exception);
398 }
399
400
401 SeedValue
402 seed_os_setegid (SeedContext ctx,
403                  SeedObject function,
404                  SeedObject this_object,
405                  size_t argument_count,
406                  const SeedValue arguments[],
407                  SeedException * exception)
408 {
409   gid_t arg;
410
411   if (argument_count != 1)
412     {
413       EXPECTED_EXCEPTION("os.setegid", "1 argument");
414     }
415   arg = seed_value_to_long (ctx, arguments[0], exception);
416
417   return seed_value_from_int (ctx, setegid(arg), exception);
418 }
419
420 SeedValue
421 seed_os_setgid (SeedContext ctx,
422                  SeedObject function,
423                  SeedObject this_object,
424                  size_t argument_count,
425                  const SeedValue arguments[],
426                  SeedException * exception)
427 {
428   gid_t arg;
429
430   if (argument_count != 1)
431     {
432       EXPECTED_EXCEPTION("os.setgid", "1 argument");
433     }
434   arg = seed_value_to_long (ctx, arguments[0], exception);
435
436   return seed_value_from_int (ctx, setgid(arg), exception);
437 }
438
439 SeedValue
440 seed_os_seteuid (SeedContext ctx,
441                  SeedObject function,
442                  SeedObject this_object,
443                  size_t argument_count,
444                  const SeedValue arguments[],
445                  SeedException * exception)
446 {
447   uid_t arg;
448
449   if (argument_count != 1)
450     {
451       EXPECTED_EXCEPTION("os.seteuid", "1 argument");
452     }
453   arg = seed_value_to_long (ctx, arguments[0], exception);
454
455   return seed_value_from_int (ctx, seteuid(arg), exception);
456 }
457
458 SeedValue
459 seed_os_setuid (SeedContext ctx,
460                  SeedObject function,
461                  SeedObject this_object,
462                  size_t argument_count,
463                  const SeedValue arguments[],
464                  SeedException * exception)
465 {
466   uid_t arg;
467
468   if (argument_count != 1)
469     {
470       EXPECTED_EXCEPTION("os.setuid", "1 argument");
471     }
472   arg = seed_value_to_long (ctx, arguments[0], exception);
473
474   return seed_value_from_int (ctx, setuid(arg), exception);
475 }
476
477 SeedValue
478 seed_os_strerror (SeedContext ctx,
479                   SeedObject function,
480                   SeedObject this_object,
481                   size_t argument_count,
482                   const SeedValue arguments[],
483                   SeedException * exception)
484 {
485   int arg;
486
487   if (argument_count != 1)
488     {
489       EXPECTED_EXCEPTION("os.strerror", "1 argument");
490     }
491   arg = seed_value_to_int (ctx, arguments[0], exception);
492
493   return seed_value_from_string (ctx, strerror(arg), exception);
494 }
495
496 SeedValue
497 seed_os_umask (SeedContext ctx,
498                SeedObject function,
499                SeedObject this_object,
500                size_t argument_count,
501                const SeedValue arguments[],
502                SeedException * exception)
503 {
504   mode_t arg;
505
506   if (argument_count != 1)
507     {
508       EXPECTED_EXCEPTION("os.umask", "1 argument");
509     }
510   arg = seed_value_to_long (ctx, arguments[0], exception);
511
512   return seed_value_from_long (ctx, umask(arg), exception);
513 }
514
515 SeedValue
516 seed_os_uname (SeedContext ctx,
517                SeedObject function,
518                SeedObject this_object,
519                size_t argument_count,
520                const SeedValue arguments[],
521                SeedException * exception)
522 {
523   SeedValue elements[5], ret;
524   guint c;
525   struct utsname name;
526
527   if (argument_count != 0)
528     {
529       EXPECTED_EXCEPTION("os.uname", "no arguments");
530     }
531   c = uname (&name);
532   // TODO: Do something with c
533   elements[0] = seed_value_from_string (ctx, name.sysname, exception);
534   elements[1] = seed_value_from_string (ctx, name.nodename, exception);
535   elements[2] = seed_value_from_string (ctx, name.release, exception);
536   elements[3] = seed_value_from_string (ctx, name.version, exception);
537   elements[4] = seed_value_from_string (ctx, name.machine, exception);
538   ret = seed_make_array (ctx, elements, 5, exception);
539
540
541   return ret;
542 }
543
544
545 SeedValue
546 seed_os_unsetenv (SeedContext ctx,
547                   SeedObject function,
548                   SeedObject this_object,
549                   size_t argument_count,
550                   const SeedValue arguments[],
551                   SeedException * exception)
552 {
553   gint ret;
554   gchar *arg;
555
556   if (argument_count != 1)
557     {
558       EXPECTED_EXCEPTION("os.unsetenv", "1 argument");
559     }
560
561   arg = seed_value_to_string (ctx, arguments[0], exception);
562   ret = unsetenv (arg);
563   g_free (arg);
564
565   return seed_value_from_int (ctx, ret, exception);
566 }
567
568 SeedValue
569 seed_os_open (SeedContext ctx,
570               SeedObject function,
571               SeedObject this_object,
572               size_t argument_count,
573               const SeedValue arguments[],
574               SeedException * exception)
575 {
576   gchar *path;
577   gint flags, ret;
578
579   if (argument_count != 2)
580     {
581       EXPECTED_EXCEPTION("os.open", "2 arguments");
582     }
583
584   path = seed_value_to_string (ctx, arguments[0], exception);
585   flags = seed_value_to_int (ctx, arguments[1], exception);
586
587   ret = open (path, flags);
588   g_free (path);
589
590   return seed_value_from_int (ctx, ret, exception);
591 }
592
593 SeedValue
594 seed_os_close (SeedContext ctx,
595                SeedObject function,
596                SeedObject this_object,
597                size_t argument_count,
598                const SeedValue arguments[],
599                SeedException * exception)
600 {
601   gint arg;
602
603   if (argument_count != 1)
604     {
605       EXPECTED_EXCEPTION("os.close", "2 arguments");
606     }
607
608   arg = seed_value_to_int (ctx, arguments[0], exception);
609
610   return seed_value_from_int (ctx, close (arg), exception);
611 }
612
613 SeedValue
614 seed_os_dup (SeedContext ctx,
615              SeedObject function,
616              SeedObject this_object,
617              size_t argument_count,
618              const SeedValue arguments[],
619              SeedException * exception)
620 {
621   gint arg;
622
623   if (argument_count != 1)
624     {
625       EXPECTED_EXCEPTION("os.dup", "1 argument");
626     }
627
628   arg = seed_value_to_int (ctx, arguments[0], exception);
629
630   return seed_value_from_int (ctx, dup (arg), exception);
631 }
632 SeedValue
633 seed_os_dup2 (SeedContext ctx,
634               SeedObject function,
635               SeedObject this_object,
636               size_t argument_count,
637               const SeedValue arguments[],
638               SeedException * exception)
639 {
640   gint arg, arg2;
641
642   if (argument_count != 2)
643     {
644       EXPECTED_EXCEPTION("os.dup2", "2 arguments");
645     }
646
647   arg = seed_value_to_int (ctx, arguments[0], exception);
648   arg2 = seed_value_to_int (ctx, arguments[0], exception);
649
650   return seed_value_from_int (ctx, dup2 (arg, arg2), exception);
651 }
652
653 SeedValue
654 seed_os_fchmod (SeedContext ctx,
655                 SeedObject function,
656                 SeedObject this_object,
657                 size_t argument_count,
658                 const SeedValue arguments[],
659                 SeedException * exception)
660 {
661   gint fd;
662   mode_t mode;
663
664   if (argument_count != 2)
665     {
666       EXPECTED_EXCEPTION ("os.fchmod", "2 arguments");
667     }
668   fd = seed_value_to_int (ctx, arguments[0], exception);
669   mode = seed_value_to_long (ctx, arguments[1], exception);
670
671   return seed_value_from_int (ctx, fchmod (fd, mode), exception);
672 }
673
674 SeedValue
675 seed_os_fchown (SeedContext ctx,
676                 SeedObject function,
677                 SeedObject this_object,
678                 size_t argument_count,
679                 const SeedValue arguments[],
680                 SeedException * exception)
681 {
682   gint fd;
683   gid_t gid;
684   uid_t uid;
685
686   if (argument_count != 3)
687     {
688       EXPECTED_EXCEPTION ("os.fchown", "3 arguments");
689     }
690   fd = seed_value_to_int (ctx, arguments[0], exception);
691   uid = seed_value_to_long (ctx, arguments[1], exception);
692   gid = seed_value_to_long (ctx, arguments[2], exception);
693
694   return seed_value_from_int (ctx, fchown (fd, uid, gid), exception);
695 }
696
697 SeedValue
698 seed_os_fdatasync (SeedContext ctx,
699                    SeedObject function,
700                    SeedObject this_object,
701                    size_t argument_count,
702                    const SeedValue arguments[],
703                    SeedException * exception)
704 {
705   gint fd;
706
707   if (argument_count != 1)
708     {
709       EXPECTED_EXCEPTION ("os.fdatasync", "1 argument");
710     }
711   fd = seed_value_to_int (ctx, arguments[0], exception);
712
713   return seed_value_from_int (ctx, fdatasync (fd), exception);
714 }
715
716 SeedValue
717 seed_os_fpathconf (SeedContext ctx,
718                    SeedObject function,
719                    SeedObject this_object,
720                    size_t argument_count,
721                    const SeedValue arguments[],
722                    SeedException * exception)
723 {
724   gint fd, name;
725
726   if (argument_count != 2)
727     {
728       EXPECTED_EXCEPTION ("os.fpathconf", "2 arguments");
729     }
730   fd = seed_value_to_int (ctx, arguments[0], exception);
731   name = seed_value_to_int (ctx, arguments[1], exception);
732
733   return seed_value_from_long (ctx, fpathconf (fd, name), exception);
734 }
735
736 SeedValue
737 seed_os_fsync (SeedContext ctx,
738                SeedObject function,
739                SeedObject this_object,
740                size_t argument_count,
741                const SeedValue arguments[],
742                SeedException * exception)
743 {
744   gint fd;
745
746   if (argument_count != 1)
747     {
748       EXPECTED_EXCEPTION ("os.fsync", "1 argument");
749     }
750   fd = seed_value_to_int (ctx, arguments[0], exception);
751
752   return seed_value_from_long (ctx, fsync (fd), exception);
753 }
754
755 SeedValue
756 seed_os_ftruncate (SeedContext ctx,
757                    SeedObject function,
758                    SeedObject this_object,
759                    size_t argument_count,
760                    const SeedValue arguments[],
761                    SeedException * exception)
762 {
763   gint fd;
764   off_t length;
765
766   if (argument_count != 2)
767     {
768       EXPECTED_EXCEPTION ("os.ftruncate", "2 arguments");
769     }
770   fd = seed_value_to_int (ctx, arguments[0], exception);
771   length = seed_value_to_int (ctx, arguments[1], exception);
772
773   return seed_value_from_long (ctx, ftruncate (fd, length), exception);
774 }
775
776 SeedValue
777 seed_os_isatty (SeedContext ctx,
778                 SeedObject function,
779                 SeedObject this_object,
780                 size_t argument_count,
781                 const SeedValue arguments[],
782                 SeedException * exception)
783 {
784   gint fd;
785
786   if (argument_count != 1)
787     {
788       EXPECTED_EXCEPTION ("os.isatty", "1 argument");
789     }
790   fd = seed_value_to_int (ctx, arguments[0], exception);
791
792   return seed_value_from_boolean (ctx, isatty (fd), exception);
793 }
794
795 SeedValue
796 seed_os_lseek (SeedContext ctx,
797                SeedObject function,
798                SeedObject this_object,
799                size_t argument_count,
800                const SeedValue arguments[],
801                SeedException * exception)
802 {
803   gint fd, whence;
804   off_t offset;
805
806   if (argument_count != 3)
807     {
808       EXPECTED_EXCEPTION ("os.lseek", "3 arguments");
809     }
810   fd = seed_value_to_int (ctx, arguments[0], exception);
811   offset = seed_value_to_long (ctx, arguments[1], exception);
812   whence = seed_value_to_int (ctx, arguments[2], exception);
813
814   return seed_value_from_long (ctx, lseek (fd, offset, whence), exception);
815 }
816
817 SeedValue
818 seed_os_openpty (SeedContext ctx,
819                  SeedObject function,
820                  SeedObject this_object,
821                  size_t argument_count,
822                  const SeedValue arguments[],
823                  SeedException * exception)
824 {
825   SeedValue fds[2], ret;
826   gint master,slave;
827
828   if (argument_count != 0)
829     {
830       EXPECTED_EXCEPTION ("os.openpty", "no arguments");
831     }
832   openpty (&master, &slave, NULL, NULL, NULL);
833
834   fds[0] = seed_value_from_int (ctx, master, exception);
835   fds[1] = seed_value_from_int (ctx, slave, exception);
836
837   ret = seed_make_array (ctx, fds, 2, exception);
838
839   return ret;
840 }
841
842 SeedValue
843 seed_os_pipe (SeedContext ctx,
844               SeedObject function,
845               SeedObject this_object,
846               size_t argument_count,
847               const SeedValue arguments[],
848               SeedException * exception)
849 {
850   SeedValue fds[2], ret;
851   gint fildes[2];
852
853   if (argument_count != 0)
854     {
855       EXPECTED_EXCEPTION ("os.pipe", "no arguments");
856     }
857   if (pipe (fildes) < 0)
858     {
859       // TODO
860     }
861
862   fds[0] = seed_value_from_int (ctx, fildes[0], exception);
863   fds[1] = seed_value_from_int (ctx, fildes[1], exception);
864
865   ret = seed_make_array (ctx, fds, 2, exception);
866
867   return ret;
868 }
869
870 SeedValue
871 seed_os_read (SeedContext ctx,
872               SeedObject function,
873               SeedObject this_object,
874               size_t argument_count,
875               const SeedValue arguments[],
876               SeedException * exception)
877 {
878   SeedValue ret;
879   gint fd, n, nr;
880   gchar *buf;
881
882   if (argument_count != 2)
883     {
884       EXPECTED_EXCEPTION ("os.read", "2 arguments");
885     }
886   fd = seed_value_to_int (ctx, arguments[0], exception);
887   n = seed_value_to_int (ctx, arguments[1], exception);
888
889   buf = g_alloca (n * sizeof (gchar));
890   nr = read (fd, buf, n);
891   buf[nr] = '\0';
892
893   if (nr)
894     ret = seed_value_from_string (ctx, buf, exception);
895   else
896     ret = seed_make_null (ctx);
897
898   return ret;
899 }
900
901 SeedValue
902 seed_os_write (SeedContext ctx,
903                SeedObject function,
904                SeedObject this_object,
905                size_t argument_count,
906                const SeedValue arguments[],
907                SeedException * exception)
908 {
909   gint fd, nw;
910   gchar *buf;
911
912   if (argument_count != 2)
913     {
914       EXPECTED_EXCEPTION ("os.write", "2 arguments");
915     }
916   fd = seed_value_to_int (ctx, arguments[0], exception);
917   buf = seed_value_to_string (ctx, arguments[1], exception);
918
919   nw = write (fd, buf, strlen (buf));
920
921   return seed_value_from_int (ctx, nw, exception);
922 }
923
924 SeedValue
925 seed_os_ttyname (SeedContext ctx,
926                  SeedObject function,
927                  SeedObject this_object,
928                  size_t argument_count,
929                  const SeedValue arguments[],
930                  SeedException * exception)
931 {
932   gint fd;
933
934   if (argument_count != 1)
935     {
936       EXPECTED_EXCEPTION ("os.ttyname", "1 argument");
937     }
938   fd = seed_value_to_int (ctx, arguments[0], exception);
939
940   return seed_value_from_string (ctx, ttyname (fd), exception);
941 }
942
943 SeedValue
944 seed_os_tcgetpgrp (SeedContext ctx,
945                    SeedObject function,
946                    SeedObject this_object,
947                    size_t argument_count,
948                    const SeedValue arguments[],
949                    SeedException * exception)
950 {
951   gint fd;
952
953   if (argument_count != 1)
954     {
955       EXPECTED_EXCEPTION ("os.tcgetpgrp", "1 argument");
956     }
957   fd = seed_value_to_int (ctx, arguments[0], exception);
958
959   return seed_value_from_long (ctx, tcgetpgrp (fd), exception);
960 }
961
962 SeedValue
963 seed_os_tcsetpgrp (SeedContext ctx,
964                    SeedObject function,
965                    SeedObject this_object,
966                    size_t argument_count,
967                    const SeedValue arguments[],
968                    SeedException * exception)
969 {
970   gint fd;
971   pid_t pgrp;
972
973   if (argument_count != 2)
974     {
975       EXPECTED_EXCEPTION ("os.tcsetpgrp", "2 arguments");
976     }
977   fd = seed_value_to_int (ctx, arguments[0], exception);
978   pgrp = seed_value_to_int (ctx, arguments[1], exception);
979
980   return seed_value_from_int (ctx, tcsetpgrp (fd, pgrp), exception);
981 }
982
983 SeedValue
984 seed_os_access (SeedContext ctx,
985                 SeedObject function,
986                 SeedObject this_object,
987                 size_t argument_count,
988                 const SeedValue arguments[],
989                 SeedException * exception)
990 {
991   int ret;
992   gchar *path;
993   int amd;
994
995   if (argument_count != 2)
996     {
997       EXPECTED_EXCEPTION ("os.access", "2 arguments");
998     }
999   path = seed_value_to_string (ctx, arguments[0], exception);
1000   amd = seed_value_to_int (ctx, arguments[1], exception);
1001
1002   ret = access (path, amd);
1003
1004   if (ret == 0)
1005     return seed_value_from_boolean (ctx, TRUE, exception);
1006   else
1007     return seed_value_from_boolean (ctx, FALSE, exception);
1008 }
1009
1010 static SeedValue
1011 seed_os_fork (SeedContext ctx,
1012               SeedObject function,
1013               SeedObject this_object,
1014               gsize argument_count,
1015               const SeedValue arguments[],
1016               SeedException *exception)
1017 {
1018   pid_t t = fork();
1019
1020   return seed_value_from_long (ctx, t, exception);
1021 }
1022
1023 seed_static_function os_funcs[] = {
1024   {"fork", seed_os_fork, 0},
1025   {"realpath", seed_os_realpath, 0},
1026   {"chdir", seed_os_chdir, 0},
1027   {"fchdir", seed_os_fchdir, 0},
1028   {"getcwd", seed_os_getcwd, 0},
1029   {"ctermid", seed_os_ctermid, 0},
1030   {"getegid", seed_os_getegid, 0},
1031   {"geteuid", seed_os_geteuid, 0},
1032   {"getgid", seed_os_getgid, 0},
1033   {"getuid", seed_os_getuid, 0},
1034   {"getlogin", seed_os_getlogin, 0},
1035   {"getpgid", seed_os_getpgid, 0},
1036   {"getpgrp", seed_os_getpgrp, 0},
1037   {"getpid", seed_os_getpid, 0},
1038   {"getppid", seed_os_getuid, 0},
1039   {"getenv", seed_os_getenv, 0},
1040   {"putenv", seed_os_putenv, 0},
1041   {"setegid", seed_os_setegid, 0},
1042   {"setgid", seed_os_setegid, 0},
1043   {"seteuid", seed_os_setegid, 0},
1044   {"setuid", seed_os_setuid, 0},
1045   {"strerror", seed_os_strerror, 0},
1046   {"umask", seed_os_umask, 0},
1047   {"uname", seed_os_uname, 0},
1048   {"unsetenv", seed_os_unsetenv, 0},
1049   {"open", seed_os_open, 0},
1050   {"close", seed_os_close, 0},
1051   {"dup", seed_os_dup, 0},
1052   {"dup2", seed_os_dup2, 0},
1053   {"fchmod", seed_os_fchmod, 0},
1054   {"fchown", seed_os_fchown, 0},
1055   {"fdatasync", seed_os_fdatasync, 0},
1056   {"fpathconf", seed_os_fpathconf, 0},
1057   {"fsync", seed_os_fsync, 0},
1058   {"ftruncate", seed_os_ftruncate, 0},
1059   {"isatty", seed_os_isatty, 0},
1060   {"lseek", seed_os_lseek, 0},
1061   {"openpty", seed_os_openpty, 0},
1062   {"pipe", seed_os_pipe, 0},
1063   {"read", seed_os_read, 0},
1064   {"write", seed_os_write, 0},
1065   {"ttyname", seed_os_ttyname, 0},
1066   {"tcgetpgrp", seed_os_tcgetpgrp, 0},
1067   {"tcsetpgrp", seed_os_tcsetpgrp, 0},
1068   {"access", seed_os_access, 0}
1069 };
1070
1071 #define OS_DEFINE_ENUM(name, value) \
1072   seed_object_set_property (eng->context, os_namespace, name,           \
1073                             seed_value_from_long (eng->context, value, NULL))
1074 #define OS_DEFINE_QUICK_ENUM(value)                                     \
1075 seed_object_set_property (eng->context, os_namespace, #value,           \
1076                           seed_value_from_long (eng->context, value, NULL)) \
1077
1078 SeedObject
1079 seed_module_init(SeedEngine * eng)
1080 {
1081   SeedClass os_namespace_class;
1082   seed_class_definition os_namespace_class_definition = seed_empty_class;
1083
1084   os_namespace_class_definition.static_functions = os_funcs;
1085   os_namespace_class = seed_create_class (&os_namespace_class_definition);
1086
1087   os_namespace = seed_make_object (eng->context, os_namespace_class, NULL);
1088
1089   OS_DEFINE_QUICK_ENUM (O_RDONLY);
1090   OS_DEFINE_QUICK_ENUM (O_WRONLY);
1091   OS_DEFINE_QUICK_ENUM (O_RDWR);
1092   OS_DEFINE_QUICK_ENUM (O_APPEND);
1093   OS_DEFINE_QUICK_ENUM (O_CREAT);
1094   OS_DEFINE_QUICK_ENUM (O_EXCL);
1095   OS_DEFINE_QUICK_ENUM (O_TRUNC);
1096
1097 #if defined (O_DSYNC)
1098   OS_DEFINE_QUICK_ENUM (O_DSYNC);
1099 #endif
1100 #if defined (O_RSYNC)
1101   OS_DEFINE_QUICK_ENUM (O_RSYNC);
1102 #endif
1103
1104   OS_DEFINE_QUICK_ENUM (O_SYNC);
1105   OS_DEFINE_QUICK_ENUM (O_NDELAY);
1106   OS_DEFINE_QUICK_ENUM (O_NONBLOCK);
1107   OS_DEFINE_QUICK_ENUM (O_NOCTTY);
1108   //  OS_DEFINE_QUICK_ENUM (O_SHLOCK);
1109   //  OS_DEFINE_QUICK_ENUM (O_EXLOCK);
1110
1111   OS_DEFINE_QUICK_ENUM (O_ASYNC);
1112 #if defined (O_DIRECT)
1113   OS_DEFINE_QUICK_ENUM (O_DIRECT);
1114 #endif
1115   OS_DEFINE_QUICK_ENUM (O_DIRECTORY);
1116   OS_DEFINE_QUICK_ENUM (O_NOFOLLOW);
1117 #if defined (O_NOATIME)
1118   OS_DEFINE_QUICK_ENUM (O_NOATIME);
1119 #endif
1120
1121   OS_DEFINE_QUICK_ENUM (SEEK_SET);
1122   OS_DEFINE_QUICK_ENUM (SEEK_CUR);
1123   OS_DEFINE_QUICK_ENUM (SEEK_END);
1124
1125   OS_DEFINE_QUICK_ENUM (F_OK);
1126   OS_DEFINE_QUICK_ENUM (R_OK);
1127   OS_DEFINE_QUICK_ENUM (W_OK);
1128   OS_DEFINE_QUICK_ENUM (X_OK);
1129
1130   return os_namespace;
1131 }