1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 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 "shnodes.h" 63 #include "sys/stat.h" 64 65 #define CNTL(x) ((x)&037) 66 #define VERSION 3 67 static const char header[6] = { CNTL('k'),CNTL('s'),CNTL('h'),0,VERSION,0 }; 68 69 int main(int argc, char *argv[]) 70 { 71 Sfio_t *in, *out; 72 Shell_t *shp; 73 Namval_t *np; 74 Shnode_t *t; 75 char *cp; 76 int n, nflag=0, vflag=0, dflag=0; 77 error_info.id = argv[0]; 78 while(n = optget(argv, usage )) switch(n) 79 { 80 case 'D': 81 dflag=1; 82 break; 83 case 'v': 84 vflag=1; 85 break; 86 case 'n': 87 nflag=1; 88 break; 89 case ':': 90 errormsg(SH_DICT,2,"%s",opt_info.arg); 91 break; 92 case '?': 93 errormsg(SH_DICT,ERROR_usage(2),"%s",opt_info.arg); 94 break; 95 } 96 shp = sh_init(argc,argv,(Shinit_f)0); 97 argv += opt_info.index; 98 argc -= opt_info.index; 99 if(error_info.errors || argc>2) 100 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 101 if(cp= *argv) 102 { 103 argv++; 104 in = sh_pathopen(cp); 105 } 106 else 107 in = sfstdin; 108 if(cp= *argv) 109 { 110 struct stat statb; 111 if(!(out = sfopen((Sfio_t*)0,cp,"w"))) 112 errormsg(SH_DICT,ERROR_system(1),"%s: cannot create",cp); 113 if(fstat(sffileno(out),&statb) >=0) 114 chmod(cp,(statb.st_mode&~S_IFMT)|S_IXUSR|S_IXGRP|S_IXOTH); 115 } 116 else 117 out = sfstdout; 118 if(dflag) 119 { 120 sh_onoption(SH_DICTIONARY); 121 sh_onoption(SH_NOEXEC); 122 } 123 if(nflag) 124 sh_onoption(SH_NOEXEC); 125 if(vflag) 126 sh_onoption(SH_VERBOSE); 127 if(!dflag) 128 sfwrite(out,header,sizeof(header)); 129 shp->inlineno = 1; 130 while(1) 131 { 132 stakset((char*)0,0); 133 if(t = (Shnode_t*)sh_parse(shp,in,0)) 134 { 135 if(t->tre.tretyp==0 && t->com.comnamp && strcmp(nv_name((Namval_t*)t->com.comnamp),"alias")==0) 136 sh_exec(t,0); 137 if(!dflag && sh_tdump(out,t) < 0) 138 errormsg(SH_DICT,ERROR_exit(1),"dump failed"); 139 } 140 else if(sfeof(in)) 141 break; 142 if(sferror(in)) 143 errormsg(SH_DICT,ERROR_system(1),"I/O error"); 144 if(t && ((t->tre.tretyp&COMMSK)==TCOM) && (np=t->com.comnamp) && (cp=nv_name(np))) 145 { 146 if(strcmp(cp,"exit")==0) 147 break; 148 /* check for exec of a command */ 149 if(strcmp(cp,"exec")==0) 150 { 151 if(t->com.comtyp&COMSCAN) 152 { 153 if(t->com.comarg->argnxt.ap) 154 break; 155 } 156 else 157 { 158 struct dolnod *ap = (struct dolnod*)t->com.comarg; 159 if(ap->dolnum>1) 160 break; 161 } 162 } 163 } 164 } 165 /* copy any remaining input */ 166 sfmove(in,out,SF_UNBOUND,-1); 167 if(in!=sfstdin) 168 sfclose(in); 169 if(out!=sfstdout) 170 sfclose(out); 171 return(0); 172 } 173