1N/A/***********************************************************************
1N/A* *
1N/A* This software is part of the ast package *
1N/A* Copyright (c) 1985-2011 AT&T Intellectual Property *
1N/A* and is licensed under the *
1N/A* Common Public License, Version 1.0 *
1N/A* by AT&T Intellectual Property *
1N/A* *
1N/A* A copy of the License is available at *
1N/A* http://www.opensource.org/licenses/cpl1.0.txt *
1N/A* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
1N/A* *
1N/A* Information and Software Systems Research *
1N/A* AT&T Research *
1N/A* Florham Park NJ *
1N/A* *
1N/A* Glenn Fowler <gsf@research.att.com> *
1N/A* David Korn <dgk@research.att.com> *
1N/A* Phong Vo <kpv@research.att.com> *
1N/A* *
1N/A***********************************************************************/
1N/A#pragma prototyped
1N/A/*
1N/A * G. S. Fowler
1N/A * D. G. Korn
1N/A * AT&T Bell Laboratories
1N/A *
1N/A * shell library support
1N/A */
1N/A
1N/A#include <ast.h>
1N/A#include <sys/stat.h>
1N/A
1N/A/*
1N/A * return pointer to the full path name of the shell
1N/A *
1N/A * SHELL is read from the environment and must start with /
1N/A *
1N/A * if set-uid or set-gid then the executable and its containing
1N/A * directory must not be owned by the real user/group
1N/A *
1N/A * root/administrator has its own test
1N/A *
1N/A * astconf("SH",NiL,NiL) is returned by default
1N/A *
1N/A * NOTE: csh is rejected because the bsh/csh differentiation is
1N/A * not done for `csh script arg ...'
1N/A */
1N/A
1N/Achar*
1N/Apathshell(void)
1N/A{
1N/A register char* sh;
1N/A int ru;
1N/A int eu;
1N/A int rg;
1N/A int eg;
1N/A struct stat st;
1N/A
1N/A static char* val;
1N/A
1N/A if ((sh = getenv("SHELL")) && *sh == '/' && strmatch(sh, "*/(sh|*[!cC]sh)*([[:digit:]])?(-+([.[:alnum:]]))?(.exe)"))
1N/A {
1N/A if (!(ru = getuid()) || !eaccess("/bin", W_OK))
1N/A {
1N/A if (stat(sh, &st))
1N/A goto defshell;
1N/A if (ru != st.st_uid && !strmatch(sh, "?(/usr)?(/local)/?([ls])bin/?([[:lower:]])sh?(.exe)"))
1N/A goto defshell;
1N/A }
1N/A else
1N/A {
1N/A eu = geteuid();
1N/A rg = getgid();
1N/A eg = getegid();
1N/A if (ru != eu || rg != eg)
1N/A {
1N/A char* s;
1N/A char dir[PATH_MAX];
1N/A
1N/A s = sh;
1N/A for (;;)
1N/A {
1N/A if (stat(s, &st))
1N/A goto defshell;
1N/A if (ru != eu && st.st_uid == ru)
1N/A goto defshell;
1N/A if (rg != eg && st.st_gid == rg)
1N/A goto defshell;
1N/A if (s != sh)
1N/A break;
1N/A if (strlen(s) >= sizeof(dir))
1N/A goto defshell;
1N/A strcpy(dir, s);
1N/A if (!(s = strrchr(dir, '/')))
1N/A break;
1N/A *s = 0;
1N/A s = dir;
1N/A }
1N/A }
1N/A }
1N/A return sh;
1N/A }
1N/A defshell:
1N/A if (!(sh = val))
1N/A {
1N/A if (!*(sh = astconf("SH", NiL, NiL)) || *sh != '/' || eaccess(sh, X_OK) || !(sh = strdup(sh)))
1N/A sh = "/bin/sh";
1N/A val = sh;
1N/A }
1N/A return sh;
1N/A}