1 // =================================
  2 // Copyright (c) 2022 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System.Collections;
  7 using System.IO;
  8 
  9 namespace System.Os
 10 {
 11     public nothrow void Exit(byte exitCode)
 12     {
 13         exit(exitCode);
 14     }
 15     
 16     public int Fork()
 17     {
 18         int result = fork();
 19         if (result == -1)
 20         {
 21             ThrowSystemError();
 22         }
 23         return result;
 24     }
 25     
 26     public void Exec(const string& programconst List<string>& args)
 27     {
 28         Exec(programargsEnvironment.Instance());
 29     }
 30     
 31     public void Exec(const string& programconst List<string>& argsconst Environment& environment)
 32     {
 33         string prog = program;
 34         bool hasExtension = Path.HasExtension(prog);
 35         if (!hasExtension)
 36         {
 37             prog.Append(".x");
 38         }
 39         long size = prog.Length() + 1 + 16;
 40         for (const string& arg : args)
 41         {
 42             size = size + arg.Length() + 1 + 16;
 43         }
 44         size = size + 16;
 45         size = size + environment.Size();
 46         size = size + 16;
 47         UniquePtr<byte> block = cast<byte*>(MemAlloc(size));
 48         MemoryWriter writer(block.Get()size);
 49         const char** argv = cast<const char**>(cast<void*>(block.Get()));
 50         writer.Write(cast<long>(0));
 51         for (const string& arg : args)
 52         {
 53             writer.Write(cast<long>(0));
 54         }
 55         writer.Write(cast<long>(0));
 56         const char** envp = cast<const char**>(cast<void*>(block.Get() + writer.Offset()));
 57         for (const Pair<stringstring>& v : environment.Variables())
 58         {
 59             writer.Write(cast<long>(0));
 60         }
 61         writer.Write(cast<long>(0));
 62         List<byte*> addresses;
 63         addresses.Add(block.Get() + writer.Offset());
 64         writer.Write(prog);
 65         for (const string& arg : args)
 66         {
 67             addresses.Add(block.Get() + writer.Offset());
 68             writer.Write(arg);
 69         }
 70         addresses.Add(null);
 71         for (const Pair<stringstring>& v : environment.Variables())
 72         {
 73             string env = v.first;
 74             env.Append('=').Append(v.second);
 75             addresses.Add(block.Get() + writer.Offset());
 76             writer.Write(env);
 77         }
 78         addresses.Add(null);
 79         MemoryWriter headerWriter(block.Get()size);
 80         for (byte* address : addresses)
 81         {
 82             headerWriter.Write(cast<ulong>(cast<void*>(address)));
 83         }
 84         int result = exec(prog.Chars()argvenvp);
 85         if (result == -1)
 86         {
 87             ThrowSystemError();
 88         }
 89     }
 90     
 91     public int Wait(byte* exitCode)
 92     {
 93         int result = wait(exitCode);
 94         if (result == -1)
 95         {
 96             SystemError systemError = GetSystemError();
 97             if (systemError.errorCode == ENOCHILD)
 98             {
 99                 return -1;
100             }
101             else
102             {
103                 throw systemError;
104             }
105         }
106         return result;
107     }
108     
109     public int WaitPid(int pidbyte* exitCode)
110     {
111         int result = waitpid(pidexitCode);
112         if (result == -1)
113         {
114             SystemError systemError = GetSystemError();
115             if (systemError.errorCode == ENOCHILD)
116             {
117                 return -1;
118             }
119             else
120             {
121                 throw systemError;
122             }
123         }
124         return result;
125     }
126     
127     public int GetPid()
128     {
129         int result = getpid();
130         if (result == -1)
131         {
132             ThrowSystemError();
133         }
134         return result;
135     }
136 
137     public int Create(const char* pathint mode)
138     {
139         int result = create(pathmode);
140         if (result == -1)
141         {
142             ThrowSystemError();
143         }
144         return result;
145     }
146     
147     public int Open(const char* pathOpenFlags flagsint mode)
148     {
149         int result = open(pathflagsmode);
150         if (result == -1)
151         {
152             ThrowSystemError();
153         }
154         return result;
155     }
156     
157     public void Close(int fd)
158     {
159         int result = close(fd);
160         if (result == -1)
161         {
162             ThrowSystemError();
163         }
164     }
165     
166     public long Read(int fdvoid* bufferlong count)
167     {
168         long result = read(fdbuffercount);
169         if (result == -1)
170         {
171             ThrowSystemError();
172         }
173         return result;
174     }
175     
176     public long Write(int fdvoid* bufferlong count)
177     {
178         long result = write(fdbuffercount);
179         if (result == -1)
180         {
181             ThrowSystemError();
182         }
183         return result;
184     }
185     
186     public int IOCtl(int fdIOControlItem itembyte* arglong argSize)
187     {
188         int result = ioctl(fditemargargSize);
189         if (result == -1)
190         {
191             ThrowSystemError();
192         }
193         return result;
194     }
195     
196     public long Seek(int fdlong posOrigin origin)
197     {
198         long result = seek(fdposorigin);
199         if (result == -1)
200         {
201             ThrowSystemError();
202         }
203         return result;
204     }
205     
206     public long Tell(int fd)
207     {
208         long result = tell(fd);
209         if (result == -1)
210         {
211             ThrowSystemError();
212         }
213         return result;
214     }
215     
216     public void Unlink(const char* path)
217     {
218         int result = unlink(path);
219         if (result == -1)
220         {
221             ThrowSystemError();
222         }
223     }
224     
225     public void GetCWD(char* pathBuflong bufSize)
226     {
227         int result = getcwd(pathBufbufSize);
228         if (result == -1)
229         {
230             ThrowSystemError();
231         }
232     }
233     
234     public void ChDir(const char* path)
235     {
236         int result = chdir(path);
237         if (result == -1)
238         {
239             ThrowSystemError();
240         }
241     }
242     
243     public void MkDir(const char* path)
244     {
245         MkDir(path0);
246     }
247     
248     public void MkDir(const char* pathint mode)
249     {
250         int result = mkdir(pathmode);
251         if (result == -1)
252         {
253             ThrowSystemError();
254         }
255     }
256     
257     public void UTime(const char* pathbyte* timeBuflong timeBufSize)
258     {
259         int result = utime(pathtimeBuftimeBufSize);
260         if (result == -1)
261         {
262             ThrowSystemError();
263         }
264     }
265 
266     public int OpenDir(const char* dirPath)
267     {
268         int result = opendir(dirPath);
269         if (result == -1)
270         {
271             ThrowSystemError();
272         }
273         return result;
274     }
275     
276     public void CloseDir(int dfd)
277     {
278         int result = closedir(dfd);
279         if (result == -1)
280         {
281             ThrowSystemError();
282         }
283     }
284     
285     public int ReadDir(int dfdbyte* dirEntryBuflong dirEntryBufSize)
286     {
287         int result = readdir(dfddirEntryBufdirEntryBufSize);
288         if (result == -1)
289         {
290             ThrowSystemError();
291         }
292         return result;
293     }
294     
295     public int OpenResource(const char* resource_name)
296     {
297         int rd = open_resource(resource_name);
298         if (rd == -1)
299         {
300             ThrowSystemError();
301         }
302         return rd;
303     }
304     
305     public void CloseResource(int rd)
306     {
307         int result = close_resource(rd);
308         if (result == -1)
309         {
310             ThrowSystemError();
311         }
312     }
313     
314     public long GetResourceSize(int rd)
315     {
316         long size = get_resource_size(rd);
317         if (size == -1)
318         {
319             ThrowSystemError();
320         }
321         return size;
322     }
323     
324     public void ReadResource(int rdlong offsetlong sizebyte* buffer)
325     {
326         int result = read_resource(rdoffsetsizebuffer);
327         if (result == -1)
328         {
329             ThrowSystemError();
330         }
331     }
332     
333     public int Decompress(byte* bufferlong count)
334     {
335         int dd = decompress(buffercount);
336         if (dd == -1)
337         {
338             ThrowSystemError();
339         }
340         return dd;
341     }
342     
343     public long GetDecompressedDataSize(int dd)
344     {
345         long size = get_decompressed_data_size(dd);
346         if (size == -1)
347         {
348             ThrowSystemError();
349         }
350         return size;
351     }
352     
353     public void GetDecompressedData(int ddbyte* bufferlong count)
354     {
355         int result = get_decompressed_data(ddbuffercount);
356         if (result == -1)
357         {
358             ThrowSystemError();
359         }
360     }
361     
362     public void CloseDecompression(int dd)
363     {
364         int result = close_decompression(dd);
365         if (result == -1)
366         {
367             ThrowSystemError();
368         }
369     }
370     
371     public string GetHostName()
372     {
373         char[256] buffer;
374         int result = get_host_name(&buffer[0]256);
375         if (result == -1)
376         {
377             ThrowSystemError();
378         }
379         return string(&buffer[0]);
380     }
381     
382     public string GetUserName()
383     {
384         char[256] buffer;
385         int result = get_user_name(&buffer[0]256);
386         if (result == -1)
387         {
388             ThrowSystemError();
389         }
390         return string(&buffer[0]);
391     }
392     
393     public void Pipe(int* readerFdint* writerFd)
394     {
395         int result = pipe(readerFdwriterFd);
396         if (result == -1)
397         {
398             ThrowSystemError();
399         }
400     }
401     
402     public int Dup(int fd)
403     {
404         int result = dup(fd);
405         if (result == -1)
406         {
407             ThrowSystemError();
408         }
409         return result;
410     }
411     
412     public void SetUID(int uid)
413     {
414         int result = setuid(uid);
415         if (result == -1)
416         {
417             ThrowSystemError();
418         }
419     }
420 
421     public void SetGID(int gid)
422     {
423         int result = setgid(gid);
424         if (result == -1)
425         {
426             ThrowSystemError();
427         }
428     }
429     
430     public int GetUID()
431     {
432         int result = getuid();
433         if (result == -1)
434         {
435             ThrowSystemError();
436         }
437         return result;
438     }
439 
440     public int GetGID()
441     {
442         int result = getgid();
443         if (result == -1)
444         {
445             ThrowSystemError();
446         }
447         return result;
448     }
449     
450     public void SetEUID(int euid)
451     {
452         int result = seteuid(euid);
453         if (result == -1)
454         {
455             ThrowSystemError();
456         }
457     }
458 
459     public void SetEGID(int egid)
460     {
461         int result = setegid(egid);
462         if (result == -1)
463         {
464             ThrowSystemError();
465         }
466     }
467     
468     public int GetEUID()
469     {
470         int result = geteuid();
471         if (result == -1)
472         {
473             ThrowSystemError();
474         }
475         return result;
476     }
477 
478     public int GetEGID()
479     {
480         int result = getegid();
481         if (result == -1)
482         {
483             ThrowSystemError();
484         }
485         return result;
486     }
487     
488     public int UMask(int mask)
489     {
490         int result = umask(mask);
491         if (result == -1)
492         {
493             ThrowSystemError();
494         }
495         return result;
496     }
497     
498     public void ChMod(const char* pathint mode)
499     {
500         int result = chmod(pathmode);
501         if (result == -1)
502         {
503             ThrowSystemError();
504         }
505     }
506     
507     public void ChOwn(const char* pathint uidint gid)
508     {
509         int result = chown(pathuidgid);
510         if (result == -1)
511         {
512             ThrowSystemError();
513         }
514     }
515     
516     public void Rename(const char* sourceconst char* target)
517     {
518         int result = rename(sourcetarget);
519         if (result == -1)
520         {
521             ThrowSystemError();
522         }
523     }
524     
525     public void AddDirChangeNotification(const char* directories)
526     {
527         int result = add_dir_change_notification(directories);
528         if (result == -1)
529         {
530             ThrowSystemError();
531         }
532     }
533     
534     public void RemoveDirChangeNotifications()
535     {
536         int result = remove_dir_change_notifications();
537         if (result == -1)
538         {
539             ThrowSystemError();
540         }
541     }
542     
543     public bool DirectoriesChanged()
544     {
545         int result = directories_changed();
546         if (result == -1)
547         {
548             ThrowSystemError();
549         }
550         return result == 1;
551     }
552     
553     public void ClearDirectoriesChanged()
554     {
555         int result = clear_directories_changed();
556         if (result == -1)
557         {
558             ThrowSystemError();
559         }
560     }
561     
562     public int MsgQ(const char* name)
563     {
564         int result = msgq(name);
565         if (result == -1)
566         {
567             ThrowSystemError();
568         }
569         return result;
570     }
571     
572     public void CloseMsgQ(int md)
573     {
574         int result = close_msgq(md);
575         if (result == -1)
576         {
577             ThrowSystemError();
578         }
579     }
580     
581     public void WaitMsg(int md)
582     {
583         int result = wait_msg(md);
584         if (result == -1)
585         {
586             ThrowSystemError();
587         }
588     }
589     
590     public void PutMsg(int mdbyte* msgDataint msgSize)
591     {
592         int result = put_msg(mdmsgDatamsgSize);
593         if (result == -1)
594         {
595             ThrowSystemError();
596         }
597     }
598     
599     public int GetMsgQLength(int md)
600     {
601         int result = get_msgq_length(md);
602         if (result == -1)
603         {
604             ThrowSystemError();
605         }
606         return result;
607     }
608     
609     public int GetMsgSize(int md)
610     {
611         int result = get_msg_size(md);
612         if (result == -1)
613         {
614             ThrowSystemError();
615         }
616         return result;
617     }
618     
619     public void GetMsg(int mdbyte* buffer)
620     {
621         int result = get_msg(mdbuffer);
622         if (result == -1)
623         {
624             ThrowSystemError();
625         }
626     }
627     
628     public void BindTerminal(int md)
629     {
630         int result = bind_terminal(md);
631         if (result == -1)
632         {
633             ThrowSystemError();
634         }
635     }
636     
637     public void UnbindTerminal()
638     {
639         int result = unbind_terminal();
640         if (result == -1)
641         {
642             ThrowSystemError();
643         }
644     }
645     
646     public void Tab(int fdint putTabMsgQint getTabMsgQ)
647     {
648         byte[8] arg;
649         MemoryWriter writer(&arg[0]8);
650         writer.Write(putTabMsgQ);
651         writer.Write(getTabMsgQ);
652         IOCtl(fdIOControlItem.tab&arg[0]8);
653     }
654     
655     public void Untab(int fd)
656     {
657         IOCtl(fdIOControlItem.untabnull0);
658     }
659     
660     public void PushPid(int fdint pid)
661     {
662         byte[4] arg;
663         MemoryWriter writer(&arg[0]4);
664         writer.Write(pid);
665         IOCtl(fdIOControlItem.push_pid&arg[0]4);
666     }
667     
668     public void PopPid(int fd)
669     {
670         IOCtl(fdIOControlItem.pop_pidnull0);
671     }
672     
673     public void TimerMsg(const Duration& durationint mdbyte* msgDataint msgSize)
674     {
675         int result = timer_msg(duration.Rep()mdmsgDatamsgSize);
676         if (result == -1)
677         {
678             ThrowSystemError();
679         }
680     }
681     
682     public int Connect(const char* nodeconst char* service)
683     {
684         int result = connect(nodeservice);
685         if (result == -1)
686         {
687             ThrowSystemError();
688         }
689         return result;
690     }
691     
692     public void Kill(int pid)
693     {
694         int result = kill(pid);
695         if (result == -1)
696         {
697             ThrowSystemError();
698         }
699     }
700 }