OSDN Git Service

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