* Stdlib.cs: On miguel's suggestion, rename Sighandler_t to SignalHandler.
[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 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         public delegate void SignalHandler (int signal);
38
39         [StructLayout (LayoutKind.Sequential)]
40         public sealed class FilePosition : IDisposable {
41
42                 [DllImport ("MonoPosixHelper",
43                                 EntryPoint="Mono_Posix_Stdlib_CreateFilePosition")]
44                 private static extern IntPtr CreateFilePosition ();
45
46                 private HandleRef pos;
47
48                 public FilePosition ()
49                 {
50                         IntPtr p = CreateFilePosition ();
51                         if (p == IntPtr.Zero)
52                                 throw new OutOfMemoryException ("Unable to malloc fpos_t!");
53                         pos = new HandleRef (this, p);
54                 }
55
56                 internal HandleRef Handle {
57                         get {return pos;}
58                 }
59
60                 public void Dispose ()
61                 {
62                         GC.SuppressFinalize (this);
63                         Cleanup ();
64                 }
65
66                 private void Cleanup ()
67                 {
68                         if (pos.Handle != IntPtr.Zero) {
69                                 Stdlib.free (pos.Handle);
70                                 pos = new HandleRef (this, IntPtr.Zero);
71                         }
72                 }
73
74                 ~FilePosition ()
75                 {
76                         Cleanup ();
77                 }
78         }
79
80         internal sealed class SignalWrapper {
81                 private IntPtr handler;
82
83                 internal SignalWrapper (IntPtr handler)
84                 {
85                         this.handler = handler;
86                 }
87
88                 private const string MPH = "MonoPosixHelper";
89
90                 [DllImport (MPH, EntryPoint="Mono_Posix_Syscall_InvokeSignalHandler")]
91                 private static extern void InvokeSignalHandler (int signum, IntPtr handler);
92
93                 public void InvokeSignalHandler (int signum)
94                 {
95                         InvokeSignalHandler (signum, handler);
96                 }
97         }
98
99         internal class XPrintfFunctions
100         {
101                 internal delegate object XPrintf (object[] parameters);
102
103                 internal static XPrintf printf;
104                 internal static XPrintf fprintf;
105                 internal static XPrintf syslog;
106
107                 static XPrintfFunctions ()
108                 {
109                         CdeclFunction _printf = new CdeclFunction ("libc", "printf", typeof(int));
110                         printf = new XPrintf (_printf.Invoke);
111
112                         CdeclFunction _fprintf = new CdeclFunction ("libc", "fprintf", typeof(int));
113                         fprintf = new XPrintf (_fprintf.Invoke);
114
115                         CdeclFunction _syslog = new CdeclFunction ("libc", "syslog", typeof(void));
116                         syslog = new XPrintf (_syslog.Invoke);
117                 }
118         }
119
120         //
121         // Convention: Functions that are part of the C standard library go here.
122         //
123         // For example, the man page should say something similar to:
124         //
125         //    CONFORMING TO
126         //           ISO 9899 (''ANSI C'')
127         //
128         // We can also place logical "sibling" exports here -- exports which
129         // strongly relate to an ANSI C function, either as an overload, or which
130         // operates on the same datatype as an ANSI C function.  Examples include
131         // fileno(3) and fdopen(3).
132         //
133         public class Stdlib
134         {
135                 private const string LIBC = "libc";
136                 private const string MPH = "MonoPosixHelper";
137
138                 internal Stdlib () {}
139
140                 //
141                 // <signal.h>
142                 //
143                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib_SIG_DFL")]
144                 private static extern IntPtr GetDefaultSignal ();
145
146                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib_SIG_ERR")]
147                 private static extern IntPtr GetErrorSignal ();
148
149                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib_SIG_IGN")]
150                 private static extern IntPtr GetIgnoreSignal ();
151
152                 private static readonly IntPtr _SIG_DFL = GetDefaultSignal ();
153                 private static readonly IntPtr _SIG_ERR = GetErrorSignal ();
154                 private static readonly IntPtr _SIG_IGN = GetIgnoreSignal ();
155
156                 private static void _ErrorHandler (int signum)
157                 {
158                         Console.Error.WriteLine ("Error handler invoked for signum " + 
159                                         signum + ".  Don't do that.");
160                 }
161
162                 private static void _DefaultHandler (int signum)
163                 {
164                         Console.Error.WriteLine ("Default handler invoked for signum " + 
165                                         signum + ".  Don't do that.");
166                 }
167
168                 private static void _IgnoreHandler (int signum)
169                 {
170                         Console.Error.WriteLine ("Ignore handler invoked for signum " + 
171                                         signum + ".  Don't do that.");
172                 }
173
174                 public static readonly SignalHandler SIG_DFL = _DefaultHandler;
175                 public static readonly SignalHandler SIG_ERR = _ErrorHandler;
176                 public static readonly SignalHandler SIG_IGN = _IgnoreHandler;
177
178                 [DllImport (LIBC, SetLastError=true, EntryPoint="signal")]
179                 private static extern IntPtr sys_signal (int signum, SignalHandler handler);
180
181                 [DllImport (LIBC, SetLastError=true, EntryPoint="signal")]
182                 private static extern IntPtr sys_signal (int signum, IntPtr handler);
183
184                 public static SignalHandler signal (Signum signum, SignalHandler handler)
185                 {
186                         int _sig = UnixConvert.FromSignum (signum);
187                         IntPtr r;
188                         if (handler == SIG_DFL)
189                                 r = sys_signal (_sig, _SIG_DFL);
190                         else if (handler == SIG_ERR)
191                                 r = sys_signal (_sig, _SIG_ERR);
192                         else if (handler == SIG_IGN)
193                                 r = sys_signal (_sig, _SIG_IGN);
194                         else
195                                 r = sys_signal (_sig, handler);
196                         return TranslateHandler (r);
197                 }
198
199                 private static SignalHandler TranslateHandler (IntPtr handler)
200                 {
201                         if (handler == _SIG_DFL)
202                                 return SIG_DFL;
203                         if (handler == _SIG_ERR)
204                                 return SIG_ERR;
205                         if (handler == _SIG_IGN)
206                                 return SIG_IGN;
207                         return new SignalHandler (new SignalWrapper (handler).InvokeSignalHandler);
208                 }
209
210                 [DllImport (LIBC, EntryPoint="raise")]
211                 private static extern int sys_raise (int sig);
212
213                 public static int raise (Signum sig)
214                 {
215                         int _sig = UnixConvert.FromSignum (sig);
216                         return sys_raise (_sig);
217                 }
218
219                 //
220                 // <stdio.h>
221                 //
222                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib__IOFBF")]
223                 private static extern int GetFullyBuffered ();
224
225                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib__IOLBF")]
226                 private static extern int GetLineBuffered ();
227
228                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib__IONBF")]
229                 private static extern int GetNonBuffered ();
230
231                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib_BUFSIZ")]
232                 private static extern int GetBufferSize ();
233
234                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib_L_tmpnam")]
235                 private static extern int GetTmpnamLength ();
236
237                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib_stdin")]
238                 private static extern IntPtr GetStandardInput ();
239
240                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib_stdout")]
241                 private static extern IntPtr GetStandardOutput ();
242
243                 [DllImport (MPH, EntryPoint="Mono_Posix_Stdlib_stderr")]
244                 private static extern IntPtr GetStandardError ();
245
246                 public static readonly int    _IOFBF       = GetFullyBuffered ();
247                 public static readonly int    _IOLBF       = GetLineBuffered ();
248                 public static readonly int    _IONBF       = GetNonBuffered ();
249                 public static readonly int    BUFSIZ       = GetBufferSize ();
250                 public static readonly int    L_tmpnam     = GetTmpnamLength ();
251                 public static readonly IntPtr stdin        = GetStandardInput ();
252                 public static readonly IntPtr stdout       = GetStandardOutput ();
253                 public static readonly IntPtr stderr       = GetStandardError ();
254
255                 [DllImport (LIBC, SetLastError=true)]
256                 public static extern void perror (string s);
257
258                 [DllImport (LIBC, SetLastError=true)]
259                 public static extern int remove (string filename);
260
261                 [DllImport (LIBC, SetLastError=true)]
262                 public static extern int rename (string oldpath, string newpath);
263
264                 [DllImport (LIBC, SetLastError=true)]
265                 public static extern IntPtr tmpfile ();
266
267                 [DllImport (LIBC, SetLastError=true, EntryPoint="tmpnam")]
268                 private static extern IntPtr sys_tmpnam (StringBuilder s);
269
270                 public static string tmpnam (StringBuilder s)
271                 {
272                         if (s != null && s.Capacity < L_tmpnam)
273                                 throw new ArgumentOutOfRangeException ("s", "s.Capacity < L_tmpnam");
274                         IntPtr r = sys_tmpnam (s);
275                         return UnixMarshal.PtrToString (r);
276                 }
277
278                 [DllImport (LIBC)]
279                 public static extern void clearerr (IntPtr stream);
280
281                 [DllImport (LIBC, SetLastError=true)]
282                 public static extern IntPtr fopen (string path, string mode);
283
284                 [DllImport (LIBC, SetLastError=true)]
285                 public static extern IntPtr fdopen (int filedes, string mode);
286
287                 [DllImport (LIBC, SetLastError=true)]
288                 public static extern void setbuf (IntPtr stream, IntPtr buf);
289
290                 public static unsafe void setbuf (IntPtr stream, byte* buf)
291                 {
292                         setbuf (stream, (IntPtr) buf);
293                 }
294
295                 [DllImport (MPH, SetLastError=true, 
296                                 EntryPoint="Mono_Posix_Stdlib_setvbuf")]
297                 public static extern int setvbuf (IntPtr stream, IntPtr buf, int mode, ulong size);
298
299                 public static unsafe int setvbuf (IntPtr stream, byte* buf, int mode, ulong size)
300                 {
301                         return setvbuf (stream, (IntPtr) buf, mode, size);
302                 }
303
304                 [DllImport (LIBC, SetLastError=true)]
305                 public static extern IntPtr freopen (string path, string mode, IntPtr stream);
306
307                 [DllImport (LIBC, SetLastError=true)]
308                 public static extern int fclose (IntPtr stream);
309
310                 [DllImport (LIBC, SetLastError=true)]
311                 public static extern int fflush (IntPtr stream);
312
313                 [DllImport (LIBC)]
314                 public static extern int feof (IntPtr stream);
315
316                 [DllImport (LIBC)]
317                 public static extern int ferror (IntPtr stream);
318
319                 [DllImport (LIBC, SetLastError=true)]
320                 public static extern int fileno (IntPtr stream);
321
322                 [DllImport (LIBC, EntryPoint="printf")]
323                 private static extern int sys_printf (string format, string message);
324
325                 public static int printf (string message)
326                 {
327                         return sys_printf ("%s", message);
328                 }
329
330                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
331                                 "Use printf (string) instead.")]
332                 public static int printf (string format, params object[] parameters)
333                 {
334                         object[] _parameters = new object[checked(parameters.Length+1)];
335                         _parameters [0] = format;
336                         Array.Copy (parameters, 0, _parameters, 1, parameters.Length);
337                         return (int) XPrintfFunctions.printf (_parameters);
338                 }
339
340                 [DllImport (LIBC, EntryPoint="fprintf")]
341                 private static extern int sys_fprintf (IntPtr stream, string format, string message);
342
343                 public static int fprintf (IntPtr stream, string message)
344                 {
345                         return sys_fprintf (stream, "%s", message);
346                 }
347
348                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
349                                 "Use fprintf (IntPtr, string) instead.")]
350                 public static int fprintf (IntPtr stream, string format, params object[] parameters)
351                 {
352                         object[] _parameters = new object[checked(parameters.Length+2)];
353                         _parameters [0] = stream;
354                         _parameters [1] = format;
355                         Array.Copy (parameters, 0, _parameters, 2, parameters.Length);
356                         return (int) XPrintfFunctions.fprintf (_parameters);
357                 }
358
359                 [DllImport (LIBC, SetLastError=true)]
360                 public static extern int fputc (int c, IntPtr stream);
361
362                 [DllImport (LIBC, SetLastError=true)]
363                 public static extern int fputs (string s, IntPtr stream);
364
365                 [DllImport (LIBC, SetLastError=true)]
366                 public static extern int putc (int c, IntPtr stream);
367
368                 [DllImport (LIBC, SetLastError=true)]
369                 public static extern int putchar (int c);
370
371                 [DllImport (LIBC, SetLastError=true)]
372                 public static extern int puts (string s);
373
374                 [DllImport (LIBC, SetLastError=true)]
375                 public static extern int fgetc (IntPtr stream);
376
377                 [DllImport (LIBC, SetLastError=true, EntryPoint="fgets")]
378                 private static extern IntPtr sys_fgets (StringBuilder sb, int size, IntPtr stream);
379
380                 public static StringBuilder fgets (StringBuilder sb, int size, IntPtr stream)
381                 {
382                         IntPtr r = sys_fgets (sb, size, stream);
383                         if (r == IntPtr.Zero)
384                                 return null;
385                         return sb;
386                 }
387
388                 public static StringBuilder fgets (StringBuilder sb, IntPtr stream)
389                 {
390                         return fgets (sb, sb.Capacity, stream);
391                 }
392
393                 [DllImport (LIBC, SetLastError=true)]
394                 public static extern int getc (IntPtr stream);
395
396                 [DllImport (LIBC, SetLastError=true)]
397                 public static extern int getchar ();
398
399                 // skip gets(3), it's evil.
400
401                 [DllImport (LIBC, SetLastError=true)]
402                 public static extern int ungetc (int c, IntPtr stream);
403
404                 [DllImport (MPH, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fread")]
405                 public static extern unsafe ulong fread (void* ptr, ulong size, ulong nmemb, IntPtr stream);
406
407                 [DllImport (MPH, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fread")]
408                 public static extern ulong fread ([Out] byte[] ptr, ulong size, ulong nmemb, IntPtr stream);
409
410                 public static ulong fread (byte[] ptr, IntPtr stream)
411                 {
412                         return fread (ptr, 1, (ulong) ptr.Length, stream);
413                 }
414
415                 [DllImport (MPH, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fwrite")]
416                 public static extern unsafe ulong fwrite (void* ptr, ulong size, ulong nmemb, IntPtr stream);
417
418                 [DllImport (MPH, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fwrite")]
419                 public static extern ulong fwrite (byte[] ptr, ulong size, ulong nmemb, IntPtr stream);
420
421                 public static ulong fwrite (byte[] ptr, IntPtr stream)
422                 {
423                         return fwrite (ptr, 1, (ulong) ptr.Length, stream);
424                 }
425
426                 [DllImport (MPH, SetLastError=true, 
427                                 EntryPoint="Mono_Posix_Stdlib_fseek")]
428                 private static extern int sys_fseek (IntPtr stream, long offset, int origin);
429
430                 public static int fseek (IntPtr stream, long offset, SeekFlags origin)
431                 {
432                         int _origin = UnixConvert.FromSeekFlags (origin);
433                         return sys_fseek (stream, offset, _origin);
434                 }
435
436                 [DllImport (MPH, SetLastError=true, 
437                                 EntryPoint="Mono_Posix_Stdlib_ftell")]
438                 private static extern long ftell (IntPtr stream);
439
440                 [DllImport (LIBC)]
441                 public static extern void rewind (IntPtr stream);
442
443                 [DllImport (MPH, SetLastError=true, 
444                                 EntryPoint="Mono_Posix_Stdlib_fgetpos")]
445                 private static extern int sys_fgetpos (IntPtr stream, HandleRef pos);
446
447                 public static int fgetpos (IntPtr stream, FilePosition pos)
448                 {
449                         return sys_fgetpos (stream, pos.Handle);
450                 }
451
452                 [DllImport (MPH, SetLastError=true, 
453                                 EntryPoint="Mono_Posix_Stdlib_fsetpos")]
454                 private static extern int sys_fsetpos (IntPtr stream, HandleRef pos);
455
456                 public static int fsetpos (IntPtr stream, FilePosition pos)
457                 {
458                         return sys_fsetpos (stream, pos.Handle);
459                 }
460
461                 //
462                 // <stdlib.h>
463                 //
464
465                 // calloc(3):
466                 //    void *calloc (size_t nmemb, size_t size);
467                 [DllImport (MPH, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_calloc")]
468                 public static extern IntPtr calloc (ulong nmemb, ulong size);
469
470                 [DllImport (LIBC)]
471                 public static extern void exit (int status);
472
473                 [DllImport (LIBC)]
474                 public static extern void free (IntPtr ptr);
475
476                 // malloc(3):
477                 //    void *malloc(size_t size);
478                 [DllImport (MPH, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_malloc")]
479                 public static extern IntPtr malloc (ulong size);
480
481                 // realloc(3):
482                 //    void *realloc(void *ptr, size_t size);
483                 [DllImport (MPH, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_realloc")]
484                 public static extern IntPtr realloc (IntPtr ptr, ulong size);
485
486                 [DllImport (MPH, SetLastError=true)]
487                 public static extern int system (string @string);
488
489                 //
490                 // <string.h>
491                 //
492
493                 [DllImport (LIBC, SetLastError=true, EntryPoint="strerror")]
494                 private static extern IntPtr sys_strerror (int errnum);
495
496                 public static IntPtr sys_strerror (Error errnum)
497                 {
498                         int e = UnixConvert.FromError (errnum);
499                         return sys_strerror (e);
500                 }
501
502                 public static string strerror (Error errnum)
503                 {
504                         IntPtr r = sys_strerror (errnum);
505                         return UnixMarshal.PtrToString (r);
506                 }
507         }
508 }
509
510 // vim: noexpandtab