1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1985-2011 AT&T Intellectual Property * 5* and is licensed under the * 6* Common Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.opensource.org/licenses/cpl1.0.txt * 11* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12* * 13* Information and Software Systems Research * 14* AT&T Research * 15* Florham Park NJ * 16* * 17* Glenn Fowler <gsf@research.att.com> * 18* David Korn <dgk@research.att.com> * 19* Phong Vo <kpv@research.att.com> * 20* * 21***********************************************************************/ 22#pragma prototyped 23/* 24 * G. S. Fowler 25 * D. G. Korn 26 * AT&T Bell Laboratories 27 * 28 * shell library support 29 */ 30 31#include <ast.h> 32#include <sys/stat.h> 33 34/* 35 * return pointer to the full path name of the shell 36 * 37 * SHELL is read from the environment and must start with / 38 * 39 * if set-uid or set-gid then the executable and its containing 40 * directory must not be owned by the real user/group 41 * 42 * root/administrator has its own test 43 * 44 * astconf("SH",NiL,NiL) is returned by default 45 * 46 * NOTE: csh is rejected because the bsh/csh differentiation is 47 * not done for `csh script arg ...' 48 */ 49 50char* 51pathshell(void) 52{ 53 register char* sh; 54 int ru; 55 int eu; 56 int rg; 57 int eg; 58 struct stat st; 59 60 static char* val; 61 62 if ((sh = getenv("SHELL")) && *sh == '/' && strmatch(sh, "*/(sh|*[!cC]sh)*([[:digit:]])?(-+([.[:alnum:]]))?(.exe)")) 63 { 64 if (!(ru = getuid()) || !eaccess("/bin", W_OK)) 65 { 66 if (stat(sh, &st)) 67 goto defshell; 68 if (ru != st.st_uid && !strmatch(sh, "?(/usr)?(/local)/?([ls])bin/?([[:lower:]])sh?(.exe)")) 69 goto defshell; 70 } 71 else 72 { 73 eu = geteuid(); 74 rg = getgid(); 75 eg = getegid(); 76 if (ru != eu || rg != eg) 77 { 78 char* s; 79 char dir[PATH_MAX]; 80 81 s = sh; 82 for (;;) 83 { 84 if (stat(s, &st)) 85 goto defshell; 86 if (ru != eu && st.st_uid == ru) 87 goto defshell; 88 if (rg != eg && st.st_gid == rg) 89 goto defshell; 90 if (s != sh) 91 break; 92 if (strlen(s) >= sizeof(dir)) 93 goto defshell; 94 strcpy(dir, s); 95 if (!(s = strrchr(dir, '/'))) 96 break; 97 *s = 0; 98 s = dir; 99 } 100 } 101 } 102 return sh; 103 } 104 defshell: 105 if (!(sh = val)) 106 { 107 if (!*(sh = astconf("SH", NiL, NiL)) || *sh != '/' || eaccess(sh, X_OK) || !(sh = strdup(sh))) 108 sh = "/bin/sh"; 109 val = sh; 110 } 111 return sh; 112} 113