From 52a7efafba1045a8c7a3fe545487d11d53e6f93a Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Sun, 29 Aug 2004 19:20:41 +0000 Subject: [PATCH] Initial commit of an platform-indepdendent implementation for the "Program" operating system concept (find and execute programs). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16084 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/System/AIX/Program.cpp | 22 ++++++ lib/System/Cygwin/Program.cpp | 22 ++++++ lib/System/Darwin/Program.cpp | 22 ++++++ lib/System/Linux/Program.cpp | 22 ++++++ lib/System/Program.cpp | 29 ++++++++ lib/System/SunOS/Program.cpp | 22 ++++++ lib/System/Unix/Program.cpp | 133 ++++++++++++++++++++++++++++++++++ lib/System/Unix/Program.inc | 133 ++++++++++++++++++++++++++++++++++ lib/System/Win32/Program.cpp | 19 +++++ lib/System/Win32/Program.inc | 19 +++++ 10 files changed, 443 insertions(+) create mode 100644 lib/System/AIX/Program.cpp create mode 100644 lib/System/Cygwin/Program.cpp create mode 100644 lib/System/Darwin/Program.cpp create mode 100644 lib/System/Linux/Program.cpp create mode 100644 lib/System/Program.cpp create mode 100644 lib/System/SunOS/Program.cpp create mode 100644 lib/System/Unix/Program.cpp create mode 100644 lib/System/Unix/Program.inc create mode 100644 lib/System/Win32/Program.cpp create mode 100644 lib/System/Win32/Program.inc diff --git a/lib/System/AIX/Program.cpp b/lib/System/AIX/Program.cpp new file mode 100644 index 00000000000..3646cfdaec5 --- /dev/null +++ b/lib/System/AIX/Program.cpp @@ -0,0 +1,22 @@ +//===- AIX/Program.cpp - AIX Program Implementation ----------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the AIX specific implementation of the Program class. +// +//===----------------------------------------------------------------------===// + +// Include the generic Unix implementation +#include "../Unix/Program.cpp" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only AIX specific code +//=== and must not be generic UNIX code (see ../Unix/Program.cpp) +//===----------------------------------------------------------------------===// + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/lib/System/Cygwin/Program.cpp b/lib/System/Cygwin/Program.cpp new file mode 100644 index 00000000000..2de0c3b2ea8 --- /dev/null +++ b/lib/System/Cygwin/Program.cpp @@ -0,0 +1,22 @@ +//===- Cygwin/Program.cpp - Cygwin Program Implementation ----- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Cygwin specific implementation of the Program class. +// +//===----------------------------------------------------------------------===// + +// Include the generic Unix implementation +#include "../Unix/Program.cpp" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Cygwin specific code +//=== and must not be generic UNIX code (see ../Unix/Program.cpp) +//===----------------------------------------------------------------------===// + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/lib/System/Darwin/Program.cpp b/lib/System/Darwin/Program.cpp new file mode 100644 index 00000000000..8c829df8a67 --- /dev/null +++ b/lib/System/Darwin/Program.cpp @@ -0,0 +1,22 @@ +//===- Darwin/Program.cpp - Darwin Program Implementatino. ---- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Darwin specific implementation of the Program class. +// +//===----------------------------------------------------------------------===// + +// Include the generic Unix implementation +#include "../Unix/Program.cpp" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Darwin specific code +//=== and must not be generic UNIX code (see ../Unix/Program.cpp) +//===----------------------------------------------------------------------===// + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/lib/System/Linux/Program.cpp b/lib/System/Linux/Program.cpp new file mode 100644 index 00000000000..0dd29d2081a --- /dev/null +++ b/lib/System/Linux/Program.cpp @@ -0,0 +1,22 @@ +//===- Linux/Program.cpp - Linux Program Implementation ------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Linux specific implementation of the Program class. +// +//===----------------------------------------------------------------------===// + +// Include the generic Unix implementation +#include "../Unix/Program.cpp" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Linux specific code +//=== and must not be generic UNIX code (see ../Unix/Program.cpp) +//===----------------------------------------------------------------------===// + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/lib/System/Program.cpp b/lib/System/Program.cpp new file mode 100644 index 00000000000..c1dd38f6fca --- /dev/null +++ b/lib/System/Program.cpp @@ -0,0 +1,29 @@ +//===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system Program concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Program.h" + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +} + +// Include the platform-specific parts of this class. +#include "platform/Program.cpp" + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/lib/System/SunOS/Program.cpp b/lib/System/SunOS/Program.cpp new file mode 100644 index 00000000000..45ec6e1ce24 --- /dev/null +++ b/lib/System/SunOS/Program.cpp @@ -0,0 +1,22 @@ +//===- SunOS/Program.cpp - SunOS Program Implementation ------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the SunOS specific implementation of the Program class. +// +//===----------------------------------------------------------------------===// + +// Include the generic Unix implementation +#include "../Unix/Program.cpp" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only SunOS specific code +//=== and must not be generic UNIX code (see ../Unix/Program.cpp) +//===----------------------------------------------------------------------===// + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/lib/System/Unix/Program.cpp b/lib/System/Unix/Program.cpp new file mode 100644 index 00000000000..6943d52af55 --- /dev/null +++ b/lib/System/Unix/Program.cpp @@ -0,0 +1,133 @@ +//===- llvm/System/Unix/Program.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Unix specific portion of the Program class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include "Unix.h" +#include +#include +#include +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +namespace llvm { +using namespace sys; + +// This function just uses the PATH environment variable to find the program. +Program +Program::FindProgramByName(const std::string& progName) { + + // Check some degenerate cases + if (progName.length() == 0) // no program + return Program(); + Program temp; + if (!temp.set_file(progName)) // invalid name + return Program(); + if (temp.executable()) // already executable as is + return temp; + + // At this point, the file name is valid and its not executable + + // Get the path. If its empty, we can't do anything to find it. + const char *PathStr = getenv("PATH"); + if (PathStr == 0) + return Program(); + + // Now we have a colon separated list of directories to search; try them. + unsigned PathLen = strlen(PathStr); + while (PathLen) { + // Find the first colon... + const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); + + // Check to see if this first directory contains the executable... + Program FilePath; + if (FilePath.set_directory(std::string(PathStr,Colon))) { + FilePath.append_file(progName); + if (FilePath.executable()) + return FilePath; // Found the executable! + } + + // Nope it wasn't in this directory, check the next path in the list! + PathLen -= Colon-PathStr; + PathStr = Colon; + + // Advance past duplicate colons + while (*PathStr == ':') { + PathStr++; + PathLen--; + } + } + return Program(); +} + +// +int +Program::ExecuteAndWait(const std::vector& args) const { + if (!executable()) + throw get() + " is not executable"; + +#ifdef HAVE_SYS_WAIT_H + // Create local versions of the parameters that can be passed into execve() + // without creating const problems. + const char* argv[ args.size() + 2 ]; + unsigned index = 0; + std::string progname(this->getLast()); + argv[index++] = progname.c_str(); + for (unsigned i = 0; i < args.size(); i++) + argv[index++] = args[i].c_str(); + argv[index] = 0; + + // Create a child process. + switch (fork()) { + // An error occured: Return to the caller. + case -1: + ThrowErrno(std::string("Couldn't execute program '") + get() + "'"); + break; + + // Child process: Execute the program. + case 0: + execve (get().c_str(), (char** const)argv, environ); + // If the execve() failed, we should exit and let the parent pick up + // our non-zero exit status. + exit (errno); + + // Parent process: Break out of the switch to do our processing. + default: + break; + } + + // Parent process: Wait for the child process to terminate. + int status; + if ((::wait (&status)) == -1) + ThrowErrno(std::string("Failed waiting for program '") + get() + "'"); + + // If the program exited normally with a zero exit status, return success! + if (WIFEXITED (status)) + return WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + throw std::string("Program '") + get() + "' received terminating signal."; + else + return 0; + +#else + throw std::string("Program::ExecuteAndWait not implemented on this platform!\n"); +#endif + +} + +} +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/lib/System/Unix/Program.inc b/lib/System/Unix/Program.inc new file mode 100644 index 00000000000..6943d52af55 --- /dev/null +++ b/lib/System/Unix/Program.inc @@ -0,0 +1,133 @@ +//===- llvm/System/Unix/Program.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Unix specific portion of the Program class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include "Unix.h" +#include +#include +#include +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +namespace llvm { +using namespace sys; + +// This function just uses the PATH environment variable to find the program. +Program +Program::FindProgramByName(const std::string& progName) { + + // Check some degenerate cases + if (progName.length() == 0) // no program + return Program(); + Program temp; + if (!temp.set_file(progName)) // invalid name + return Program(); + if (temp.executable()) // already executable as is + return temp; + + // At this point, the file name is valid and its not executable + + // Get the path. If its empty, we can't do anything to find it. + const char *PathStr = getenv("PATH"); + if (PathStr == 0) + return Program(); + + // Now we have a colon separated list of directories to search; try them. + unsigned PathLen = strlen(PathStr); + while (PathLen) { + // Find the first colon... + const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); + + // Check to see if this first directory contains the executable... + Program FilePath; + if (FilePath.set_directory(std::string(PathStr,Colon))) { + FilePath.append_file(progName); + if (FilePath.executable()) + return FilePath; // Found the executable! + } + + // Nope it wasn't in this directory, check the next path in the list! + PathLen -= Colon-PathStr; + PathStr = Colon; + + // Advance past duplicate colons + while (*PathStr == ':') { + PathStr++; + PathLen--; + } + } + return Program(); +} + +// +int +Program::ExecuteAndWait(const std::vector& args) const { + if (!executable()) + throw get() + " is not executable"; + +#ifdef HAVE_SYS_WAIT_H + // Create local versions of the parameters that can be passed into execve() + // without creating const problems. + const char* argv[ args.size() + 2 ]; + unsigned index = 0; + std::string progname(this->getLast()); + argv[index++] = progname.c_str(); + for (unsigned i = 0; i < args.size(); i++) + argv[index++] = args[i].c_str(); + argv[index] = 0; + + // Create a child process. + switch (fork()) { + // An error occured: Return to the caller. + case -1: + ThrowErrno(std::string("Couldn't execute program '") + get() + "'"); + break; + + // Child process: Execute the program. + case 0: + execve (get().c_str(), (char** const)argv, environ); + // If the execve() failed, we should exit and let the parent pick up + // our non-zero exit status. + exit (errno); + + // Parent process: Break out of the switch to do our processing. + default: + break; + } + + // Parent process: Wait for the child process to terminate. + int status; + if ((::wait (&status)) == -1) + ThrowErrno(std::string("Failed waiting for program '") + get() + "'"); + + // If the program exited normally with a zero exit status, return success! + if (WIFEXITED (status)) + return WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + throw std::string("Program '") + get() + "' received terminating signal."; + else + return 0; + +#else + throw std::string("Program::ExecuteAndWait not implemented on this platform!\n"); +#endif + +} + +} +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/lib/System/Win32/Program.cpp b/lib/System/Win32/Program.cpp new file mode 100644 index 00000000000..7a6b124d2d2 --- /dev/null +++ b/lib/System/Win32/Program.cpp @@ -0,0 +1,19 @@ +//===- Win32/Program.cpp - Win32 Program Implelementation ----- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of the Program class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/lib/System/Win32/Program.inc b/lib/System/Win32/Program.inc new file mode 100644 index 00000000000..7a6b124d2d2 --- /dev/null +++ b/lib/System/Win32/Program.inc @@ -0,0 +1,19 @@ +//===- Win32/Program.cpp - Win32 Program Implelementation ----- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of the Program class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab -- 2.34.1