OSDN Git Service

* fhandler.h (fhandler_dev_raw): Add definition for method
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / fhandler.h
1 /* fhandler.h
2
3    Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #ifndef _FHANDLER_H_
12 #define _FHANDLER_H_
13
14 #include <sys/ioctl.h>
15
16 /* Classes
17
18   Code is located in fhandler.cc unless another file name is given.
19
20   fhandler_base           normal I/O
21
22      fhandler_disk_file
23      fhandler_serial      Adds vmin and vtime.
24      fhandler_dev_null    Not really I/O
25      fhandler_dev_zero    Faked
26
27      fhandler_dev_raw     (fhandler_raw.cc)
28      fhandler_dev_floppy  (fhandler_floppy.cc)
29      fhandler_dev_tape    (fhandler_tape.cc)
30
31      fhandler_pipe
32      fhandler_socket      (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   void fixup_after_fork (HANDLE);
408 };
409
410 class fhandler_dev_floppy: public fhandler_dev_raw
411 {
412 protected:
413   virtual int is_eom (int win_error);
414   virtual int is_eof (int win_error);
415
416 public:
417   fhandler_dev_floppy (const char *name, int unit);
418
419   virtual int open (const char *path, int flags, mode_t mode = 0);
420   virtual int close (void);
421
422   virtual off_t lseek (off_t offset, int whence);
423
424   virtual int ioctl (unsigned int cmd, void *buf);
425 };
426
427 class fhandler_dev_tape: public fhandler_dev_raw
428 {
429   int norewind;
430   int lasterr;
431
432 protected:
433   virtual void clear (void);
434
435   virtual int is_eom (int win_error);
436   virtual int is_eof (int win_error);
437
438 public:
439   fhandler_dev_tape (const char *name, int unit);
440
441   virtual int open (const char *path, int flags, mode_t mode = 0);
442   virtual int close (void);
443
444   virtual off_t lseek (off_t offset, int whence);
445
446   virtual int fstat (struct stat *buf);
447
448   virtual int dup (fhandler_base *child);
449
450   virtual int ioctl (unsigned int cmd, void *buf);
451
452 private:
453   int tape_write_marks (int marktype, DWORD len);
454   int tape_get_pos (unsigned long *ret);
455   int tape_set_pos (int mode, long count, BOOLEAN sfm_func = FALSE);
456   int tape_erase (int mode);
457   int tape_prepare (int action);
458   BOOLEAN tape_get_feature (DWORD parm);
459   int tape_get_blocksize (long *min, long *def, long *max, long *cur);
460   int tape_set_blocksize (long count);
461   int tape_status (struct mtget *get);
462   int tape_compression (long count);
463 };
464
465 /* Standard disk file */
466
467 class fhandler_disk_file: public fhandler_base
468 {
469 private:
470   int check_execable_p (const char *path);
471
472 public:
473   fhandler_disk_file (const char *name);
474
475   int open (const char *path, int flags, mode_t mode = 0);
476   int open (path_conv& real_path, int flags, mode_t mode);
477   int close ();
478   int lock (int, struct flock *);
479   BOOL is_device () { return FALSE; }
480   int fstat (struct stat *buf);
481
482   HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, off_t off);
483   int munmap (HANDLE h, caddr_t addr, size_t len);
484   int msync (HANDLE h, caddr_t addr, size_t len, int flags);
485 };
486
487 class fhandler_serial: public fhandler_base
488 {
489 private:
490   unsigned int vmin_;                   /* from termios */
491   unsigned int vtime_;                  /* from termios */
492   pid_t pgrp_;
493
494 public:
495   int overlapped_armed;
496   OVERLAPPED io_status;
497
498   /* Constructor */
499   fhandler_serial (const char *name, DWORD devtype = FH_SERIAL, int unit = 0);
500
501   int open (const char *path, int flags, mode_t mode);
502   int close ();
503   void init (HANDLE h, DWORD a, mode_t flags);
504   void overlapped_setup ();
505   int dup (fhandler_base *child);
506   int raw_read (void *ptr, size_t ulen);
507   int raw_write (const void *ptr, size_t ulen);
508   int tcsendbreak (int);
509   int tcdrain ();
510   int tcflow (int);
511   int tcsetattr (int a, const struct termios *t);
512   int tcgetattr (struct termios *t);
513   off_t lseek (off_t, int) { return 0; }
514   int tcflush (int);
515   void dump ();
516   int is_tty () { return 1; }
517   void fixup_after_fork (HANDLE parent);
518   void fixup_after_exec (HANDLE);
519
520   /* We maintain a pgrp so that tcsetpgrp and tcgetpgrp work, but we
521      don't use it for permissions checking.  fhandler_tty_slave does
522      permission checking on pgrps.  */
523   virtual int tcgetpgrp () { return pgrp_; }
524   virtual int tcsetpgrp (const pid_t pid) { pgrp_ = pid; return 0; }
525   select_record *select_read (select_record *s);
526   select_record *select_write (select_record *s);
527   select_record *select_except (select_record *s);
528   int ready_for_read (int fd, DWORD howlong, int ignra);
529 };
530
531 #define acquire_output_mutex(ms) \
532   __acquire_output_mutex (__PRETTY_FUNCTION__, __LINE__, ms);
533
534 #define release_output_mutex() \
535   __release_output_mutex (__PRETTY_FUNCTION__, __LINE__);
536
537 class tty;
538 class tty_min;
539 class fhandler_termios: public fhandler_base
540 {
541 protected:
542   HANDLE output_handle;
543   virtual void doecho (const void *, DWORD) {};
544   virtual int accept_input () {return 1;};
545 public:
546   tty_min *tc;
547   fhandler_termios (DWORD dev, const char *name = 0, int unit = 0) :
548   fhandler_base (dev, name, unit)
549   {
550     // nothing to do
551   }
552   HANDLE get_output_handle () const { return output_handle; }
553   int line_edit (const char *rptr, int nread, int always_accept = 0);
554   void set_output_handle (HANDLE h) { output_handle = h; }
555   void tcinit (tty_min *this_tc, int force = FALSE);
556   virtual int is_tty () { return 1; }
557   int tcgetpgrp ();
558   int tcsetpgrp (int pid);
559   void set_ctty (int ttynum, int flags);
560   int bg_check (int sig);
561   virtual DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms) {return 1;}
562   virtual void __release_output_mutex (const char *fn, int ln) {}
563 };
564
565 /* This is a input and output console handle */
566 class fhandler_console: public fhandler_termios
567 {
568 private:
569
570 /* Output state */
571
572   // enum {normal, gotesc, gotsquare, gotarg1, gotcommand} state;
573 #define normal 1
574 #define gotesc 2
575 #define gotsquare 3
576 #define gotarg1 4
577 #define gotrsquare 5
578 #define gotcommand 6
579 #define gettitle 7
580 #define eattitle 8
581 #define MAXARGS 10
582   int state_;
583   int args_[MAXARGS];
584   int nargs_;
585
586   DWORD default_color;
587
588 /* Output calls */
589
590   BOOL fillin_info ();
591   void clear_screen (int, int, int, int);
592   void scroll_screen (int, int, int, int, int, int);
593   void cursor_set (BOOL, int, int);
594   void cursor_get (int *, int *);
595   void cursor_rel (int, int);
596   const unsigned char * write_normal (unsigned const char*, unsigned const char *);
597   void char_command (char);
598   int output_tcsetattr (int a, const struct termios *t);
599
600 /* Input calls */
601   int igncr_enabled ();
602   int input_tcsetattr (int a, const struct termios *t);
603   void set_cursor_maybe ();
604
605 public:
606
607   fhandler_console (const char *name);
608
609   fhandler_console* is_console () { return this; }
610
611   int open (const char *path, int flags, mode_t mode = 0);
612
613   int write (const void *ptr, size_t len);
614   void doecho (const void *str, DWORD len) { (void) write (str, len); }
615   int read (void *ptr, size_t len);
616   int close ();
617
618   int tcflush (int);
619   int tcsetattr (int a, const struct termios *t);
620   int tcgetattr (struct termios *t);
621
622   /* Special dup as we must dup two handles */
623   int dup (fhandler_base *child);
624
625   int ioctl (unsigned int cmd, void *);
626   void init (HANDLE, DWORD, mode_t);
627
628   select_record *select_read (select_record *s);
629   select_record *select_write (select_record *s);
630   select_record *select_except (select_record *s);
631   int ready_for_read (int fd, DWORD howlong, int ignra);
632   void fixup_after_exec (HANDLE);
633   void set_close_on_exec (int val);
634   void fixup_after_fork (HANDLE parent);
635   void set_input_state ();
636 };
637
638 class fhandler_tty_common: public fhandler_termios
639 {
640 public:
641   fhandler_tty_common (DWORD dev, const char *name = 0, int unit = 0) :
642     fhandler_termios (dev, name, unit),
643     ttynum (unit)
644   {
645     // nothing to do
646   }
647   HANDLE output_done_event;     // Raised by master when tty's output buffer
648                                 // written. Write status in tty::write_retval.
649   HANDLE ioctl_request_event;   // Raised by slave to perform ioctl() request.
650                                 // Ioctl() request in tty::cmd/arg.
651   HANDLE ioctl_done_event;      // Raised by master on ioctl() completion.
652                                 // Ioctl() status in tty::ioctl_retval.
653   HANDLE output_mutex;
654   HANDLE inuse;                 // used to indicate that a tty is in use
655
656
657   DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
658   void __release_output_mutex (const char *fn, int ln);
659
660   int ttynum;                   // Master tty num.
661   virtual int dup (fhandler_base *child);
662
663   tty *get_ttyp () { return (tty *)tc; }
664   int get_unit () { return ttynum; }
665
666   int close ();
667   void set_close_on_exec (int val);
668   void fixup_after_fork (HANDLE parent);
669   select_record *select_read (select_record *s);
670   select_record *select_write (select_record *s);
671   select_record *select_except (select_record *s);
672   int ready_for_read (int fd, DWORD howlong, int ignra);
673 };
674
675 class fhandler_tty_slave: public fhandler_tty_common
676 {
677 public:
678   /* Constructor */
679   fhandler_tty_slave (const char *name);
680   fhandler_tty_slave (int, const char *name);
681
682   int open (const char *path, int flags, mode_t mode = 0);
683   int write (const void *ptr, size_t len);
684   int read (void *ptr, size_t len);
685   void init (HANDLE, DWORD, mode_t);
686
687   int tcsetattr (int a, const struct termios *t);
688   int tcgetattr (struct termios *t);
689   int tcflush (int);
690   int ioctl (unsigned int cmd, void *);
691
692   off_t lseek (off_t, int) { return 0; }
693 };
694
695 class fhandler_pty_master: public fhandler_tty_common
696 {
697   int pktmode;                  // non-zero if pty in a packet mode.
698 public:
699   int need_nl;                  // Next read should start with \n
700
701   /* Constructor */
702   fhandler_pty_master (const char *name, DWORD devtype = FH_PTYM, int unit = -1);
703
704   int process_slave_output (char *buf, size_t len, int pktmode_on);
705   void doecho (const void *str, DWORD len);
706   int accept_input ();
707   int open (const char *path, int flags, mode_t mode = 0);
708   int write (const void *ptr, size_t len);
709   int read (void *ptr, size_t len);
710   int close ();
711
712   int tcsetattr (int a, const struct termios *t);
713   int tcgetattr (struct termios *t);
714   int tcflush (int);
715   int ioctl (unsigned int cmd, void *);
716
717   off_t lseek (off_t, int) { return 0; }
718   char *ptsname ();
719
720   void set_close_on_exec (int val);
721   BOOL hit_eof ();
722 };
723
724 class fhandler_tty_master: public fhandler_pty_master
725 {
726 public:
727   /* Constructor */
728   fhandler_tty_master (const char *name, int unit);
729   fhandler_console *console;    // device handler to perform real i/o.
730   HANDLE hThread;               // process_output thread handle.
731
732   int init (int);
733   int init_console ();
734   void fixup_after_fork (HANDLE parent);
735   void fixup_after_exec (HANDLE);
736 };
737
738 class fhandler_dev_null: public fhandler_base
739 {
740 public:
741   fhandler_dev_null (const char *name);
742
743   void dump ();
744   select_record *select_read (select_record *s);
745   select_record *select_write (select_record *s);
746   select_record *select_except (select_record *s);
747 };
748
749 class fhandler_dev_zero: public fhandler_base
750 {
751 public:
752   fhandler_dev_zero (const char *name);
753   int open (const char *path, int flags, mode_t mode = 0);
754   int write (const void *ptr, size_t len);
755   int read (void *ptr, size_t len);
756   off_t lseek (off_t offset, int whence);
757   int close (void);
758
759   void dump ();
760 };
761
762 class fhandler_dev_random: public fhandler_base
763 {
764 protected:
765   int unit;
766   HCRYPTPROV crypt_prov;
767   long pseudo;
768
769   BOOL crypt_gen_random (void *ptr, size_t len);
770   int pseudo_write (const void *ptr, size_t len);
771   int pseudo_read (void *ptr, size_t len);
772
773 public:
774   fhandler_dev_random (const char *name, int unit);
775   int get_unit () { return unit; }
776   int open (const char *path, int flags, mode_t mode = 0);
777   int write (const void *ptr, size_t len);
778   int read (void *ptr, size_t len);
779   off_t lseek (off_t offset, int whence);
780   int close (void);
781   int dup (fhandler_base *child);
782
783   void dump ();
784 };
785
786 class fhandler_dev_mem: public fhandler_base
787 {
788 protected:
789   int unit;
790   DWORD mem_size;
791   DWORD pos;
792
793 public:
794   fhandler_dev_mem (const char *name, int unit);
795   ~fhandler_dev_mem (void);
796
797   int open (const char *path, int flags, mode_t mode = 0);
798   int write (const void *ptr, size_t ulen);
799   int read (void *ptr, size_t ulen);
800   off_t lseek (off_t offset, int whence);
801   int close (void);
802   int fstat (struct stat *buf);
803   int dup (fhandler_base *child);
804
805   HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, off_t off);
806   int munmap (HANDLE h, caddr_t addr, size_t len);
807   int msync (HANDLE h, caddr_t addr, size_t len, int flags);
808
809   void dump ();
810 } ;
811
812 class fhandler_dev_clipboard: public fhandler_base
813 {
814 public:
815   fhandler_dev_clipboard (const char *name);
816   int is_windows (void) { return 1; }
817   int open (const char *path, int flags, mode_t mode = 0);
818   int write (const void *ptr, size_t len);
819   int read (void *ptr, size_t len);
820   off_t lseek (off_t offset, int whence);
821   int close (void);
822
823   void dump ();
824 };
825
826 class fhandler_windows: public fhandler_base
827 {
828 private:
829   HWND hWnd_;   // the window whose messages are to be retrieved by read() call
830   int method_;  // write method (Post or Send)
831 public:
832   fhandler_windows (const char *name = 0);
833   int is_windows (void) { return 1; }
834   int open (const char *path, int flags, mode_t mode = 0);
835   int write (const void *ptr, size_t len);
836   int read (void *ptr, size_t len);
837   int ioctl (unsigned int cmd, void *);
838   off_t lseek (off_t, int) { return 0; }
839   int close (void) { return 0; }
840
841   void set_close_on_exec (int val);
842   void fixup_after_fork (HANDLE parent);
843   select_record *select_read (select_record *s);
844   select_record *select_write (select_record *s);
845   select_record *select_except (select_record *s);
846   int ready_for_read (int fd, DWORD howlong, int ignra);
847 };
848
849 #if 0
850 /* You can't do this */
851 typedef union
852 {
853   fhandler_normal normal;
854   fhandler_dev_null dev_null;
855   fhandler bare;
856   fhandler_serial tty;
857 } fhandler_union;
858 #else
859 #define fhandler_union fhandler_console
860 #endif
861 struct select_record
862 {
863   int fd;
864   HANDLE h;
865   fhandler_base *fh;
866   BOOL saw_error;
867   BOOL windows_handle;
868   BOOL read_ready, write_ready, except_ready;
869   BOOL read_selected, write_selected, except_selected;
870   int (*startup) (select_record *me, class select_stuff *stuff);
871   int (*poll) (select_record *me, fd_set *readfds, fd_set *writefds,
872                fd_set *exceptfds);
873   int (*verify) (select_record *me, fd_set *readfds, fd_set *writefds,
874                  fd_set *exceptfds);
875   void (*cleanup) (select_record *me, class select_stuff *stuff);
876   struct select_record *next;
877
878   select_record (fhandler_base *in_fh = NULL) : fd (0), h (NULL),
879                  fh (in_fh), saw_error (0), windows_handle (0),
880                  read_ready (0), write_ready (0), except_ready (0),
881                  read_selected (0), write_selected (0), except_selected (0),
882                  startup (NULL), poll (NULL), verify (NULL), cleanup (NULL),
883                  next (NULL) {}
884 };
885
886 class select_stuff
887 {
888 public:
889   ~select_stuff ();
890   select_stuff (): always_ready (0), windows_used (0), start (0)
891   {
892     memset (device_specific, 0, sizeof (device_specific));
893   }
894   BOOL always_ready, windows_used;
895   select_record start;
896   void *device_specific[FH_NDEV];
897
898   int test_and_set (int i, fd_set *readfds, fd_set *writefds,
899                      fd_set *exceptfds);
900   int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
901   int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
902 };
903
904 uid_t __stdcall get_file_owner (int, const char *);
905 gid_t __stdcall get_file_group (int, const char *);
906 int __stdcall set_console_state_for_spawn ();
907
908 #endif /* _FHANDLER_H_ */