mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-03 14:21:30 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16336 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			128 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*===- SystemUtils.h - Utilities to do low-level system stuff -------------===*\
 | 
						|
 *                                                                            
 | 
						|
 *                     The LLVM Compiler Infrastructure                       
 | 
						|
 *
 | 
						|
 * This file was developed by the LLVM research group and is distributed under
 | 
						|
 * the University of Illinois Open Source License. See LICENSE.TXT for details.
 | 
						|
 * 
 | 
						|
 *===----------------------------------------------------------------------===
 | 
						|
 *
 | 
						|
 * This file contains functions used to do a variety of low-level, often
 | 
						|
 * system-specific, tasks.
 | 
						|
 *
 | 
						|
\*===----------------------------------------------------------------------===*/
 | 
						|
 | 
						|
#include "SysUtils.h"
 | 
						|
#include "llvm/Config/dlfcn.h"
 | 
						|
#include "llvm/Config/fcntl.h"
 | 
						|
#include "llvm/Config/unistd.h"
 | 
						|
#include "llvm/Config/sys/stat.h"
 | 
						|
#include "llvm/Config/sys/types.h"
 | 
						|
#include "llvm/Config/sys/wait.h"
 | 
						|
#include <errno.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
/*
 | 
						|
 * isExecutable - This function returns true if given struct stat describes the
 | 
						|
 * file as being executable.
 | 
						|
 */ 
 | 
						|
unsigned isExecutable(const struct stat *buf) {
 | 
						|
  if (!(buf->st_mode & S_IFREG))
 | 
						|
    return 0;                         // Not a regular file?
 | 
						|
 | 
						|
  if (buf->st_uid == getuid())        // Owner of file?
 | 
						|
    return buf->st_mode & S_IXUSR;
 | 
						|
  else if (buf->st_gid == getgid())   // In group of file?
 | 
						|
    return buf->st_mode & S_IXGRP;
 | 
						|
  else                                // Unrelated to file?
 | 
						|
    return buf->st_mode & S_IXOTH;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * isExecutableFile - This function returns true if the filename specified
 | 
						|
 * exists and is executable.
 | 
						|
 */
 | 
						|
unsigned isExecutableFile(const char *ExeFileName) {
 | 
						|
  struct stat buf;
 | 
						|
  if (stat(ExeFileName, &buf))
 | 
						|
    return 0;                        // Must not be executable!
 | 
						|
 | 
						|
  return isExecutable(&buf);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * FindExecutable - Find a named executable in the directories listed in $PATH.
 | 
						|
 * If the executable cannot be found, returns NULL.
 | 
						|
 */ 
 | 
						|
char *FindExecutable(const char *ExeName) {
 | 
						|
  /* Try to find the executable in the path */
 | 
						|
  const char *PathStr = getenv("PATH");
 | 
						|
  if (PathStr == 0) return 0;
 | 
						|
 | 
						|
  /* Now we have a colon separated list of directories to search, try them. */
 | 
						|
  unsigned PathLen = strlen(PathStr);
 | 
						|
  while (PathLen) {
 | 
						|
    /* Find the next colon */
 | 
						|
    const char *Colon = strchr(PathStr, ':');
 | 
						|
    
 | 
						|
    /* Check to see if this first directory contains the executable... */
 | 
						|
    unsigned DirLen = Colon ? (unsigned)(Colon-PathStr) : strlen(PathStr);
 | 
						|
    char *FilePath = alloca(sizeof(char) * (DirLen+1+strlen(ExeName)+1));
 | 
						|
    unsigned i, e;
 | 
						|
    for (i = 0; i != DirLen; ++i)
 | 
						|
      FilePath[i] = PathStr[i];
 | 
						|
    FilePath[i] = '/';
 | 
						|
    for (i = 0, e = strlen(ExeName); i != e; ++i)
 | 
						|
      FilePath[DirLen + 1 + i] = ExeName[i];
 | 
						|
    FilePath[DirLen + 1 + i] = '\0';
 | 
						|
    if (isExecutableFile(FilePath))
 | 
						|
      return strdup(FilePath); /* Found the executable! */
 | 
						|
 | 
						|
    /* If Colon is NULL, there are no more colon separators and no more dirs */
 | 
						|
    if (!Colon) break;
 | 
						|
 | 
						|
    /* Nope, it wasn't in this directory, check the next range! */
 | 
						|
    PathLen -= DirLen;
 | 
						|
    PathStr = Colon;
 | 
						|
    while (*PathStr == ':') {   /* Advance past colons */
 | 
						|
      PathStr++;
 | 
						|
      PathLen--;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Advance past the colon */
 | 
						|
    ++Colon;
 | 
						|
  }
 | 
						|
 | 
						|
  /* If we fell out, we ran out of directories to search, return failure. */
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * The type of the execve() function is long and boring, but required.
 | 
						|
 */
 | 
						|
typedef int(*execveTy)(const char*, char *const[], char *const[]);
 | 
						|
 | 
						|
/*
 | 
						|
 * This method finds the real `execve' call in the C library and executes the
 | 
						|
 * given program.
 | 
						|
 */
 | 
						|
int executeProgram(const char *filename, char *const argv[], char *const envp[])
 | 
						|
{
 | 
						|
  /*
 | 
						|
   * Find a pointer to the *real* execve() function starting the search in the
 | 
						|
   * next library and forward, to avoid finding the one defined in this file.
 | 
						|
   */
 | 
						|
  const char *error;
 | 
						|
  execveTy execvePtr = (execveTy) dlsym(RTLD_NEXT, "execve");
 | 
						|
  if ((error = dlerror()) != NULL) {
 | 
						|
    fprintf(stderr, "%s\n", error);
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Really execute the program */
 | 
						|
  return execvePtr(filename, argv, envp);
 | 
						|
}
 |