--- /dev/null
+/*
+ * sudo version 1.1 allows users to execute commands as root
+ * Copyright (C) 1991 The Root Group, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you make modifications to the source, we would be happy to have
+ * them to include in future releases. Feel free to send them to:
+ * Jeff Nieusma nieusma@rootgroup.com
+ * 3959 Arbol CT (303) 447-8093
+ * Boulder, CO 80301-1752
+ *
+ *******************************************************************
+ *
+ * This module contains the find_path() command that returns
+ * a pointer to a static area with the absolute path of the
+ * command or NULL if the command is not found in the path
+ *
+ * I also added the strdup() function in here after I found most
+ * systems don't have it...
+ *
+ * Jeff Nieusma Thu Mar 21 23:11:23 MST 1991
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <string.h>
+#include <strings.h>
+extern char *malloc();
+extern char *getenv();
+
+extern char **Argv;
+char *find_path();
+static char *do_stat();
+static char *check_link();
+char *strdup();
+
+
+
+/*******************************************************************
+ *
+ * find_path()
+ *
+ * this function finds the full pathname for a command
+ */
+
+char *find_path(file)
+char *file;
+{
+register char *n;
+char *path=NULL;
+char *cmd;
+
+if ( strlen ( file ) > MAXPATHLEN ) {
+ fprintf ( stderr, "%s: path too long: %s\n", Argv[0], file );
+ exit (1);
+ }
+
+if ( *file == '.' && *(file+1) == '/' || *file == '/' )
+ return ( do_stat ( NULL, file ) );
+
+if ( ( path=getenv("PATH") ) == NULL ) return ( NULL ) ;
+if ( ( path=strdup(path) ) == NULL ) {
+ perror ( "find_path: malloc" );
+ exit (1);
+ }
+
+while ( n = index ( path, ':' ) ) {
+ *n='\0';
+ if ( cmd = do_stat ( path, file ) ) return ( cmd );
+ path=n+1;
+ }
+
+if ( cmd = do_stat ( path, file ) )
+ return ( cmd );
+else
+ return ( NULL );
+
+}
+
+
+
+
+/**********************************************************************
+ *
+ * check_link()
+ *
+ * this function makes sure the argument is not a symbolic link.
+ * it returns the pathname of the binary or NULL
+ */
+
+static char *check_link(path)
+char *path;
+{
+char buf1[MAXPATHLEN+1]; /* is the link */
+char *s, *buf;
+register int rtn;
+
+/* the recursive buck stops here */
+if ( path == NULL ) return NULL ;
+
+/* I'd rather play with pointers than arrays... */
+buf = buf1;
+
+/* If this is NOT a sym link, return */
+if ( ( rtn=readlink(path, buf, MAXPATHLEN)) < 0 )
+ return (path);
+
+/* if it is a sym link, NULL terminate the string */
+buf[rtn]='\0';
+
+/* if the link points to an absolute path, start again... */
+if ( *buf == '/' ) return ( do_stat( NULL, buf ) );
+
+/* if the link points to ./something or something/ we need to
+ * strip off the filename portion of the current path */
+if ( ( s=rindex(path,'/') ) == NULL ) {
+ fprintf( stderr, "check_link: This path is very wierd: %s \n", path );
+ exit (1);
+ }
+else
+ *s='\0';
+
+/* as long as the link has ./ or ../ in it, get rid of it... */
+while ( *buf == '.' ) {
+
+ if ( strncmp(buf, "../", 3) == 0 ) {
+ if ( ( s=rindex(path, '/')) ) {
+ *s='\0';
+ if ( *path == '\0' ) strcpy ( path, "/" );
+ }
+ buf += 3;
+ continue;
+ }
+ else if ( strncmp(buf, "./", 2) == 0 ) {
+ buf += 2;
+ continue;
+ }
+ else
+ break;
+
+ }
+
+/* we have to copy the path buffer since do_stat() will bzero() it */
+if ( ( s = strdup ( path ) ) == NULL ) {
+ perror ( "check_link: malloc" );
+ exit (1);
+ }
+
+return ( do_stat ( s, buf ) );
+}
+
+
+
+/******************************************************************
+ *
+ * do_stat()
+ *
+ * This function takes a path and a file and stat()s the file
+ * If the file exists, the full path to that file is returned
+ * otherwise NULL is returned
+ */
+
+static char *do_stat( path, file )
+char *path, *file;
+{
+static char buf[MAXPATHLEN+1];
+struct stat s;
+register char type;
+
+
+if ( *file == '.' && *(file+1) == '/' )
+ type=1;
+else if ( *file == '/' )
+ type=2;
+else if ( path == NULL )
+ type=2;
+else if ( *path == '.' && *(path+1) == (char)NULL )
+ type=3;
+else
+ type=0;
+
+
+switch ( type ) {
+ case 1:
+ file += 2;
+ case 3:
+ if ( (path=(char *)malloc(MAXPATHLEN+1)) == NULL ) {
+ perror ("do_stat: malloc");
+ exit (1);
+ }
+#ifdef hpux
+ if ( ! getcwd ( path, (size_t)(MAXPATHLEN+1) ) ) {
+ perror ("do_stat: getcwd");
+ exit (1);
+ }
+#else
+ if ( ! getwd ( path ) ) {
+ perror ("do_stat: getwd");
+ exit (1);
+ }
+#endif
+ break;
+ case 2:
+ default:
+ break;
+ }
+
+
+if ( ( ( path? strlen(path) : 0 ) + strlen (file) ) > MAXPATHLEN - 1 ) {
+ fprintf ( stderr, "%s: path too long: %s/%s\n", Argv[0], path, file );
+ exit (1);
+ }
+
+bzero ( buf, MAXPATHLEN+1 );
+if ( path ) strcat ( buf, path );
+if ( *file != '/' && path [strlen(path)-1] != '/' ) strcat ( buf, "/" );
+strcat ( buf, file );
+if ( ! stat ( buf, &s ) )
+ return ( check_link ( buf ) );
+else
+ return ( NULL );
+
+}
+
+
+
+
+/******************************************************************
+ *
+ * strdup()
+ *
+ * this function returns a pointer a string copied into
+ * a malloc()ed buffer
+ */
+
+char *strdup(s1)
+char *s1;
+{
+char *s;
+if ( ( s=(char *)malloc(strlen(s1)+1)) == NULL )
+ return (NULL);
+strcpy(s,s1);
+return (s);
+}