134f9b3eeSRoland Mainz /***********************************************************************
234f9b3eeSRoland Mainz *                                                                      *
334f9b3eeSRoland Mainz *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
534f9b3eeSRoland Mainz *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
734f9b3eeSRoland Mainz *                    by AT&T Intellectual Property                     *
834f9b3eeSRoland Mainz *                                                                      *
934f9b3eeSRoland Mainz *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
1234f9b3eeSRoland Mainz *                                                                      *
1334f9b3eeSRoland Mainz *              Information and Software Systems Research               *
1434f9b3eeSRoland Mainz *                            AT&T Research                             *
1534f9b3eeSRoland Mainz *                           Florham Park NJ                            *
1634f9b3eeSRoland Mainz *                                                                      *
1734f9b3eeSRoland Mainz *                  David Korn <dgk@research.att.com>                   *
1834f9b3eeSRoland Mainz *                                                                      *
1934f9b3eeSRoland Mainz ***********************************************************************/
2034f9b3eeSRoland Mainz #pragma prototyped
2134f9b3eeSRoland Mainz /*
2234f9b3eeSRoland Mainz  * regression test intercept control
2334f9b3eeSRoland Mainz  * enable with SHOPT_REGRESS==1 in Makefile
2434f9b3eeSRoland Mainz  * not for production use
2534f9b3eeSRoland Mainz  * see --man for details
2634f9b3eeSRoland Mainz  * all string constants inline here instead of in data/...
2734f9b3eeSRoland Mainz  *
2834f9b3eeSRoland Mainz  *   David Korn
2934f9b3eeSRoland Mainz  *   at&t research
3034f9b3eeSRoland Mainz  */
3134f9b3eeSRoland Mainz 
3234f9b3eeSRoland Mainz #include	"defs.h"
3334f9b3eeSRoland Mainz 
3434f9b3eeSRoland Mainz #if SHOPT_REGRESS
3534f9b3eeSRoland Mainz 
3634f9b3eeSRoland Mainz #include	<error.h>
3734f9b3eeSRoland Mainz #include	<ls.h>
3834f9b3eeSRoland Mainz #include	"io.h"
3934f9b3eeSRoland Mainz #include	"builtins.h"
4034f9b3eeSRoland Mainz #include	<tmx.h>
4134f9b3eeSRoland Mainz 
4234f9b3eeSRoland Mainz #define REGRESS_HEADER	"ksh:REGRESS:"
4334f9b3eeSRoland Mainz 
4434f9b3eeSRoland Mainz #define TRACE(r,i,f)		sh_regress(REGRESS_##r, i, sfprints f, __LINE__, __FILE__)
4534f9b3eeSRoland Mainz 
4634f9b3eeSRoland Mainz static const char	usage[] =
4734f9b3eeSRoland Mainz "[-1p0?\n@(#)$Id: __regress__ (AT&T Research) 2009-03-29 $\n]"
4834f9b3eeSRoland Mainz USAGE_LICENSE
4934f9b3eeSRoland Mainz "[+NAME?__regress__ - shell regression test intercept control]"
5034f9b3eeSRoland Mainz "[+DESCRIPTION?\b__regress__\b controls the regression test intercepts "
5134f9b3eeSRoland Mainz     "for shells compiled with SHOPT_REGRESS==1. Shells compiled this way are "
5234f9b3eeSRoland Mainz     "for testing only. In addition to \b__regress__\b and the \b--regress\b "
5334f9b3eeSRoland Mainz     "command line option, these shells may contain system library function "
5434f9b3eeSRoland Mainz     "intercepts that behave different from the native counterparts.]"
5534f9b3eeSRoland Mainz "[+?Each option controls a different test and possibly a different set "
5634f9b3eeSRoland Mainz     "of intercepts. The options are interpreted \bdd\b(1) style -- '-' or "
5734f9b3eeSRoland Mainz     "'--' prefix not required. This simplifies the specification of the "
5834f9b3eeSRoland Mainz     "command line \b--regress\b=\avalue\a option, where \avalue\a is passed "
5934f9b3eeSRoland Mainz     "as an option to the \b__regress__\b builtin. Typically regression test "
6034f9b3eeSRoland Mainz     "intercepts are enabled with one or more command line \b--regress\b "
6134f9b3eeSRoland Mainz     "options, with optional specific calls to \b__regress__\b in test "
6234f9b3eeSRoland Mainz     "scripts to enable/disable intercepts as the test progresses.]"
6334f9b3eeSRoland Mainz "[+?Each enabled intercept may result in trace lines of the form \b" REGRESS_HEADER
6434f9b3eeSRoland Mainz     "\aoption\a:\aintercept\a:\ainfo\a on the standard error, where "
6534f9b3eeSRoland Mainz     "\aoption\a is one of the options below, \aintercept\a is the name of "
6634f9b3eeSRoland Mainz     "the specific intercept for \aoption\a, and \ainfo\a is \aoption\a "
6734f9b3eeSRoland Mainz     "specific information. Unless noted otherwise, one regression test trace "
6834f9b3eeSRoland Mainz     "line is produced each time an enabled intercept is called.]"
6934f9b3eeSRoland Mainz "[101:egid?The intercept effective gid is set to \aoriginal-egid\a. The "
7034f9b3eeSRoland Mainz     "effective gid of the underlying system process is not affected. The "
7134f9b3eeSRoland Mainz     "trace line info is either \begid==rgid\b or \begid!=rgid\b. The "
7234f9b3eeSRoland Mainz     "intercepts are:]#?[original-egid:=1]"
7334f9b3eeSRoland Mainz     "{"
7434f9b3eeSRoland Mainz         "[+getegid()?The intercept effecive gid is returned. The "
7534f9b3eeSRoland Mainz             "\bsetgid\b() intercept may change this between the real gid and "
7634f9b3eeSRoland Mainz             "\aoriginal-egid\a.]"
7734f9b3eeSRoland Mainz         "[+setgid(gid)?Sets the intercept effective gid to \agid\a. "
7834f9b3eeSRoland Mainz             "Fails if \agid\a is neither the real gid nor "
7934f9b3eeSRoland Mainz             "\aoriginal-egid\a.]"
8034f9b3eeSRoland Mainz     "}"
8134f9b3eeSRoland Mainz "[102:euid?The intercept effective uid is set to \aoriginal-euid\a. The "
8234f9b3eeSRoland Mainz     "effective uid of the underlying system process is not affected. The "
8334f9b3eeSRoland Mainz     "trace line info is either \beuid==ruid\b or \beuid!=ruid\b. The "
8434f9b3eeSRoland Mainz     "intercepts are:]#?[original-euid:=1]"
8534f9b3eeSRoland Mainz     "{"
8634f9b3eeSRoland Mainz         "[+geteuid()?The intercept effecive uid is returned. The "
8734f9b3eeSRoland Mainz             "\bsetuid\b() intercept may change this between the real uid and "
8834f9b3eeSRoland Mainz             "\aoriginal-euid\a.]"
8934f9b3eeSRoland Mainz         "[+setuid(uid)?Sets the intercept effective uid to \auid\a. "
9034f9b3eeSRoland Mainz             "Fails if \auid\a is neither the real uid nor "
9134f9b3eeSRoland Mainz             "\aoriginal-euid\a.]"
9234f9b3eeSRoland Mainz     "}"
9334f9b3eeSRoland Mainz "[103:p_suid?Specifies a value for SHOPT_P_SUID. Effective uids greater "
9434f9b3eeSRoland Mainz     "than the non-privileged-uid disable the priveleged mode. The intercepts "
9534f9b3eeSRoland Mainz     "are:]#?[non-privileged-uid:=1]"
9634f9b3eeSRoland Mainz     "{"
9734f9b3eeSRoland Mainz         "[+SHOPT_P_SUID?The SHOPT_P_SUID macro value is overridden by "
9834f9b3eeSRoland Mainz             "\bp_suid\b. A trace line is output for each SHOPT_P_SUID "
9934f9b3eeSRoland Mainz             "access.]"
10034f9b3eeSRoland Mainz     "}"
10134f9b3eeSRoland Mainz "[104:source?The intercepts are:]"
10234f9b3eeSRoland Mainz     "{"
10334f9b3eeSRoland Mainz         "[+sh_source()?The trace line info is the path of the script "
10434f9b3eeSRoland Mainz             "being sourced. Used to trace shell startup scripts.]"
10534f9b3eeSRoland Mainz     "}"
10634f9b3eeSRoland Mainz "[105:etc?Map file paths matching \b/etc/\b* to \aetc-dir\a/*. The "
10734f9b3eeSRoland Mainz     "intercepts are:]:[etc-dir:=/etc]"
10834f9b3eeSRoland Mainz     "{"
10934f9b3eeSRoland Mainz         "[+sh_open()?Paths matching \b/etc/\b* are changed to "
11034f9b3eeSRoland Mainz             "\aetc-dir\a/*.]"
11134f9b3eeSRoland Mainz     "}"
11234f9b3eeSRoland Mainz "[+SEE ALSO?\bksh\b(1), \bregress\b(1), \brt\b(1)]"
11334f9b3eeSRoland Mainz ;
11434f9b3eeSRoland Mainz 
11534f9b3eeSRoland Mainz static const char*	regress_options[] =
11634f9b3eeSRoland Mainz {
11734f9b3eeSRoland Mainz 	"ERROR",
11834f9b3eeSRoland Mainz 	"egid",
11934f9b3eeSRoland Mainz 	"euid",
12034f9b3eeSRoland Mainz 	"p_suid",
12134f9b3eeSRoland Mainz 	"source",
12234f9b3eeSRoland Mainz 	"etc",
12334f9b3eeSRoland Mainz };
12434f9b3eeSRoland Mainz 
sh_regress_init(Shell_t * shp)12534f9b3eeSRoland Mainz void sh_regress_init(Shell_t* shp)
12634f9b3eeSRoland Mainz {
12734f9b3eeSRoland Mainz 	static Regress_t	state;
12834f9b3eeSRoland Mainz 
12934f9b3eeSRoland Mainz 	shp->regress = &state;
13034f9b3eeSRoland Mainz }
13134f9b3eeSRoland Mainz 
13234f9b3eeSRoland Mainz /*
13334f9b3eeSRoland Mainz  * regress info trace output
13434f9b3eeSRoland Mainz  */
13534f9b3eeSRoland Mainz 
sh_regress(unsigned int index,const char * intercept,const char * info,unsigned int line,const char * file)13634f9b3eeSRoland Mainz void sh_regress(unsigned int index, const char* intercept, const char* info, unsigned int line, const char* file)
13734f9b3eeSRoland Mainz {
13834f9b3eeSRoland Mainz 	char*	name;
13934f9b3eeSRoland Mainz 	char	buf[16];
14034f9b3eeSRoland Mainz 
14134f9b3eeSRoland Mainz 	if (index >= 1 && index <= elementsof(regress_options))
14234f9b3eeSRoland Mainz 		name = (char*)regress_options[index];
14334f9b3eeSRoland Mainz 	else
14434f9b3eeSRoland Mainz 		sfsprintf(name = buf, sizeof(buf), "%u", index);
14534f9b3eeSRoland Mainz 	sfprintf(sfstderr, REGRESS_HEADER "%s:%s:%s\n", name, intercept, fmtesc(info));
14634f9b3eeSRoland Mainz }
14734f9b3eeSRoland Mainz 
14834f9b3eeSRoland Mainz /*
14934f9b3eeSRoland Mainz  * egid intercepts
15034f9b3eeSRoland Mainz  */
15134f9b3eeSRoland Mainz 
15234f9b3eeSRoland Mainz static gid_t	intercept_sgid = 0;
15334f9b3eeSRoland Mainz static gid_t	intercept_egid = -1;
15434f9b3eeSRoland Mainz static gid_t	intercept_rgid = -1;
15534f9b3eeSRoland Mainz 
getegid(void)15634f9b3eeSRoland Mainz gid_t getegid(void)
15734f9b3eeSRoland Mainz {
15834f9b3eeSRoland Mainz 	if (intercept_rgid == -1)
15934f9b3eeSRoland Mainz 		intercept_rgid = getgid();
16034f9b3eeSRoland Mainz 	if (sh_isregress(REGRESS_egid))
16134f9b3eeSRoland Mainz 	{
16234f9b3eeSRoland Mainz 		TRACE(egid, "getegid", ("%s", intercept_egid == intercept_rgid ? "egid==rgid" : "egid!=rgid"));
16334f9b3eeSRoland Mainz 		return intercept_egid;
16434f9b3eeSRoland Mainz 	}
16534f9b3eeSRoland Mainz 	return intercept_rgid;
16634f9b3eeSRoland Mainz }
16734f9b3eeSRoland Mainz 
setgid(gid_t gid)16834f9b3eeSRoland Mainz int setgid(gid_t gid)
16934f9b3eeSRoland Mainz {
17034f9b3eeSRoland Mainz 	if (intercept_rgid == -1)
17134f9b3eeSRoland Mainz 		intercept_rgid = getgid();
17234f9b3eeSRoland Mainz 	if (sh_isregress(REGRESS_egid))
17334f9b3eeSRoland Mainz 	{
17434f9b3eeSRoland Mainz 		if (gid != intercept_rgid && gid != intercept_sgid)
17534f9b3eeSRoland Mainz 		{
17634f9b3eeSRoland Mainz 			TRACE(egid, "setgid", ("%s", "EPERM"));
17734f9b3eeSRoland Mainz 			errno = EPERM;
17834f9b3eeSRoland Mainz 			return -1;
17934f9b3eeSRoland Mainz 		}
18034f9b3eeSRoland Mainz 		intercept_egid = gid;
18134f9b3eeSRoland Mainz 		TRACE(egid, "setgid", ("%s", intercept_egid == intercept_rgid ? "egid==rgid" : "egid!=rgid"));
18234f9b3eeSRoland Mainz 	}
18334f9b3eeSRoland Mainz 	else if (gid != intercept_rgid)
18434f9b3eeSRoland Mainz 	{
18534f9b3eeSRoland Mainz 		errno = EPERM;
18634f9b3eeSRoland Mainz 		return -1;
18734f9b3eeSRoland Mainz 	}
18834f9b3eeSRoland Mainz 	return 0;
18934f9b3eeSRoland Mainz }
19034f9b3eeSRoland Mainz 
19134f9b3eeSRoland Mainz /*
19234f9b3eeSRoland Mainz  * euid intercepts
19334f9b3eeSRoland Mainz  */
19434f9b3eeSRoland Mainz 
19534f9b3eeSRoland Mainz static uid_t	intercept_suid = 0;
19634f9b3eeSRoland Mainz static uid_t	intercept_euid = -1;
19734f9b3eeSRoland Mainz static uid_t	intercept_ruid = -1;
19834f9b3eeSRoland Mainz 
geteuid(void)19934f9b3eeSRoland Mainz uid_t geteuid(void)
20034f9b3eeSRoland Mainz {
20134f9b3eeSRoland Mainz 	if (intercept_ruid == -1)
20234f9b3eeSRoland Mainz 		intercept_ruid = getuid();
20334f9b3eeSRoland Mainz 	if (sh_isregress(REGRESS_euid))
20434f9b3eeSRoland Mainz 	{
20534f9b3eeSRoland Mainz 		TRACE(euid, "geteuid", ("%s", intercept_euid == intercept_ruid ? "euid==ruid" : "euid!=ruid"));
20634f9b3eeSRoland Mainz 		return intercept_euid;
20734f9b3eeSRoland Mainz 	}
20834f9b3eeSRoland Mainz 	return intercept_ruid;
20934f9b3eeSRoland Mainz }
21034f9b3eeSRoland Mainz 
setuid(uid_t uid)21134f9b3eeSRoland Mainz int setuid(uid_t uid)
21234f9b3eeSRoland Mainz {
21334f9b3eeSRoland Mainz 	if (intercept_ruid == -1)
21434f9b3eeSRoland Mainz 		intercept_ruid = getuid();
21534f9b3eeSRoland Mainz 	if (sh_isregress(REGRESS_euid))
21634f9b3eeSRoland Mainz 	{
21734f9b3eeSRoland Mainz 		if (uid != intercept_ruid && uid != intercept_suid)
21834f9b3eeSRoland Mainz 		{
21934f9b3eeSRoland Mainz 			TRACE(euid, "setuid", ("%s", "EPERM"));
22034f9b3eeSRoland Mainz 			errno = EPERM;
22134f9b3eeSRoland Mainz 			return -1;
22234f9b3eeSRoland Mainz 		}
22334f9b3eeSRoland Mainz 		intercept_euid = uid;
22434f9b3eeSRoland Mainz 		TRACE(euid, "setuid", ("%s", intercept_euid == intercept_ruid ? "euid==ruid" : "euid!=ruid"));
22534f9b3eeSRoland Mainz 	}
22634f9b3eeSRoland Mainz 	else if (uid != intercept_ruid)
22734f9b3eeSRoland Mainz 	{
22834f9b3eeSRoland Mainz 		errno = EPERM;
22934f9b3eeSRoland Mainz 		return -1;
23034f9b3eeSRoland Mainz 	}
23134f9b3eeSRoland Mainz 	return 0;
23234f9b3eeSRoland Mainz }
23334f9b3eeSRoland Mainz 
23434f9b3eeSRoland Mainz /*
23534f9b3eeSRoland Mainz  * p_suid intercept
23634f9b3eeSRoland Mainz  */
23734f9b3eeSRoland Mainz 
23834f9b3eeSRoland Mainz static uid_t	intercept_p_suid = 0x7fffffff;
23934f9b3eeSRoland Mainz 
sh_regress_p_suid(unsigned int line,const char * file)24034f9b3eeSRoland Mainz uid_t sh_regress_p_suid(unsigned int line, const char* file)
24134f9b3eeSRoland Mainz {
24234f9b3eeSRoland Mainz 	REGRESS(p_suid, "SHOPT_P_SUID", ("%d", intercept_p_suid));
24334f9b3eeSRoland Mainz 	return intercept_p_suid;
24434f9b3eeSRoland Mainz }
24534f9b3eeSRoland Mainz 
24634f9b3eeSRoland Mainz /*
24734f9b3eeSRoland Mainz  * p_suid intercept
24834f9b3eeSRoland Mainz  */
24934f9b3eeSRoland Mainz 
25034f9b3eeSRoland Mainz static char*	intercept_etc = 0;
25134f9b3eeSRoland Mainz 
sh_regress_etc(const char * path,unsigned int line,const char * file)25234f9b3eeSRoland Mainz char* sh_regress_etc(const char* path, unsigned int line, const char* file)
25334f9b3eeSRoland Mainz {
25434f9b3eeSRoland Mainz 	REGRESS(etc, "sh_open", ("%s => %s%s", path, intercept_etc, path+4));
25534f9b3eeSRoland Mainz 	return intercept_etc;
25634f9b3eeSRoland Mainz }
25734f9b3eeSRoland Mainz 
25834f9b3eeSRoland Mainz /*
25934f9b3eeSRoland Mainz  * __regress__ builtin
26034f9b3eeSRoland Mainz  */
26134f9b3eeSRoland Mainz 
b___regress__(int argc,char ** argv,Shbltin_t * context)262*b30d1939SAndy Fiddaman int b___regress__(int argc, char** argv, Shbltin_t *context)
26334f9b3eeSRoland Mainz {
264*b30d1939SAndy Fiddaman 	register Shell_t*	shp = context->shp;
26534f9b3eeSRoland Mainz 	int			n;
26634f9b3eeSRoland Mainz 
26734f9b3eeSRoland Mainz 	for (;;)
26834f9b3eeSRoland Mainz 	{
26934f9b3eeSRoland Mainz 		switch (n = optget(argv, usage))
27034f9b3eeSRoland Mainz 		{
27134f9b3eeSRoland Mainz 		case '?':
27234f9b3eeSRoland Mainz 			errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg);
27334f9b3eeSRoland Mainz 			break;
27434f9b3eeSRoland Mainz 		case ':':
27534f9b3eeSRoland Mainz 			errormsg(SH_DICT, 2, "%s", opt_info.arg);
27634f9b3eeSRoland Mainz 			break;
27734f9b3eeSRoland Mainz 		case 0:
27834f9b3eeSRoland Mainz 			break;
27934f9b3eeSRoland Mainz 		default:
28034f9b3eeSRoland Mainz 			if (n < -100)
28134f9b3eeSRoland Mainz 			{
28234f9b3eeSRoland Mainz 				n = -(n + 100);
28334f9b3eeSRoland Mainz 				if (opt_info.arg || opt_info.number)
28434f9b3eeSRoland Mainz 					sh_onregress(n);
28534f9b3eeSRoland Mainz 				else
28634f9b3eeSRoland Mainz 					sh_offregress(n);
28734f9b3eeSRoland Mainz 				switch (n)
28834f9b3eeSRoland Mainz 				{
28934f9b3eeSRoland Mainz 				case REGRESS_egid:
29034f9b3eeSRoland Mainz 					if (sh_isregress(n))
29134f9b3eeSRoland Mainz 					{
29234f9b3eeSRoland Mainz 						intercept_egid = intercept_sgid = (gid_t)opt_info.number;
29334f9b3eeSRoland Mainz 						TRACE(egid, argv[0], ("%d", intercept_egid));
29434f9b3eeSRoland Mainz 					}
29534f9b3eeSRoland Mainz 					else
29634f9b3eeSRoland Mainz 						TRACE(egid, argv[0], ("%s", "off"));
29734f9b3eeSRoland Mainz 					break;
29834f9b3eeSRoland Mainz 				case REGRESS_euid:
29934f9b3eeSRoland Mainz 					if (sh_isregress(n))
30034f9b3eeSRoland Mainz 					{
30134f9b3eeSRoland Mainz 						intercept_euid = intercept_suid = (uid_t)opt_info.number;
30234f9b3eeSRoland Mainz 						TRACE(euid, argv[0], ("%d", intercept_euid));
30334f9b3eeSRoland Mainz 					}
30434f9b3eeSRoland Mainz 					else
30534f9b3eeSRoland Mainz 						TRACE(euid, argv[0], ("%s", "off"));
30634f9b3eeSRoland Mainz 					break;
30734f9b3eeSRoland Mainz 				case REGRESS_p_suid:
30834f9b3eeSRoland Mainz 					if (sh_isregress(n))
30934f9b3eeSRoland Mainz 					{
31034f9b3eeSRoland Mainz 						intercept_p_suid = (uid_t)opt_info.number;
31134f9b3eeSRoland Mainz 						TRACE(p_suid, argv[0], ("%d", intercept_p_suid));
31234f9b3eeSRoland Mainz 					}
31334f9b3eeSRoland Mainz 					else
31434f9b3eeSRoland Mainz 						TRACE(p_suid, argv[0], ("%s", "off"));
31534f9b3eeSRoland Mainz 					break;
31634f9b3eeSRoland Mainz 				case REGRESS_source:
31734f9b3eeSRoland Mainz 					TRACE(source, argv[0], ("%s", sh_isregress(n) ? "on" : "off"));
31834f9b3eeSRoland Mainz 					break;
31934f9b3eeSRoland Mainz 				case REGRESS_etc:
32034f9b3eeSRoland Mainz 					if (sh_isregress(n))
32134f9b3eeSRoland Mainz 					{
32234f9b3eeSRoland Mainz 						intercept_etc = opt_info.arg;
32334f9b3eeSRoland Mainz 						TRACE(etc, argv[0], ("%s", intercept_etc));
32434f9b3eeSRoland Mainz 					}
32534f9b3eeSRoland Mainz 					else
32634f9b3eeSRoland Mainz 						TRACE(etc, argv[0], ("%s", "off"));
32734f9b3eeSRoland Mainz 					break;
32834f9b3eeSRoland Mainz 				}
32934f9b3eeSRoland Mainz 			}
33034f9b3eeSRoland Mainz 			continue;
33134f9b3eeSRoland Mainz 		}
33234f9b3eeSRoland Mainz 		break;
33334f9b3eeSRoland Mainz 	}
33434f9b3eeSRoland Mainz 	if (error_info.errors || *(argv + opt_info.index))
33534f9b3eeSRoland Mainz 		errormsg(SH_DICT, ERROR_usage(2), "%s", optusage(NiL));
33634f9b3eeSRoland Mainz 	return 0;
33734f9b3eeSRoland Mainz }
33834f9b3eeSRoland Mainz 
33934f9b3eeSRoland Mainz #else
34034f9b3eeSRoland Mainz 
34134f9b3eeSRoland Mainz NoN(regress)
34234f9b3eeSRoland Mainz 
34334f9b3eeSRoland Mainz #endif
344