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