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