15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
225c51f124SMoriah Waterland /*
2324e7a8c7SPaul Wernau  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245c51f124SMoriah Waterland  * Use is subject to license terms.
255c51f124SMoriah Waterland  */
265c51f124SMoriah Waterland 
275c51f124SMoriah Waterland /*
285c51f124SMoriah Waterland  * The purpose of this lex specification is to estimate the
295c51f124SMoriah Waterland  * correctness of the various scripts that accompany packages. It
305c51f124SMoriah Waterland  * is not flawless, but it is a better review than that of prior
315c51f124SMoriah Waterland  * package validators. It looks for indications of interaction,
325c51f124SMoriah Waterland  * root calls and attempts to modify locked files.
335c51f124SMoriah Waterland  */
345c51f124SMoriah Waterland %e 1500
355c51f124SMoriah Waterland %p 3500
365c51f124SMoriah Waterland %s WHROOT
375c51f124SMoriah Waterland %{
385c51f124SMoriah Waterland #undef	input
395c51f124SMoriah Waterland #undef	unput
405c51f124SMoriah Waterland FILE *scr_fp;
415c51f124SMoriah Waterland #define	input()		(((yytchar=yysptr>yysbuf?U(*--yysptr):getc(scr_fp))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)
425c51f124SMoriah Waterland #define	unput(p)	ungetc(p, scr_fp)
435c51f124SMoriah Waterland 
445c51f124SMoriah Waterland #define	INTERACT_D	0x00000001	/* definitely */
455c51f124SMoriah Waterland #define	ROOT_D		0x00000002
465c51f124SMoriah Waterland #define	LOCKED_D	0x00000004
475c51f124SMoriah Waterland #define	INTERACT_M	0x00010000	/* might be true, or we ... */
485c51f124SMoriah Waterland #define	ROOT_M		0x00020000	/* ... might be reading it wrong. */
495c51f124SMoriah Waterland #define	LOCKED_M	0x00040000
505c51f124SMoriah Waterland #define	WPARM1_M	0x00080000	/* attempt to write to $1 */
515c51f124SMoriah Waterland #define	USEPARM1_M	0x00100000	/* other attempt to use $1 */
525c51f124SMoriah Waterland #define	ODDPARM_M	0x00200000	/* use of some other parameter */
535c51f124SMoriah Waterland #define	PKGDB_M		0x00400000	/* read access to DB */
545c51f124SMoriah Waterland #define	INITVAL		0x40000000
555c51f124SMoriah Waterland 
565c51f124SMoriah Waterland /* Abbreviations */
575c51f124SMoriah Waterland #define	INTERACT	(INTERACT_D | INTERACT_M)
585c51f124SMoriah Waterland #define	ROOT		(ROOT_D | ROOT_M)
595c51f124SMoriah Waterland #define	LOCKED		(LOCKED_D | LOCKED_M)
605c51f124SMoriah Waterland #define	HASPARM		(WPARM1_M | USEPARM1_M | ODDPARM_M)
615c51f124SMoriah Waterland 
625c51f124SMoriah Waterland /* Things the preinstall and preremove scripts can't do. */
635c51f124SMoriah Waterland #define	PRE_MASK	(INTERACT | LOCKED | PKGDB_M | HASPARM)
645c51f124SMoriah Waterland /*
655c51f124SMoriah Waterland  * Things the class action script can't do. Don't get the impression that
665c51f124SMoriah Waterland  * this means the class action script can be interactive; but, it can
675c51f124SMoriah Waterland  * legitimately read stdin (which is what INTERACT tests for).
685c51f124SMoriah Waterland  */
695c51f124SMoriah Waterland #define	CAS_MASK	(LOCKED | PKGDB_M | WPARM1_M | ODDPARM_M)
705c51f124SMoriah Waterland /* Things the postinstall and postremove scripts can't do. */
715c51f124SMoriah Waterland #define	POST_MASK	(INTERACT | HASPARM)
725c51f124SMoriah Waterland /* Things the request script can't do. */
735c51f124SMoriah Waterland #define	REQ_MASK	(ROOT | ODDPARM_M)
745c51f124SMoriah Waterland /* Things the checkinstall script can't do. */
755c51f124SMoriah Waterland #define	CHK_MASK	(INTERACT | ROOT | ODDPARM_M)
765c51f124SMoriah Waterland 
775c51f124SMoriah Waterland /* Nothing definite - not worth returning an error */
785c51f124SMoriah Waterland #define	MAYBE_ONLY	~(INTERACT_D | ROOT_D | LOCKED_D)
795c51f124SMoriah Waterland 
805c51f124SMoriah Waterland #define	WRN_INST_F	"WARNING: script <%s> uses installf but no " \
815c51f124SMoriah Waterland 			    "installf -f was detected."
825c51f124SMoriah Waterland #define	WRN_REM_F	"WARNING: script <%s> uses removef but no " \
835c51f124SMoriah Waterland 			    "removef -f was detected."
845c51f124SMoriah Waterland #define	WRN_INTERACT	"WARNING: script <%s> may require " \
855c51f124SMoriah Waterland 			    "user interaction at line <%d>."
865c51f124SMoriah Waterland #define	WRN_LOCKED	"WARNING: script <%s> may seek access to the " \
875c51f124SMoriah Waterland 			    "transitional package database at line <%d>. " \
885c51f124SMoriah Waterland 			    "This is safest in the postinstall or " \
895c51f124SMoriah Waterland 			    "postremove script."
905c51f124SMoriah Waterland #define	WRN_ROOT	"WARNING: script <%s> may not have permission " \
915c51f124SMoriah Waterland 			    "to execute line <%d>."
925c51f124SMoriah Waterland #define	WRN_FORM_ARG	"WARNING: not sure where script <%s> gets the "\
935c51f124SMoriah Waterland 			    "parameter at line <%d>."
945c51f124SMoriah Waterland #define	WRN_FORM_USE	"WARNING: script <%s> questionable usage of "\
955c51f124SMoriah Waterland 			    "parameter at line <%d>."
965c51f124SMoriah Waterland #define	WRN_TRANSDB	"WARNING: script <%s> questionable read " \
975c51f124SMoriah Waterland 			    "of package database at line <%d>. An " \
985c51f124SMoriah Waterland 			    "intermediate buffer may be appropriate."
995c51f124SMoriah Waterland #define	WRN_SPACEACC	"WARNING: script <%s> updates the package database " \
1005c51f124SMoriah Waterland 			    "but provides no space file to account for " \
1015c51f124SMoriah Waterland 			    "the additional package object."
1025c51f124SMoriah Waterland #define	ERR_INTERACT	"ERROR: script <%s> requires user " \
1035c51f124SMoriah Waterland 			    "interaction at line <%d>."
1045c51f124SMoriah Waterland #define	ERR_LOCKED	"ERROR: script <%s> attempts to modify locked " \
1055c51f124SMoriah Waterland 			    "package database at line <%d>."
1065c51f124SMoriah Waterland #define	ERR_ROOT	"ERROR: script <%s> requires root permission at " \
1075c51f124SMoriah Waterland 			    "line <%d>."
1085c51f124SMoriah Waterland #define	ERR_FOPEN	"ERROR: Cannot evaluate script <%s>, errno=%d."
1095c51f124SMoriah Waterland #define	ERR_ARGS	"ERROR: scripteval() - no script provided for " \
1105c51f124SMoriah Waterland 			    "evaluation."
1115c51f124SMoriah Waterland extern int errno;
1125c51f124SMoriah Waterland 
1135c51f124SMoriah Waterland static int line_no;	/* current line number */
1145c51f124SMoriah Waterland int pipe_release = 0;	/* loop level for release of pipe */
1155c51f124SMoriah Waterland int loop_depth = 0;	/* current number of nested loops */
1165c51f124SMoriah Waterland int case_depth = 0;	/* same for case ... */
1175c51f124SMoriah Waterland int if_depth = 0;	/* ... and if statements */
1185c51f124SMoriah Waterland int cur_level = 0;	/* current number of nested anything */
1195c51f124SMoriah Waterland int braces = 0;		/* depth into a function */
1205c51f124SMoriah Waterland 
1215c51f124SMoriah Waterland int lock_level = 0;
1225c51f124SMoriah Waterland int root_level = 0;
1235c51f124SMoriah Waterland 
1245c51f124SMoriah Waterland struct statstrct {
1255c51f124SMoriah Waterland 	unsigned int in_function:1;
1265c51f124SMoriah Waterland 	unsigned int in_pipe:1;
1275c51f124SMoriah Waterland 	unsigned int in_loop:1;
1285c51f124SMoriah Waterland 	unsigned int in_case:1;
1295c51f124SMoriah Waterland 	unsigned int in_if:1;
1305c51f124SMoriah Waterland 	unsigned int in_awk:1;
1315c51f124SMoriah Waterland 	unsigned int allow_int:1;	/* Allow an interactive function. */
1325c51f124SMoriah Waterland 	unsigned int pkg_rtn_done:1;
1335c51f124SMoriah Waterland 	unsigned int pkgchk_f:1;
1345c51f124SMoriah Waterland 	unsigned int instf:1;
1355c51f124SMoriah Waterland 	unsigned int instf_f:1;
1365c51f124SMoriah Waterland 	unsigned int remf:1;
1375c51f124SMoriah Waterland 	unsigned int remf_f:1;
1385c51f124SMoriah Waterland 	unsigned int nospacefile:1;
1395c51f124SMoriah Waterland 	unsigned int needspacefile:1;
1405c51f124SMoriah Waterland } status = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1415c51f124SMoriah Waterland 
1425c51f124SMoriah Waterland %}
1435c51f124SMoriah Waterland %%
1445c51f124SMoriah Waterland %{
1455c51f124SMoriah Waterland /*
1465c51f124SMoriah Waterland  * Validate a few OK patterns that look like bad patterns. These include:
1475c51f124SMoriah Waterland  *	1. comments
1485c51f124SMoriah Waterland  *	2. quoted strings
1495c51f124SMoriah Waterland  *	3. writes to $1 (request script)
1505c51f124SMoriah Waterland  *	4. reads from $1 (CAS)
1515c51f124SMoriah Waterland  *	5. writes to /dev/null
1525c51f124SMoriah Waterland  */
1535c51f124SMoriah Waterland %}
15424e7a8c7SPaul Wernau #.*$ 	{
15524e7a8c7SPaul Wernau 	if (status.in_awk == 0)
15624e7a8c7SPaul Wernau 		return INITVAL;
15724e7a8c7SPaul Wernau 	else
15824e7a8c7SPaul Wernau 		REJECT; /* No comments in the middle of an awk statement */
15924e7a8c7SPaul Wernau 	}
1605c51f124SMoriah Waterland 
1615c51f124SMoriah Waterland \`	unput(' ');	/* No executable matching */
1625c51f124SMoriah Waterland 
1635c51f124SMoriah Waterland %{
1645c51f124SMoriah Waterland /* Anybody can write to /dev/null and anybody can write to /tmp. */
1655c51f124SMoriah Waterland %}
1665c51f124SMoriah Waterland \>[ \t]*"/dev/null"	return INITVAL;
1675c51f124SMoriah Waterland \>[ \t]*"/tmp"		return INITVAL;
1685c51f124SMoriah Waterland 
1695c51f124SMoriah Waterland %{
1705c51f124SMoriah Waterland /* If it's escaped, the next entry may as well be a space. */
1715c51f124SMoriah Waterland %}
1725c51f124SMoriah Waterland \\	{
1735c51f124SMoriah Waterland 	char ch;
1745c51f124SMoriah Waterland 
1755c51f124SMoriah Waterland 	if ((ch = input()) == '\n')
1765c51f124SMoriah Waterland 		line_no++;
1775c51f124SMoriah Waterland 
1785c51f124SMoriah Waterland 	unput(' ');
1795c51f124SMoriah Waterland }
1805c51f124SMoriah Waterland 
1815c51f124SMoriah Waterland %{
1825c51f124SMoriah Waterland /* In the quotes is OK. */
1835c51f124SMoriah Waterland %}
1845c51f124SMoriah Waterland \"	{
1855c51f124SMoriah Waterland 	char ch;
1865c51f124SMoriah Waterland 	while ((ch = input()) != '\"') {
1875c51f124SMoriah Waterland 		if (ch == '\\') {
1885c51f124SMoriah Waterland 			input();	/* Read this into the bit bucket. */
1895c51f124SMoriah Waterland 			continue;
1905c51f124SMoriah Waterland 		}
1915c51f124SMoriah Waterland 		if (ch == '\n')
1925c51f124SMoriah Waterland 			line_no++;
1935c51f124SMoriah Waterland 		else if (ch == '\0')
1945c51f124SMoriah Waterland 			return (0);	/* EOF */
1955c51f124SMoriah Waterland 	}
1965c51f124SMoriah Waterland }
1975c51f124SMoriah Waterland 
1985c51f124SMoriah Waterland %{
1995c51f124SMoriah Waterland /* In the single quotes is OK if they aren't associated with an awk script. */
2005c51f124SMoriah Waterland %}
2015c51f124SMoriah Waterland \'	{
2025c51f124SMoriah Waterland 	char ch;
2035c51f124SMoriah Waterland 
20424e7a8c7SPaul Wernau 	if (status.in_awk != 0) {
2055c51f124SMoriah Waterland 		REJECT;;
20624e7a8c7SPaul Wernau 	}
2075c51f124SMoriah Waterland 
2085c51f124SMoriah Waterland 	while ((ch = input()) != '\'') {
2095c51f124SMoriah Waterland 		if (ch == '\\') {
2105c51f124SMoriah Waterland 			input();	/* Read this into the bit bucket. */
2115c51f124SMoriah Waterland 			continue;
2125c51f124SMoriah Waterland 		}
2135c51f124SMoriah Waterland 		if (ch == '\n')
2145c51f124SMoriah Waterland 			line_no++;
2155c51f124SMoriah Waterland 		else if (ch == '\0')
2165c51f124SMoriah Waterland 			return (0);	/* EOF */
2175c51f124SMoriah Waterland 	}
2185c51f124SMoriah Waterland }
2195c51f124SMoriah Waterland 
2205c51f124SMoriah Waterland %{
2215c51f124SMoriah Waterland /*
2225c51f124SMoriah Waterland  * Check for use of parameters passed to the script.
2235c51f124SMoriah Waterland  *	1. writes to $1 as though it were a file
2245c51f124SMoriah Waterland  *	2. use of $1 in any capacity
2255c51f124SMoriah Waterland  *	3. use of other parameters
2265c51f124SMoriah Waterland  * Within a function or an awk script, these parameters aren't
2275c51f124SMoriah Waterland  * the one's of interest.
2285c51f124SMoriah Waterland  */
2295c51f124SMoriah Waterland %}
2305c51f124SMoriah Waterland \>[\t ]*\$1/[\t\n ]	{
2315c51f124SMoriah Waterland 	if (status.in_function == 0 && status.in_awk == 0)
2325c51f124SMoriah Waterland 		return (WPARM1_M);
2335c51f124SMoriah Waterland }
2345c51f124SMoriah Waterland 
2355c51f124SMoriah Waterland ^$1/[\t\n ]	|
2365c51f124SMoriah Waterland [\t ]$1/[\t\n ]	{
2375c51f124SMoriah Waterland 	if (status.in_function == 0 && status.in_awk == 0)
2385c51f124SMoriah Waterland 		return (USEPARM1_M);
2395c51f124SMoriah Waterland }
2405c51f124SMoriah Waterland 
2415c51f124SMoriah Waterland \$[2-9]	|
2425c51f124SMoriah Waterland \$[0-9][0-9]+ {
2435c51f124SMoriah Waterland 	if (status.in_function == 0 && status.in_awk == 0)
2445c51f124SMoriah Waterland 		return (ODDPARM_M);
2455c51f124SMoriah Waterland }
2465c51f124SMoriah Waterland 
2475c51f124SMoriah Waterland %{
2485c51f124SMoriah Waterland /*
2495c51f124SMoriah Waterland  * Detect shell function.
2505c51f124SMoriah Waterland  */
2515c51f124SMoriah Waterland %}
2525c51f124SMoriah Waterland "()"[ \t]*\n[ \t]*/\{	{ status.in_function = 1; line_no++; }
2535c51f124SMoriah Waterland "()"[ ]*/\{	status.in_function = 1;
2545c51f124SMoriah Waterland 
2555c51f124SMoriah Waterland "{" {
2565c51f124SMoriah Waterland 	if (status.in_function == 1)
2575c51f124SMoriah Waterland 		braces++;
2585c51f124SMoriah Waterland }
2595c51f124SMoriah Waterland 
2605c51f124SMoriah Waterland "}" {
2615c51f124SMoriah Waterland 	if (status.in_function == 1) {
2625c51f124SMoriah Waterland 		braces--;
2635c51f124SMoriah Waterland 		if (braces == 0)
2645c51f124SMoriah Waterland 			status.in_function = 0;
2655c51f124SMoriah Waterland 	}
2665c51f124SMoriah Waterland }
2675c51f124SMoriah Waterland 
2685c51f124SMoriah Waterland %{
2695c51f124SMoriah Waterland /*
2705c51f124SMoriah Waterland  * Detect for or while loop.
2715c51f124SMoriah Waterland  */
2725c51f124SMoriah Waterland %}
2735c51f124SMoriah Waterland ^for/[\t\n ]		|
27424e7a8c7SPaul Wernau ^[\t ]+for/[\t\n ]	|
2755c51f124SMoriah Waterland ^while/[\t\n ]		|
27624e7a8c7SPaul Wernau ^[\t ]+while/[\t\n ] {
2775c51f124SMoriah Waterland 	status.in_loop = 1;
2785c51f124SMoriah Waterland 	loop_depth++;
2795c51f124SMoriah Waterland 	cur_level++;
2805c51f124SMoriah Waterland 	REJECT;		/* What's in the argument is important too. */
2815c51f124SMoriah Waterland }
2825c51f124SMoriah Waterland 
2835c51f124SMoriah Waterland ^done/[\t\n ] 	|
28424e7a8c7SPaul Wernau ^[\t ]+done/[\t\n ]  {
28524e7a8c7SPaul Wernau 	if (status.in_loop == 1) {
2865c51f124SMoriah Waterland 		loop_depth--;
2875c51f124SMoriah Waterland 		cur_level--;
2885c51f124SMoriah Waterland 		if (loop_depth == 0)
2895c51f124SMoriah Waterland 			status.in_loop = 0;
29024e7a8c7SPaul Wernau 	}
2915c51f124SMoriah Waterland }
2925c51f124SMoriah Waterland 
2935c51f124SMoriah Waterland %{
2945c51f124SMoriah Waterland /*
2955c51f124SMoriah Waterland  * Detect case.
2965c51f124SMoriah Waterland  */
2975c51f124SMoriah Waterland %}
2985c51f124SMoriah Waterland ^case/[\t\n ]	|
29924e7a8c7SPaul Wernau ^[\t ]+case/[\t\n ] {
3005c51f124SMoriah Waterland 	status.in_case = 1;
3015c51f124SMoriah Waterland 	case_depth++;
3025c51f124SMoriah Waterland 	cur_level++;
3035c51f124SMoriah Waterland 	REJECT;		/* What's in the argument is important too. */
3045c51f124SMoriah Waterland }
3055c51f124SMoriah Waterland 
3065c51f124SMoriah Waterland ^esac/[\t\n ] 	|
30724e7a8c7SPaul Wernau ^[\t ]+esac/[\t\n ] {
30824e7a8c7SPaul Wernau 	if (status.in_case == 1) {
3095c51f124SMoriah Waterland 		case_depth--;
3105c51f124SMoriah Waterland 		cur_level--;
3115c51f124SMoriah Waterland 		if (case_depth == 0)
3125c51f124SMoriah Waterland 			status.in_case = 0;
31324e7a8c7SPaul Wernau 	}
3145c51f124SMoriah Waterland }
3155c51f124SMoriah Waterland 
3165c51f124SMoriah Waterland %{
3175c51f124SMoriah Waterland /*
3185c51f124SMoriah Waterland  * Detect if.
3195c51f124SMoriah Waterland  */
3205c51f124SMoriah Waterland %}
3215c51f124SMoriah Waterland ^if" "*"["	|
32224e7a8c7SPaul Wernau ^[\t ]+if" "*"[" {
3235c51f124SMoriah Waterland 	status.in_if = 1;
3245c51f124SMoriah Waterland 	if_depth++;
3255c51f124SMoriah Waterland 	cur_level++;
3265c51f124SMoriah Waterland 	REJECT;		/* What's in the argument is important too. */
3275c51f124SMoriah Waterland }
3285c51f124SMoriah Waterland 
3295c51f124SMoriah Waterland ^fi/[\t\n ]	|
33024e7a8c7SPaul Wernau ^[\t ]+fi/[\t\n ]  {
33124e7a8c7SPaul Wernau 	if (status.in_if == 1) {
3325c51f124SMoriah Waterland 		if_depth--;
3335c51f124SMoriah Waterland 		cur_level--;
3345c51f124SMoriah Waterland 		if (if_depth == 0)
3355c51f124SMoriah Waterland 			status.in_if = 0;
33624e7a8c7SPaul Wernau 	}
3375c51f124SMoriah Waterland }
3385c51f124SMoriah Waterland 
3395c51f124SMoriah Waterland %{
3405c51f124SMoriah Waterland /*
3415c51f124SMoriah Waterland  * Detect awk or nawk function. If the function is enclosed in "`"s
3425c51f124SMoriah Waterland  * the entire line will be grabbed., so we check for that possibility.
3435c51f124SMoriah Waterland  */
3445c51f124SMoriah Waterland %}
3455c51f124SMoriah Waterland ^n?awk[^\n^']*\' 	|
34624e7a8c7SPaul Wernau [\t \\\(\/]n?awk[^\n^']*\'	{status.in_awk = 1;
34724e7a8c7SPaul Wernau #ifdef VERBOSE
34824e7a8c7SPaul Wernau 	printf("open awk statment, line %d\n", line_no);
34924e7a8c7SPaul Wernau #endif
35024e7a8c7SPaul Wernau }
3515c51f124SMoriah Waterland 
3525c51f124SMoriah Waterland 
3535c51f124SMoriah Waterland \' {
35424e7a8c7SPaul Wernau 	if (status.in_awk == 1) {
35524e7a8c7SPaul Wernau #ifdef VERBOSE
35624e7a8c7SPaul Wernau 		printf("close awk statement, line %d\n", line_no);
35724e7a8c7SPaul Wernau #endif
3585c51f124SMoriah Waterland 		status.in_awk = 0;
35924e7a8c7SPaul Wernau 	}
3605c51f124SMoriah Waterland }
3615c51f124SMoriah Waterland 
3625c51f124SMoriah Waterland %{
3635c51f124SMoriah Waterland /* Detect pipe target. */
3645c51f124SMoriah Waterland %}
3655c51f124SMoriah Waterland [\$A-Za-z]	{
36624e7a8c7SPaul Wernau 	if (status.in_pipe == 1 && pipe_release == cur_level) {
3675c51f124SMoriah Waterland 		status.in_pipe = 0;	/* target located */
3685c51f124SMoriah Waterland 		pipe_release = 0;
36924e7a8c7SPaul Wernau #ifdef VERBOSE
37024e7a8c7SPaul Wernau 		printf("end pipe, line %d\n", line_no);
37124e7a8c7SPaul Wernau #endif
3725c51f124SMoriah Waterland 		status.allow_int = 1;	/* this isn't really interactive. */
3735c51f124SMoriah Waterland 		REJECT;	/* put it back */
3745c51f124SMoriah Waterland 	}
3755c51f124SMoriah Waterland }
3765c51f124SMoriah Waterland 
3775c51f124SMoriah Waterland %{
3785c51f124SMoriah Waterland /* If it's a pipe, note that and continue. */
3795c51f124SMoriah Waterland %}
3805c51f124SMoriah Waterland "||"		|
3815c51f124SMoriah Waterland "|"		{
3825c51f124SMoriah Waterland 	if (status.in_pipe == 0) {
3835c51f124SMoriah Waterland 		status.in_pipe = 1;
38424e7a8c7SPaul Wernau #ifdef VERBOSE
38524e7a8c7SPaul Wernau 		printf("start pipe, line %d\n", line_no);
38624e7a8c7SPaul Wernau #endif
3875c51f124SMoriah Waterland 		pipe_release = cur_level;
3885c51f124SMoriah Waterland 	}
3895c51f124SMoriah Waterland }
3905c51f124SMoriah Waterland 
3915c51f124SMoriah Waterland %{
3925c51f124SMoriah Waterland /*
3935c51f124SMoriah Waterland  * Test input for admin-type telltale interactive functions. Definite's
3945c51f124SMoriah Waterland  * first, maybe's next.
3955c51f124SMoriah Waterland  */
3965c51f124SMoriah Waterland %}
3975c51f124SMoriah Waterland ^ckdate/[\t\n ]		|
3985c51f124SMoriah Waterland [\t \/]ckdate/[\t\n ]	|
3995c51f124SMoriah Waterland ^ckint/[\t\n ]		|
4005c51f124SMoriah Waterland [\t \/]ckint/[\t\n ]	|
4015c51f124SMoriah Waterland ^ckrange/[\t\n ]	|
4025c51f124SMoriah Waterland [\t \/]ckrange/[\t\n ]	|
4035c51f124SMoriah Waterland ^cktime/[\t\n ]		|
4045c51f124SMoriah Waterland [\t \/]cktime/[\t\n ]	|
4055c51f124SMoriah Waterland ^ckyorn/[\t\n ]		|
4065c51f124SMoriah Waterland [\t \/]ckyorn/[\t\n ]	|
4075c51f124SMoriah Waterland ^ckgid/[\t\n ]		|
4085c51f124SMoriah Waterland [\t \/]ckgid/[\t\n ]	|
4095c51f124SMoriah Waterland ^ckpath/[\t\n ]		|
4105c51f124SMoriah Waterland [\t \/]ckpath/[\t\n ]	|
4115c51f124SMoriah Waterland ^ckstr/[\t\n ]		|
4125c51f124SMoriah Waterland [\t \/]ckstr/[\t\n ]	|
4135c51f124SMoriah Waterland ^ckuid/[\t\n ]		|
4145c51f124SMoriah Waterland [\t \/]ckuid/[\t\n ]		{
4155c51f124SMoriah Waterland 	if (status.in_pipe == 1 || status.allow_int == 1)
4165c51f124SMoriah Waterland 		return (INITVAL);
4175c51f124SMoriah Waterland 	else
4185c51f124SMoriah Waterland 		return (INTERACT_M);	/* maybe should be _D */
4195c51f124SMoriah Waterland }
4205c51f124SMoriah Waterland 
4215c51f124SMoriah Waterland ^read/[\t\n ]		|
4225c51f124SMoriah Waterland [\t ]read/[\t\n ]	|
4235c51f124SMoriah Waterland "=[ ]+&<"[\t ]	{
4245c51f124SMoriah Waterland 	if (status.in_pipe == 1 || status.allow_int == 1)
4255c51f124SMoriah Waterland 		return (INITVAL);
4265c51f124SMoriah Waterland 	else
4275c51f124SMoriah Waterland 		return (INTERACT_M);
4285c51f124SMoriah Waterland }
4295c51f124SMoriah Waterland 
4305c51f124SMoriah Waterland %{
4315c51f124SMoriah Waterland /* Scan for root authority commands. Definite's first, maybe's next. */
4325c51f124SMoriah Waterland %}
4335c51f124SMoriah Waterland ^mkdir/[\t\n ]		|
4345c51f124SMoriah Waterland [\t \/]mkdir/[\t\n ]	|
4355c51f124SMoriah Waterland ^mv/[\t\n ]		|
4365c51f124SMoriah Waterland [\t \/]mv/[\t\n ]	|
4375c51f124SMoriah Waterland ^cpio/[\t\n ]		|
4385c51f124SMoriah Waterland [\t \/]cpio/[\t\n ]	|
4395c51f124SMoriah Waterland ^tar/[\t\n ]		|
4405c51f124SMoriah Waterland [\t \/]tar/[\t\n ]	|
4415c51f124SMoriah Waterland ^(un)?compress/[\t\n ]	|
4425c51f124SMoriah Waterland [\t \/](un)?compress/[\t\n ]	|
4435c51f124SMoriah Waterland ^rmdir/[\t\n ]		|
4445c51f124SMoriah Waterland [\t \/]rmdir/[\t\n ]	return (ROOT_D);
4455c51f124SMoriah Waterland 
4465c51f124SMoriah Waterland ^r?cp(dir)?/[\t\n ]	|
4475c51f124SMoriah Waterland [\t \/]r?cp(dir)?/[\t\n ]	|
4485c51f124SMoriah Waterland ^rm/[\t\n ]	|
4495c51f124SMoriah Waterland [\t \/]rm/[\t\n ]	|
4505c51f124SMoriah Waterland \>[ \t]*[\$\/a-zA-Z0-9]	return (ROOT_M);
4515c51f124SMoriah Waterland 
4525c51f124SMoriah Waterland %{
4535c51f124SMoriah Waterland /* These root commands may also be locked. */
4545c51f124SMoriah Waterland 
4555c51f124SMoriah Waterland /* Here we analyze any pkgchk calls. If it's "pkgchk ... -f ..." then that calls for root authority. We then check for a "-R" argument. */
4565c51f124SMoriah Waterland %}
4575c51f124SMoriah Waterland ^pkgchk[^\n^|^>^;]*"-f"	|
4585c51f124SMoriah Waterland [\t \/]pkgchk[^\n^|^>^;]*"-f"	{
4595c51f124SMoriah Waterland 	status.pkgchk_f = 1;
4605c51f124SMoriah Waterland 	REJECT;		/* We need the intermediate args. */
4615c51f124SMoriah Waterland }
4625c51f124SMoriah Waterland 
4635c51f124SMoriah Waterland %{
4645c51f124SMoriah Waterland /* If it's "pkgchk ... -R ..." then the local package database is not being tested and no database warning is necessary. */
4655c51f124SMoriah Waterland %}
4665c51f124SMoriah Waterland ^pkgchk[^\n^|^>^;]*"-R"[ \t][\/\$]/[^ ^\t^\n]		|
4675c51f124SMoriah Waterland [\t \/]pkgchk[^\n^|^>^;]*"-R"[ \t][\/\$]/[^ ^\t^\n]  {
4685c51f124SMoriah Waterland 	if (status.pkgchk_f)
4695c51f124SMoriah Waterland 		return (ROOT_D);
4705c51f124SMoriah Waterland 	else
4715c51f124SMoriah Waterland 		return (INITVAL);
4725c51f124SMoriah Waterland }
4735c51f124SMoriah Waterland 
4745c51f124SMoriah Waterland %{
4755c51f124SMoriah Waterland /* If it's just "pkgchk ..." then we need to mention something about access to the package database. With Solaris 2.5, an improved locking mechanism is in place, so this message may be something we can drop later. */
4765c51f124SMoriah Waterland %}
4775c51f124SMoriah Waterland ^pkgchk/[\t\n ]		|
4785c51f124SMoriah Waterland [\t \/]pkgchk/[\t\n ]  {
4795c51f124SMoriah Waterland 	if (status.pkgchk_f) {
4805c51f124SMoriah Waterland 		status.pkgchk_f = 0;
4815c51f124SMoriah Waterland 		return (ROOT_D | PKGDB_M);
4825c51f124SMoriah Waterland 	} else
4835c51f124SMoriah Waterland 		return (PKGDB_M);
4845c51f124SMoriah Waterland }
4855c51f124SMoriah Waterland 
4865c51f124SMoriah Waterland %{
4875c51f124SMoriah Waterland /* The installf and removef utilities require root authority, they modify the package database and they must be invoked at least once with a "-f" argument. */
4885c51f124SMoriah Waterland 
4895c51f124SMoriah Waterland /* First test for a "-f" argument. */
4905c51f124SMoriah Waterland %}
4915c51f124SMoriah Waterland ^installf[^\n^|^>^;]*"-f"	|
4925c51f124SMoriah Waterland [\t \/]installf[^\n^|^>^;]*"-f"	{
4935c51f124SMoriah Waterland 	status.instf_f = 1;
4945c51f124SMoriah Waterland 
4955c51f124SMoriah Waterland 	REJECT;		/* The whole line needs to be re-reviewed. */
4965c51f124SMoriah Waterland }
4975c51f124SMoriah Waterland 
4985c51f124SMoriah Waterland ^removef[^\n^|^>^;]*"-f"	|
4995c51f124SMoriah Waterland [\t \/]removef[^\n^|^>^;]*"-f"	{
5005c51f124SMoriah Waterland 	status.remf_f = 1;
5015c51f124SMoriah Waterland 
5025c51f124SMoriah Waterland 	REJECT;		/* The whole line needs to be re-reviewed. */
5035c51f124SMoriah Waterland }
5045c51f124SMoriah Waterland 
5055c51f124SMoriah Waterland ^installf/[\t\n ]	|
5065c51f124SMoriah Waterland [\t \/]installf/[\t\n ]	{
5075c51f124SMoriah Waterland 	status.instf = 1;
5085c51f124SMoriah Waterland 	status.needspacefile = 1;
5095c51f124SMoriah Waterland 
5105c51f124SMoriah Waterland 	root_level = ROOT_D;
5115c51f124SMoriah Waterland 	lock_level = LOCKED_M;
5125c51f124SMoriah Waterland 
5135c51f124SMoriah Waterland 	BEGIN WHROOT;
5145c51f124SMoriah Waterland }
5155c51f124SMoriah Waterland 
5165c51f124SMoriah Waterland ^removef/[\t\n ]	|
5175c51f124SMoriah Waterland [\t \/]removef/[\t\n ]	{
5185c51f124SMoriah Waterland 	status.remf = 1;
5195c51f124SMoriah Waterland 
5205c51f124SMoriah Waterland 	root_level = ROOT_D;
5215c51f124SMoriah Waterland 	lock_level = LOCKED_M;
5225c51f124SMoriah Waterland 	BEGIN WHROOT;
5235c51f124SMoriah Waterland }
5245c51f124SMoriah Waterland 
5255c51f124SMoriah Waterland %{
5265c51f124SMoriah Waterland /* There's no question that use of a pkgadd or pkgrm in a script is bound to cause problems unless it is to a different root. */
5275c51f124SMoriah Waterland %}
5285c51f124SMoriah Waterland ^pkgadd/[\t\n ]	|
5295c51f124SMoriah Waterland [\t \/]pkgadd/[\t\n ]	|
5305c51f124SMoriah Waterland ^pkgrm/[\t\n ]		|
5315c51f124SMoriah Waterland [\t \/]pkgrm/[\t\n ] {
5325c51f124SMoriah Waterland 	root_level = ROOT_D;
5335c51f124SMoriah Waterland 	lock_level = LOCKED_D;
5345c51f124SMoriah Waterland 	BEGIN WHROOT;
5355c51f124SMoriah Waterland }
5365c51f124SMoriah Waterland 
5375c51f124SMoriah Waterland %{
5385c51f124SMoriah Waterland /* The only way to get here is if we are in the middle of a pkg command. */
5395c51f124SMoriah Waterland %}
5405c51f124SMoriah Waterland <WHROOT>. {
5415c51f124SMoriah Waterland 	if (status.pkg_rtn_done) {
5425c51f124SMoriah Waterland 		status.pkg_rtn_done = 0;
5435c51f124SMoriah Waterland 		BEGIN 0;
5445c51f124SMoriah Waterland 	} else
5455c51f124SMoriah Waterland 		REJECT;
5465c51f124SMoriah Waterland }
5475c51f124SMoriah Waterland <WHROOT>[ \t]+"-R"[ \t][\/\$]/[^ ^\t^\n] {
5485c51f124SMoriah Waterland 	status.pkg_rtn_done = 1;
5495c51f124SMoriah Waterland 	return (root_level);		/* "-R" means locking is unlikely. */
5505c51f124SMoriah Waterland }
5515c51f124SMoriah Waterland <WHROOT>[\n]		{
5525c51f124SMoriah Waterland 	if (status.pkg_rtn_done) {
5535c51f124SMoriah Waterland 		status.pkg_rtn_done = 0;
5545c51f124SMoriah Waterland 		line_no++;
5555c51f124SMoriah Waterland 		BEGIN 0;
5565c51f124SMoriah Waterland 	} else {
5575c51f124SMoriah Waterland 		status.pkg_rtn_done = 1;
5585c51f124SMoriah Waterland 		unput('\n');
5595c51f124SMoriah Waterland 		return (root_level | lock_level); /* No "-R". */
5605c51f124SMoriah Waterland 	}
5615c51f124SMoriah Waterland }
5625c51f124SMoriah Waterland <WHROOT>[;|>]		{
5635c51f124SMoriah Waterland 	status.pkg_rtn_done = 1;
5645c51f124SMoriah Waterland 	return (root_level | lock_level); /* End of command without a "-R". */
5655c51f124SMoriah Waterland }
5665c51f124SMoriah Waterland 
56724e7a8c7SPaul Wernau \n	{ line_no++; status.allow_int = 0;
56824e7a8c7SPaul Wernau #ifdef VERBOSE
56924e7a8c7SPaul Wernau 	printf("allow_int = 0\n");
57024e7a8c7SPaul Wernau #endif
57124e7a8c7SPaul Wernau }
57224e7a8c7SPaul Wernau 
57324e7a8c7SPaul Wernau .	{
57424e7a8c7SPaul Wernau 	/*
57524e7a8c7SPaul Wernau 	XXX - bug - resets prematurely if we pipe into a while loop or
57624e7a8c7SPaul Wernau 	other such construct
57724e7a8c7SPaul Wernau 	status.allow_int = 0;
57824e7a8c7SPaul Wernau 	*/
57924e7a8c7SPaul Wernau }
58024e7a8c7SPaul Wernau 
5815c51f124SMoriah Waterland %%
5825c51f124SMoriah Waterland #include <stdio.h>
5835c51f124SMoriah Waterland #include <limits.h>
5845c51f124SMoriah Waterland #include <dirent.h>
5855c51f124SMoriah Waterland #include <unistd.h>
5865c51f124SMoriah Waterland #include <libintl.h>
5875c51f124SMoriah Waterland 
5885c51f124SMoriah Waterland #ifdef DEBUG
5895c51f124SMoriah Waterland /*
5905c51f124SMoriah Waterland  * Since this is a lex specification twice removed from the binary,
5915c51f124SMoriah Waterland  * I strongly recommend leaving the DEBUG portions in place. When new
5925c51f124SMoriah Waterland  * keywords are added, this will be very important. After modifying
5935c51f124SMoriah Waterland  * the specification, create an executable to test in this way.
5945c51f124SMoriah Waterland  *
5955c51f124SMoriah Waterland  *	lex scriptvfy.l
5965c51f124SMoriah Waterland  *	cc -o scriptvfy -g lex.yy.c $ROOT/usr/lib/libpkg.a \
5975c51f124SMoriah Waterland  *	    -DDEBUG [-DVERBOSE] -ll -lintl
5985c51f124SMoriah Waterland  *	scriptvfy test_directory
5995c51f124SMoriah Waterland  */
6005c51f124SMoriah Waterland 
6015c51f124SMoriah Waterland main(int argc, char *argv[])
6025c51f124SMoriah Waterland {
6035c51f124SMoriah Waterland 	int val;
6045c51f124SMoriah Waterland 
6055c51f124SMoriah Waterland 	line_no = 1;
6065c51f124SMoriah Waterland 
6075c51f124SMoriah Waterland 	if (argc == 1) {
6085c51f124SMoriah Waterland 		printf("No directory provided.\n");
6095c51f124SMoriah Waterland 		exit(1);
6105c51f124SMoriah Waterland 	}
6115c51f124SMoriah Waterland 
6125c51f124SMoriah Waterland 	val = checkscripts(argv[1], 0);
6135c51f124SMoriah Waterland 
6145c51f124SMoriah Waterland 	printf("return code is %d\n", val);
6155c51f124SMoriah Waterland }
6165c51f124SMoriah Waterland #endif
6175c51f124SMoriah Waterland 
6185c51f124SMoriah Waterland /*
6195c51f124SMoriah Waterland  * This function evaluates the provided script and returns a bit string
6205c51f124SMoriah Waterland  * describing what patterns were located.
6215c51f124SMoriah Waterland  */
6225c51f124SMoriah Waterland static int
6235c51f124SMoriah Waterland scripteval(char *script_name, char *script_path, int mask, int silent)
6245c51f124SMoriah Waterland {
6255c51f124SMoriah Waterland 	int val = 0;
6265c51f124SMoriah Waterland 	int error = 0;
6275c51f124SMoriah Waterland 	line_no = 1;
6285c51f124SMoriah Waterland 
629*c57b7750SToomas Soome 	if ((script_path == NULL) || (*script_path == '\0') ||
6305c51f124SMoriah Waterland 	    (script_name == NULL)) {
6315c51f124SMoriah Waterland 		logerr(gettext(ERR_ARGS));
6325c51f124SMoriah Waterland 		return (0);
6335c51f124SMoriah Waterland 	}
6345c51f124SMoriah Waterland 
6355c51f124SMoriah Waterland #ifdef VERBOSE
6365c51f124SMoriah Waterland 	printf("Evaluating %s\n", script_path);
6375c51f124SMoriah Waterland #endif
6385c51f124SMoriah Waterland 
6395c51f124SMoriah Waterland 	if ((scr_fp = fopen(script_path, "r")) == NULL) {
6405c51f124SMoriah Waterland 		logerr(gettext(ERR_FOPEN), script_path, errno);
6415c51f124SMoriah Waterland 		return (0);
6425c51f124SMoriah Waterland 	}
6435c51f124SMoriah Waterland 
6445c51f124SMoriah Waterland #ifdef VERBOSE
64524e7a8c7SPaul Wernau 	printf("Opened script\n");
6465c51f124SMoriah Waterland #endif
6475c51f124SMoriah Waterland 
6485c51f124SMoriah Waterland 	while (val = yylex()) {
6495c51f124SMoriah Waterland #ifdef VERBOSE
6505c51f124SMoriah Waterland 		printf("  Match is %s, returned 0x%x at line %d\n",
6515c51f124SMoriah Waterland 		    yytext, val, line_no);
6525c51f124SMoriah Waterland 		printf("    in_function = %d, in_awk = %d, in_loop = %d, " \
6535c51f124SMoriah Waterland 		    "in_case = %d, in_if = %d, in_pipe = %d\n",
6545c51f124SMoriah Waterland 		    status.in_function, status.in_awk, status.in_loop,
6555c51f124SMoriah Waterland 		    status.in_case, status.in_if, status.in_pipe);
6565c51f124SMoriah Waterland 		printf("    loop_depth = %d, case_depth = %d, " \
6575c51f124SMoriah Waterland 		    "if_depth = %d, pipe_release = %d, cur_level = %d\n",
6585c51f124SMoriah Waterland 		    loop_depth, case_depth, if_depth, pipe_release, cur_level);
6595c51f124SMoriah Waterland #endif
6605c51f124SMoriah Waterland 
6615c51f124SMoriah Waterland 		val &= mask;
6625c51f124SMoriah Waterland 		if (val) {
6635c51f124SMoriah Waterland 			error |= ((val & MAYBE_ONLY) ? 1 : 2);
6645c51f124SMoriah Waterland 
6655c51f124SMoriah Waterland 			/*
6665c51f124SMoriah Waterland 			 * So at this point, val contains all status bits
6675c51f124SMoriah Waterland 			 * appropriate to this script.
6685c51f124SMoriah Waterland 			 */
6695c51f124SMoriah Waterland 			if (!silent) {
6705c51f124SMoriah Waterland 				char *msg_ptr;
6715c51f124SMoriah Waterland 				if (val & INTERACT_D)
6725c51f124SMoriah Waterland 					msg_ptr = gettext(ERR_INTERACT);
6735c51f124SMoriah Waterland 				else if (val & ROOT_D)
6745c51f124SMoriah Waterland 					msg_ptr = gettext(ERR_ROOT);
6755c51f124SMoriah Waterland 				else if (val & LOCKED_D)
6765c51f124SMoriah Waterland 					msg_ptr = gettext(ERR_LOCKED);
6775c51f124SMoriah Waterland 				else if (val & INTERACT_M)
6785c51f124SMoriah Waterland 					msg_ptr = gettext(WRN_INTERACT);
6795c51f124SMoriah Waterland 				else if (val & ROOT_M)
6805c51f124SMoriah Waterland 					msg_ptr = gettext(WRN_ROOT);
6815c51f124SMoriah Waterland 				else if (val & LOCKED_M)
6825c51f124SMoriah Waterland 					msg_ptr = gettext(WRN_LOCKED);
6835c51f124SMoriah Waterland 				else if (val & WPARM1_M)
6845c51f124SMoriah Waterland 					msg_ptr = gettext(WRN_FORM_USE);
6855c51f124SMoriah Waterland 				else if (val & USEPARM1_M)
6865c51f124SMoriah Waterland 					msg_ptr = gettext(WRN_FORM_USE);
6875c51f124SMoriah Waterland 				else if (val &  ODDPARM_M)
6885c51f124SMoriah Waterland 					msg_ptr = gettext(WRN_FORM_ARG);
6895c51f124SMoriah Waterland 				else if (val &  PKGDB_M)
6905c51f124SMoriah Waterland 					msg_ptr = gettext(WRN_TRANSDB);
6915c51f124SMoriah Waterland 				else
6925c51f124SMoriah Waterland 					msg_ptr = gettext("unknown error");
6935c51f124SMoriah Waterland 
6945c51f124SMoriah Waterland 				logerr(msg_ptr, script_name, line_no);
6955c51f124SMoriah Waterland 			}
6965c51f124SMoriah Waterland 		}
6975c51f124SMoriah Waterland 	}
6985c51f124SMoriah Waterland 
6995c51f124SMoriah Waterland 	/* Warn if required about missing "-f" calls. */
7005c51f124SMoriah Waterland 	if (status.instf && !(status.instf_f))
7015c51f124SMoriah Waterland 		logerr(gettext(WRN_INST_F), script_name);
7025c51f124SMoriah Waterland 
7035c51f124SMoriah Waterland 	if (status.remf && !(status.remf_f))
7045c51f124SMoriah Waterland 		logerr(gettext(WRN_REM_F), script_name);
7055c51f124SMoriah Waterland 
7065c51f124SMoriah Waterland 	status.instf = status.instf_f = status.remf = status.remf_f = 0;
7075c51f124SMoriah Waterland 
7085c51f124SMoriah Waterland 	/* Warn if installf was used but no space file is in place. */
7095c51f124SMoriah Waterland 	if (status.nospacefile && status.needspacefile) {
7105c51f124SMoriah Waterland 		logerr(gettext(WRN_SPACEACC), script_name);
7115c51f124SMoriah Waterland 		status.needspacefile = 0;
7125c51f124SMoriah Waterland 	}
7135c51f124SMoriah Waterland 
7145c51f124SMoriah Waterland 	status.in_pipe = 0;	/* Pipes may dangle. */
7155c51f124SMoriah Waterland 	fclose(scr_fp);
7165c51f124SMoriah Waterland 
7175c51f124SMoriah Waterland 	if (error == 3)
7185c51f124SMoriah Waterland 		error = 2;
7195c51f124SMoriah Waterland 
7205c51f124SMoriah Waterland 	return (error);
7215c51f124SMoriah Waterland }
7225c51f124SMoriah Waterland 
7235c51f124SMoriah Waterland /* Test a preinstall or preremove script for validity. */
7245c51f124SMoriah Waterland int
7255c51f124SMoriah Waterland pre_valid(char *script_name, char *script_path, int silent)
7265c51f124SMoriah Waterland {
7275c51f124SMoriah Waterland 	return (scripteval(script_name, script_path, PRE_MASK, silent));
7285c51f124SMoriah Waterland }
7295c51f124SMoriah Waterland 
7305c51f124SMoriah Waterland /* Test a class action script for validity. */
7315c51f124SMoriah Waterland int
7325c51f124SMoriah Waterland cas_valid(char *script_name, char *script_path, int silent)
7335c51f124SMoriah Waterland {
7345c51f124SMoriah Waterland 	return (scripteval(script_name, script_path, CAS_MASK, silent));
7355c51f124SMoriah Waterland }
7365c51f124SMoriah Waterland 
7375c51f124SMoriah Waterland /* Test a postinstall or postremove script for validity. */
7385c51f124SMoriah Waterland int
7395c51f124SMoriah Waterland post_valid(char *script_name, char *script_path, int silent)
7405c51f124SMoriah Waterland {
7415c51f124SMoriah Waterland 	return (scripteval(script_name, script_path, POST_MASK, silent));
7425c51f124SMoriah Waterland }
7435c51f124SMoriah Waterland 
7445c51f124SMoriah Waterland /* Test a class action script for validity. */
7455c51f124SMoriah Waterland int
7465c51f124SMoriah Waterland req_valid(char *script_name, char *script_path, int silent)
7475c51f124SMoriah Waterland {
7485c51f124SMoriah Waterland 	return (scripteval(script_name, script_path, REQ_MASK, silent));
7495c51f124SMoriah Waterland }
7505c51f124SMoriah Waterland 
7515c51f124SMoriah Waterland 
7525c51f124SMoriah Waterland /* Test a class action script for validity. */
7535c51f124SMoriah Waterland int
7545c51f124SMoriah Waterland chk_valid(char *script_name, char *script_path, int silent)
7555c51f124SMoriah Waterland {
7565c51f124SMoriah Waterland 	return (scripteval(script_name, script_path, CHK_MASK, silent));
7575c51f124SMoriah Waterland }
7585c51f124SMoriah Waterland 
7595c51f124SMoriah Waterland /* This tests all of the scripts in the provided directory. */
7605c51f124SMoriah Waterland int
7615c51f124SMoriah Waterland checkscripts(char *inst_dir, int silent)
7625c51f124SMoriah Waterland {
7635c51f124SMoriah Waterland 	DIR *dirfp;
7645c51f124SMoriah Waterland 	struct dirent *dp;
7655c51f124SMoriah Waterland 	char path[PATH_MAX];
7665c51f124SMoriah Waterland 	int retval = 0;
7675c51f124SMoriah Waterland 
7685c51f124SMoriah Waterland 	/* For future reference, determine if a space file is present. */
7695c51f124SMoriah Waterland 	sprintf(path, "%s/%s", inst_dir, "space");
7705c51f124SMoriah Waterland 	if (access(path, F_OK) != 0)
7715c51f124SMoriah Waterland 		status.nospacefile = 1;
7725c51f124SMoriah Waterland 
7735c51f124SMoriah Waterland 	if ((dirfp = opendir(inst_dir)) == NULL)
7745c51f124SMoriah Waterland 		return (0);
7755c51f124SMoriah Waterland 
7765c51f124SMoriah Waterland 	while ((dp = readdir(dirfp)) != NULL) {
7775c51f124SMoriah Waterland #ifdef VERBOSE
7785c51f124SMoriah Waterland 		printf("Looking at file %s\n", dp->d_name);
7795c51f124SMoriah Waterland #endif
78024e7a8c7SPaul Wernau #ifdef BUG_DEBUG
78124e7a8c7SPaul Wernau 		if ((status.in_function != 0)
78224e7a8c7SPaul Wernau 		    || (status.in_pipe != 0)
78324e7a8c7SPaul Wernau 		    || (status.in_loop != 0)
78424e7a8c7SPaul Wernau 		    || (status.in_case != 0)
78524e7a8c7SPaul Wernau 		    || (status.in_if != 0)
78624e7a8c7SPaul Wernau 		    || (status.in_awk != 0)
78724e7a8c7SPaul Wernau 		    || (pipe_release != 0)
78824e7a8c7SPaul Wernau 		    || (loop_depth != 0)
78924e7a8c7SPaul Wernau 		    || (case_depth != 0)
79024e7a8c7SPaul Wernau 		    || (if_depth != 0)
79124e7a8c7SPaul Wernau 		    || (cur_level != 0)
79224e7a8c7SPaul Wernau 		    || (braces != 0)) {
79324e7a8c7SPaul Wernau 			printf("    in_function = %d, in_awk = %d, "
79424e7a8c7SPaul Wernau 			    "in_loop = %d, in_case = %d, in_if = %d, "
79524e7a8c7SPaul Wernau 			    "in_pipe = %d\n",
79624e7a8c7SPaul Wernau 			    status.in_function, status.in_awk, status.in_loop,
79724e7a8c7SPaul Wernau 			    status.in_case, status.in_if, status.in_pipe);
79824e7a8c7SPaul Wernau 			printf("    loop_depth = %d, case_depth = %d, "
79924e7a8c7SPaul Wernau 			    "if_depth = %d, pipe_release = %d, "
80024e7a8c7SPaul Wernau 			    "cur_level = %d\n",
80124e7a8c7SPaul Wernau 			    loop_depth, case_depth, if_depth, pipe_release,
80224e7a8c7SPaul Wernau 			    cur_level);
80324e7a8c7SPaul Wernau 			printf("ERROR: found a bug: variable still open\n");
80424e7a8c7SPaul Wernau 			return (0);
80524e7a8c7SPaul Wernau 		} else {
80624e7a8c7SPaul Wernau 			printf("SUCCESS: All variables reset.\n");
80724e7a8c7SPaul Wernau 		}
80824e7a8c7SPaul Wernau #endif
80924e7a8c7SPaul Wernau 		/* Reset all variables before processing the next file */
81024e7a8c7SPaul Wernau 		status.in_function = status.in_pipe = status.in_loop =
81124e7a8c7SPaul Wernau 		    status.in_case = status.in_if = status.in_awk = 0;
81224e7a8c7SPaul Wernau 		pipe_release = loop_depth = case_depth = if_depth =
81324e7a8c7SPaul Wernau 		    cur_level = braces = 0;
81424e7a8c7SPaul Wernau 
8155c51f124SMoriah Waterland 		if (dp->d_name[0] == '.')
8165c51f124SMoriah Waterland 			continue;
8175c51f124SMoriah Waterland 
8185c51f124SMoriah Waterland 		if ((strcmp(dp->d_name, "preinstall") == 0) ||
8195c51f124SMoriah Waterland 		    (strcmp(dp->d_name, "preremove") == 0)) {
8205c51f124SMoriah Waterland 			sprintf(path, "%s/%s", inst_dir, dp->d_name);
8215c51f124SMoriah Waterland 			retval |= pre_valid(dp->d_name, path, silent);
8225c51f124SMoriah Waterland 			continue;
8235c51f124SMoriah Waterland 		}
8245c51f124SMoriah Waterland 
8255c51f124SMoriah Waterland 		if ((strncmp(dp->d_name, "i.", 2) == 0) ||
8265c51f124SMoriah Waterland 		    (strncmp(dp->d_name, "r.", 2) == 0)) {
8275c51f124SMoriah Waterland 			sprintf(path, "%s/%s", inst_dir, dp->d_name);
8285c51f124SMoriah Waterland 			retval |= cas_valid(dp->d_name, path, silent);
8295c51f124SMoriah Waterland 			continue;
8305c51f124SMoriah Waterland 		}
8315c51f124SMoriah Waterland 
8325c51f124SMoriah Waterland 		if ((strcmp(dp->d_name, "postinstall") == 0) ||
8335c51f124SMoriah Waterland 		    (strcmp(dp->d_name, "postremove") == 0)) {
8345c51f124SMoriah Waterland 			sprintf(path, "%s/%s", inst_dir, dp->d_name);
8355c51f124SMoriah Waterland 			retval |= post_valid(dp->d_name, path, silent);
8365c51f124SMoriah Waterland 			continue;
8375c51f124SMoriah Waterland 		}
8385c51f124SMoriah Waterland 
8395c51f124SMoriah Waterland 		if (strcmp(dp->d_name, "request") == 0) {
8405c51f124SMoriah Waterland 			sprintf(path, "%s/%s", inst_dir, dp->d_name);
8415c51f124SMoriah Waterland 			retval |= req_valid(dp->d_name, path, silent);
8425c51f124SMoriah Waterland 			continue;
8435c51f124SMoriah Waterland 		}
8445c51f124SMoriah Waterland 		if (strcmp(dp->d_name, "checkinstall") == 0) {
8455c51f124SMoriah Waterland 			sprintf(path, "%s/%s", inst_dir, dp->d_name);
8465c51f124SMoriah Waterland 			retval |= chk_valid(dp->d_name, path, silent);
8475c51f124SMoriah Waterland 			continue;
8485c51f124SMoriah Waterland 		}
8495c51f124SMoriah Waterland 	}
8505c51f124SMoriah Waterland 
8515c51f124SMoriah Waterland 	(void) closedir(dirfp);
8525c51f124SMoriah Waterland 
8535c51f124SMoriah Waterland 	return (retval);
8545c51f124SMoriah Waterland }
855