1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * David Korn <dgk@research.att.com> * 18*4887Schin * * 19*4887Schin ***********************************************************************/ 20*4887Schin #pragma prototyped 21*4887Schin /* 22*4887Schin * David Korn 23*4887Schin * AT&T Labs 24*4887Schin * 25*4887Schin * shell script to shell binary converter 26*4887Schin * 27*4887Schin */ 28*4887Schin 29*4887Schin static const char usage[] = 30*4887Schin "[-?\n@(#)$Id: shcomp (AT&T Research) 2003-03-02 $\n]" 31*4887Schin USAGE_LICENSE 32*4887Schin "[+NAME?shcomp - compile a shell script]" 33*4887Schin "[+DESCRIPTION?Unless \b-D\b is specified, \bshcomp\b takes a shell script, " 34*4887Schin "\ainfile\a, and creates a binary format file, \aoutfile\a, that " 35*4887Schin "\bksh\b can read and execute with the same effect as the original " 36*4887Schin "script.]" 37*4887Schin "[+?Since aliases are processed as the script is read, alias definitions " 38*4887Schin "whose value requires variable expansion will not work correctly.]" 39*4887Schin "[+?If \b-D\b is specifed, all double quoted strings that are preceded by " 40*4887Schin "\b$\b are output. These are the messages that need to be " 41*4887Schin "translated to locale specific versions for internationalization.]" 42*4887Schin "[+?If \aoutfile\a is omitted, then the results will be written to " 43*4887Schin "standard output. If \ainfile\a is also omitted, the shell script " 44*4887Schin "will be read from standard input.]" 45*4887Schin "[D:dictionary?Generate a list of strings that need to be placed in a message " 46*4887Schin "catalog for internationalization.]" 47*4887Schin "[n:noexec?Displays warning messages for obsolete or non-conforming " 48*4887Schin "constructs.] " 49*4887Schin "[v:verbose?Displays input from \ainfile\a onto standard error as it " 50*4887Schin "reads it.]" 51*4887Schin "\n" 52*4887Schin "\n[infile [outfile]]\n" 53*4887Schin "\n" 54*4887Schin "[+EXIT STATUS?]{" 55*4887Schin "[+0?Successful completion.]" 56*4887Schin "[+>0?An error occurred.]" 57*4887Schin "}" 58*4887Schin "[+SEE ALSO?\bksh\b(1)]" 59*4887Schin ; 60*4887Schin 61*4887Schin #include <shell.h> 62*4887Schin #include "shnodes.h" 63*4887Schin #include "sys/stat.h" 64*4887Schin 65*4887Schin #define CNTL(x) ((x)&037) 66*4887Schin #define VERSION 3 67*4887Schin static const char header[6] = { CNTL('k'),CNTL('s'),CNTL('h'),0,VERSION,0 }; 68*4887Schin 69*4887Schin int main(int argc, char *argv[]) 70*4887Schin { 71*4887Schin Sfio_t *in, *out; 72*4887Schin Shell_t *shp; 73*4887Schin Namval_t *np; 74*4887Schin Shnode_t *t; 75*4887Schin char *cp; 76*4887Schin int n, nflag=0, vflag=0, dflag=0; 77*4887Schin error_info.id = argv[0]; 78*4887Schin while(n = optget(argv, usage )) switch(n) 79*4887Schin { 80*4887Schin case 'D': 81*4887Schin dflag=1; 82*4887Schin break; 83*4887Schin case 'v': 84*4887Schin vflag=1; 85*4887Schin break; 86*4887Schin case 'n': 87*4887Schin nflag=1; 88*4887Schin break; 89*4887Schin case ':': 90*4887Schin errormsg(SH_DICT,2,"%s",opt_info.arg); 91*4887Schin break; 92*4887Schin case '?': 93*4887Schin errormsg(SH_DICT,ERROR_usage(2),"%s",opt_info.arg); 94*4887Schin break; 95*4887Schin } 96*4887Schin shp = sh_init(argc,argv,(Shinit_f)0); 97*4887Schin argv += opt_info.index; 98*4887Schin argc -= opt_info.index; 99*4887Schin if(error_info.errors || argc>2) 100*4887Schin errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 101*4887Schin if(cp= *argv) 102*4887Schin { 103*4887Schin argv++; 104*4887Schin in = sh_pathopen(cp); 105*4887Schin } 106*4887Schin else 107*4887Schin in = sfstdin; 108*4887Schin if(cp= *argv) 109*4887Schin { 110*4887Schin struct stat statb; 111*4887Schin if(!(out = sfopen((Sfio_t*)0,cp,"w"))) 112*4887Schin errormsg(SH_DICT,ERROR_system(1),"%s: cannot create",cp); 113*4887Schin if(fstat(sffileno(out),&statb) >=0) 114*4887Schin chmod(cp,(statb.st_mode&~S_IFMT)|S_IXUSR|S_IXGRP|S_IXOTH); 115*4887Schin } 116*4887Schin else 117*4887Schin out = sfstdout; 118*4887Schin if(dflag) 119*4887Schin { 120*4887Schin sh_onoption(SH_DICTIONARY); 121*4887Schin sh_onoption(SH_NOEXEC); 122*4887Schin } 123*4887Schin if(nflag) 124*4887Schin sh_onoption(SH_NOEXEC); 125*4887Schin if(vflag) 126*4887Schin sh_onoption(SH_VERBOSE); 127*4887Schin if(!dflag) 128*4887Schin sfwrite(out,header,sizeof(header)); 129*4887Schin shp->inlineno = 1; 130*4887Schin while(1) 131*4887Schin { 132*4887Schin stakset((char*)0,0); 133*4887Schin if(t = (Shnode_t*)sh_parse(shp,in,0)) 134*4887Schin { 135*4887Schin if(t->tre.tretyp==0 && t->com.comnamp && strcmp(nv_name((Namval_t*)t->com.comnamp),"alias")==0) 136*4887Schin sh_exec(t,0); 137*4887Schin if(!dflag && sh_tdump(out,t) < 0) 138*4887Schin errormsg(SH_DICT,ERROR_exit(1),"dump failed"); 139*4887Schin } 140*4887Schin else if(sfeof(in)) 141*4887Schin break; 142*4887Schin if(sferror(in)) 143*4887Schin errormsg(SH_DICT,ERROR_system(1),"I/O error"); 144*4887Schin if(t && ((t->tre.tretyp&COMMSK)==TCOM) && (np=t->com.comnamp) && (cp=nv_name(np))) 145*4887Schin { 146*4887Schin if(strcmp(cp,"exit")==0) 147*4887Schin break; 148*4887Schin /* check for exec of a command */ 149*4887Schin if(strcmp(cp,"exec")==0) 150*4887Schin { 151*4887Schin if(t->com.comtyp&COMSCAN) 152*4887Schin { 153*4887Schin if(t->com.comarg->argnxt.ap) 154*4887Schin break; 155*4887Schin } 156*4887Schin else 157*4887Schin { 158*4887Schin struct dolnod *ap = (struct dolnod*)t->com.comarg; 159*4887Schin if(ap->dolnum>1) 160*4887Schin break; 161*4887Schin } 162*4887Schin } 163*4887Schin } 164*4887Schin } 165*4887Schin /* copy any remaining input */ 166*4887Schin sfmove(in,out,SF_UNBOUND,-1); 167*4887Schin if(in!=sfstdin) 168*4887Schin sfclose(in); 169*4887Schin if(out!=sfstdout) 170*4887Schin sfclose(out); 171*4887Schin return(0); 172*4887Schin } 173