Files
cdesktop/cde/programs/dtappbuilder/src/abmf/dtb_utils.c
2020-09-05 15:49:46 -06:00

363 lines
8.8 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* $XConsortium: dtb_utils.c /main/3 1995/11/06 18:04:26 rswiston $
*
* @(#)dtb_utils.c 1.1 20 Sep 1994 cde_app_builder/src/abmf
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
*/
/*
* dtb_utils.c - partial set of dtb_utils functions
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <ab_private/util.h>
#include <ab_private/dtb_utils.h>
/*
* Map Xt/Xm symbols to symbols we have defined
*/
#define String STRING
#define Boolean BOOL
#define False FALSE
#define True TRUE
#define min(a,b) util_min(a,b)
/*************************************************************************
** **
** Constants (#define and const) **
** **
**************************************************************************/
/*************************************************************************
** **
** Private Functions (C declarations and macros) **
** **
**************************************************************************/
/*
* Private functions used for finding paths
*/
static int determine_exe_dir(char *argv0, char *buf, int bufSize);
static int determine_exe_dir_from_argv(char *argv0, char *buf, int bufSize);
static int determine_exe_dir_from_path (char *argv0, char *buf, int bufSize);
static Boolean path_is_executable(char *path, uid_t euid, gid_t egid);
/*************************************************************************
** **
** Data **
** **
**************************************************************************/
/*
* Directory where the binary for this process whate loaded from
*/
static char *dtb_exe_dir = (char *)NULL;
/*************************************************************************
** **
** Function Definitions **
** **
**************************************************************************/
void
dtb_save_command(char *argv0)
{
char exe_dir[MAXPATHLEN+1];
/*
* Save the path to the executable
*/
if (determine_exe_dir(argv0, exe_dir, MAXPATHLEN+1) >= 0)
{
dtb_exe_dir = (char *)malloc(strlen(exe_dir)+1);
if (dtb_exe_dir != NULL)
{
strcpy(dtb_exe_dir, exe_dir);
}
}
}
/*
* Returns the directory that the executable for this process was loaded
* from.
*/
String
dtb_get_exe_dir(void)
{
return dtb_exe_dir;
}
/*
* Determines the directory the executable for this process was loaded from.
*/
static int
determine_exe_dir(char *argv0, char *buf, int bufSize)
{
Boolean foundDir= False;
if ((buf == NULL) || (bufSize < 1))
{
return -1;
}
if (determine_exe_dir_from_argv(argv0, buf, bufSize) >= 0)
{
foundDir = True;
}
if (!foundDir)
{
if (determine_exe_dir_from_path(argv0, buf, bufSize) >= 0)
{
foundDir = True;
}
}
/*
* Convert relative path to absolute, so that directory changes will
* not affect us.
*/
if (foundDir && (buf[0] != '/'))
{
char cwd[MAXPATHLEN+1];
char *env_pwd = NULL;
char *path_prefix = NULL;
char abs_exe_dir[MAXPATHLEN+1];
if (getcwd(cwd, MAXPATHLEN+1) != NULL)
{
path_prefix = cwd;
}
else
{
env_pwd = getenv("PWD");
if (env_pwd != NULL)
{
path_prefix = env_pwd;
}
}
if (path_prefix != NULL)
{
strcpy(abs_exe_dir, path_prefix);
if (strcmp(buf, ".") != 0)
{
strcat(abs_exe_dir, "/");
strcat(abs_exe_dir, buf);
}
strcpy(buf, abs_exe_dir);
}
}
return foundDir? 0:-1;
}
/*
* Looks for absolute path in arv[0].
*/
static int
determine_exe_dir_from_argv(char *argv0, char *buf, int bufSize)
{
int i= 0;
Boolean foundit= False;
for (i= strlen(argv0)-1; (i >= 0) && (argv0[i] != '/'); --i)
{
}
if (i >= 0)
{
int maxStringSize= min(i, bufSize);
strncpy(buf, argv0, maxStringSize);
buf[min(maxStringSize, bufSize-1)]= 0;
foundit = True;
}
return foundit? 0:-1;
}
/*
* Assumes: bufSize > 0
*/
static int
determine_exe_dir_from_path (char *argv0, char *buf, int bufSize)
{
Boolean foundDir= False;
Boolean moreDirs= True;
char *szExeName= argv0;
int iExeNameLen= strlen(szExeName);
char *szTemp= NULL;
char szPathVar[MAXPATHLEN+1];
int iPathVarLen= 0;
char szCurrentPath[MAXPATHLEN+1];
int iCurrentPathLen= 0;
int iCurrentPathStart= 0;
int i = 0;
uid_t euid= geteuid();
uid_t egid= getegid();
szTemp= getenv("PATH");
if (szTemp == NULL)
{
moreDirs= False;
}
else
{
strncpy(szPathVar, szTemp, MAXPATHLEN);
szPathVar[MAXPATHLEN]= 0;
iPathVarLen= strlen(szPathVar);
}
while ((!foundDir) && (moreDirs))
{
/* find the current directory name */
for (i= iCurrentPathStart; (i < iPathVarLen) && (szPathVar[i] != ':');
)
{
++i;
}
iCurrentPathLen= i - iCurrentPathStart;
if ((iCurrentPathLen + iExeNameLen + 2) > MAXPATHLEN)
{
iCurrentPathLen= MAXPATHLEN - (iExeNameLen + 2);
}
/* create a possible path to the executable */
strncpy(szCurrentPath, &szPathVar[iCurrentPathStart], iCurrentPathLen);
szCurrentPath[iCurrentPathLen]= 0;
strcat(szCurrentPath, "/");
strcat(szCurrentPath, szExeName);
/* see if the executable exists (and we can execute it) */
if (path_is_executable(szCurrentPath, euid, egid))
{
foundDir= True;
}
/* skip past the current directory name */
if (!foundDir)
{
iCurrentPathStart+= iCurrentPathLen;
while ( (iCurrentPathStart < iPathVarLen)
&& (szPathVar[iCurrentPathStart] != ':') )
{
++iCurrentPathStart; /* find : */
}
if (iCurrentPathStart < iPathVarLen)
{
++iCurrentPathStart; /* skip : */
}
if (iCurrentPathStart >= iPathVarLen)
{
moreDirs= False;
}
}
} /* while !foundDir */
if (foundDir)
{
szCurrentPath[iCurrentPathLen]= 0;
strncpy(buf, szCurrentPath, bufSize);
buf[bufSize-1]= 0;
}
return foundDir? 0:-1;
}
/*
* returns False is path does not exist or is not executable
*/
static Boolean
path_is_executable(char *path, uid_t euid, gid_t egid)
{
Boolean bExecutable= False;
struct stat sStat;
if (stat(path, &sStat) == 0)
{
Boolean bDetermined= False;
if (!bDetermined)
{
if (!S_ISREG(sStat.st_mode))
{
/* not a regular file */
bDetermined= True;
bExecutable= False;
}
}
if (!bDetermined)
{
if ( (euid == 0)
&& ( ((sStat.st_mode & S_IXOTH) != 0)
|| ((sStat.st_mode & S_IXGRP) != 0)
|| ((sStat.st_mode & S_IXUSR) != 0) )
)
{
bDetermined= True;
bExecutable= True;
}
}
if (!bDetermined)
{
if ( (((sStat.st_mode & S_IXOTH) != 0) )
|| (((sStat.st_mode & S_IXGRP) != 0) && (sStat.st_gid == egid))
|| (((sStat.st_mode & S_IXUSR) != 0) && (sStat.st_gid == euid))
)
{
bDetermined= True;
bExecutable= True;
}
}
} /* if stat */
return bExecutable;
}