2005-09-20 Alexander Olk <alex.olk@googlemail.com>
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / Stdlib.cs
1 //
2 // Mono.Unix/Stdlib.cs
3 //
4 // Authors:
5 //   Jonathan Pryor (jonpryor@vt.edu)
6 //
7 // (C) 2004-2005 Jonathan Pryor
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections;
31 using System.IO;
32 using System.Runtime.InteropServices;
33 using System.Text;
34 using Mono.Unix;
35
36 namespace Mono.Unix {
37
38         #region Enumerations
39
40         [Map]
41         public enum Error : int {
42                 // errors & their values liberally copied from
43                 // FC2 /usr/include/asm/errno.h
44                 
45                 EPERM           =   1, // Operation not permitted 
46                 ENOENT          =   2, // No such file or directory 
47                 ESRCH           =   3, // No such process 
48                 EINTR           =   4, // Interrupted system call 
49                 EIO             =   5, // I/O error 
50                 ENXIO           =   6, // No such device or address 
51                 E2BIG           =   7, // Arg list too long 
52                 ENOEXEC         =   8, // Exec format error 
53                 EBADF           =   9, // Bad file number 
54                 ECHILD          =  10, // No child processes 
55                 EAGAIN          =  11, // Try again 
56                 ENOMEM          =  12, // Out of memory 
57                 EACCES          =  13, // Permission denied 
58                 EFAULT          =  14, // Bad address 
59                 ENOTBLK         =  15, // Block device required 
60                 EBUSY           =  16, // Device or resource busy 
61                 EEXIST          =  17, // File exists 
62                 EXDEV           =  18, // Cross-device link 
63                 ENODEV          =  19, // No such device 
64                 ENOTDIR         =  20, // Not a directory 
65                 EISDIR          =  21, // Is a directory 
66                 EINVAL          =  22, // Invalid argument 
67                 ENFILE          =  23, // File table overflow 
68                 EMFILE          =  24, // Too many open files 
69                 ENOTTY          =  25, // Not a typewriter 
70                 ETXTBSY         =  26, // Text file busy 
71                 EFBIG           =  27, // File too large 
72                 ENOSPC          =  28, // No space left on device 
73                 ESPIPE          =  29, // Illegal seek 
74                 EROFS           =  30, // Read-only file system 
75                 EMLINK          =  31, // Too many links 
76                 EPIPE           =  32, // Broken pipe 
77                 EDOM            =  33, // Math argument out of domain of func 
78                 ERANGE          =  34, // Math result not representable 
79                 EDEADLK         =  35, // Resource deadlock would occur 
80                 ENAMETOOLONG    =  36, // File name too long 
81                 ENOLCK          =  37, // No record locks available 
82                 ENOSYS          =  38, // Function not implemented 
83                 ENOTEMPTY       =  39, // Directory not empty 
84                 ELOOP           =  40, // Too many symbolic links encountered 
85                 EWOULDBLOCK     =  EAGAIN, // Operation would block 
86                 ENOMSG          =  42, // No message of desired type 
87                 EIDRM           =  43, // Identifier removed 
88                 ECHRNG          =  44, // Channel number out of range 
89                 EL2NSYNC        =  45, // Level 2 not synchronized 
90                 EL3HLT          =  46, // Level 3 halted 
91                 EL3RST          =  47, // Level 3 reset 
92                 ELNRNG          =  48, // Link number out of range 
93                 EUNATCH         =  49, // Protocol driver not attached 
94                 ENOCSI          =  50, // No CSI structure available 
95                 EL2HLT          =  51, // Level 2 halted 
96                 EBADE           =  52, // Invalid exchange 
97                 EBADR           =  53, // Invalid request descriptor 
98                 EXFULL          =  54, // Exchange full 
99                 ENOANO          =  55, // No anode 
100                 EBADRQC         =  56, // Invalid request code 
101                 EBADSLT         =  57, // Invalid slot 
102                       
103                 EDEADLOCK             =  EDEADLK,
104                       
105                 EBFONT          =  59, // Bad font file format 
106                 ENOSTR          =  60, // Device not a stream 
107                 ENODATA         =  61, // No data available 
108                 ETIME           =  62, // Timer expired 
109                 ENOSR           =  63, // Out of streams resources 
110                 ENONET          =  64, // Machine is not on the network 
111                 ENOPKG          =  65, // Package not installed 
112                 EREMOTE         =  66, // Object is remote 
113                 ENOLINK         =  67, // Link has been severed 
114                 EADV            =  68, // Advertise error 
115                 ESRMNT          =  69, // Srmount error 
116                 ECOMM           =  70, // Communication error on send 
117                 EPROTO          =  71, // Protocol error 
118                 EMULTIHOP       =  72, // Multihop attempted 
119                 EDOTDOT         =  73, // RFS specific error 
120                 EBADMSG         =  74, // Not a data message 
121                 EOVERFLOW       =  75, // Value too large for defined data type 
122                 ENOTUNIQ        =  76, // Name not unique on network 
123                 EBADFD          =  77, // File descriptor in bad state 
124                 EREMCHG         =  78, // Remote address changed 
125                 ELIBACC         =  79, // Can not access a needed shared library 
126                 ELIBBAD         =  80, // Accessing a corrupted shared library 
127                 ELIBSCN         =  81, // .lib section in a.out corrupted 
128                 ELIBMAX         =  82, // Attempting to link in too many shared libraries 
129                 ELIBEXEC        =  83, // Cannot exec a shared library directly 
130                 EILSEQ          =  84, // Illegal byte sequence 
131                 ERESTART        =  85, // Interrupted system call should be restarted 
132                 ESTRPIPE        =  86, // Streams pipe error 
133                 EUSERS          =  87, // Too many users 
134                 ENOTSOCK        =  88, // Socket operation on non-socket 
135                 EDESTADDRREQ    =  89, // Destination address required 
136                 EMSGSIZE        =  90, // Message too long 
137                 EPROTOTYPE      =  91, // Protocol wrong type for socket 
138                 ENOPROTOOPT     =  92, // Protocol not available 
139                 EPROTONOSUPPORT =  93, // Protocol not supported 
140                 ESOCKTNOSUPPORT =  94, // Socket type not supported 
141                 EOPNOTSUPP      =  95, // Operation not supported on transport endpoint 
142                 EPFNOSUPPORT    =  96, // Protocol family not supported 
143                 EAFNOSUPPORT    =  97, // Address family not supported by protocol 
144                 EADDRINUSE      =  98, // Address already in use 
145                 EADDRNOTAVAIL   =  99, // Cannot assign requested address 
146                 ENETDOWN        = 100, // Network is down 
147                 ENETUNREACH     = 101, // Network is unreachable 
148                 ENETRESET       = 102, // Network dropped connection because of reset 
149                 ECONNABORTED    = 103, // Software caused connection abort 
150                 ECONNRESET      = 104, // Connection reset by peer 
151                 ENOBUFS         = 105, // No buffer space available 
152                 EISCONN         = 106, // Transport endpoint is already connected 
153                 ENOTCONN        = 107, // Transport endpoint is not connected 
154                 ESHUTDOWN       = 108, // Cannot send after transport endpoint shutdown 
155                 ETOOMANYREFS    = 109, // Too many references: cannot splice 
156                 ETIMEDOUT       = 110, // Connection timed out 
157                 ECONNREFUSED    = 111, // Connection refused 
158                 EHOSTDOWN       = 112, // Host is down 
159                 EHOSTUNREACH    = 113, // No route to host 
160                 EALREADY        = 114, // Operation already in progress 
161                 EINPROGRESS     = 115, // Operation now in progress 
162                 ESTALE          = 116, // Stale NFS file handle 
163                 EUCLEAN         = 117, // Structure needs cleaning 
164                 ENOTNAM         = 118, // Not a XENIX named type file 
165                 ENAVAIL         = 119, // No XENIX semaphores available 
166                 EISNAM          = 120, // Is a named type file 
167                 EREMOTEIO       = 121, // Remote I/O error 
168                 EDQUOT          = 122, // Quota exceeded 
169
170                 ENOMEDIUM       = 123, // No medium found 
171                 EMEDIUMTYPE     = 124, // Wrong medium type 
172         }
173
174         #endregion
175
176         #region Classes
177
178         public sealed class FilePosition : IDisposable {
179
180                 private static readonly int FilePositionDumpSize = 
181                         Stdlib.DumpFilePosition (null, new HandleRef (null, IntPtr.Zero), 0);
182
183                 private HandleRef pos;
184
185                 public FilePosition ()
186                 {
187                         IntPtr p = Stdlib.CreateFilePosition ();
188                         if (p == IntPtr.Zero)
189                                 throw new OutOfMemoryException ("Unable to malloc fpos_t!");
190                         pos = new HandleRef (this, p);
191                 }
192
193                 internal HandleRef Handle {
194                         get {return pos;}
195                 }
196
197                 public void Dispose ()
198                 {
199                         Cleanup ();
200                         GC.SuppressFinalize (this);
201                 }
202
203                 private void Cleanup ()
204                 {
205                         if (pos.Handle != IntPtr.Zero) {
206                                 Stdlib.free (pos.Handle);
207                                 pos = new HandleRef (this, IntPtr.Zero);
208                         }
209                 }
210
211                 public override string ToString ()
212                 {
213                         return "(" + base.ToString () + " " + GetDump () + ")";
214                 }
215
216                 private string GetDump ()
217                 {
218                         if (FilePositionDumpSize <= 0)
219                                 return "internal error";
220
221                         StringBuilder buf = new StringBuilder (FilePositionDumpSize+1);
222
223                         if (Stdlib.DumpFilePosition (buf, Handle, FilePositionDumpSize+1) <= 0)
224                                 return "internal error dumping fpos_t";
225
226                         return buf.ToString ();
227                 }
228
229                 public override bool Equals (object obj)
230                 {
231                         if (obj == null || GetType() != obj.GetType())
232                                 return false;
233                         return ToString().Equals (obj.ToString());
234                 }
235
236                 public override int GetHashCode ()
237                 {
238                         return ToString ().GetHashCode ();
239                 }
240
241                 ~FilePosition ()
242                 {
243                         Cleanup ();
244                 }
245
246                 public static bool operator== (FilePosition lhs, FilePosition rhs)
247                 {
248                         return Object.Equals (lhs, rhs);
249                 }
250
251                 public static bool operator!= (FilePosition lhs, FilePosition rhs)
252                 {
253                         return !Object.Equals (lhs, rhs);
254                 }
255         }
256
257
258         //
259         // Right now using this attribute gives an assert because it
260         // isn't implemented.
261         //
262 #if NET_2_0 && UNMANAGED_FN_PTR_SUPPORT_FIXED
263         [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
264 #endif
265         public delegate void SignalHandler (int signal);
266
267 #if !NET_2_0
268         internal sealed class SignalWrapper {
269                 private IntPtr handler;
270
271                 internal SignalWrapper (IntPtr handler)
272                 {
273                         this.handler = handler;
274                 }
275
276                 public void InvokeSignalHandler (int signum)
277                 {
278                         Stdlib.InvokeSignalHandler (signum, handler);
279                 }
280         }
281 #endif
282
283         internal class XPrintfFunctions
284         {
285                 internal delegate object XPrintf (object[] parameters);
286
287                 internal static XPrintf printf;
288                 internal static XPrintf fprintf;
289                 internal static XPrintf snprintf;
290                 internal static XPrintf syslog;
291
292                 static XPrintfFunctions ()
293                 {
294                         CdeclFunction _printf = new CdeclFunction (Stdlib.LIBC, "printf", typeof(int));
295                         printf = new XPrintf (_printf.Invoke);
296
297                         CdeclFunction _fprintf = new CdeclFunction (Stdlib.LIBC, "fprintf", typeof(int));
298                         fprintf = new XPrintf (_fprintf.Invoke);
299
300                         CdeclFunction _snprintf = new CdeclFunction (Stdlib.MPH, 
301                                         "Mono_Posix_Stdlib_snprintf", typeof(int));
302                         snprintf = new XPrintf (_snprintf.Invoke);
303
304                         CdeclFunction _syslog = new CdeclFunction (Syscall.LIBC, "syslog", typeof(void));
305                         syslog = new XPrintf (_syslog.Invoke);
306                 }
307         }
308
309         //
310         // Convention: Functions that are part of the C standard library go here.
311         //
312         // For example, the man page should say something similar to:
313         //
314         //    CONFORMING TO
315         //           ISO 9899 (''ANSI C'')
316         //
317         // The intent is that members of this class should be portable to any system
318         // supporting the C runtime (read: non-Unix, including Windows).  Using
319         // anything from Syscall is non-portable, but restricting yourself to just
320         // Stdlib is intended to be portable.
321         //
322         public class Stdlib
323         {
324                 internal const string LIBC = "msvcrt";
325                 internal const string MPH  = "MonoPosixHelper";
326
327                 internal Stdlib () {}
328
329                 #region <errno.h> Declarations
330                 //
331                 // <errno.h>  -- COMPLETE
332                 //
333
334                 public static Error GetLastError ()
335                 {
336                         int errno = Marshal.GetLastWin32Error ();
337                         return UnixConvert.ToError (errno);
338                 }
339
340                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
341                                 EntryPoint="Mono_Posix_Stdlib_SetLastError")]
342                 private static extern void SetLastError (int error);
343
344                 public static void SetLastError (Error error)
345                 {
346                         int _error = UnixConvert.FromError (error);
347                         SetLastError (_error);
348                 }
349                 #endregion
350
351                 //
352                 // <signal.h>
353                 //
354                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
355                                 EntryPoint="Mono_Posix_Stdlib_InvokeSignalHandler")]
356                 internal static extern void InvokeSignalHandler (int signum, IntPtr handler);
357
358                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
359                                 EntryPoint="Mono_Posix_Stdlib_SIG_DFL")]
360                 private static extern IntPtr GetDefaultSignal ();
361
362                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
363                                 EntryPoint="Mono_Posix_Stdlib_SIG_ERR")]
364                 private static extern IntPtr GetErrorSignal ();
365
366                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
367                                 EntryPoint="Mono_Posix_Stdlib_SIG_IGN")]
368                 private static extern IntPtr GetIgnoreSignal ();
369
370                 private static readonly IntPtr _SIG_DFL = GetDefaultSignal ();
371                 private static readonly IntPtr _SIG_ERR = GetErrorSignal ();
372                 private static readonly IntPtr _SIG_IGN = GetIgnoreSignal ();
373
374                 private static void _ErrorHandler (int signum)
375                 {
376                         Console.Error.WriteLine ("Error handler invoked for signum " + 
377                                         signum + ".  Don't do that.");
378                 }
379
380                 private static void _DefaultHandler (int signum)
381                 {
382                         Console.Error.WriteLine ("Default handler invoked for signum " + 
383                                         signum + ".  Don't do that.");
384                 }
385
386                 private static void _IgnoreHandler (int signum)
387                 {
388                         Console.Error.WriteLine ("Ignore handler invoked for signum " + 
389                                         signum + ".  Don't do that.");
390                 }
391
392                 public static readonly SignalHandler SIG_DFL = new SignalHandler (_DefaultHandler);
393                 public static readonly SignalHandler SIG_ERR = new SignalHandler (_ErrorHandler);
394                 public static readonly SignalHandler SIG_IGN = new SignalHandler (_IgnoreHandler);
395
396                 private static readonly SignalHandler[] registered_signals;
397
398                 static Stdlib ()
399                 {
400                         Array signals = Enum.GetValues(typeof(Signum));
401                         registered_signals = new SignalHandler [(int) signals.GetValue (signals.Length-1)];
402                 }
403
404                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
405                                 SetLastError=true, EntryPoint="signal")]
406                 private static extern IntPtr sys_signal (int signum, SignalHandler handler);
407
408                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
409                                 SetLastError=true, EntryPoint="signal")]
410                 private static extern IntPtr sys_signal (int signum, IntPtr handler);
411
412                 public static SignalHandler signal (Signum signum, SignalHandler handler)
413                 {
414                         int _sig = UnixConvert.FromSignum (signum);
415
416                         lock (registered_signals) {
417                                 registered_signals [(int) signum] = handler;
418                         }
419
420                         IntPtr r;
421                         if (handler == SIG_DFL)
422                                 r = sys_signal (_sig, _SIG_DFL);
423                         else if (handler == SIG_ERR)
424                                 r = sys_signal (_sig, _SIG_ERR);
425                         else if (handler == SIG_IGN)
426                                 r = sys_signal (_sig, _SIG_IGN);
427                         else
428                                 r = sys_signal (_sig, handler);
429                         return TranslateHandler (r);
430                 }
431
432                 private static SignalHandler TranslateHandler (IntPtr handler)
433                 {
434                         if (handler == _SIG_DFL)
435                                 return SIG_DFL;
436                         if (handler == _SIG_ERR)
437                                 return SIG_ERR;
438                         if (handler == _SIG_IGN)
439                                 return SIG_IGN;
440 #if NET_2_0
441                         return (SignalHandler) Marshal.GetDelegateForFunctionPointer (handler, typeof(SignalHandler));
442 #else
443                         return new SignalHandler (new SignalWrapper (handler).InvokeSignalHandler);
444 #endif
445                 }
446
447                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, EntryPoint="raise")]
448                 private static extern int sys_raise (int sig);
449
450                 public static int raise (Signum sig)
451                 {
452                         int _sig = UnixConvert.FromSignum (sig);
453                         return sys_raise (_sig);
454                 }
455
456                 //
457                 // <stdio.h> -- COMPLETE except for :
458                 //    - the scanf(3) family .
459                 //    - vararg functions.
460                 //    - Horribly unsafe functions (gets(3)).
461                 //
462                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
463                                 EntryPoint="Mono_Posix_Stdlib__IOFBF")]
464                 private static extern int GetFullyBuffered ();
465
466                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
467                                 EntryPoint="Mono_Posix_Stdlib__IOLBF")]
468                 private static extern int GetLineBuffered ();
469
470                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
471                                 EntryPoint="Mono_Posix_Stdlib__IONBF")]
472                 private static extern int GetNonBuffered ();
473
474                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
475                                 EntryPoint="Mono_Posix_Stdlib_BUFSIZ")]
476                 private static extern int GetBufferSize ();
477
478                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
479                                 EntryPoint="Mono_Posix_Stdlib_CreateFilePosition")]
480                 internal static extern IntPtr CreateFilePosition ();
481
482                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
483                                 EntryPoint="Mono_Posix_Stdlib_DumpFilePosition")]
484                 internal static extern int DumpFilePosition (StringBuilder buf, HandleRef handle, int len);
485
486                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
487                                 EntryPoint="Mono_Posix_Stdlib_EOF")]
488                 private static extern int GetEOF ();
489
490                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
491                                 EntryPoint="Mono_Posix_Stdlib_FILENAME_MAX")]
492                 private static extern int GetFilenameMax ();
493
494                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
495                                 EntryPoint="Mono_Posix_Stdlib_FOPEN_MAX")]
496                 private static extern int GetFopenMax ();
497
498                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
499                                 EntryPoint="Mono_Posix_Stdlib_L_tmpnam")]
500                 private static extern int GetTmpnamLength ();
501
502                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
503                                 EntryPoint="Mono_Posix_Stdlib_stdin")]
504                 private static extern IntPtr GetStandardInput ();
505
506                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
507                                 EntryPoint="Mono_Posix_Stdlib_stdout")]
508                 private static extern IntPtr GetStandardOutput ();
509
510                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
511                                 EntryPoint="Mono_Posix_Stdlib_stderr")]
512                 private static extern IntPtr GetStandardError ();
513
514                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
515                                 EntryPoint="Mono_Posix_Stdlib_TMP_MAX")]
516                 private static extern int GetTmpMax ();
517
518                 public static readonly int    _IOFBF       = GetFullyBuffered ();
519                 public static readonly int    _IOLBF       = GetLineBuffered ();
520                 public static readonly int    _IONBF       = GetNonBuffered ();
521                 public static readonly int    BUFSIZ       = GetBufferSize ();
522                 public static readonly int    EOF          = GetEOF ();
523                 public static readonly int    FOPEN_MAX    = GetFopenMax ();
524                 public static readonly int    FILENAME_MAX = GetFilenameMax ();
525                 public static readonly int    L_tmpnam     = GetTmpnamLength ();
526                 public static readonly IntPtr stderr       = GetStandardError ();
527                 public static readonly IntPtr stdin        = GetStandardInput ();
528                 public static readonly IntPtr stdout       = GetStandardOutput ();
529                 public static readonly int    TMP_MAX      = GetTmpMax ();
530
531                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
532                 public static extern int remove (string filename);
533
534                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
535                 public static extern int rename (string oldpath, string newpath);
536
537                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
538                 public static extern IntPtr tmpfile ();
539
540                 private static object tmpnam_lock = new object ();
541
542                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
543                                 SetLastError=true, EntryPoint="tmpnam")]
544                 private static extern IntPtr sys_tmpnam (StringBuilder s);
545
546                 [Obsolete ("Syscall.mkstemp() should be preferred.")]
547                 public static string tmpnam (StringBuilder s)
548                 {
549                         if (s != null && s.Capacity < L_tmpnam)
550                                 throw new ArgumentOutOfRangeException ("s", "s.Capacity < L_tmpnam");
551                         lock (tmpnam_lock) {
552                                 IntPtr r = sys_tmpnam (s);
553                                 return UnixMarshal.PtrToString (r);
554                         }
555                 }
556
557                 [Obsolete ("Syscall.mkstemp() should be preferred.")]
558                 public static string tmpnam ()
559                 {
560                         lock (tmpnam_lock) {
561                                 IntPtr r = sys_tmpnam (null);
562                                 return UnixMarshal.PtrToString (r);
563                         }
564                 }
565
566                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
567                 public static extern int fclose (IntPtr stream);
568
569                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
570                 public static extern int fflush (IntPtr stream);
571
572                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
573                 public static extern IntPtr fopen (string path, string mode);
574
575                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
576                 public static extern IntPtr freopen (string path, string mode, IntPtr stream);
577
578                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
579                 public static extern void setbuf (IntPtr stream, IntPtr buf);
580
581                 public static unsafe void setbuf (IntPtr stream, byte* buf)
582                 {
583                         setbuf (stream, (IntPtr) buf);
584                 }
585
586                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
587                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_setvbuf")]
588                 public static extern int setvbuf (IntPtr stream, IntPtr buf, int mode, ulong size);
589
590                 public static unsafe int setvbuf (IntPtr stream, byte* buf, int mode, ulong size)
591                 {
592                         return setvbuf (stream, (IntPtr) buf, mode, size);
593                 }
594
595                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
596                                 EntryPoint="fprintf")]
597                 private static extern int sys_fprintf (IntPtr stream, string format, string message);
598
599                 public static int fprintf (IntPtr stream, string message)
600                 {
601                         return sys_fprintf (stream, "%s", message);
602                 }
603
604                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
605                                 "Use fprintf (IntPtr, string) instead.")]
606                 public static int fprintf (IntPtr stream, string format, params object[] parameters)
607                 {
608                         object[] _parameters = new object[checked(parameters.Length+2)];
609                         _parameters [0] = stream;
610                         _parameters [1] = format;
611                         Array.Copy (parameters, 0, _parameters, 2, parameters.Length);
612                         return (int) XPrintfFunctions.fprintf (_parameters);
613                 }
614
615                 /* SKIP: fscanf(3) */
616
617                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
618                                 EntryPoint="printf")]
619                 private static extern int sys_printf (string format, string message);
620
621                 public static int printf (string message)
622                 {
623                         return sys_printf ("%s", message);
624                 }
625
626                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
627                                 "Use printf (string) instead.")]
628                 public static int printf (string format, params object[] parameters)
629                 {
630                         object[] _parameters = new object[checked(parameters.Length+1)];
631                         _parameters [0] = format;
632                         Array.Copy (parameters, 0, _parameters, 1, parameters.Length);
633                         return (int) XPrintfFunctions.printf (_parameters);
634                 }
635
636                 /* SKIP: scanf(3) */
637
638                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
639                                 EntryPoint="Mono_Posix_Stdlib_snprintf")]
640                 private static extern int sys_snprintf (StringBuilder s, ulong n, 
641                                 string format, string message);
642
643                 public static int snprintf (StringBuilder s, ulong n, string message)
644                 {
645                         if (n > (ulong) s.Capacity)
646                                 throw new ArgumentOutOfRangeException ("n", "n must be <= s.Capacity");
647                         return sys_snprintf (s, n, "%s", message);
648                 }
649
650                 public static int snprintf (StringBuilder s, string message)
651                 {
652                         return sys_snprintf (s, (ulong) s.Capacity, "%s", message);
653                 }
654
655                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
656                                 "Use snprintf (StringBuilder, string) instead.")]
657                 public static int snprintf (StringBuilder s, ulong n, 
658                                 string format, params object[] parameters)
659                 {
660                         if (n > (ulong) s.Capacity)
661                                 throw new ArgumentOutOfRangeException ("n", "n must be <= s.Capacity");
662
663                         object[] _parameters = new object[checked(parameters.Length+3)];
664                         _parameters [0] = s;
665                         _parameters [1] = n;
666                         _parameters [2] = format;
667                         Array.Copy (parameters, 0, _parameters, 3, parameters.Length);
668                         return (int) XPrintfFunctions.snprintf (_parameters);
669                 }
670
671                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
672                                 "Use snprintf (StringBuilder, string) instead.")]
673                 public static int snprintf (StringBuilder s,
674                                 string format, params object[] parameters)
675                 {
676                         object[] _parameters = new object[checked(parameters.Length+3)];
677                         _parameters [0] = s;
678                         _parameters [1] = (ulong) s.Capacity;
679                         _parameters [2] = format;
680                         Array.Copy (parameters, 0, _parameters, 3, parameters.Length);
681                         return (int) XPrintfFunctions.snprintf (_parameters);
682                 }
683
684                 /*
685                  * SKIP:
686                  *    sprintf(3)
687                  *    sscanf(3)
688                  *    vfprintf(3)
689                  *    vfscanf(3)
690                  *    vprintf(3)
691                  *    vscanf(3)
692                  *    vsnprintf(3)
693                  *    vsprint(3)
694                  *    vsscanf(3)
695                  */
696
697                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
698                 public static extern int fgetc (IntPtr stream);
699
700                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
701                                 SetLastError=true, EntryPoint="fgets")]
702                 private static extern IntPtr sys_fgets (StringBuilder sb, int size, IntPtr stream);
703
704                 public static StringBuilder fgets (StringBuilder sb, int size, IntPtr stream)
705                 {
706                         IntPtr r = sys_fgets (sb, size, stream);
707                         if (r == IntPtr.Zero)
708                                 return null;
709                         return sb;
710                 }
711
712                 public static StringBuilder fgets (StringBuilder sb, IntPtr stream)
713                 {
714                         return fgets (sb, sb.Capacity, stream);
715                 }
716
717                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
718                 public static extern int fputc (int c, IntPtr stream);
719
720                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
721                 public static extern int fputs (string s, IntPtr stream);
722
723                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
724                 public static extern int getc (IntPtr stream);
725
726                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
727                 public static extern int getchar ();
728
729                 /* SKIP: gets(3) */
730
731                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
732                 public static extern int putc (int c, IntPtr stream);
733
734                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
735                 public static extern int putchar (int c);
736
737                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
738                 public static extern int puts (string s);
739
740                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
741                 public static extern int ungetc (int c, IntPtr stream);
742
743                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
744                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fread")]
745                 public static extern ulong fread (IntPtr ptr, ulong size, ulong nmemb, IntPtr stream);
746
747                 public static unsafe ulong fread (void* ptr, ulong size, ulong nmemb, IntPtr stream)
748                 {
749                         return fread ((IntPtr) ptr, size, nmemb, stream);
750                 }
751
752                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
753                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fread")]
754                 private static extern ulong sys_fread ([Out] byte[] ptr, 
755                                 ulong size, ulong nmemb, IntPtr stream);
756
757                 public static ulong fread (byte[] ptr, ulong size, ulong nmemb, IntPtr stream)
758                 {
759                         if ((size * nmemb) > (ulong) ptr.Length)
760                                 throw new ArgumentOutOfRangeException ("nmemb");
761                         return sys_fread (ptr, size, nmemb, stream);
762                 }
763
764                 public static ulong fread (byte[] ptr, IntPtr stream)
765                 {
766                         return fread (ptr, 1, (ulong) ptr.Length, stream);
767                 }
768
769                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
770                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fwrite")]
771                 public static extern ulong fwrite (IntPtr ptr, ulong size, ulong nmemb, IntPtr stream);
772
773                 public static unsafe ulong fwrite (void* ptr, ulong size, ulong nmemb, IntPtr stream)
774                 {
775                         return fwrite ((IntPtr) ptr, size, nmemb, stream);
776                 }
777
778                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
779                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fwrite")]
780                 private static extern ulong sys_fwrite (byte[] ptr, 
781                                 ulong size, ulong nmemb, IntPtr stream);
782
783                 public static ulong fwrite (byte[] ptr, ulong size, ulong nmemb, IntPtr stream)
784                 {
785                         if ((size * nmemb) > (ulong) ptr.Length)
786                                 throw new ArgumentOutOfRangeException ("nmemb");
787                         return sys_fwrite (ptr, size, nmemb, stream);
788                 }
789
790                 public static ulong fwrite (byte[] ptr, IntPtr stream)
791                 {
792                         return fwrite (ptr, 1, (ulong) ptr.Length, stream);
793                 }
794
795                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
796                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fgetpos")]
797                 private static extern int sys_fgetpos (IntPtr stream, HandleRef pos);
798
799                 public static int fgetpos (IntPtr stream, FilePosition pos)
800                 {
801                         return sys_fgetpos (stream, pos.Handle);
802                 }
803
804                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
805                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fseek")]
806                 private static extern int sys_fseek (IntPtr stream, long offset, int origin);
807
808                 public static int fseek (IntPtr stream, long offset, SeekFlags origin)
809                 {
810                         int _origin = UnixConvert.FromSeekFlags (origin);
811                         return sys_fseek (stream, offset, _origin);
812                 }
813
814                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
815                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fsetpos")]
816                 private static extern int sys_fsetpos (IntPtr stream, HandleRef pos);
817
818                 public static int fsetpos (IntPtr stream, FilePosition pos)
819                 {
820                         return sys_fsetpos (stream, pos.Handle);
821                 }
822
823                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
824                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_ftell")]
825                 public static extern long ftell (IntPtr stream);
826
827                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
828                 public static extern void rewind (IntPtr stream);
829
830                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
831                 public static extern void clearerr (IntPtr stream);
832
833                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
834                 public static extern int feof (IntPtr stream);
835
836                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
837                 public static extern int ferror (IntPtr stream);
838
839                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
840                 public static extern void perror (string s);
841
842                 //
843                 // <stdlib.h>
844                 //
845                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
846                                 EntryPoint="Mono_Posix_Stdlib_EXIT_FAILURE")]
847                 private static extern int GetExitFailure();
848
849                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
850                                 EntryPoint="Mono_Posix_Stdlib_EXIT_SUCCESS")]
851                 private static extern int GetExitSuccess ();
852
853                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
854                                 EntryPoint="Mono_Posix_Stdlib_MB_CUR_MAX")]
855                 private static extern int GetMbCurMax ();
856
857                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
858                                 EntryPoint="Mono_Posix_Stdlib_RAND_MAX")]
859                 private static extern int GetRandMax ();
860
861                 public static readonly int  EXIT_FAILURE = GetExitFailure ();
862                 public static readonly int  EXIT_SUCCESS = GetExitSuccess ();
863                 public static readonly int  MB_CUR_MAX   = GetMbCurMax ();
864                 public static readonly int  RAND_MAX     = GetRandMax ();
865
866                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
867                 public static extern int rand ();
868
869                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
870                 public static extern void srand (uint seed);
871
872                 // calloc(3):
873                 //    void *calloc (size_t nmemb, size_t size);
874                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
875                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_calloc")]
876                 public static extern IntPtr calloc (ulong nmemb, ulong size);
877
878                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
879                 public static extern void free (IntPtr ptr);
880
881                 // malloc(3):
882                 //    void *malloc(size_t size);
883                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
884                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_malloc")]
885                 public static extern IntPtr malloc (ulong size);
886
887                 // realloc(3):
888                 //    void *realloc(void *ptr, size_t size);
889                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
890                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_realloc")]
891                 public static extern IntPtr realloc (IntPtr ptr, ulong size);
892
893                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
894                 public static extern void abort ();
895
896                 /* SKIP: atexit(3) -- the GC should have collected most references by the
897                  * time this runs, so no delegates should exist, making it pointless. */
898
899                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
900                 public static extern void exit (int status);
901
902                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
903                 public static extern void _Exit (int status);
904
905                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, EntryPoint="getenv")]
906                 private static extern IntPtr sys_getenv (string name);
907
908                 public static string getenv (string name)
909                 {
910                         IntPtr r = sys_getenv (name);
911                         return UnixMarshal.PtrToString (r);
912                 }
913
914                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
915                 public static extern int system (string @string);
916
917                 //
918                 // <string.h>
919                 //
920
921                 private static object strerror_lock = new object ();
922
923                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
924                                 SetLastError=true, EntryPoint="strerror")]
925                 private static extern IntPtr sys_strerror (int errnum);
926
927                 public static string strerror (Error errnum)
928                 {
929                         int e = UnixConvert.FromError (errnum);
930                         lock (strerror_lock) {
931                                 IntPtr r = sys_strerror (e);
932                                 return UnixMarshal.PtrToString (r);
933                         }
934                 }
935         }
936
937         #endregion // Classes
938 }
939
940 // vim: noexpandtab