OSDN Git Service

* fhandler.h (fhandler_pipe::hit_eof): New method.
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / pipe.cc
1 /* pipe.cc: pipe for Cygwin.
2
3    Copyright 1996, 1998, 1999, 2000, 2001 Red Hat, Inc.
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 #include "winsup.h"
12 #include <unistd.h>
13 #include <sys/fcntl.h>
14 #include <errno.h>
15 #include "cygerrno.h"
16 #include "security.h"
17 #include "fhandler.h"
18 #include "dtable.h"
19 #include "cygheap.h"
20 #include "thread.h"
21 #include "sigproc.h"
22 #include "pinfo.h"
23
24 static unsigned pipecount;
25 static const NO_COPY char pipeid_fmt[] = "stupid_pipe.%u.%u";
26
27 fhandler_pipe::fhandler_pipe (const char *name, DWORD devtype) :
28         fhandler_base (devtype, name),
29         guard (0), writepipe_exists(0), orig_pid (0), id (0)
30 {
31   set_cb (sizeof *this);
32 }
33
34 off_t
35 fhandler_pipe::lseek (off_t offset, int whence)
36 {
37   debug_printf ("(%d, %d)", offset, whence);
38   set_errno (ESPIPE);
39   return -1;
40 }
41
42 void
43 fhandler_pipe::set_close_on_exec (int val)
44 {
45   this->fhandler_base::set_close_on_exec (val);
46   if (guard)
47     set_inheritance (guard, val);
48   if (writepipe_exists)
49     set_inheritance (writepipe_exists, val);
50 }
51
52 int
53 fhandler_pipe::read (void *in_ptr, size_t in_len)
54 {
55   int res = this->fhandler_base::read (in_ptr, in_len);
56   ReleaseMutex (guard);
57   return res;
58 }
59
60 int fhandler_pipe::close ()
61 {
62   int res = this->fhandler_base::close ();
63   if (guard)
64     CloseHandle (guard);
65   if (writepipe_exists)
66 {debug_printf ("writepipe_exists closed");
67     CloseHandle (writepipe_exists);
68 }
69   return res;
70 }
71
72 bool
73 fhandler_pipe::hit_eof ()
74 {
75   char buf[80];
76   HANDLE ev;
77   if (!orig_pid)
78     return bg_ok;
79   __small_sprintf (buf, pipeid_fmt, orig_pid, id);
80   if ((ev = OpenEvent (EVENT_ALL_ACCESS, FALSE, buf)))
81     CloseHandle (ev);
82   debug_printf ("%s %p", buf, ev);
83   return ev == NULL;
84 }
85
86 int
87 fhandler_pipe::dup (fhandler_base *child)
88 {
89   int res = this->fhandler_base::dup (child);
90   if (res)
91     return res;
92
93   fhandler_pipe *ftp = (fhandler_pipe *) child;
94
95   if (guard == NULL)
96     ftp->guard = NULL;
97   else if (!DuplicateHandle (hMainProc, guard, hMainProc, &ftp->guard, 0, 1,
98                              DUPLICATE_SAME_ACCESS))
99     return -1;
100
101   if (writepipe_exists == NULL)
102     ftp->writepipe_exists = NULL;
103   else if (!DuplicateHandle (hMainProc, writepipe_exists, hMainProc,
104                              &ftp->writepipe_exists, 0, 1,
105                              DUPLICATE_SAME_ACCESS))
106     return -1;
107
108   ftp->id = id;
109   ftp->orig_pid = orig_pid;
110   return 0;
111 }
112
113
114 int
115 make_pipe (int fildes[2], unsigned int psize, int mode)
116 {
117   SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "make_pipe");
118
119   HANDLE r, w;
120   int  fdr = -1, fdw = -1;
121   SECURITY_ATTRIBUTES *sa = (mode & O_NOINHERIT) ?  &sec_none_nih : &sec_none;
122   int res = -1;
123
124   if ((fdr = cygheap->fdtab.find_unused_handle ()) < 0)
125     set_errno (ENMFILE);
126   else if ((fdw = cygheap->fdtab.find_unused_handle (fdr + 1)) < 0)
127     set_errno (ENMFILE);
128   else if (!CreatePipe (&r, &w, sa, psize))
129     __seterrno ();
130   else
131     {
132       fhandler_pipe *fhr = (fhandler_pipe *) cygheap->fdtab.build_fhandler (fdr, FH_PIPER, "/dev/piper");
133       fhandler_pipe *fhw = (fhandler_pipe *) cygheap->fdtab.build_fhandler (fdw, FH_PIPEW, "/dev/pipew");
134
135       int binmode = mode & O_TEXT ? 0 : 1;
136       fhr->init (r, GENERIC_READ, binmode);
137       fhw->init (w, GENERIC_WRITE, binmode);
138       if (mode & O_NOINHERIT)
139        {
140          fhr->set_close_on_exec_flag (1);
141          fhw->set_close_on_exec_flag (1);
142        }
143
144       fildes[0] = fdr;
145       fildes[1] = fdw;
146
147       res = 0;
148       fhr->create_guard (sa);
149       if (wincap.has_unreliable_pipes ())
150         {
151           char buf[80];
152           int count = pipecount++;      /* FIXME: Should this be InterlockedIncrement? */
153           __small_sprintf (buf, pipeid_fmt, myself->pid, count);
154           fhw->writepipe_exists = CreateEvent (sa, TRUE, FALSE, buf);
155           fhr->orig_pid = myself->pid;
156           fhr->id = count;
157         }
158     }
159
160   syscall_printf ("%d = make_pipe ([%d, %d], %d, %p)", res, fdr, fdw, psize, mode);
161   ReleaseResourceLock(LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "make_pipe");
162   return res;
163 }
164
165 extern "C" int
166 pipe (int filedes[2])
167 {
168   extern DWORD binmode;
169   return make_pipe (filedes, 16384, (!binmode || binmode == O_BINARY) ? O_BINARY : O_TEXT);
170 }
171
172 extern "C" int
173 _pipe (int filedes[2], unsigned int psize, int mode)
174 {
175   int res = make_pipe (filedes, psize, mode);
176   /* This type of pipe is not interruptible so set the appropriate flag. */
177   if (!res)
178     cygheap->fdtab[filedes[0]]->set_r_no_interrupt (1);
179   return res;
180 }