1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 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 50 char* 51 pathshell(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