xref: /onnv-gate/usr/src/lib/libshell/common/sh/shcomp.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1982-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                  David Korn <dgk@research.att.com>                   *
184887Schin *                                                                      *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin  * David Korn
234887Schin  * AT&T Labs
244887Schin  *
254887Schin  * shell script to shell binary converter
264887Schin  *
274887Schin  */
284887Schin 
294887Schin static const char usage[] =
304887Schin "[-?\n@(#)$Id: shcomp (AT&T Research) 2003-03-02 $\n]"
314887Schin USAGE_LICENSE
324887Schin "[+NAME?shcomp - compile a shell script]"
334887Schin "[+DESCRIPTION?Unless \b-D\b is specified, \bshcomp\b takes a shell script, "
344887Schin 	"\ainfile\a, and creates a binary format file, \aoutfile\a, that "
354887Schin 	"\bksh\b can read and execute with the same effect as the original "
364887Schin 	"script.]"
374887Schin "[+?Since aliases are processed as the script is read, alias definitions "
384887Schin 	"whose value requires variable expansion will not work correctly.]"
39*12068SRoger.Faulkner@Oracle.COM "[+?If \b-D\b is specified, all double quoted strings that are preceded by "
404887Schin 	"\b$\b are output.  These are the messages that need to be "
414887Schin 	"translated to locale specific versions for internationalization.]"
424887Schin "[+?If \aoutfile\a is omitted, then the results will be written to "
434887Schin 	"standard output.  If \ainfile\a is also omitted, the shell script "
444887Schin 	"will be read from standard input.]"
454887Schin "[D:dictionary?Generate a list of strings that need to be placed in a message "
464887Schin 	"catalog for internationalization.]"
474887Schin "[n:noexec?Displays warning messages for obsolete or non-conforming "
484887Schin 	"constructs.] "
494887Schin "[v:verbose?Displays input from \ainfile\a onto standard error as it "
504887Schin 	"reads it.]"
514887Schin "\n"
524887Schin "\n[infile [outfile]]\n"
534887Schin "\n"
544887Schin "[+EXIT STATUS?]{"
554887Schin         "[+0?Successful completion.]"
564887Schin         "[+>0?An error occurred.]"
574887Schin "}"
584887Schin "[+SEE ALSO?\bksh\b(1)]"
594887Schin ;
604887Schin 
614887Schin #include	<shell.h>
628462SApril.Chin@Sun.COM #include	"defs.h"
634887Schin #include	"shnodes.h"
644887Schin #include	"sys/stat.h"
654887Schin 
664887Schin #define CNTL(x)	((x)&037)
674887Schin #define VERSION	3
684887Schin static const char header[6] = { CNTL('k'),CNTL('s'),CNTL('h'),0,VERSION,0 };
694887Schin 
main(int argc,char * argv[])704887Schin int main(int argc, char *argv[])
714887Schin {
724887Schin 	Sfio_t *in, *out;
734887Schin 	Shell_t	*shp;
744887Schin 	Namval_t *np;
754887Schin 	Shnode_t *t;
764887Schin 	char *cp;
774887Schin 	int n, nflag=0, vflag=0, dflag=0;
784887Schin 	error_info.id = argv[0];
794887Schin 	while(n = optget(argv, usage )) switch(n)
804887Schin 	{
814887Schin 	    case 'D':
824887Schin 		dflag=1;
834887Schin 		break;
844887Schin 	    case 'v':
854887Schin 		vflag=1;
864887Schin 		break;
874887Schin 	    case 'n':
884887Schin 		nflag=1;
894887Schin 		break;
904887Schin 	    case ':':
914887Schin 		errormsg(SH_DICT,2,"%s",opt_info.arg);
924887Schin 		break;
934887Schin 	    case '?':
944887Schin 		errormsg(SH_DICT,ERROR_usage(2),"%s",opt_info.arg);
954887Schin 		break;
964887Schin 	}
974887Schin 	shp = sh_init(argc,argv,(Shinit_f)0);
988462SApril.Chin@Sun.COM 	shp->shcomp = 1;
994887Schin 	argv += opt_info.index;
1004887Schin 	argc -= opt_info.index;
1014887Schin 	if(error_info.errors || argc>2)
1024887Schin 		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
1034887Schin 	if(cp= *argv)
1044887Schin 	{
1054887Schin 		argv++;
1064887Schin 		in = sh_pathopen(cp);
1074887Schin 	}
1084887Schin 	else
1094887Schin 		in = sfstdin;
1104887Schin 	if(cp= *argv)
1114887Schin 	{
1124887Schin 		struct stat statb;
1134887Schin 		if(!(out = sfopen((Sfio_t*)0,cp,"w")))
1144887Schin 			errormsg(SH_DICT,ERROR_system(1),"%s: cannot create",cp);
1154887Schin 		if(fstat(sffileno(out),&statb) >=0)
1164887Schin 			chmod(cp,(statb.st_mode&~S_IFMT)|S_IXUSR|S_IXGRP|S_IXOTH);
1174887Schin 	}
1184887Schin 	else
1194887Schin 		out = sfstdout;
1204887Schin 	if(dflag)
1214887Schin 	{
1224887Schin 		sh_onoption(SH_DICTIONARY);
1234887Schin 		sh_onoption(SH_NOEXEC);
1244887Schin 	}
1254887Schin 	if(nflag)
1264887Schin 		sh_onoption(SH_NOEXEC);
1274887Schin 	if(vflag)
1284887Schin 		sh_onoption(SH_VERBOSE);
1294887Schin 	if(!dflag)
1304887Schin 		sfwrite(out,header,sizeof(header));
1314887Schin 	shp->inlineno = 1;
1328462SApril.Chin@Sun.COM #if SHOPT_BRACEPAT
1338462SApril.Chin@Sun.COM         sh_onoption(SH_BRACEEXPAND);
1348462SApril.Chin@Sun.COM #endif
1354887Schin 	while(1)
1364887Schin 	{
1374887Schin 		stakset((char*)0,0);
1384887Schin 		if(t = (Shnode_t*)sh_parse(shp,in,0))
1394887Schin 		{
1408462SApril.Chin@Sun.COM 			if((t->tre.tretyp&(COMMSK|COMSCAN))==0 && t->com.comnamp && strcmp(nv_name((Namval_t*)t->com.comnamp),"alias")==0)
1414887Schin 				sh_exec(t,0);
1424887Schin 			if(!dflag && sh_tdump(out,t) < 0)
1434887Schin 				errormsg(SH_DICT,ERROR_exit(1),"dump failed");
1444887Schin 		}
1454887Schin 		else if(sfeof(in))
1464887Schin 			break;
1474887Schin 		if(sferror(in))
1484887Schin 			errormsg(SH_DICT,ERROR_system(1),"I/O error");
1494887Schin 		if(t && ((t->tre.tretyp&COMMSK)==TCOM) && (np=t->com.comnamp) && (cp=nv_name(np)))
1504887Schin 		{
1514887Schin 			if(strcmp(cp,"exit")==0)
1524887Schin 				break;
1534887Schin 			/* check for exec of a command */
1544887Schin 			if(strcmp(cp,"exec")==0)
1554887Schin 			{
1564887Schin 				if(t->com.comtyp&COMSCAN)
1574887Schin 				{
1584887Schin 					if(t->com.comarg->argnxt.ap)
1594887Schin 						break;
1604887Schin 				}
1614887Schin 				else
1624887Schin 				{
1634887Schin 					struct dolnod *ap = (struct dolnod*)t->com.comarg;
1644887Schin 					if(ap->dolnum>1)
1654887Schin 						break;
1664887Schin 				}
1674887Schin 			}
1684887Schin 		}
1694887Schin 	}
1704887Schin 	/* copy any remaining input */
1714887Schin 	sfmove(in,out,SF_UNBOUND,-1);
1724887Schin 	if(in!=sfstdin)
1734887Schin 		sfclose(in);
1744887Schin 	if(out!=sfstdout)
1754887Schin 		sfclose(out);
1764887Schin 	return(0);
1774887Schin }
178