OSDN Git Service

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