OSDN Git Service

* cygerrno.h: New file. Use this throughout whenever errno manipulation is
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / pinfo.cc
1 /* pinfo.cc: process table support
2
3    Copyright 1996, 1997, 1998, 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 #include "winsup.h"
12 #include <stdlib.h>
13 #include <time.h>
14 #include <errno.h>
15 #include <limits.h>
16 #include "dtable.h"
17 #include "pinfo.h"
18 #include "cygerrno.h"
19
20 static char NO_COPY pinfo_dummy[sizeof(pinfo)] = {0};
21
22 pinfo NO_COPY myself ((_pinfo *)&pinfo_dummy);  // Avoid myself != NULL checks
23 static pinfo NO_COPY myself_identity ((_pinfo *)&pinfo_dummy);
24
25 /* Initialize the process table.
26    This is done once when the dll is first loaded.  */
27
28 void __stdcall
29 set_myself (pid_t pid)
30 {
31   DWORD winpid = GetCurrentProcessId ();
32   if (pid == 1)
33     pid = cygwin_pid (winpid);
34   myself.init (pid, 1);
35   myself->dwProcessId = winpid;
36   myself->process_state |= PID_IN_USE;
37   myself->start_time = time (NULL); /* Register our starting time. */
38   pid_t myself_cyg_pid = cygwin_pid (myself->dwProcessId);
39   if (pid != myself_cyg_pid)
40     myself_identity.init (myself_cyg_pid, PID_EXECED);
41
42   char buf[30];
43   __small_sprintf (buf, "cYg%8x %x", _STRACE_INTERFACE_ACTIVATE_ADDR,
44                    &strace.active);
45   OutputDebugString (buf);
46
47   (void) GetModuleFileName (NULL, myself->progname,
48                             sizeof(myself->progname));
49   if (strace.active)
50     {
51       extern char osname[];
52       strace.prntf (1, NULL, "**********************************************");
53       strace.prntf (1, NULL, "Program name: %s", myself->progname);
54       strace.prntf (1, NULL, "App version:  %d.%d, api: %d.%d",
55                        user_data->dll_major, user_data->dll_minor,
56                        user_data->api_major, user_data->api_minor);
57       strace.prntf (1, NULL, "DLL version:  %d.%d, api: %d.%d",
58                        cygwin_version.dll_major, cygwin_version.dll_minor,
59                        cygwin_version.api_major, cygwin_version.api_minor);
60       strace.prntf (1, NULL, "DLL build:    %s", cygwin_version.dll_build_date);
61       strace.prntf (1, NULL, "OS version:   Windows %s", osname);
62       strace.prntf (1, NULL, "**********************************************");
63     }
64
65   return;
66 }
67
68 /* Initialize the process table entry for the current task.
69    This is not called for fork'd tasks, only exec'd ones.  */
70 void __stdcall
71 pinfo_init (LPBYTE info)
72 {
73   if (info != NULL)
74     {
75       /* The process was execed.  Reuse entry from the original
76          owner of this pid. */
77       environ_init (0);   /* Needs myself but affects calls below */
78
79       /* spawn has already set up a pid structure for us so we'll use that */
80
81       myself->process_state |= PID_CYGPARENT;
82
83       /* Inherit file descriptor information from parent in info.
84        */
85       LPBYTE b = fdtab.de_linearize_fd_array (info);
86       extern char title_buf[];
87       if (b && *b)
88         old_title = strcpy (title_buf, (char *)b);
89     }
90   else
91     {
92       /* Invent our own pid.  */
93
94       set_myself (1);
95       myself->ppid = 1;
96       myself->pgid = myself->sid = myself->pid;
97       myself->ctty = -1;
98       myself->uid = USHRT_MAX;
99
100       environ_init (0);         /* call after myself has been set up */
101     }
102
103   debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);
104 }
105
106 struct sigaction&
107 _pinfo::getsig(int sig)
108 {
109 #ifdef _MT_SAFE
110   if ( thread2signal )
111     return thread2signal->sigs[sig];
112   return sigs[sig];
113 #else
114   return sigs[sig];
115 #endif
116 };
117
118 sigset_t&
119 _pinfo::getsigmask ()
120 {
121 #ifdef _MT_SAFE
122   if ( thread2signal )
123     return *thread2signal->sigmask;
124   return sig_mask;
125 #else
126   return sig_mask;
127 #endif
128 };
129
130 void
131 _pinfo::setsigmask (sigset_t _mask)
132 {
133 #ifdef _MT_SAFE
134   if ( thread2signal )
135         *(thread2signal->sigmask) = _mask;
136   sig_mask=_mask;
137 #else
138   sig_mask=_mask;
139 #endif
140 }
141
142 LONG *
143 _pinfo::getsigtodo(int sig)
144 {
145 #ifdef _MT_SAFE
146   if ( thread2signal )
147     return thread2signal->sigtodo + __SIGOFFSET + sig;
148   return _sigtodo + __SIGOFFSET + sig;
149 #else
150   return _sigtodo + __SIGOFFSET + sig;
151 #endif
152 }
153
154 extern HANDLE hMainThread;
155
156 HANDLE
157 _pinfo::getthread2signal()
158 {
159 #ifdef _MT_SAFE
160   if ( thread2signal )
161     return thread2signal->win32_obj_id;
162   return hMainThread;
163 #else
164   return hMainThread;
165 #endif
166 }
167
168 void
169 _pinfo::setthread2signal(void *_thr)
170 {
171 #ifdef _MT_SAFE
172    // assert has myself lock
173    thread2signal=(ThreadItem*)_thr;
174 #else
175 #endif
176 }
177
178 void
179 _pinfo::copysigs(_pinfo *_other)
180 {
181   sigs = _other->sigs;
182 }
183
184 void
185 _pinfo::record_death ()
186 {
187   /* CGF FIXME - needed? */
188   if (dwProcessId == GetCurrentProcessId () && !my_parent_is_alive ())
189     {
190       process_state = PID_NOT_IN_USE;
191       hProcess = NULL;
192     }
193 }
194
195 void
196 pinfo::init (pid_t n, DWORD create)
197 {
198   if (n == myself->pid)
199     {
200       child = myself;
201       destroy = 0;
202       h = NULL;
203       return;
204     }
205
206   int created;
207   char mapname[MAX_PATH];
208   __small_sprintf (mapname, "cygpid.%x", n);
209
210   int mapsize;
211   if (create & PID_EXECED)
212     mapsize = PINFO_REDIR_SIZE;
213   else
214     mapsize = sizeof (_pinfo);
215
216   if (!create)
217     {
218       /* CGF FIXME -- deal with inheritance after an exec */
219       h = OpenFileMappingA (FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapname);
220       created = 0;
221     }
222   else
223     {
224       h = CreateFileMapping ((HANDLE) 0xffffffff, &sec_none_nih,
225                               PAGE_READWRITE, 0, mapsize, mapname);
226       created = h && GetLastError () != ERROR_ALREADY_EXISTS;
227     }
228
229   if (!h)
230     {
231       if (create)
232         __seterrno ();
233       child = NULL;
234       return;
235     }
236
237   child = (_pinfo *) MapViewOfFile (h, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
238
239   if (child->process_state & PID_EXECED)
240     {
241       pid_t realpid = child->pid;
242       release ();
243       if (realpid == n)
244         api_fatal ("retrieval of execed process info for pid %d failed due to recursion.", n);
245       return init (realpid);
246     }
247
248   if (created)
249     {
250       if (!(create & PID_EXECED))
251         child->pid = n;
252       else
253         {
254           child->pid = myself->pid;
255           child->process_state |= PID_IN_USE | PID_EXECED;
256         }
257     }
258
259   destroy = 1;
260 }
261
262 /* DOCTOOL-START
263
264 <sect1 id="func-cygwin-winpid-to-pid">
265   <title>cygwin_winpid_to_pid</title>
266
267   <funcsynopsis>
268     <funcdef>extern "C" pid_t
269       <function>cygwin_winpid_to_pid</function>
270       </funcdef>
271       <paramdef>int <parameter>winpid</parameter></paramdef>
272   </funcsynopsis>
273
274   <para>Given a windows pid, converts to the corresponding Cygwin
275 pid, if any.  Returns -1 if windows pid does not correspond to
276 a cygwin pid.</para>
277   <example>
278     <title>Example use of cygwin_winpid_to_pid</title>
279     <programlisting>
280       extern "C" cygwin_winpid_to_pid (int winpid);
281       pid_t mypid;
282       mypid = cygwin_winpid_to_pid (windows_pid);
283     </programlisting>
284   </example>
285 </sect1>
286
287    DOCTOOL-END */
288
289 extern "C" pid_t
290 cygwin_winpid_to_pid (int winpid)
291 {
292   pinfo p (winpid);
293   if (p)
294     return p->pid;
295
296   set_errno (ESRCH);
297   return (pid_t) -1;
298 }
299
300 #include <tlhelp32.h>
301 #include <psapi.h>
302
303 typedef BOOL (WINAPI * ENUMPROCESSES) (DWORD *, DWORD, DWORD *);
304 typedef HANDLE (WINAPI * CREATESNAPSHOT) (DWORD, DWORD);
305 typedef BOOL (WINAPI * PROCESSWALK) (HANDLE, LPPROCESSENTRY32);
306 typedef BOOL (WINAPI * CLOSESNAPSHOT) (HANDLE);
307
308 static NO_COPY CREATESNAPSHOT myCreateToolhelp32Snapshot = NULL;
309 static NO_COPY PROCESSWALK myProcess32First = NULL;
310 static NO_COPY PROCESSWALK myProcess32Next  = NULL;
311 static BOOL WINAPI enum_init (DWORD *lpidProcess, DWORD cb, DWORD *cbneeded);
312
313 static NO_COPY ENUMPROCESSES myEnumProcesses = enum_init;
314
315 static BOOL WINAPI
316 EnumProcessesW95 (DWORD *lpidProcess, DWORD cb, DWORD *cbneeded)
317 {
318   HANDLE h;
319
320   *cbneeded = 0;
321   h = myCreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
322   if (!h)
323     return 0;
324
325   PROCESSENTRY32 proc;
326   int i = 0;
327   proc.dwSize = sizeof (proc);
328   if (myProcess32First(h, &proc))
329     do
330       lpidProcess[i++] = cygwin_pid (proc.th32ProcessID);
331     while (myProcess32Next (h, &proc));
332   CloseHandle (h);
333   if (i == 0)
334     return 0;
335   *cbneeded = i * sizeof (DWORD);
336   return 1;
337 }
338
339 void
340 winpids::init ()
341 {
342   DWORD n;
343   if (!myEnumProcesses (pidlist, sizeof (pidlist) / sizeof (pidlist[0]), &n))
344     npids = 0;
345   else
346     npids = n / sizeof (pidlist[0]);
347
348   pidlist[npids] = 0;
349 }
350
351 static BOOL WINAPI
352 enum_init (DWORD *lpidProcess, DWORD cb, DWORD *cbneeded)
353 {
354   HINSTANCE h;
355   if (os_being_run == winNT)
356     {
357       h = LoadLibrary ("psapi.dll");
358       if (!h)
359         return 0;
360       myEnumProcesses = (ENUMPROCESSES) GetProcAddress (h, "EnumProcesses");
361       if (!myEnumProcesses)
362         return 0;
363     }
364   else
365     {
366       h = GetModuleHandle("kernel32.dll");
367       myCreateToolhelp32Snapshot = (CREATESNAPSHOT)
368                   GetProcAddress(h, "CreateToolhelp32Snapshot");
369       myProcess32First = (PROCESSWALK)
370               GetProcAddress(h, "Process32First");
371       myProcess32Next  = (PROCESSWALK)
372               GetProcAddress(h, "Process32Next");
373       if (!myCreateToolhelp32Snapshot || !myProcess32First || !myProcess32Next)
374         return 0;
375
376       myEnumProcesses = EnumProcessesW95;
377     }
378
379   return myEnumProcesses (lpidProcess, cb, cbneeded);
380 }