OSDN Git Service

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