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