diff options
author | Christopher Faylor <me@cgf.cx> | 2002-05-02 08:26:05 +0400 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2002-05-02 08:26:05 +0400 |
commit | c477dccfa8a48767cc68ea8a3fa89b4a4c748052 (patch) | |
tree | 6e4b5443c41d749aefda1d94ce6ca2af24999ed9 /winsup/cygwin/fhandler_process.cc | |
parent | 7a90892d0c2a257dc468e2b247cd13b8caa51ab2 (diff) |
add new files
Diffstat (limited to 'winsup/cygwin/fhandler_process.cc')
-rw-r--r-- | winsup/cygwin/fhandler_process.cc | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc new file mode 100644 index 000000000..32812c5b8 --- /dev/null +++ b/winsup/cygwin/fhandler_process.cc @@ -0,0 +1,294 @@ +/* fhandler_process.cc: fhandler for /proc/<pid> virtual filesystem + + Copyright 2002 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include "winsup.h" +#include <sys/fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/cygwin.h> +#include "cygerrno.h" +#include "security.h" +#include "fhandler.h" +#include "sigproc.h" +#include "pinfo.h" +#include "path.h" +#include "shared_info.h" +#include <assert.h> + +#define _COMPILING_NEWLIB +#include <dirent.h> + +static const int PROCESS_PPID = 0; +static const int PROCESS_EXENAME = 1; +static const int PROCESS_WINPID = 2; +static const int PROCESS_WINEXENAME = 3; +static const int PROCESS_STATUS = 4; +static const int PROCESS_UID = 5; +static const int PROCESS_GID = 6; +static const int PROCESS_PGID = 7; +static const int PROCESS_SID = 8; +static const int PROCESS_CTTY = 9; + +static const char *process_listing[] = { + "ppid", + "exename", + "winpid", + "winexename", + "status", + "uid", + "gid", + "pgid", + "sid", + "ctty", + NULL +}; + +static const int PROCESS_LINK_COUNT = (sizeof(process_listing) / sizeof(const char *)) - 1; + +/* Returns 0 if path doesn't exist, >0 if path is a directory, + * <0 if path is a file. + */ +int +fhandler_process::exists (const char *path) +{ + debug_printf ("exists (%s)", path); + path += proc_len + 1; + while (*path != 0 && !SLASH_P (*path)) + path++; + if (*path == 0) + return 2; + + for (int i = 0; process_listing[i]; i++) + if (pathmatch (path + 1, process_listing[i])) + return -1; + return 1; +} + +fhandler_process::fhandler_process (): + fhandler_proc (FH_PROCESS) +{ +} + +int +fhandler_process::fstat (struct __stat64 *buf, path_conv *path) +{ + int file_type = exists ((const char *) get_name ()); + switch (file_type) + { + case 0: + set_errno (ENOENT); + return -1; + case 1: + buf->st_mode = S_IFDIR | 0555; + buf->st_nlink = 1; + return 0; + case 2: + buf->st_mode = S_IFDIR | 0555; + buf->st_nlink = PROCESS_LINK_COUNT; + return 0; + default: + case -1: + buf->st_mode = S_IFREG | 0444; + buf->st_nlink = 1; + return 0; + } +} + +struct dirent * +fhandler_process::readdir (DIR * dir) +{ + if (dir->__d_position >= PROCESS_LINK_COUNT) + return NULL; + strcpy (dir->__d_dirent->d_name, process_listing[dir->__d_position++]); + syscall_printf ("%p = readdir (%p) (%s)", &dir->__d_dirent, dir, + dir->__d_dirent->d_name); + return dir->__d_dirent; +} + +int +fhandler_process::open (path_conv *pc, int flags, mode_t mode) +{ + int process_file_no = -1, pid; + winpids pids; + _pinfo *p; + + int res = fhandler_virtual::open (pc, flags, mode); + if (!res) + goto out; + + const char *path; + path = (const char *) *pc + proc_len + 1; + pid = atoi (path); + while (*path != 0 && !SLASH_P (*path)) + path++; + + if (*path == 0) + { + if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + { + set_errno (EEXIST); + res = 0; + goto out; + } + else if (mode & O_WRONLY) + { + set_errno (EISDIR); + res = 0; + goto out; + } + else + { + flags |= O_DIROPEN; + goto success; + } + } + + process_file_no = -1; + for (int i = 0; process_listing[i]; i++) + { + if (path_prefix_p + (process_listing[i], path + 1, strlen (process_listing[i]))) + process_file_no = i; + } + if (process_file_no == -1) + { + if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + { + set_errno (EROFS); + res = 0; + goto out; + } + else + { + set_errno (ENOENT); + res = 0; + goto out; + } + } + if (mode & O_WRONLY) + { + set_errno (EROFS); + res = 0; + goto out; + } + for (unsigned i = 0; i < pids.npids; i++) + { + p = pids[i]; + + if (!proc_exists (p)) + continue; + + if (p->pid == pid) + goto found; + } + set_errno (ENOENT); + res = 0; + goto out; +found: + switch (process_file_no) + { + case PROCESS_UID: + case PROCESS_GID: + case PROCESS_PGID: + case PROCESS_SID: + case PROCESS_CTTY: + case PROCESS_PPID: + { + filebuf = new char[bufalloc = 40]; + int num; + switch (process_file_no) + { + case PROCESS_PPID: + num = p->ppid; + break; + case PROCESS_UID: + num = p->uid; + break; + case PROCESS_PGID: + num = p->pgid; + break; + case PROCESS_SID: + num = p->sid; + break; + default: + case PROCESS_CTTY: + num = p->ctty; + break; + } + __small_sprintf (filebuf, "%d\n", num); + filesize = strlen (filebuf); + break; + } + case PROCESS_EXENAME: + { + filebuf = new char[bufalloc = MAX_PATH]; + if (p->process_state & (PID_ZOMBIE | PID_EXITED)) + strcpy (filebuf, "<defunct>"); + else + { + mount_table->conv_to_posix_path (p->progname, filebuf, 1); + int len = strlen (filebuf); + if (len > 4) + { + char *s = filebuf + len - 4; + if (strcasecmp (s, ".exe") == 0) + *s = 0; + } + } + filesize = strlen (filebuf); + break; + } + case PROCESS_WINPID: + { + filebuf = new char[bufalloc = 40]; + __small_sprintf (filebuf, "%d\n", p->dwProcessId); + filesize = strlen (filebuf); + break; + } + case PROCESS_WINEXENAME: + { + int len = strlen (p->progname); + filebuf = new char[len + 2]; + strcpy (filebuf, p->progname); + filebuf[len] = '\n'; + filesize = len + 1; + break; + } + case PROCESS_STATUS: + { + filebuf = new char[bufalloc = 3]; + filebuf[0] = ' '; + filebuf[1] = '\n'; + filebuf[2] = 0; + if (p->process_state & PID_STOPPED) + filebuf[0] = 'S'; + else if (p->process_state & PID_TTYIN) + filebuf[0] = 'I'; + else if (p->process_state & PID_TTYOU) + filebuf[0] = 'O'; + filesize = 2; + break; + } + } + + if (flags & O_APPEND) + position = filesize; + else + position = 0; + +success: + res = 1; + set_open_status (); + set_flags (flags); +out: + syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode); + return res; +} |