Changed API for fetching StackFrames in bulk on multiple threads ThreadMirror.FetchFr...
[mono.git] / mcs / class / Mono.Posix / Mono.Unix.Native / Stdlib.cs
1 //
2 // Mono.Unix/Stdlib.cs
3 //
4 // Authors:
5 //   Jonathan Pryor (jonpryor@vt.edu)
6 //
7 // (C) 2004-2006 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.Native;
35
36 namespace Mono.Unix.Native {
37
38         #region Enumerations
39
40         [Map]
41         public enum Errno : 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 : MarshalByRefObject, IDisposable 
179 #if NET_2_0
180                 , IEquatable <FilePosition>
181 #endif
182         {
183
184                 private static readonly int FilePositionDumpSize = 
185                         Stdlib.DumpFilePosition (null, new HandleRef (null, IntPtr.Zero), 0);
186
187                 private HandleRef pos;
188
189                 public FilePosition ()
190                 {
191                         IntPtr p = Stdlib.CreateFilePosition ();
192                         if (p == IntPtr.Zero)
193                                 throw new OutOfMemoryException ("Unable to malloc fpos_t!");
194                         pos = new HandleRef (this, p);
195                 }
196
197                 internal HandleRef Handle {
198                         get {return pos;}
199                 }
200
201                 public void Dispose ()
202                 {
203                         Cleanup ();
204                         GC.SuppressFinalize (this);
205                 }
206
207                 private void Cleanup ()
208                 {
209                         if (pos.Handle != IntPtr.Zero) {
210                                 Stdlib.free (pos.Handle);
211                                 pos = new HandleRef (this, IntPtr.Zero);
212                         }
213                 }
214
215                 public override string ToString ()
216                 {
217                         return "(" + base.ToString () + " " + GetDump () + ")";
218                 }
219
220                 private string GetDump ()
221                 {
222                         if (FilePositionDumpSize <= 0)
223                                 return "internal error";
224
225                         StringBuilder buf = new StringBuilder (FilePositionDumpSize+1);
226
227                         if (Stdlib.DumpFilePosition (buf, Handle, FilePositionDumpSize+1) <= 0)
228                                 return "internal error dumping fpos_t";
229
230                         return buf.ToString ();
231                 }
232
233                 public override bool Equals (object obj)
234                 {
235                         FilePosition fp = obj as FilePosition;
236                         if (obj == null || fp == null)
237                                 return false;
238                         return ToString().Equals (obj.ToString());
239                 }
240
241                 public bool Equals (FilePosition value)
242                 {
243                         if (object.ReferenceEquals (this, value))
244                                 return true;
245                         return ToString().Equals (value.ToString());
246                 }
247
248                 public override int GetHashCode ()
249                 {
250                         return ToString ().GetHashCode ();
251                 }
252
253                 ~FilePosition ()
254                 {
255                         Cleanup ();
256                 }
257
258                 public static bool operator== (FilePosition lhs, FilePosition rhs)
259                 {
260                         return Object.Equals (lhs, rhs);
261                 }
262
263                 public static bool operator!= (FilePosition lhs, FilePosition rhs)
264                 {
265                         return !Object.Equals (lhs, rhs);
266                 }
267         }
268
269
270         public enum SignalAction {
271                 Default,
272                 Ignore,
273                 Error
274         }
275
276         //
277         // Right now using this attribute gives an assert because it
278         // isn't implemented.
279         //
280 #if NET_2_0 && UNMANAGED_FN_PTR_SUPPORT_FIXED
281         [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
282 #endif
283         public delegate void SignalHandler (int signal);
284
285 #if !NET_2_0
286         internal sealed class SignalWrapper {
287                 private IntPtr handler;
288
289                 internal SignalWrapper (IntPtr handler)
290                 {
291                         this.handler = handler;
292                 }
293
294                 public void InvokeSignalHandler (int signum)
295                 {
296                         Stdlib.InvokeSignalHandler (signum, handler);
297                 }
298         }
299 #endif
300
301         internal class XPrintfFunctions
302         {
303                 internal delegate object XPrintf (object[] parameters);
304
305                 internal static XPrintf printf;
306                 internal static XPrintf fprintf;
307                 internal static XPrintf snprintf;
308                 internal static XPrintf syslog;
309
310                 static XPrintfFunctions ()
311                 {
312                         CdeclFunction _printf = new CdeclFunction (Stdlib.LIBC, "printf", typeof(int));
313                         printf = new XPrintf (_printf.Invoke);
314
315                         CdeclFunction _fprintf = new CdeclFunction (Stdlib.LIBC, "fprintf", typeof(int));
316                         fprintf = new XPrintf (_fprintf.Invoke);
317
318                         CdeclFunction _snprintf = new CdeclFunction (Stdlib.MPH, 
319                                         "Mono_Posix_Stdlib_snprintf", typeof(int));
320                         snprintf = new XPrintf (_snprintf.Invoke);
321
322                         CdeclFunction _syslog = new CdeclFunction (Syscall.MPH, 
323                                         "Mono_Posix_Stdlib_syslog2", typeof(int));
324                         syslog = new XPrintf (_syslog.Invoke);
325                 }
326         }
327
328         //
329         // Convention: Functions that are part of the C standard library go here.
330         //
331         // For example, the man page should say something similar to:
332         //
333         //    CONFORMING TO
334         //           ISO 9899 (''ANSI C'')
335         //
336         // The intent is that members of this class should be portable to any system
337         // supporting the C runtime (read: non-Unix, including Windows).  Using
338         // anything from Syscall is non-portable, but restricting yourself to just
339         // Stdlib is intended to be portable.
340         //
341         // The only methods in here should be:
342         //  (1) low-level functions (as defined above).
343         //  (2) "Trivial" function overloads.  For example, if the parameters to a
344         //      function are related (e.g. fwrite(3))
345         //  (3) The return type SHOULD NOT be changed.  If you want to provide a
346         //      convenience function with a nicer return type, place it into one of
347         //      the Mono.Unix.Std* wrapper classes, and give it a .NET-styled name.
348         //      - EXCEPTION: No public functions should have a `void' return type.
349         //        `void' return types should be replaced with `int'.
350         //        Rationality: `void'-return functions typically require a
351         //        complicated call sequence, such as clear errno, then call, then
352         //        check errno to see if any errors occurred.  This sequence can't 
353         //        be done safely in managed code, as errno may change as part of 
354         //        the P/Invoke mechanism.
355         //        Instead, add a MonoPosixHelper export which does:
356         //          errno = 0;
357         //          INVOKE SYSCALL;
358         //          return errno == 0 ? 0 : -1;
359         //        This lets managed code check the return value in the usual manner.
360         //  (4) Exceptions SHOULD NOT be thrown.  EXCEPTIONS: 
361         //      - If you're wrapping *broken* methods which make assumptions about 
362         //        input data, such as that an argument refers to N bytes of data.  
363         //        This is currently limited to cuserid(3) and encrypt(3).
364         //      - If you call functions which themselves generate exceptions.  
365         //        This is the case for using NativeConvert, which will throw an
366         //        exception if an invalid/unsupported value is used.
367         //
368         public class Stdlib
369         {
370                 internal const string LIBC = "msvcrt";
371                 internal const string MPH  = "MonoPosixHelper";
372
373                 internal Stdlib () {}
374
375                 #region <errno.h> Declarations
376                 //
377                 // <errno.h>  -- COMPLETE
378                 //
379
380                 public static Errno GetLastError ()
381                 {
382                         int errno = Marshal.GetLastWin32Error ();
383                         return NativeConvert.ToErrno (errno);
384                 }
385
386                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
387                                 EntryPoint="Mono_Posix_Stdlib_SetLastError")]
388                 private static extern void SetLastError (int error);
389
390                 protected static void SetLastError (Errno error)
391                 {
392                         int _error = NativeConvert.FromErrno (error);
393                         SetLastError (_error);
394                 }
395
396                 #endregion
397
398                 //
399                 // <signal.h>
400                 //
401                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
402                                 EntryPoint="Mono_Posix_Stdlib_InvokeSignalHandler")]
403                 internal static extern void InvokeSignalHandler (int signum, IntPtr handler);
404
405                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
406                                 EntryPoint="Mono_Posix_Stdlib_SIG_DFL")]
407                 private static extern IntPtr GetDefaultSignal ();
408
409                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
410                                 EntryPoint="Mono_Posix_Stdlib_SIG_ERR")]
411                 private static extern IntPtr GetErrorSignal ();
412
413                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
414                                 EntryPoint="Mono_Posix_Stdlib_SIG_IGN")]
415                 private static extern IntPtr GetIgnoreSignal ();
416
417                 private static readonly IntPtr _SIG_DFL = GetDefaultSignal ();
418                 private static readonly IntPtr _SIG_ERR = GetErrorSignal ();
419                 private static readonly IntPtr _SIG_IGN = GetIgnoreSignal ();
420
421                 private static void _ErrorHandler (int signum)
422                 {
423                         Console.Error.WriteLine ("Error handler invoked for signum " + 
424                                         signum + ".  Don't do that.");
425                 }
426
427                 private static void _DefaultHandler (int signum)
428                 {
429                         Console.Error.WriteLine ("Default handler invoked for signum " + 
430                                         signum + ".  Don't do that.");
431                 }
432
433                 private static void _IgnoreHandler (int signum)
434                 {
435                         Console.Error.WriteLine ("Ignore handler invoked for signum " + 
436                                         signum + ".  Don't do that.");
437                 }
438
439                 [CLSCompliant (false)]
440                 public static readonly SignalHandler SIG_DFL = new SignalHandler (_DefaultHandler);
441                 [CLSCompliant (false)]
442                 public static readonly SignalHandler SIG_ERR = new SignalHandler (_ErrorHandler);
443                 [CLSCompliant (false)]
444                 public static readonly SignalHandler SIG_IGN = new SignalHandler (_IgnoreHandler);
445
446                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
447                                 SetLastError=true, EntryPoint="signal")]
448                 private static extern IntPtr sys_signal (int signum, SignalHandler handler);
449
450                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
451                                 SetLastError=true, EntryPoint="signal")]
452                 private static extern IntPtr sys_signal (int signum, IntPtr handler);
453
454                 [CLSCompliant (false)]
455                 [Obsolete ("This is not safe; " + 
456                                 "use Mono.Unix.UnixSignal for signal delivery or SetSignalAction()")]
457                 public static SignalHandler signal (Signum signum, SignalHandler handler)
458                 {
459                         int _sig = NativeConvert.FromSignum (signum);
460
461                         Delegate[] handlers = handler.GetInvocationList ();
462                         for (int i = 0; i < handlers.Length; ++i) {
463                                 Marshal.Prelink (handlers [i].Method);
464                         }
465
466                         IntPtr r;
467                         if (handler == SIG_DFL)
468                                 r = sys_signal (_sig, _SIG_DFL);
469                         else if (handler == SIG_ERR)
470                                 r = sys_signal (_sig, _SIG_ERR);
471                         else if (handler == SIG_IGN)
472                                 r = sys_signal (_sig, _SIG_IGN);
473                         else
474                                 r = sys_signal (_sig, handler);
475                         return TranslateHandler (r);
476                 }
477
478                 private static SignalHandler TranslateHandler (IntPtr handler)
479                 {
480                         if (handler == _SIG_DFL)
481                                 return SIG_DFL;
482                         if (handler == _SIG_ERR)
483                                 return SIG_ERR;
484                         if (handler == _SIG_IGN)
485                                 return SIG_IGN;
486 #if NET_2_0
487                         return (SignalHandler) Marshal.GetDelegateForFunctionPointer (handler, typeof(SignalHandler));
488 #else
489                         return new SignalHandler (new SignalWrapper (handler).InvokeSignalHandler);
490 #endif
491                 }
492
493                 public static int SetSignalAction (Signum signal, SignalAction action)
494                 {
495                         return SetSignalAction (NativeConvert.FromSignum (signal), action);
496                 }
497
498                 public static int SetSignalAction (RealTimeSignum rts, SignalAction action)
499                 {
500                         return SetSignalAction (NativeConvert.FromRealTimeSignum (rts), action);
501                 }
502                 
503                 private static int SetSignalAction (int signum, SignalAction action)
504                 {
505                         IntPtr handler = IntPtr.Zero;
506                         switch (action) {
507                                 case SignalAction.Default:
508                                         handler = _SIG_DFL;
509                                         break;
510                                 case SignalAction.Ignore:
511                                         handler = _SIG_IGN;
512                                         break;
513                                 case SignalAction.Error:
514                                         handler = _SIG_ERR;
515                                         break;
516                                 default:
517                                         throw new ArgumentException ("Invalid action value.", "action");
518                         }
519                         IntPtr r = sys_signal (signum, handler);
520                         if (r == _SIG_ERR)
521                                 return -1;
522                         return 0;
523                 }
524
525                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, EntryPoint="raise")]
526                 private static extern int sys_raise (int sig);
527
528                 [CLSCompliant (false)]
529                 public static int raise (Signum sig)
530                 {
531                         return sys_raise (NativeConvert.FromSignum (sig));
532                 }
533
534                 public static int raise (RealTimeSignum rts)
535                 {
536                         return sys_raise (NativeConvert.FromRealTimeSignum (rts));
537                 }
538
539                 //
540                 // <stdio.h> -- COMPLETE except for :
541                 //    - the scanf(3) family .
542                 //    - vararg functions.
543                 //    - Horribly unsafe functions (gets(3)).
544                 //
545                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
546                                 EntryPoint="Mono_Posix_Stdlib__IOFBF")]
547                 private static extern int GetFullyBuffered ();
548
549                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
550                                 EntryPoint="Mono_Posix_Stdlib__IOLBF")]
551                 private static extern int GetLineBuffered ();
552
553                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
554                                 EntryPoint="Mono_Posix_Stdlib__IONBF")]
555                 private static extern int GetNonBuffered ();
556
557                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
558                                 EntryPoint="Mono_Posix_Stdlib_BUFSIZ")]
559                 private static extern int GetBufferSize ();
560
561                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
562                                 EntryPoint="Mono_Posix_Stdlib_CreateFilePosition")]
563                 internal static extern IntPtr CreateFilePosition ();
564
565                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
566                                 EntryPoint="Mono_Posix_Stdlib_DumpFilePosition")]
567                 internal static extern int DumpFilePosition (StringBuilder buf, HandleRef handle, int len);
568
569                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
570                                 EntryPoint="Mono_Posix_Stdlib_EOF")]
571                 private static extern int GetEOF ();
572
573                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
574                                 EntryPoint="Mono_Posix_Stdlib_FILENAME_MAX")]
575                 private static extern int GetFilenameMax ();
576
577                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
578                                 EntryPoint="Mono_Posix_Stdlib_FOPEN_MAX")]
579                 private static extern int GetFopenMax ();
580
581                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
582                                 EntryPoint="Mono_Posix_Stdlib_L_tmpnam")]
583                 private static extern int GetTmpnamLength ();
584
585                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
586                                 EntryPoint="Mono_Posix_Stdlib_stdin")]
587                 private static extern IntPtr GetStandardInput ();
588
589                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
590                                 EntryPoint="Mono_Posix_Stdlib_stdout")]
591                 private static extern IntPtr GetStandardOutput ();
592
593                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
594                                 EntryPoint="Mono_Posix_Stdlib_stderr")]
595                 private static extern IntPtr GetStandardError ();
596
597                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
598                                 EntryPoint="Mono_Posix_Stdlib_TMP_MAX")]
599                 private static extern int GetTmpMax ();
600
601                 [CLSCompliant (false)]
602                 public static readonly int    _IOFBF       = GetFullyBuffered ();
603                 [CLSCompliant (false)]
604                 public static readonly int    _IOLBF       = GetLineBuffered ();
605                 [CLSCompliant (false)]
606                 public static readonly int    _IONBF       = GetNonBuffered ();
607                 [CLSCompliant (false)]
608                 public static readonly int    BUFSIZ       = GetBufferSize ();
609                 [CLSCompliant (false)]
610                 public static readonly int    EOF          = GetEOF ();
611                 [CLSCompliant (false)]
612                 public static readonly int    FOPEN_MAX    = GetFopenMax ();
613                 [CLSCompliant (false)]
614                 public static readonly int    FILENAME_MAX = GetFilenameMax ();
615                 [CLSCompliant (false)]
616                 public static readonly int    L_tmpnam     = GetTmpnamLength ();
617                 public static readonly IntPtr stderr       = GetStandardError ();
618                 public static readonly IntPtr stdin        = GetStandardInput ();
619                 public static readonly IntPtr stdout       = GetStandardOutput ();
620                 [CLSCompliant (false)]
621                 public static readonly int    TMP_MAX      = GetTmpMax ();
622
623                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
624                 public static extern int remove (
625                                 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
626                                 string filename);
627
628                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
629                 public static extern int rename (
630                                 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
631                                 string oldpath, 
632                                 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
633                                 string newpath);
634
635                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
636                 public static extern IntPtr tmpfile ();
637
638                 private static object tmpnam_lock = new object ();
639
640                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
641                                 SetLastError=true, EntryPoint="tmpnam")]
642                 private static extern IntPtr sys_tmpnam (StringBuilder s);
643
644                 [Obsolete ("Syscall.mkstemp() should be preferred.")]
645                 public static string tmpnam (StringBuilder s)
646                 {
647                         if (s != null && s.Capacity < L_tmpnam)
648                                 throw new ArgumentOutOfRangeException ("s", "s.Capacity < L_tmpnam");
649                         lock (tmpnam_lock) {
650                                 IntPtr r = sys_tmpnam (s);
651                                 return UnixMarshal.PtrToString (r);
652                         }
653                 }
654
655                 [Obsolete ("Syscall.mkstemp() should be preferred.")]
656                 public static string tmpnam ()
657                 {
658                         lock (tmpnam_lock) {
659                                 IntPtr r = sys_tmpnam (null);
660                                 return UnixMarshal.PtrToString (r);
661                         }
662                 }
663
664                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
665                 public static extern int fclose (IntPtr stream);
666
667                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
668                 public static extern int fflush (IntPtr stream);
669
670                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
671                 public static extern IntPtr fopen (
672                                 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
673                                 string path, string mode);
674
675                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
676                 public static extern IntPtr freopen (
677                                 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
678                                 string path, string mode, IntPtr stream);
679
680                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, 
681                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_setbuf")]
682                 public static extern int setbuf (IntPtr stream, IntPtr buf);
683
684                 [CLSCompliant (false)]
685                 public static unsafe int setbuf (IntPtr stream, byte* buf)
686                 {
687                         return setbuf (stream, (IntPtr) buf);
688                 }
689
690                 [CLSCompliant (false)]
691                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
692                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_setvbuf")]
693                 public static extern int setvbuf (IntPtr stream, IntPtr buf, int mode, ulong size);
694
695                 [CLSCompliant (false)]
696                 public static unsafe int setvbuf (IntPtr stream, byte* buf, int mode, ulong size)
697                 {
698                         return setvbuf (stream, (IntPtr) buf, mode, size);
699                 }
700
701                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
702                                 EntryPoint="fprintf")]
703                 private static extern int sys_fprintf (IntPtr stream, string format, string message);
704
705                 public static int fprintf (IntPtr stream, string message)
706                 {
707                         return sys_fprintf (stream, "%s", message);
708                 }
709
710                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
711                                 "Use fprintf (IntPtr, string) instead.")]
712                 public static int fprintf (IntPtr stream, string format, params object[] parameters)
713                 {
714                         object[] _parameters = new object[checked(parameters.Length+2)];
715                         _parameters [0] = stream;
716                         _parameters [1] = format;
717                         Array.Copy (parameters, 0, _parameters, 2, parameters.Length);
718                         return (int) XPrintfFunctions.fprintf (_parameters);
719                 }
720
721                 /* SKIP: fscanf(3) */
722
723                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
724                                 EntryPoint="printf")]
725                 private static extern int sys_printf (string format, string message);
726
727                 public static int printf (string message)
728                 {
729                         return sys_printf ("%s", message);
730                 }
731
732                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
733                                 "Use printf (string) instead.")]
734                 public static int printf (string format, params object[] parameters)
735                 {
736                         object[] _parameters = new object[checked(parameters.Length+1)];
737                         _parameters [0] = format;
738                         Array.Copy (parameters, 0, _parameters, 1, parameters.Length);
739                         return (int) XPrintfFunctions.printf (_parameters);
740                 }
741
742                 /* SKIP: scanf(3) */
743
744                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
745                                 EntryPoint="Mono_Posix_Stdlib_snprintf")]
746                 private static extern int sys_snprintf (StringBuilder s, ulong n, 
747                                 string format, string message);
748
749                 [CLSCompliant (false)]
750                 public static int snprintf (StringBuilder s, ulong n, string message)
751                 {
752                         if (n > (ulong) s.Capacity)
753                                 throw new ArgumentOutOfRangeException ("n", "n must be <= s.Capacity");
754                         return sys_snprintf (s, n, "%s", message);
755                 }
756
757                 public static int snprintf (StringBuilder s, string message)
758                 {
759                         return sys_snprintf (s, (ulong) s.Capacity, "%s", message);
760                 }
761
762                 [CLSCompliant (false)]
763                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
764                                 "Use snprintf (StringBuilder, string) instead.")]
765                 public static int snprintf (StringBuilder s, ulong n, 
766                                 string format, params object[] parameters)
767                 {
768                         if (n > (ulong) s.Capacity)
769                                 throw new ArgumentOutOfRangeException ("n", "n must be <= s.Capacity");
770
771                         object[] _parameters = new object[checked(parameters.Length+3)];
772                         _parameters [0] = s;
773                         _parameters [1] = n;
774                         _parameters [2] = format;
775                         Array.Copy (parameters, 0, _parameters, 3, parameters.Length);
776                         return (int) XPrintfFunctions.snprintf (_parameters);
777                 }
778
779                 [CLSCompliant (false)]
780                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
781                                 "Use snprintf (StringBuilder, string) instead.")]
782                 public static int snprintf (StringBuilder s,
783                                 string format, params object[] parameters)
784                 {
785                         object[] _parameters = new object[checked(parameters.Length+3)];
786                         _parameters [0] = s;
787                         _parameters [1] = (ulong) s.Capacity;
788                         _parameters [2] = format;
789                         Array.Copy (parameters, 0, _parameters, 3, parameters.Length);
790                         return (int) XPrintfFunctions.snprintf (_parameters);
791                 }
792
793                 /*
794                  * SKIP:
795                  *    sprintf(3)
796                  *    sscanf(3)
797                  *    vfprintf(3)
798                  *    vfscanf(3)
799                  *    vprintf(3)
800                  *    vscanf(3)
801                  *    vsnprintf(3)
802                  *    vsprint(3)
803                  *    vsscanf(3)
804                  */
805
806                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
807                 public static extern int fgetc (IntPtr stream);
808
809                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
810                                 SetLastError=true, EntryPoint="fgets")]
811                 private static extern IntPtr sys_fgets (StringBuilder sb, int size, IntPtr stream);
812
813                 public static StringBuilder fgets (StringBuilder sb, int size, IntPtr stream)
814                 {
815                         IntPtr r = sys_fgets (sb, size, stream);
816                         if (r == IntPtr.Zero)
817                                 return null;
818                         return sb;
819                 }
820
821                 public static StringBuilder fgets (StringBuilder sb, IntPtr stream)
822                 {
823                         return fgets (sb, sb.Capacity, stream);
824                 }
825
826                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
827                 public static extern int fputc (int c, IntPtr stream);
828
829                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
830                 public static extern int fputs (string s, IntPtr stream);
831
832                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
833                 public static extern int getc (IntPtr stream);
834
835                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
836                 public static extern int getchar ();
837
838                 /* SKIP: gets(3) */
839
840                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
841                 public static extern int putc (int c, IntPtr stream);
842
843                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
844                 public static extern int putchar (int c);
845
846                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
847                 public static extern int puts (string s);
848
849                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
850                 public static extern int ungetc (int c, IntPtr stream);
851
852                 [CLSCompliant (false)]
853                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
854                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fread")]
855                 public static extern ulong fread (IntPtr ptr, ulong size, ulong nmemb, IntPtr stream);
856
857                 [CLSCompliant (false)]
858                 public static unsafe ulong fread (void* ptr, ulong size, ulong nmemb, IntPtr stream)
859                 {
860                         return fread ((IntPtr) ptr, size, nmemb, stream);
861                 }
862
863                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
864                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fread")]
865                 private static extern ulong sys_fread ([Out] byte[] ptr, 
866                                 ulong size, ulong nmemb, IntPtr stream);
867
868                 [CLSCompliant (false)]
869                 public static ulong fread (byte[] ptr, ulong size, ulong nmemb, IntPtr stream)
870                 {
871                         if ((size * nmemb) > (ulong) ptr.Length)
872                                 throw new ArgumentOutOfRangeException ("nmemb");
873                         return sys_fread (ptr, size, nmemb, stream);
874                 }
875
876                 [CLSCompliant (false)]
877                 public static ulong fread (byte[] ptr, IntPtr stream)
878                 {
879                         return fread (ptr, 1, (ulong) ptr.Length, stream);
880                 }
881
882                 [CLSCompliant (false)]
883                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
884                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fwrite")]
885                 public static extern ulong fwrite (IntPtr ptr, ulong size, ulong nmemb, IntPtr stream);
886
887                 [CLSCompliant (false)]
888                 public static unsafe ulong fwrite (void* ptr, ulong size, ulong nmemb, IntPtr stream)
889                 {
890                         return fwrite ((IntPtr) ptr, size, nmemb, stream);
891                 }
892
893                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
894                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fwrite")]
895                 private static extern ulong sys_fwrite (byte[] ptr, 
896                                 ulong size, ulong nmemb, IntPtr stream);
897
898                 [CLSCompliant (false)]
899                 public static ulong fwrite (byte[] ptr, ulong size, ulong nmemb, IntPtr stream)
900                 {
901                         if ((size * nmemb) > (ulong) ptr.Length)
902                                 throw new ArgumentOutOfRangeException ("nmemb");
903                         return sys_fwrite (ptr, size, nmemb, stream);
904                 }
905
906                 [CLSCompliant (false)]
907                 public static ulong fwrite (byte[] ptr, IntPtr stream)
908                 {
909                         return fwrite (ptr, 1, (ulong) ptr.Length, stream);
910                 }
911
912                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
913                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fgetpos")]
914                 private static extern int sys_fgetpos (IntPtr stream, HandleRef pos);
915
916                 public static int fgetpos (IntPtr stream, FilePosition pos)
917                 {
918                         return sys_fgetpos (stream, pos.Handle);
919                 }
920
921                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
922                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fseek")]
923                 private static extern int sys_fseek (IntPtr stream, long offset, int origin);
924
925                 [CLSCompliant (false)]
926                 public static int fseek (IntPtr stream, long offset, SeekFlags origin)
927                 {
928                         int _origin = NativeConvert.FromSeekFlags (origin);
929                         return sys_fseek (stream, offset, _origin);
930                 }
931
932                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
933                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fsetpos")]
934                 private static extern int sys_fsetpos (IntPtr stream, HandleRef pos);
935
936                 public static int fsetpos (IntPtr stream, FilePosition pos)
937                 {
938                         return sys_fsetpos (stream, pos.Handle);
939                 }
940
941                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
942                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_ftell")]
943                 public static extern long ftell (IntPtr stream);
944
945                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
946                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_rewind")]
947                 public static extern int rewind (IntPtr stream);
948
949                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
950                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_clearerr")]
951                 public static extern int clearerr (IntPtr stream);
952
953                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
954                 public static extern int feof (IntPtr stream);
955
956                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
957                 public static extern int ferror (IntPtr stream);
958
959                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, 
960                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_perror")]
961                 private static extern int perror (string s, int err);
962
963                 public static int perror (string s)
964                 {
965                         return perror (s, Marshal.GetLastWin32Error ());
966                 }
967
968                 //
969                 // <stdlib.h>
970                 //
971                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
972                                 EntryPoint="Mono_Posix_Stdlib_EXIT_FAILURE")]
973                 private static extern int GetExitFailure();
974
975                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
976                                 EntryPoint="Mono_Posix_Stdlib_EXIT_SUCCESS")]
977                 private static extern int GetExitSuccess ();
978
979                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
980                                 EntryPoint="Mono_Posix_Stdlib_MB_CUR_MAX")]
981                 private static extern int GetMbCurMax ();
982
983                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
984                                 EntryPoint="Mono_Posix_Stdlib_RAND_MAX")]
985                 private static extern int GetRandMax ();
986
987                 [CLSCompliant (false)]
988                 public static readonly int  EXIT_FAILURE = GetExitFailure ();
989                 [CLSCompliant (false)]
990                 public static readonly int  EXIT_SUCCESS = GetExitSuccess ();
991                 [CLSCompliant (false)]
992                 public static readonly int  MB_CUR_MAX   = GetMbCurMax ();
993                 [CLSCompliant (false)]
994                 public static readonly int  RAND_MAX     = GetRandMax ();
995
996                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
997                 public static extern int rand ();
998
999                 [CLSCompliant (false)]
1000                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
1001                 public static extern void srand (uint seed);
1002
1003                 // calloc(3):
1004                 //    void *calloc (size_t nmemb, size_t size);
1005                 [CLSCompliant (false)]
1006                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
1007                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_calloc")]
1008                 public static extern IntPtr calloc (ulong nmemb, ulong size);
1009
1010                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
1011                 public static extern void free (IntPtr ptr);
1012
1013                 // malloc(3):
1014                 //    void *malloc(size_t size);
1015                 [CLSCompliant (false)]
1016                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
1017                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_malloc")]
1018                 public static extern IntPtr malloc (ulong size);
1019
1020                 // realloc(3):
1021                 //    void *realloc(void *ptr, size_t size);
1022                 [CLSCompliant (false)]
1023                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
1024                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_realloc")]
1025                 public static extern IntPtr realloc (IntPtr ptr, ulong size);
1026
1027                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
1028                 public static extern void abort ();
1029
1030                 /* SKIP: atexit(3) -- the GC should have collected most references by the
1031                  * time this runs, so no delegates should exist, making it pointless. */
1032
1033                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
1034                 public static extern void exit (int status);
1035
1036                 [CLSCompliant (false)]
1037                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
1038                 public static extern void _Exit (int status);
1039
1040                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, EntryPoint="getenv")]
1041                 private static extern IntPtr sys_getenv (string name);
1042
1043                 public static string getenv (string name)
1044                 {
1045                         IntPtr r = sys_getenv (name);
1046                         return UnixMarshal.PtrToString (r);
1047                 }
1048
1049                 [CLSCompliant (false)]
1050                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
1051                 public static extern int system (string @string);
1052
1053                 //
1054                 // <string.h>
1055                 //
1056
1057                 private static object strerror_lock = new object ();
1058
1059                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
1060                                 SetLastError=true, EntryPoint="strerror")]
1061                 private static extern IntPtr sys_strerror (int errnum);
1062
1063                 [CLSCompliant (false)]
1064                 public static string strerror (Errno errnum)
1065                 {
1066                         int e = NativeConvert.FromErrno (errnum);
1067                         lock (strerror_lock) {
1068                                 IntPtr r = sys_strerror (e);
1069                                 return UnixMarshal.PtrToString (r);
1070                         }
1071                 }
1072
1073                 // strlen(3):
1074                 //    size_t strlen(const char *s);
1075                 [CLSCompliant (false)]
1076                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
1077                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_strlen")]
1078                 public static extern ulong strlen (IntPtr s);
1079         }
1080
1081         #endregion // Classes
1082 }
1083
1084 // vim: noexpandtab