OSDN Git Service

* fhandler.h (class fhandler_dev_random): Add members for managing
[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
577 public:
578
579   fhandler_console (const char *name);
580
581   fhandler_console* is_console () { return this; }
582
583   int open (const char *path, int flags, mode_t mode = 0);
584
585   int write (const void *ptr, size_t len);
586   void doecho (const void *str, DWORD len) { (void) write (str, len); }
587   int read (void *ptr, size_t len);
588   int close ();
589
590   int tcflush (int);
591   int tcsetattr (int a, const struct termios *t);
592   int tcgetattr (struct termios *t);
593
594   int tcsetpgrp (const pid_t pid) { tc->pgid = pid; return 0; }
595
596   /* Special dup as we must dup two handles */
597   int dup (fhandler_base *child);
598
599   int ioctl (unsigned int cmd, void *);
600   void init (HANDLE, DWORD, mode_t);
601
602   select_record *select_read (select_record *s);
603   select_record *select_write (select_record *s);
604   select_record *select_except (select_record *s);
605   int ready_for_read (int fd, DWORD howlong, int ignra);
606   int de_linearize (const char *, const char *, const char *);
607   void set_close_on_exec (int val);
608   void fixup_after_fork (HANDLE parent);
609   void set_input_state ()
610   {
611     if (TTYISSETF (RSTCONS))
612       input_tcsetattr (0, &tc->ti);
613   }
614 };
615
616 class fhandler_tty_common: public fhandler_termios
617 {
618 public:
619   fhandler_tty_common (DWORD dev, const char *name = 0, int unit = 0) :
620     fhandler_termios (dev, name, unit),
621     ttynum (unit)
622   {
623     // nothing to do
624   }
625   HANDLE output_done_event;     // Raised by master when tty's output buffer
626                                 // written. Write status in tty::write_retval.
627   HANDLE ioctl_request_event;   // Raised by slave to perform ioctl() request.
628                                 // Ioctl() request in tty::cmd/arg.
629   HANDLE ioctl_done_event;      // Raised by master on ioctl() completion.
630                                 // Ioctl() status in tty::ioctl_retval.
631   HANDLE output_mutex;
632   HANDLE inuse;                 // used to indicate that a tty is in use
633
634
635   DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
636   void __release_output_mutex (const char *fn, int ln);
637
638   int ttynum;                   // Master tty num.
639   virtual int dup (fhandler_base *child);
640
641   tty *get_ttyp () { return (tty *)tc; }
642   int get_unit () { return ttynum; }
643
644   int close ();
645   void set_close_on_exec (int val);
646   void fixup_after_fork (HANDLE parent);
647   select_record *select_read (select_record *s);
648   select_record *select_write (select_record *s);
649   select_record *select_except (select_record *s);
650   int ready_for_read (int fd, DWORD howlong, int ignra);
651 };
652
653 class fhandler_tty_slave: public fhandler_tty_common
654 {
655 public:
656   /* Constructor */
657   fhandler_tty_slave (const char *name);
658   fhandler_tty_slave (int, const char *name);
659
660   int open (const char *path, int flags, mode_t mode = 0);
661   int write (const void *ptr, size_t len);
662   int read (void *ptr, size_t len);
663   void init (HANDLE, DWORD, mode_t);
664
665   int tcsetattr (int a, const struct termios *t);
666   int tcgetattr (struct termios *t);
667   int tcflush (int);
668   int ioctl (unsigned int cmd, void *);
669
670   off_t lseek (off_t, int) { return 0; }
671 };
672
673 class fhandler_pty_master: public fhandler_tty_common
674 {
675   int pktmode;                  // non-zero if pty in a packet mode.
676 public:
677   int need_nl;                  // Next read should start with \n
678
679   /* Constructor */
680   fhandler_pty_master (const char *name, DWORD devtype = FH_PTYM, int unit = -1);
681
682   int process_slave_output (char *buf, size_t len, int pktmode_on);
683   void doecho (const void *str, DWORD len);
684   int accept_input ();
685   int open (const char *path, int flags, mode_t mode = 0);
686   int write (const void *ptr, size_t len);
687   int read (void *ptr, size_t len);
688   int close ();
689
690   int tcsetattr (int a, const struct termios *t);
691   int tcgetattr (struct termios *t);
692   int tcflush (int);
693   int ioctl (unsigned int cmd, void *);
694
695   off_t lseek (off_t, int) { return 0; }
696   char *ptsname ();
697
698   void set_close_on_exec (int val);
699   void fixup_after_fork (HANDLE parent);
700   BOOL hit_eof ();
701 };
702
703 class fhandler_tty_master: public fhandler_pty_master
704 {
705 public:
706   /* Constructor */
707   fhandler_tty_master (const char *name, int unit);
708   fhandler_console *console;    // device handler to perform real i/o.
709   HANDLE hThread;               // process_output thread handle.
710
711   int init (int);
712   int init_console ();
713   void fixup_after_fork (HANDLE parent);
714   int de_linearize (const char *, const char *, const char *);
715 };
716
717 class fhandler_dev_null: public fhandler_base
718 {
719 public:
720   fhandler_dev_null (const char *name);
721
722   void dump ();
723   select_record *select_read (select_record *s);
724   select_record *select_write (select_record *s);
725   select_record *select_except (select_record *s);
726 };
727
728 class fhandler_dev_zero: public fhandler_base
729 {
730 public:
731   fhandler_dev_zero (const char *name);
732   int open (const char *path, int flags, mode_t mode = 0);
733   int write (const void *ptr, size_t len);
734   int read (void *ptr, size_t len);
735   off_t lseek (off_t offset, int whence);
736   int close (void);
737
738   void dump ();
739 };
740
741 class fhandler_dev_random: public fhandler_base
742 {
743 protected:
744   int unit;
745   HCRYPTPROV crypt_prov;
746   long pseudo;
747
748   BOOL crypt_gen_random (void *ptr, size_t len);
749   int pseudo_write (const void *ptr, size_t len);
750   int pseudo_read (void *ptr, size_t len);
751
752 public:
753   fhandler_dev_random (const char *name, int unit);
754   int get_unit () { return unit; }
755   int open (const char *path, int flags, mode_t mode = 0);
756   int write (const void *ptr, size_t len);
757   int read (void *ptr, size_t len);
758   off_t lseek (off_t offset, int whence);
759   int close (void);
760   int dup (fhandler_base *child);
761
762   void dump ();
763 };
764
765 class fhandler_windows: public fhandler_base
766 {
767 private:
768   HWND hWnd_;   // the window whose messages are to be retrieved by read() call
769   int method_;  // write method (Post or Send)
770 public:
771   fhandler_windows (const char *name = 0);
772   int is_windows (void) { return 1; }
773   int open (const char *path, int flags, mode_t mode = 0);
774   int write (const void *ptr, size_t len);
775   int read (void *ptr, size_t len);
776   int ioctl (unsigned int cmd, void *);
777   off_t lseek (off_t, int) { return 0; }
778   int close (void) { return 0; }
779
780   void set_close_on_exec (int val);
781   void fixup_after_fork (HANDLE parent);
782   select_record *select_read (select_record *s);
783   select_record *select_write (select_record *s);
784   select_record *select_except (select_record *s);
785   int ready_for_read (int fd, DWORD howlong, int ignra);
786 };
787
788 #if 0
789 /* You can't do this */
790 typedef union
791 {
792   fhandler_normal normal;
793   fhandler_dev_null dev_null;
794   fhandler bare;
795   fhandler_serial tty;
796 } fhandler_union;
797 #else
798 #define fhandler_union fhandler_console
799 #endif
800 struct select_record
801 {
802   int fd;
803   HANDLE h;
804   fhandler_base *fh;
805   BOOL saw_error;
806   BOOL windows_handle;
807   BOOL read_ready, write_ready, except_ready;
808   BOOL read_selected, write_selected, except_selected;
809   int (*startup) (select_record *me, class select_stuff *stuff);
810   int (*poll) (select_record *me, fd_set *readfds, fd_set *writefds,
811                fd_set *exceptfds);
812   int (*verify) (select_record *me, fd_set *readfds, fd_set *writefds,
813                  fd_set *exceptfds);
814   void (*cleanup) (select_record *me, class select_stuff *stuff);
815   struct select_record *next;
816
817   select_record (fhandler_base *in_fh = NULL) : fd (0), h (NULL),
818                  fh (in_fh), saw_error (0), windows_handle (0),
819                  read_ready (0), write_ready (0), except_ready (0),
820                  read_selected (0), write_selected (0), except_selected (0),
821                  startup (NULL), poll (NULL), verify (NULL), cleanup (NULL),
822                  next (NULL) {}
823 };
824
825 class select_stuff
826 {
827 public:
828   ~select_stuff ();
829   select_stuff (): always_ready (0), windows_used (0), start (0)
830   {
831     memset (device_specific, 0, sizeof (device_specific));
832   }
833   BOOL always_ready, windows_used;
834   select_record start;
835   void *device_specific[FH_NDEV];
836
837   int test_and_set (int i, fd_set *readfds, fd_set *writefds,
838                      fd_set *exceptfds);
839   int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
840   int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
841 };
842
843 uid_t __stdcall get_file_owner (int, const char *);
844 gid_t __stdcall get_file_group (int, const char *);
845
846 #endif /* _FHANDLER_H_ */