1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or http://www.opensolaris.org/os/licensing.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21
22#
23# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24#
25
26#
27# This test checks whether ksh93 does unneccesaty |libc::getpwnam()|
28# calls for "~(modifer)pattern"-style shell patterns
29#
30# This was reported as CR #6807179 ("ksh93 does unneccesary |libc::getpwnam()| lookups for ~(modifier) pattern patterns"):
31# ------------ snip ------------
32# ksh93 does unneccesary |libc::getpwnam()| lookups for
33# ~(modifer)pattern patterns, e.g. [[ $foo == ~(E)hello.*world ]].
34# The problem is that the shell ~(modifer)pattern is an extended
35# pattern syntax which allows to specify a "modifer" to change
36# the behaviour for "pattern". However the '~' at the beginning
37# of this string is causing a tilde expansion (or better: It's
38# filling an internal buffer as preparation for tilde expansion
39# and this code calls |libc::getpwnam()|) which shouldn't be
40# done in this case.
41# [1]=For example the "modifer" allows to specifcy "perl",
42# "fgrep", "grep", "egrep", "POSIX shell", "korn shell" and
43# other types of pattern matching systems (or select stuff
44# like archors, case-insensitive matching etc. etc.).
45# ------------ snip ------------
46#
47
48# test setup
49function err_exit
50{
51	print -u2 -n "\t"
52	print -u2 -r ${Command}[$1]: "${@:2}"
53	(( Errors < 127 && Errors++ ))
54}
55alias err_exit='err_exit $LINENO'
56
57set -o nounset
58Command=${0##*/}
59integer Errors=0
60
61typeset tmpfile
62
63tmpfile="$(mktemp -t "sun_solaris_cr_6807179_shellpattern_uses_getpwnam.${PPID}.$$.XXXXXX")" || err_exit "Cannot create temporary file."
64rm -f "${tmpfile}"
65
66
67# test 1: Check if the shell uses |libc::getpwnam()| for pattern "~(Elr)wo.*ld"
68truss -u :: -o "${tmpfile}" ${SHELL} -c '[[ ${hello} == ~(Elr)wo.*ld ]] ; true' || err_exit "truss returned failure=$?"
69[[ "$( < "${tmpfile}")" != *getpwnam* ]] || err_exit "truss log reports the use of getpwnam() for pattern ~(Elr)wo.*ld"
70rm "${tmpfile}" || err_exit "rm ${tmpfile} failed."
71
72
73# test 2: Check if the shell uses |libc::getpwnam()| for pattern "~(Si)wo*ld"
74truss -u :: -o "${tmpfile}" ${SHELL} -c '[[ ${hello} == ~(Si)wo*ld ]] ; true' || err_exit "truss returned failure=$?"
75[[ "$( < "${tmpfile}")" != *getpwnam* ]] || err_exit "truss log reports the use of getpwnam() for pattern ~(Si)wo*ld"
76rm "${tmpfile}" || err_exit "rm ${tmpfile} failed."
77
78
79# test 3: Same as test 1 but uses ~root/ as pattern which will force the use of |libc::getpwnam()|
80getent passwd root >/dev/null || err_exit "getent passwd root failed" # safeguard to make sure we get a warning if user root is missing
81
82truss -u :: -o "${tmpfile}" ${SHELL} -c '[[ ${hello} == ~root/ ]] ; true' || err_exit "truss returned failure=$?"
83[[ "$( < "${tmpfile}" )" == *getpwnam* ]] || err_exit "truss log reports the use of getpwnam() for pattern ~root/"
84rm "${tmpfile}" || err_exit "rm ${tmpfile} failed."
85
86
87# tests done
88exit $((Errors))
89