OSDN Git Service

3f8a1c1e0306b5d6718475ae5a50ff2764a5b08d
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / fhandler.h
1 /* fhandler.h
2
3    Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #ifndef _FHANDLER_H_
12 #define _FHANDLER_H_
13
14 #include <sys/ioctl.h>
15
16 /* Classes
17
18   Code is located in fhandler.cc unless another file name is given.
19
20   fhandler_base           normal I/O
21
22      fhandler_disk_file
23      fhandler_serial      Adds vmin and vtime.
24      fhandler_dev_null    Not really I/O
25      fhandler_dev_zero    Faked
26
27      fhandler_dev_raw     (fhandler_raw.cc)
28      fhandler_dev_floppy  (fhandler_floppy.cc)
29      fhandler_dev_tape    (fhandler_tape.cc)
30
31      fhandler_pipe
32      fhandler_socket      (net.cc)
33
34      fhandler_tty_slave   (tty.cc)
35      fhandler_pty_master  (tty.cc)
36      fhandler_tty_master  (tty.cc)
37
38      fhandler_console     Out with ansi control. (console.cc)
39
40      fhandler_windows     Windows messages I/O (fhandler_windows.cc)
41
42      fhandler_dev_random  /dev/[u]random implementation (fhandler_random.cc)
43
44      fhandler_dev_mem     /dev/mem implementation (fhandler_mem.cc)
45
46      fhandler_proc        Interesting possibility, not implemented yet
47 */
48
49 enum
50 {
51   FH_RBINARY = 0x00001000,      /* binary read mode */
52   FH_WBINARY = 0x00002000,      /* binary write mode */
53   FH_CLOEXEC = 0x00004000,      /* close-on-exec */
54   FH_RBINSET = 0x00008000,      /* binary read mode has been explicitly set */
55   FH_WBINSET = 0x00010000,      /* binary write mode has been explicitly set */
56   FH_APPEND  = 0x00020000,      /* always append */
57   FH_ASYNC   = 0x00040000,      /* async I/O */
58   FH_HADEOF  = 0x00080000,      /* EOF seen */
59
60   FH_SYMLINK = 0x00100000,      /* is a symlink */
61   FH_EXECABL = 0x00200000,      /* file looked like it would run:
62                                  * ends in .exe or .bat or begins with #! */
63   FH_W95LSBUG= 0x00400000,      /* set when lseek is called as a flag that
64                                  * _write should check if we've moved beyond
65                                  * EOF, zero filling if so. */
66   FH_NOFRNAME= 0x00800000,      /* Set if shouldn't free unix_path_name_ and
67                                    windows_path_name_ on destruction. */
68   FH_NOEINTR = 0x01000000,      /* Set if I/O should be uninterruptible. */
69   FH_FFIXUP  = 0x02000000,      /* Set if need to fixup after fork. */
70   FH_LOCAL   = 0x04000000,      /* File is unix domain socket */
71   FH_FIFO    = 0x08000000,      /* File is FIFO */
72   FH_HASACLS = 0x40000000,      /* True if fs of file has ACLS */
73
74   /* Device flags */
75
76   /* Slow devices */
77   FH_CONSOLE = 0x00000001,      /* is a console */
78   FH_CONIN   = 0x00000002,      /* console input */
79   FH_CONOUT  = 0x00000003,      /* console output */
80   FH_TTYM    = 0x00000004,      /* is a tty master */
81   FH_TTYS    = 0x00000005,      /* is a tty slave */
82   FH_PTYM    = 0x00000006,      /* is a pty master */
83   FH_SERIAL  = 0x00000007,      /* is a serial port */
84   FH_PIPE    = 0x00000008,      /* is a pipe */
85   FH_PIPER   = 0x00000009,      /* read end of a pipe */
86   FH_PIPEW   = 0x0000000a,      /* write end of a pipe */
87   FH_SOCKET  = 0x0000000b,      /* is a socket */
88   FH_WINDOWS = 0x0000000c,      /* is a window */
89
90   FH_SLOW    = 0x00000010,      /* "slow" device if below this */
91
92   /* Fast devices */
93   FH_DISK    = 0x00000010,      /* is a disk */
94   FH_FLOPPY  = 0x00000011,      /* is a floppy */
95   FH_TAPE    = 0x00000012,      /* is a tape */
96   FH_NULL    = 0x00000013,      /* is the null device */
97   FH_ZERO    = 0x00000014,      /* is the zero device */
98   FH_RANDOM  = 0x00000015,      /* is a random device */
99   FH_MEM     = 0x00000016,      /* is a mem device */
100
101   FH_NDEV    = 0x00000017,      /* Maximum number of devices */
102   FH_DEVMASK = 0x00000fff,      /* devices live here */
103   FH_BAD     = 0xffffffff
104 };
105
106 #define FHDEVN(n)       ((n) & FH_DEVMASK)
107 #define FHISSETF(x)     __ISSETF (this, x, FH)
108 #define FHSETF(x)       __SETF (this, x, FH)
109 #define FHCLEARF(x)     __CLEARF (this, x, FH)
110 #define FHCONDSETF(n, x) __CONDSETF(n, this, x, FH)
111
112 #define FHSTATOFF       0
113
114 extern const char *windows_device_names[];
115 extern struct __cygwin_perfile *perfile_table;
116 #define __fmode (*(user_data->fmode_ptr))
117
118 class select_record;
119 class path_conv;
120 class fhandler_disk_file;
121
122 class fhandler_base
123 {
124 private:
125   DWORD status;
126 public:
127   int cb;
128 private:
129   int access_;
130   HANDLE io_handle;
131
132   int rpos_; /* Used in text reading */
133   int rsize_;
134
135   unsigned long namehash_;      /* hashed filename, used as inode num */
136
137   /* Full unix path name of this file */
138   /* File open flags from open () and fcntl () calls */
139   int openflags_;
140
141 protected:
142   char *rabuf;          /* used for crlf conversion in text files */
143   size_t ralen;
144   size_t raixget;
145   size_t raixput;
146   size_t rabuflen;
147
148   char *unix_path_name_;
149   char *win32_path_name_;
150
151 public:
152   void set_name (const char * unix_path, const char * win32_path = NULL,
153                  int unit = 0);
154
155   virtual fhandler_base& operator =(fhandler_base &x);
156   fhandler_base (DWORD dev, const char *name = 0, int unit = 0);
157   virtual ~fhandler_base ();
158
159   /* Non-virtual simple accessor functions. */
160   void set_io_handle (HANDLE);
161
162   void set_cb (size_t size) { cb = size; }
163   DWORD get_device () { return status & FH_DEVMASK; }
164   virtual int get_unit () { return 0; }
165   virtual BOOL is_slow () { return get_device () < FH_SLOW; }
166
167   int get_access () { return access_; }
168   void set_access (int x) { access_ = x; }
169
170   int get_async () { return FHISSETF (ASYNC); }
171   void set_async (int x) { FHCONDSETF (x, ASYNC); }
172
173   int get_flags () { return openflags_; }
174   void set_flags (int x) { openflags_ = x; }
175
176   int get_w_binary () { return FHISSETF (WBINARY); }
177   int get_r_binary () { return FHISSETF (RBINARY); }
178
179   int get_w_binset () { return FHISSETF (WBINSET); }
180   int get_r_binset () { return FHISSETF (RBINSET); }
181
182   void set_w_binary (int b) { FHCONDSETF (b, WBINARY); FHSETF (WBINSET); }
183   void set_r_binary (int b) { FHCONDSETF (b, RBINARY); FHSETF (RBINSET); }
184
185   int get_default_fmode (int flags);
186
187   int get_r_no_interrupt () { return FHISSETF (NOEINTR); }
188   void set_r_no_interrupt (int b) { FHCONDSETF (b, NOEINTR); }
189
190   int get_close_on_exec () { return FHISSETF (CLOEXEC); }
191   int set_close_on_exec_flag (int b) { return FHCONDSETF (b, CLOEXEC); }
192
193   void set_check_win95_lseek_bug (int b = 1) { FHCONDSETF (b, W95LSBUG); }
194   int get_check_win95_lseek_bug () { return FHISSETF (W95LSBUG); }
195
196   int get_need_fork_fixup () { return FHISSETF (FFIXUP); }
197   void set_need_fork_fixup () { FHSETF (FFIXUP); }
198
199   virtual void set_close_on_exec (int val);
200   virtual void fixup_after_fork (HANDLE parent);
201
202   int get_symlink_p () { return FHISSETF (SYMLINK); }
203   void set_symlink_p (int val) { FHCONDSETF (val, SYMLINK); }
204   void set_symlink_p () { FHSETF (SYMLINK); }
205
206   int get_socket_p () { return FHISSETF (LOCAL); }
207   void set_socket_p (int val) { FHCONDSETF (val, LOCAL); }
208   void set_socket_p () { FHSETF (LOCAL); }
209
210   int get_execable_p () { return FHISSETF (EXECABL); }
211   void set_execable_p (int val) { FHCONDSETF (val, EXECABL); }
212   void set_execable_p () { FHSETF (EXECABL); }
213
214   int get_append_p () { return FHISSETF (APPEND); }
215   void set_append_p (int val) { FHCONDSETF (val, APPEND); }
216   void set_append_p () { FHSETF (APPEND); }
217
218   int get_readahead_valid () { return raixget < ralen; }
219   int puts_readahead (const char *s, size_t len = (size_t) -1);
220   int put_readahead (char value);
221
222   int get_readahead ();
223   int peek_readahead (int queryput = 0);
224
225   int eat_readahead (int n);
226
227   void set_readahead_valid (int val, int ch = -1);
228
229   int get_readahead_into_buffer (char *buf, size_t buflen);
230
231   int has_acls () { return FHISSETF (HASACLS); }
232   void set_has_acls (int val) { FHCONDSETF (val, HASACLS); }
233
234   int no_free_names () { return FHISSETF (NOFRNAME); }
235   void set_no_free_names (int val) { FHCONDSETF (val, NOFRNAME); }
236   void set_no_free_names () { FHSETF (NOFRNAME); }
237
238   const char *get_name () { return unix_path_name_; }
239   const char *get_win32_name () { return win32_path_name_; }
240   unsigned long get_namehash () { return namehash_; }
241
242   virtual void hclose (HANDLE h) {CloseHandle (h);}
243   virtual void set_inheritance (HANDLE &h, int not_inheriting,
244                                 const char *name = NULL);
245
246   /* fixup fd possibly non-inherited handles after fork */
247   void fork_fixup (HANDLE parent, HANDLE &h, const char *name);
248
249   /* Potentially overridden virtual functions. */
250   virtual int open (const char *, int flags, mode_t mode = 0)
251   {
252     return open (flags, mode);
253   }
254   virtual int open (int flags, mode_t mode = 0);
255   virtual int close ();
256   virtual int fstat (struct stat *buf);
257   virtual int ioctl (unsigned int cmd, void *);
258   virtual char const * ttyname () { return get_name(); }
259   virtual int read (void *ptr, size_t len);
260   virtual int write (const void *ptr, size_t len);
261   virtual off_t lseek (off_t offset, int whence);
262   virtual int lock (int, struct flock *);
263   virtual void dump ();
264   virtual int dup (fhandler_base *child);
265
266   virtual HANDLE mmap (caddr_t *addr, size_t len, DWORD access,
267                        int flags, off_t off);
268   virtual int munmap (HANDLE h, caddr_t addr, size_t len);
269   virtual int msync (HANDLE h, caddr_t addr, size_t len, int flags);
270
271   void *operator new (size_t, void *p) {return p;}
272
273   virtual void init (HANDLE, DWORD, mode_t);
274
275   virtual int tcflush (int);
276   virtual int tcsendbreak (int);
277   virtual int tcdrain ();
278   virtual int tcflow (int);
279   virtual int tcsetattr (int a, const struct termios *t);
280   virtual int tcgetattr (struct termios *t);
281   virtual int tcsetpgrp (const pid_t pid);
282   virtual int tcgetpgrp ();
283   virtual int is_tty () { return 0; }
284   virtual BOOL is_device () { return TRUE; }
285   virtual char *ptsname () { return NULL;}
286   virtual class fhandler_socket *is_socket () { return 0; }
287   virtual class fhandler_console *is_console () { return 0; }
288   virtual int is_windows () {return 0; }
289
290   virtual int raw_read (void *ptr, size_t ulen);
291   virtual int raw_write (const void *ptr, size_t ulen);
292
293   virtual void fixup_after_exec (HANDLE) {}
294
295   /* Virtual accessor functions to hide the fact
296      that some fd's have two handles. */
297   virtual HANDLE get_handle () const { return io_handle; }
298   virtual HANDLE get_io_handle () const { return io_handle; }
299   virtual HANDLE get_output_handle () const { return io_handle; }
300   virtual BOOL hit_eof () {return FALSE;}
301   virtual select_record *select_read (select_record *s);
302   virtual select_record *select_write (select_record *s);
303   virtual select_record *select_except (select_record *s);
304   virtual int ready_for_read (int fd, DWORD howlong, int ignra);
305   virtual const char * get_native_name ()
306   {
307     return windows_device_names[FHDEVN (status)];
308   }
309   virtual int bg_check (int) {return 1;}
310   void clear_readahead ()
311   {
312     raixput = raixget = ralen = rabuflen = 0;
313     rabuf = NULL;
314   }
315   void operator delete (void *);
316 };
317
318 class fhandler_socket: public fhandler_base
319 {
320 private:
321   int addr_family;
322 public:
323   fhandler_socket (const char *name = 0);
324   fhandler_socket (unsigned int, const char *name = 0);
325   int get_socket () const { return (int) get_handle(); }
326   fhandler_socket * is_socket () { return this; }
327   int write (const void *ptr, size_t len);
328   int read (void *ptr, size_t len);
329   int ioctl (unsigned int cmd, void *);
330   off_t lseek (off_t, int) { return 0; }
331   int close ();
332   void hclose (HANDLE) {close ();}
333
334   select_record *select_read (select_record *s);
335   select_record *select_write (select_record *s);
336   select_record *select_except (select_record *s);
337   int ready_for_read (int fd, DWORD howlong, int ignra);
338   int get_addr_family () {return addr_family;}
339   void set_addr_family (int af) {addr_family = af;}
340 };
341
342 class fhandler_pipe: public fhandler_base
343 {
344 public:
345   fhandler_pipe (const char *name = 0, DWORD devtype = FH_PIPE);
346   off_t lseek (off_t offset, int whence);
347   /* This strange test is due to the fact that we can't rely on
348      Windows shells to "do the right thing" with pipes.  Apparently
349      the can keep one end of the pipe open when it shouldn't be. */
350   BOOL is_slow () {return os_being_run == winNT;}
351   select_record *select_read (select_record *s);
352   select_record *select_write (select_record *s);
353   select_record *select_except (select_record *s);
354   int ready_for_read (int fd, DWORD howlong, int ignra);
355 };
356
357 class fhandler_dev_raw: public fhandler_base
358 {
359 protected:
360   char *devbuf;
361   size_t devbufsiz;
362   size_t devbufstart;
363   size_t devbufend;
364   int eom_detected    : 1;
365   int eof_detected    : 1;
366   int lastblk_to_read : 1;
367   int is_writing      : 1;
368   int has_written     : 1;
369   int varblkop        : 1;
370   int unit;
371
372   virtual void clear (void);
373   virtual int writebuf (void);
374
375   /* returns not null, if `win_error' determines an end of media condition */
376   virtual int is_eom(int win_error) = 0;
377   /* returns not null, if `win_error' determines an end of file condition */
378   virtual int is_eof(int win_error) = 0;
379
380   fhandler_dev_raw (DWORD dev, const char *name, int unit);
381
382 public:
383   ~fhandler_dev_raw (void);
384
385   int open (const char *path, int flags, mode_t mode = 0);
386   int close (void);
387
388   int raw_read (void *ptr, size_t ulen);
389   int raw_write (const void *ptr, size_t ulen);
390
391   int fstat (struct stat *buf);
392
393   int dup (fhandler_base *child);
394
395   int ioctl (unsigned int cmd, void *buf);
396 };
397
398 class fhandler_dev_floppy: public fhandler_dev_raw
399 {
400 protected:
401   virtual int is_eom (int win_error);
402   virtual int is_eof (int win_error);
403
404 public:
405   fhandler_dev_floppy (const char *name, int unit);
406
407   virtual int open (const char *path, int flags, mode_t mode = 0);
408   virtual int close (void);
409
410   virtual off_t lseek (off_t offset, int whence);
411
412   virtual int ioctl (unsigned int cmd, void *buf);
413 };
414
415 class fhandler_dev_tape: public fhandler_dev_raw
416 {
417   int norewind;
418   int lasterr;
419
420 protected:
421   virtual void clear (void);
422
423   virtual int is_eom (int win_error);
424   virtual int is_eof (int win_error);
425
426 public:
427   fhandler_dev_tape (const char *name, int unit);
428
429   virtual int open (const char *path, int flags, mode_t mode = 0);
430   virtual int close (void);
431
432   virtual off_t lseek (off_t offset, int whence);
433
434   virtual int fstat (struct stat *buf);
435
436   virtual int dup (fhandler_base *child);
437
438   virtual int ioctl (unsigned int cmd, void *buf);
439
440 private:
441   int tape_write_marks (int marktype, DWORD len);
442   int tape_get_pos (unsigned long *ret);
443   int tape_set_pos (int mode, long count, BOOLEAN sfm_func = FALSE);
444   int tape_erase (int mode);
445   int tape_prepare (int action);
446   BOOLEAN tape_get_feature (DWORD parm);
447   int tape_get_blocksize (long *min, long *def, long *max, long *cur);
448   int tape_set_blocksize (long count);
449   int tape_status (struct mtget *get);
450   int tape_compression (long count);
451 };
452
453 /* Standard disk file */
454
455 class fhandler_disk_file: public fhandler_base
456 {
457 private:
458   int check_execable_p (const char *path);
459
460 public:
461   fhandler_disk_file (const char *name);
462
463   int open (const char *path, int flags, mode_t mode = 0);
464   int open (path_conv& real_path, int flags, mode_t mode);
465   int close ();
466   int lock (int, struct flock *);
467   BOOL is_device () { return FALSE; }
468   int fstat (struct stat *buf);
469
470   HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, off_t off);
471   int munmap (HANDLE h, caddr_t addr, size_t len);
472   int msync (HANDLE h, caddr_t addr, size_t len, int flags);
473 };
474
475 class fhandler_serial: public fhandler_base
476 {
477 private:
478   unsigned int vmin_;                   /* from termios */
479   unsigned int vtime_;                  /* from termios */
480   pid_t pgrp_;
481
482 public:
483   int overlapped_armed;
484   OVERLAPPED io_status;
485
486   /* Constructor */
487   fhandler_serial (const char *name, DWORD devtype = FH_SERIAL, int unit = 0);
488
489   int open (const char *path, int flags, mode_t mode);
490   int close ();
491   void init (HANDLE h, DWORD a, mode_t flags);
492   void overlapped_setup ();
493   int dup (fhandler_base *child);
494   int raw_read (void *ptr, size_t ulen);
495   int raw_write (const void *ptr, size_t ulen);
496   int tcsendbreak (int);
497   int tcdrain ();
498   int tcflow (int);
499   int tcsetattr (int a, const struct termios *t);
500   int tcgetattr (struct termios *t);
501   off_t lseek (off_t, int) { return 0; }
502   int tcflush (int);
503   void dump ();
504   int is_tty () { return 1; }
505   void fixup_after_fork (HANDLE parent);
506   void fixup_after_exec (HANDLE);
507
508   /* We maintain a pgrp so that tcsetpgrp and tcgetpgrp work, but we
509      don't use it for permissions checking.  fhandler_tty_slave does
510      permission checking on pgrps.  */
511   virtual int tcgetpgrp () { return pgrp_; }
512   virtual int tcsetpgrp (const pid_t pid) { pgrp_ = pid; return 0; }
513   select_record *select_read (select_record *s);
514   select_record *select_write (select_record *s);
515   select_record *select_except (select_record *s);
516   int ready_for_read (int fd, DWORD howlong, int ignra);
517 };
518
519 #define acquire_output_mutex(ms) \
520   __acquire_output_mutex (__PRETTY_FUNCTION__, __LINE__, ms);
521
522 #define release_output_mutex() \
523   __release_output_mutex (__PRETTY_FUNCTION__, __LINE__);
524
525 class tty;
526 class tty_min;
527 class fhandler_termios: public fhandler_base
528 {
529 protected:
530   HANDLE output_handle;
531   virtual void doecho (const void *, DWORD) {};
532   virtual int accept_input () {return 1;};
533 public:
534   tty_min *tc;
535   fhandler_termios (DWORD dev, const char *name = 0, int unit = 0) :
536   fhandler_base (dev, name, unit)
537   {
538     // nothing to do
539   }
540   HANDLE get_output_handle () const { return output_handle; }
541   int line_edit (const char *rptr, int nread, int always_accept = 0);
542   void set_output_handle (HANDLE h) { output_handle = h; }
543   void tcinit (tty_min *this_tc, int force = FALSE);
544   virtual int is_tty () { return 1; }
545   int tcgetpgrp ();
546   int tcsetpgrp (int pid);
547   void set_ctty (int ttynum, int flags);
548   int bg_check (int sig);
549   virtual DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms) {return 1;}
550   virtual void __release_output_mutex (const char *fn, int ln) {}
551 };
552
553 /* This is a input and output console handle */
554 class fhandler_console: public fhandler_termios
555 {
556 private:
557
558 /* Output state */
559
560   // enum {normal, gotesc, gotsquare, gotarg1, gotcommand} state;
561 #define normal 1
562 #define gotesc 2
563 #define gotsquare 3
564 #define gotarg1 4
565 #define gotrsquare 5
566 #define gotcommand 6
567 #define gettitle 7
568 #define eattitle 8
569 #define MAXARGS 10
570   int state_;
571   int args_[MAXARGS];
572   int nargs_;
573
574   DWORD default_color;
575
576 /* Output calls */
577
578   BOOL fillin_info ();
579   void clear_screen (int, int, int, int);
580   void scroll_screen (int, int, int, int, int, int);
581   void cursor_set (BOOL, int, int);
582   void cursor_get (int *, int *);
583   void cursor_rel (int, int);
584   const unsigned char * write_normal (unsigned const char*, unsigned const char *);
585   void char_command (char);
586   int output_tcsetattr (int a, const struct termios *t);
587
588 /* Input calls */
589   int igncr_enabled ();
590   int input_tcsetattr (int a, const struct termios *t);
591   void set_cursor_maybe ();
592
593 public:
594
595   fhandler_console (const char *name);
596
597   fhandler_console* is_console () { return this; }
598
599   int open (const char *path, int flags, mode_t mode = 0);
600
601   int write (const void *ptr, size_t len);
602   void doecho (const void *str, DWORD len) { (void) write (str, len); }
603   int read (void *ptr, size_t len);
604   int close ();
605
606   int tcflush (int);
607   int tcsetattr (int a, const struct termios *t);
608   int tcgetattr (struct termios *t);
609
610   int tcsetpgrp (const pid_t pid);
611
612   /* Special dup as we must dup two handles */
613   int dup (fhandler_base *child);
614
615   int ioctl (unsigned int cmd, void *);
616   void init (HANDLE, DWORD, mode_t);
617
618   select_record *select_read (select_record *s);
619   select_record *select_write (select_record *s);
620   select_record *select_except (select_record *s);
621   int ready_for_read (int fd, DWORD howlong, int ignra);
622   void fixup_after_exec (HANDLE);
623   void set_close_on_exec (int val);
624   void fixup_after_fork (HANDLE parent);
625   void set_input_state ();
626 };
627
628 class fhandler_tty_common: public fhandler_termios
629 {
630 public:
631   fhandler_tty_common (DWORD dev, const char *name = 0, int unit = 0) :
632     fhandler_termios (dev, name, unit),
633     ttynum (unit)
634   {
635     // nothing to do
636   }
637   HANDLE output_done_event;     // Raised by master when tty's output buffer
638                                 // written. Write status in tty::write_retval.
639   HANDLE ioctl_request_event;   // Raised by slave to perform ioctl() request.
640                                 // Ioctl() request in tty::cmd/arg.
641   HANDLE ioctl_done_event;      // Raised by master on ioctl() completion.
642                                 // Ioctl() status in tty::ioctl_retval.
643   HANDLE output_mutex;
644   HANDLE inuse;                 // used to indicate that a tty is in use
645
646
647   DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
648   void __release_output_mutex (const char *fn, int ln);
649
650   int ttynum;                   // Master tty num.
651   virtual int dup (fhandler_base *child);
652
653   tty *get_ttyp () { return (tty *)tc; }
654   int get_unit () { return ttynum; }
655
656   int close ();
657   void set_close_on_exec (int val);
658   void fixup_after_fork (HANDLE parent);
659   select_record *select_read (select_record *s);
660   select_record *select_write (select_record *s);
661   select_record *select_except (select_record *s);
662   int ready_for_read (int fd, DWORD howlong, int ignra);
663 };
664
665 class fhandler_tty_slave: public fhandler_tty_common
666 {
667 public:
668   /* Constructor */
669   fhandler_tty_slave (const char *name);
670   fhandler_tty_slave (int, const char *name);
671
672   int open (const char *path, int flags, mode_t mode = 0);
673   int write (const void *ptr, size_t len);
674   int read (void *ptr, size_t len);
675   void init (HANDLE, DWORD, mode_t);
676
677   int tcsetattr (int a, const struct termios *t);
678   int tcgetattr (struct termios *t);
679   int tcflush (int);
680   int ioctl (unsigned int cmd, void *);
681
682   off_t lseek (off_t, int) { return 0; }
683 };
684
685 class fhandler_pty_master: public fhandler_tty_common
686 {
687   int pktmode;                  // non-zero if pty in a packet mode.
688 public:
689   int need_nl;                  // Next read should start with \n
690
691   /* Constructor */
692   fhandler_pty_master (const char *name, DWORD devtype = FH_PTYM, int unit = -1);
693
694   int process_slave_output (char *buf, size_t len, int pktmode_on);
695   void doecho (const void *str, DWORD len);
696   int accept_input ();
697   int open (const char *path, int flags, mode_t mode = 0);
698   int write (const void *ptr, size_t len);
699   int read (void *ptr, size_t len);
700   int close ();
701
702   int tcsetattr (int a, const struct termios *t);
703   int tcgetattr (struct termios *t);
704   int tcflush (int);
705   int ioctl (unsigned int cmd, void *);
706
707   off_t lseek (off_t, int) { return 0; }
708   char *ptsname ();
709
710   void set_close_on_exec (int val);
711   BOOL hit_eof ();
712 };
713
714 class fhandler_tty_master: public fhandler_pty_master
715 {
716 public:
717   /* Constructor */
718   fhandler_tty_master (const char *name, int unit);
719   fhandler_console *console;    // device handler to perform real i/o.
720   HANDLE hThread;               // process_output thread handle.
721
722   int init (int);
723   int init_console ();
724   void fixup_after_fork (HANDLE parent);
725   void fixup_after_exec (HANDLE);
726 };
727
728 class fhandler_dev_null: public fhandler_base
729 {
730 public:
731   fhandler_dev_null (const char *name);
732
733   void dump ();
734   select_record *select_read (select_record *s);
735   select_record *select_write (select_record *s);
736   select_record *select_except (select_record *s);
737 };
738
739 class fhandler_dev_zero: public fhandler_base
740 {
741 public:
742   fhandler_dev_zero (const char *name);
743   int open (const char *path, int flags, mode_t mode = 0);
744   int write (const void *ptr, size_t len);
745   int read (void *ptr, size_t len);
746   off_t lseek (off_t offset, int whence);
747   int close (void);
748
749   void dump ();
750 };
751
752 class fhandler_dev_random: public fhandler_base
753 {
754 protected:
755   int unit;
756   HCRYPTPROV crypt_prov;
757   long pseudo;
758
759   BOOL crypt_gen_random (void *ptr, size_t len);
760   int pseudo_write (const void *ptr, size_t len);
761   int pseudo_read (void *ptr, size_t len);
762
763 public:
764   fhandler_dev_random (const char *name, int unit);
765   int get_unit () { return unit; }
766   int open (const char *path, int flags, mode_t mode = 0);
767   int write (const void *ptr, size_t len);
768   int read (void *ptr, size_t len);
769   off_t lseek (off_t offset, int whence);
770   int close (void);
771   int dup (fhandler_base *child);
772
773   void dump ();
774 };
775
776 class fhandler_dev_mem: public fhandler_base
777 {
778 protected:
779   int unit;
780   DWORD mem_size;
781   DWORD pos;
782   bool init_phase;
783
784   void init (void);
785
786 public:
787   fhandler_dev_mem (const char *name, int unit);
788   ~fhandler_dev_mem (void);
789
790   int open (const char *path, int flags, mode_t mode = 0);
791   int write (const void *ptr, size_t ulen);
792   int read (void *ptr, size_t ulen);
793   off_t lseek (off_t offset, int whence);
794   int close (void);
795   int fstat (struct stat *buf);
796   int dup (fhandler_base *child);
797
798   HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, off_t off);
799   int munmap (HANDLE h, caddr_t addr, size_t len);
800   int msync (HANDLE h, caddr_t addr, size_t len, int flags);
801
802   void dump ();
803 };
804
805 class fhandler_windows: public fhandler_base
806 {
807 private:
808   HWND hWnd_;   // the window whose messages are to be retrieved by read() call
809   int method_;  // write method (Post or Send)
810 public:
811   fhandler_windows (const char *name = 0);
812   int is_windows (void) { return 1; }
813   int open (const char *path, int flags, mode_t mode = 0);
814   int write (const void *ptr, size_t len);
815   int read (void *ptr, size_t len);
816   int ioctl (unsigned int cmd, void *);
817   off_t lseek (off_t, int) { return 0; }
818   int close (void) { return 0; }
819
820   void set_close_on_exec (int val);
821   void fixup_after_fork (HANDLE parent);
822   select_record *select_read (select_record *s);
823   select_record *select_write (select_record *s);
824   select_record *select_except (select_record *s);
825   int ready_for_read (int fd, DWORD howlong, int ignra);
826 };
827
828 #if 0
829 /* You can't do this */
830 typedef union
831 {
832   fhandler_normal normal;
833   fhandler_dev_null dev_null;
834   fhandler bare;
835   fhandler_serial tty;
836 } fhandler_union;
837 #else
838 #define fhandler_union fhandler_console
839 #endif
840 struct select_record
841 {
842   int fd;
843   HANDLE h;
844   fhandler_base *fh;
845   BOOL saw_error;
846   BOOL windows_handle;
847   BOOL read_ready, write_ready, except_ready;
848   BOOL read_selected, write_selected, except_selected;
849   int (*startup) (select_record *me, class select_stuff *stuff);
850   int (*poll) (select_record *me, fd_set *readfds, fd_set *writefds,
851                fd_set *exceptfds);
852   int (*verify) (select_record *me, fd_set *readfds, fd_set *writefds,
853                  fd_set *exceptfds);
854   void (*cleanup) (select_record *me, class select_stuff *stuff);
855   struct select_record *next;
856
857   select_record (fhandler_base *in_fh = NULL) : fd (0), h (NULL),
858                  fh (in_fh), saw_error (0), windows_handle (0),
859                  read_ready (0), write_ready (0), except_ready (0),
860                  read_selected (0), write_selected (0), except_selected (0),
861                  startup (NULL), poll (NULL), verify (NULL), cleanup (NULL),
862                  next (NULL) {}
863 };
864
865 class select_stuff
866 {
867 public:
868   ~select_stuff ();
869   select_stuff (): always_ready (0), windows_used (0), start (0)
870   {
871     memset (device_specific, 0, sizeof (device_specific));
872   }
873   BOOL always_ready, windows_used;
874   select_record start;
875   void *device_specific[FH_NDEV];
876
877   int test_and_set (int i, fd_set *readfds, fd_set *writefds,
878                      fd_set *exceptfds);
879   int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
880   int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
881 };
882
883 uid_t __stdcall get_file_owner (int, const char *);
884 gid_t __stdcall get_file_group (int, const char *);
885 int __stdcall set_console_state_for_spawn ();
886
887 #endif /* _FHANDLER_H_ */