OSDN Git Service

* fhandler.h (select_stuff): Eliminate use of 'total'.
[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
239   /* fixup fd possibly non-inherited handles after fork */
240   void fork_fixup (HANDLE parent, HANDLE &h, const char *name);
241
242   /* Potentially overridden virtual functions. */
243   virtual int open (const char *, int flags, mode_t mode = 0)
244   {
245     return open (flags, mode);
246   }
247   virtual int open (int flags, mode_t mode = 0);
248   virtual int close ();
249   virtual int fstat (struct stat *buf);
250   virtual int ioctl (unsigned int cmd, void *);
251   virtual char const * ttyname () { return get_name(); }
252   virtual int read (void *ptr, size_t len);
253   virtual int write (const void *ptr, size_t len);
254   virtual off_t lseek (off_t offset, int whence);
255   virtual int lock (int, struct flock *);
256   virtual void dump ();
257   virtual int dup (fhandler_base *child);
258
259   void *operator new (size_t, void *p) {return p;}
260
261   virtual void init (HANDLE, DWORD, mode_t);
262
263   virtual int tcflush (int);
264   virtual int tcsendbreak (int);
265   virtual int tcdrain ();
266   virtual int tcflow (int);
267   virtual int tcsetattr (int a, const struct termios *t);
268   virtual int tcgetattr (struct termios *t);
269   virtual int tcsetpgrp (const pid_t pid);
270   virtual int tcgetpgrp ();
271   virtual int is_tty () { return 0; }
272   virtual BOOL is_device () { return TRUE; }
273   virtual char *ptsname () { return NULL;}
274   virtual class fhandler_socket *is_socket () { return 0; }
275   virtual class fhandler_console *is_console () { return 0; }
276   virtual int is_windows () {return 0; }
277
278   virtual int raw_read (void *ptr, size_t ulen);
279   virtual int raw_write (const void *ptr, size_t ulen);
280
281   /* Function to save state of a fhandler_base into memory. */
282   virtual int linearize (unsigned char *);
283   /* Function to de-linearize into a fd */
284   virtual int de_linearize (const char *, const char *, const char *);
285
286   /* Virtual accessor functions to hide the fact
287      that some fd's have two handles. */
288   virtual HANDLE get_handle () const { return io_handle; }
289   virtual HANDLE get_io_handle () const { return io_handle; }
290   virtual HANDLE get_output_handle () const { return io_handle; }
291   virtual BOOL hit_eof () {return FALSE;}
292   virtual select_record *select_read (select_record *s);
293   virtual select_record *select_write (select_record *s);
294   virtual select_record *select_except (select_record *s);
295   virtual int ready_for_read (int fd, DWORD howlong, int ignra);
296   virtual const char * get_native_name ()
297   {
298     return windows_device_names[FHDEVN (status)];
299   }
300   virtual int bg_check (int) {return 1;}
301 };
302
303 class fhandler_socket: public fhandler_base
304 {
305 private:
306   int addr_family;
307 public:
308   fhandler_socket (const char *name = 0);
309   fhandler_socket (unsigned int, const char *name = 0);
310   ~fhandler_socket ();
311   int get_socket () const { return (int) get_handle(); }
312   fhandler_socket * is_socket () { return this; }
313   int write (const void *ptr, size_t len);
314   int read (void *ptr, size_t len);
315   int ioctl (unsigned int cmd, void *);
316   off_t lseek (off_t, int) { return 0; }
317   int close ();
318
319   select_record *select_read (select_record *s);
320   select_record *select_write (select_record *s);
321   select_record *select_except (select_record *s);
322   int ready_for_read (int fd, DWORD howlong, int ignra);
323   int get_addr_family () {return addr_family;}
324   void set_addr_family (int af) {addr_family = af;}
325 };
326
327 class fhandler_pipe: public fhandler_base
328 {
329 public:
330   fhandler_pipe (const char *name = 0, DWORD devtype = FH_PIPE);
331   off_t lseek (off_t offset, int whence);
332   /* This strange test is due to the fact that we can't rely on
333      Windows shells to "do the right thing" with pipes.  Apparently
334      the can keep one end of the pipe open when it shouldn't be. */
335   BOOL is_slow () {return os_being_run == winNT;}
336   select_record *select_read (select_record *s);
337   select_record *select_write (select_record *s);
338   select_record *select_except (select_record *s);
339   int ready_for_read (int fd, DWORD howlong, int ignra);
340 };
341
342 class fhandler_dev_raw: public fhandler_base
343 {
344 protected:
345   char *devbuf;
346   size_t devbufsiz;
347   size_t devbufstart;
348   size_t devbufend;
349   int eom_detected    : 1;
350   int eof_detected    : 1;
351   int lastblk_to_read : 1;
352   int is_writing      : 1;
353   int has_written     : 1;
354   int unit;
355
356   virtual void clear (void);
357   virtual int writebuf (void);
358
359   /* returns not null, if `win_error' determines an end of media condition */
360   virtual int is_eom(int win_error) = 0;
361   /* returns not null, if `win_error' determines an end of file condition */
362   virtual int is_eof(int win_error) = 0;
363
364   fhandler_dev_raw (DWORD dev, const char *name, int unit);
365
366 public:
367   ~fhandler_dev_raw (void);
368
369   /* Function to de-linearize into a fd */
370   int de_linearize (const char *, const char *, const char *);
371
372   int open (const char *path, int flags, mode_t mode = 0);
373   int close (void);
374
375   int raw_read (void *ptr, size_t ulen);
376   int raw_write (const void *ptr, size_t ulen);
377
378   int fstat (struct stat *buf);
379
380   int dup (fhandler_base *child);
381
382   int ioctl (unsigned int cmd, void *buf);
383 };
384
385 class fhandler_dev_floppy: public fhandler_dev_raw
386 {
387 protected:
388   virtual int is_eom (int win_error);
389   virtual int is_eof (int win_error);
390
391 public:
392   fhandler_dev_floppy (const char *name, int unit);
393
394   virtual int open (const char *path, int flags, mode_t mode = 0);
395   virtual int close (void);
396
397   virtual off_t lseek (off_t offset, int whence);
398
399   virtual int ioctl (unsigned int cmd, void *buf);
400 };
401
402 class fhandler_dev_tape: public fhandler_dev_raw
403 {
404   int norewind;
405   int lasterr;
406
407 protected:
408   virtual void clear (void);
409
410   virtual int is_eom (int win_error);
411   virtual int is_eof (int win_error);
412
413 public:
414   fhandler_dev_tape (const char *name, int unit);
415
416   virtual int open (const char *path, int flags, mode_t mode = 0);
417   virtual int close (void);
418
419   virtual off_t lseek (off_t offset, int whence);
420
421   virtual int fstat (struct stat *buf);
422
423   virtual int dup (fhandler_base *child);
424
425   virtual int ioctl (unsigned int cmd, void *buf);
426
427 private:
428   int tape_write_marks (int marktype, DWORD len);
429   int tape_get_pos (unsigned long *ret);
430   int tape_set_pos (int mode, long count, BOOLEAN sfm_func = FALSE);
431   int tape_erase (int mode);
432   int tape_prepare (int action);
433   BOOLEAN tape_get_feature (DWORD parm);
434   int tape_get_blocksize (long *min, long *def, long *max, long *cur);
435   int tape_set_blocksize (long count);
436   int tape_status (struct mtget *get);
437   int tape_compression (long count);
438 };
439
440 /* Standard disk file */
441
442 class fhandler_disk_file: public fhandler_base
443 {
444 private:
445   int check_execable_p (const char *path);
446
447 public:
448   fhandler_disk_file (const char *name);
449
450   int open (const char *path, int flags, mode_t mode = 0);
451   int open (path_conv& real_path, int flags, mode_t mode);
452   int close ();
453   int lock (int, struct flock *);
454   BOOL is_device () { return FALSE; }
455   int fstat (struct stat *buf);
456 };
457
458 class fhandler_serial: public fhandler_base
459 {
460 private:
461   unsigned int vmin_;                   /* from termios */
462   unsigned int vtime_;                  /* from termios */
463   pid_t pgrp_;
464
465 public:
466   int overlapped_armed;
467   OVERLAPPED io_status;
468
469   /* Constructor */
470   fhandler_serial (const char *name, DWORD devtype = FH_SERIAL, int unit = 0);
471
472   int open (const char *path, int flags, mode_t mode);
473   int close ();
474   void init (HANDLE h, DWORD a, mode_t flags);
475   void overlapped_setup ();
476   int dup (fhandler_base *child);
477   int raw_read (void *ptr, size_t ulen);
478   int raw_write (const void *ptr, size_t ulen);
479   int tcsendbreak (int);
480   int tcdrain ();
481   int tcflow (int);
482   int tcsetattr (int a, const struct termios *t);
483   int tcgetattr (struct termios *t);
484   off_t lseek (off_t, int) { return 0; }
485   int tcflush (int);
486   void dump ();
487   int is_tty () { return 1; }
488   void fixup_after_fork (HANDLE parent);
489   int de_linearize (const char *, const char *, const char *);
490
491   /* We maintain a pgrp so that tcsetpgrp and tcgetpgrp work, but we
492      don't use it for permissions checking.  fhandler_tty_slave does
493      permission checking on pgrps.  */
494   virtual int tcgetpgrp () { return pgrp_; }
495   virtual int tcsetpgrp (const pid_t pid) { pgrp_ = pid; return 0; }
496   select_record *select_read (select_record *s);
497   select_record *select_write (select_record *s);
498   select_record *select_except (select_record *s);
499   int ready_for_read (int fd, DWORD howlong, int ignra);
500 };
501
502 class fhandler_termios: public fhandler_base
503 {
504 protected:
505   HANDLE output_handle;
506   virtual void doecho (const void *, DWORD) {};
507   virtual int accept_input () {return 1;};
508 public:
509   tty_min *tc;
510   fhandler_termios (DWORD dev, const char *name = 0, int unit = 0) :
511   fhandler_base (dev, name, unit)
512   {
513     // nothing to do
514   }
515   HANDLE restart_output_event;
516   HANDLE get_output_handle () const { return output_handle; }
517   int line_edit (const char *rptr, int nread, int always_accept = 0);
518   void set_output_handle (HANDLE h) { output_handle = h; }
519   void tcinit (tty_min *this_tc, int force = FALSE);
520   virtual int is_tty () { return 1; }
521   int tcgetpgrp ();
522   int tcsetpgrp (int pid);
523   void set_ctty (int ttynum, int flags);
524   int bg_check (int sig);
525 };
526
527 /* This is a input and output console handle */
528 class fhandler_console: public fhandler_termios
529 {
530 private:
531
532 /* Output state */
533
534   // enum {normal, gotesc, gotsquare, gotarg1, gotcommand} state;
535 #define normal 1
536 #define gotesc 2
537 #define gotsquare 3
538 #define gotarg1 4
539 #define gotrsquare 5
540 #define gotcommand 6
541 #define gettitle 7
542 #define eattitle 8
543 #define MAXARGS 10
544   int state_;
545   int args_[MAXARGS];
546   int nargs_;
547
548   DWORD default_color;
549
550 /* Output calls */
551
552   BOOL fillin_info ();
553   void clear_screen (int, int, int, int);
554   void scroll_screen (int, int, int, int, int, int);
555   void cursor_set (BOOL, int, int);
556   void cursor_get (int *, int *);
557   void cursor_rel (int, int);
558   const unsigned char * write_normal (unsigned const char*, unsigned const char *);
559   void char_command (char);
560   int output_tcsetattr (int a, const struct termios *t);
561
562 /* Input calls */
563   int igncr_enabled ();
564   int input_tcsetattr (int a, const struct termios *t);
565
566 public:
567
568   fhandler_console (const char *name);
569
570   fhandler_console* is_console () { return this; }
571
572   int open (const char *path, int flags, mode_t mode = 0);
573
574   int write (const void *ptr, size_t len);
575   void doecho (const void *str, DWORD len) { (void) write (str, len); }
576   int read (void *ptr, size_t len);
577   int close ();
578
579   int tcflush (int);
580   int tcsetattr (int a, const struct termios *t);
581   int tcgetattr (struct termios *t);
582
583   int tcsetpgrp (const pid_t pid) { tc->pgid = pid; return 0; }
584
585   /* Special dup as we must dup two handles */
586   int dup (fhandler_base *child);
587
588   int ioctl (unsigned int cmd, void *);
589   void init (HANDLE, DWORD, mode_t);
590
591   select_record *select_read (select_record *s);
592   select_record *select_write (select_record *s);
593   select_record *select_except (select_record *s);
594   int ready_for_read (int fd, DWORD howlong, int ignra);
595   int de_linearize (const char *, const char *, const char *);
596   void set_close_on_exec (int val);
597   void fixup_after_fork (HANDLE parent);
598   void set_input_state ()
599   {
600     if (TTYISSETF (RSTCONS))
601       input_tcsetattr (0, &tc->ti);
602   }
603 };
604
605 class fhandler_tty_common: public fhandler_termios
606 {
607 public:
608   fhandler_tty_common (DWORD dev, const char *name = 0, int unit = 0) :
609     fhandler_termios (dev, name, unit),
610     ttynum (unit)
611   {
612     // nothing to do
613   }
614   HANDLE output_done_event;     // Raised by master when tty's output buffer
615                                 // written. Write status in tty::write_retval.
616   HANDLE ioctl_request_event;   // Raised by slave to perform ioctl() request.
617                                 // Ioctl() request in tty::cmd/arg.
618   HANDLE ioctl_done_event;      // Raised by master on ioctl() completion.
619                                 // Ioctl() status in tty::ioctl_retval.
620   HANDLE output_mutex;
621   HANDLE inuse;                 // used to indicate that a tty is in use
622
623
624   DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
625   void __release_output_mutex (const char *fn, int ln);
626
627   int ttynum;                   // Master tty num.
628   virtual int dup (fhandler_base *child);
629
630   tty *get_ttyp () { return (tty *)tc; }
631   int get_unit () { return ttynum; }
632
633   int close ();
634   void set_close_on_exec (int val);
635   void fixup_after_fork (HANDLE parent);
636   select_record *select_read (select_record *s);
637   select_record *select_write (select_record *s);
638   select_record *select_except (select_record *s);
639   int ready_for_read (int fd, DWORD howlong, int ignra);
640 };
641
642 class fhandler_tty_slave: public fhandler_tty_common
643 {
644   void send_ioctl_request ();
645
646 public:
647   /* Constructor */
648   fhandler_tty_slave (const char *name);
649   fhandler_tty_slave (int, const char *name);
650
651   int open (const char *path, int flags, mode_t mode = 0);
652   int write (const void *ptr, size_t len);
653   int read (void *ptr, size_t len);
654   void init (HANDLE, DWORD, mode_t);
655
656   int tcsetattr (int a, const struct termios *t);
657   int tcgetattr (struct termios *t);
658   int tcflush (int);
659   int ioctl (unsigned int cmd, void *);
660
661   off_t lseek (off_t, int) { return 0; }
662 };
663
664 class fhandler_pty_master: public fhandler_tty_common
665 {
666   int pktmode;                  // non-zero if pty in a packet mode.
667 public:
668   int need_nl;                  // Next read should start with \n
669
670   /* Constructor */
671   fhandler_pty_master (const char *name, DWORD devtype = FH_PTYM, int unit = -1);
672
673   int process_slave_output (char *buf, size_t len, int pktmode_on);
674   void doecho (const void *str, DWORD len);
675   int accept_input ();
676   int open (const char *path, int flags, mode_t mode = 0);
677   int write (const void *ptr, size_t len);
678   int read (void *ptr, size_t len);
679   int close ();
680
681   int tcsetattr (int a, const struct termios *t);
682   int tcgetattr (struct termios *t);
683   int tcflush (int);
684   int ioctl (unsigned int cmd, void *);
685
686   off_t lseek (off_t, int) { return 0; }
687   char *ptsname ();
688
689   void set_close_on_exec (int val);
690   void fixup_after_fork (HANDLE parent);
691   BOOL hit_eof ();
692 };
693
694 class fhandler_tty_master: public fhandler_pty_master
695 {
696 public:
697   /* Constructor */
698   fhandler_tty_master (const char *name, int unit);
699   fhandler_console *console;    // device handler to perform real i/o.
700   HANDLE hThread;               // process_output thread handle.
701
702   int init (int);
703   int init_console ();
704   void fixup_after_fork (HANDLE parent);
705   int de_linearize (const char *, const char *, const char *);
706 };
707
708 class fhandler_dev_null: public fhandler_base
709 {
710 public:
711   fhandler_dev_null (const char *name);
712
713   void dump ();
714   select_record *select_read (select_record *s);
715   select_record *select_write (select_record *s);
716   select_record *select_except (select_record *s);
717 };
718
719 class fhandler_dev_zero: public fhandler_base
720 {
721 public:
722   fhandler_dev_zero (const char *name);
723   int open (const char *path, int flags, mode_t mode = 0);
724   int write (const void *ptr, size_t len);
725   int read (void *ptr, size_t len);
726   off_t lseek (off_t offset, int whence);
727   int close (void);
728
729   void dump ();
730 };
731
732 class fhandler_windows: public fhandler_base
733 {
734 private:
735   HWND hWnd_;   // the window whose messages are to be retrieved by read() call
736   int method_;  // write method (Post or Send)
737 public:
738   fhandler_windows (const char *name = 0);
739   int is_windows (void) { return 1; }
740   int open (const char *path, int flags, mode_t mode = 0);
741   int write (const void *ptr, size_t len);
742   int read (void *ptr, size_t len);
743   int ioctl (unsigned int cmd, void *);
744   off_t lseek (off_t, int) { return 0; }
745   int close (void) { return 0; }
746
747   void set_close_on_exec (int val);
748   void fixup_after_fork (HANDLE parent);
749   select_record *select_read (select_record *s);
750   select_record *select_write (select_record *s);
751   select_record *select_except (select_record *s);
752   int ready_for_read (int fd, DWORD howlong, int ignra);
753 };
754
755 #if 0
756 /* You can't do this */
757 typedef union
758 {
759   fhandler_normal normal;
760   fhandler_dev_null dev_null;
761   fhandler bare;
762   fhandler_serial tty;
763 } fhandler_union;
764 #else
765 #define fhandler_union fhandler_console
766 #endif
767 struct select_record
768 {
769   int fd;
770   HANDLE h;
771   fhandler_base *fh;
772   BOOL saw_error;
773   BOOL windows_handle;
774   BOOL read_ready, write_ready, except_ready;
775   BOOL read_selected, write_selected, except_selected;
776   int (*startup) (select_record *me, class select_stuff *stuff);
777   int (*poll) (select_record *me, fd_set *readfds, fd_set *writefds,
778                fd_set *exceptfds);
779   int (*verify) (select_record *me, fd_set *readfds, fd_set *writefds,
780                  fd_set *exceptfds);
781   void (*cleanup) (select_record *me, class select_stuff *stuff);
782   struct select_record *next;
783
784   select_record (fhandler_base *in_fh = NULL) : fd (0), h (NULL),
785                  fh (in_fh), saw_error (0), windows_handle (0),
786                  read_ready (0), write_ready (0), except_ready (0),
787                  read_selected (0), write_selected (0), except_selected (0),
788                  startup (NULL), poll (NULL), verify (NULL), cleanup (NULL),
789                  next (NULL) {}
790 };
791
792 class select_stuff
793 {
794 public:
795   ~select_stuff ();
796   select_stuff (): always_ready (0), windows_used (0), start (0)
797   {
798     memset (device_specific, 0, sizeof (device_specific));
799   }
800   BOOL always_ready, windows_used;
801   select_record start;
802   void *device_specific[FH_NDEV];
803
804   int test_and_set (int i, fd_set *readfds, fd_set *writefds,
805                      fd_set *exceptfds);
806   int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
807   int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
808 };
809
810 uid_t __stdcall get_file_owner (int, const char *);
811 gid_t __stdcall get_file_group (int, const char *);
812
813 void __stdcall set_inheritance (HANDLE &h, int val, const char *name = NULL);
814
815 #endif /* _FHANDLER_H_ */