OSDN Git Service

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