1 |
|
|
/* $OpenBSD: main.c,v 1.19 2015/10/22 04:08:17 deraadt Exp $ */ |
2 |
|
|
/**************************************************************** |
3 |
|
|
Copyright (C) Lucent Technologies 1997 |
4 |
|
|
All Rights Reserved |
5 |
|
|
|
6 |
|
|
Permission to use, copy, modify, and distribute this software and |
7 |
|
|
its documentation for any purpose and without fee is hereby |
8 |
|
|
granted, provided that the above copyright notice appear in all |
9 |
|
|
copies and that both that the copyright notice and this |
10 |
|
|
permission notice and warranty disclaimer appear in supporting |
11 |
|
|
documentation, and that the name Lucent Technologies or any of |
12 |
|
|
its entities not be used in advertising or publicity pertaining |
13 |
|
|
to distribution of the software without specific, written prior |
14 |
|
|
permission. |
15 |
|
|
|
16 |
|
|
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
17 |
|
|
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. |
18 |
|
|
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY |
19 |
|
|
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
20 |
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER |
21 |
|
|
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
22 |
|
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF |
23 |
|
|
THIS SOFTWARE. |
24 |
|
|
****************************************************************/ |
25 |
|
|
|
26 |
|
|
const char *version = "version 20110810"; |
27 |
|
|
|
28 |
|
|
#define DEBUG |
29 |
|
|
#include <stdio.h> |
30 |
|
|
#include <ctype.h> |
31 |
|
|
#include <locale.h> |
32 |
|
|
#include <stdlib.h> |
33 |
|
|
#include <string.h> |
34 |
|
|
#include <signal.h> |
35 |
|
|
#include <unistd.h> |
36 |
|
|
#include "awk.h" |
37 |
|
|
#include "ytab.h" |
38 |
|
|
|
39 |
|
|
extern char **environ; |
40 |
|
|
extern int nfields; |
41 |
|
|
extern char *__progname; |
42 |
|
|
|
43 |
|
|
int dbg = 0; |
44 |
|
|
Awkfloat srand_seed = 1; |
45 |
|
|
char *cmdname; /* gets argv[0] for error messages */ |
46 |
|
|
extern FILE *yyin; /* lex input file */ |
47 |
|
|
char *lexprog; /* points to program argument if it exists */ |
48 |
|
|
extern int errorflag; /* non-zero if any syntax errors; set by yyerror */ |
49 |
|
|
int compile_time = 2; /* for error printing: */ |
50 |
|
|
/* 2 = cmdline, 1 = compile, 0 = running */ |
51 |
|
|
|
52 |
|
|
#define MAX_PFILE 20 /* max number of -f's */ |
53 |
|
|
|
54 |
|
|
char *pfile[MAX_PFILE]; /* program filenames from -f's */ |
55 |
|
|
int npfile = 0; /* number of filenames */ |
56 |
|
|
int curpfile = 0; /* current filename */ |
57 |
|
|
|
58 |
|
|
int safe = 0; /* 1 => "safe" mode */ |
59 |
|
|
|
60 |
|
|
int main(int argc, char *argv[]) |
61 |
|
|
{ |
62 |
|
|
const char *fs = NULL; |
63 |
|
|
|
64 |
|
1962 |
setlocale(LC_ALL, ""); |
65 |
|
981 |
setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */ |
66 |
|
|
|
67 |
✗✓ |
981 |
if (pledge("stdio rpath wpath cpath proc exec flock", NULL) == -1) { |
68 |
|
|
fprintf(stderr, "%s: pledge: incorrect arguments\n", |
69 |
|
|
cmdname); |
70 |
|
|
exit(1); |
71 |
|
|
} |
72 |
|
|
|
73 |
|
981 |
cmdname = __progname; |
74 |
✗✓ |
981 |
if (argc == 1) { |
75 |
|
|
fprintf(stderr, "usage: %s [-safe] [-V] [-d[n]] [-F fs] " |
76 |
|
|
"[-v var=value] [prog | -f progfile]\n\tfile ...\n", |
77 |
|
|
cmdname); |
78 |
|
|
exit(1); |
79 |
|
|
} |
80 |
|
981 |
signal(SIGFPE, fpecatch); |
81 |
|
|
|
82 |
|
981 |
yyin = NULL; |
83 |
|
981 |
symtab = makesymtab(NSYMTAB); |
84 |
✓✓✓✓ ✓✗ |
3224 |
while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') { |
85 |
✗✓ |
71 |
if (strcmp(argv[1], "--") == 0) { /* explicit end of args */ |
86 |
|
|
argc--; |
87 |
|
|
argv++; |
88 |
|
|
break; |
89 |
|
|
} |
90 |
✗✓✓✗ ✗✗✗ |
71 |
switch (argv[1][1]) { |
91 |
|
|
case 's': |
92 |
|
|
if (strcmp(argv[1], "-safe") == 0) |
93 |
|
|
safe = 1; |
94 |
|
|
break; |
95 |
|
|
case 'f': /* next argument is program filename */ |
96 |
✗✓ |
20 |
if (argv[1][2] != 0) { /* arg is -fsomething */ |
97 |
|
|
if (npfile >= MAX_PFILE - 1) |
98 |
|
|
FATAL("too many -f options"); |
99 |
|
|
pfile[npfile++] = &argv[1][2]; |
100 |
|
|
} else { /* arg is -f something */ |
101 |
|
20 |
argc--; argv++; |
102 |
✗✓ |
20 |
if (argc <= 1) |
103 |
|
|
FATAL("no program filename"); |
104 |
✗✓ |
20 |
if (npfile >= MAX_PFILE - 1) |
105 |
|
|
FATAL("too many -f options"); |
106 |
|
20 |
pfile[npfile++] = argv[1]; |
107 |
|
|
} |
108 |
|
20 |
break; |
109 |
|
|
case 'F': /* set field separator */ |
110 |
✓✗ |
51 |
if (argv[1][2] != 0) { /* arg is -Fsomething */ |
111 |
✓✓✓✗
|
54 |
if (argv[1][2] == 't' && argv[1][3] == 0) /* wart: t=>\t */ |
112 |
|
3 |
fs = "\t"; |
113 |
✓✗ |
48 |
else if (argv[1][2] != 0) |
114 |
|
48 |
fs = &argv[1][2]; |
115 |
|
|
} else { /* arg is -F something */ |
116 |
|
|
argc--; argv++; |
117 |
|
|
if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0) /* wart: t=>\t */ |
118 |
|
|
fs = "\t"; |
119 |
|
|
else if (argc > 1 && argv[1][0] != 0) |
120 |
|
|
fs = &argv[1][0]; |
121 |
|
|
} |
122 |
✓✗✗✓
|
102 |
if (fs == NULL || *fs == '\0') |
123 |
|
|
WARNING("field separator FS is empty"); |
124 |
|
|
break; |
125 |
|
|
case 'v': /* -v a=1 to be done NOW. one -v for each */ |
126 |
|
|
if (argv[1][2] != 0) { /* arg is -vsomething */ |
127 |
|
|
if (isclvar(&argv[1][2])) |
128 |
|
|
setclvar(&argv[1][2]); |
129 |
|
|
else |
130 |
|
|
FATAL("invalid -v option argument: %s", &argv[1][2]); |
131 |
|
|
} else { /* arg is -v something */ |
132 |
|
|
argc--; argv++; |
133 |
|
|
if (argc <= 1) |
134 |
|
|
FATAL("no variable name"); |
135 |
|
|
if (isclvar(argv[1])) |
136 |
|
|
setclvar(argv[1]); |
137 |
|
|
else |
138 |
|
|
FATAL("invalid -v option argument: %s", argv[1]); |
139 |
|
|
} |
140 |
|
|
break; |
141 |
|
|
case 'd': |
142 |
|
|
dbg = atoi(&argv[1][2]); |
143 |
|
|
if (dbg == 0) |
144 |
|
|
dbg = 1; |
145 |
|
|
printf("awk %s\n", version); |
146 |
|
|
break; |
147 |
|
|
case 'V': /* added for exptools "standard" */ |
148 |
|
|
printf("awk %s\n", version); |
149 |
|
|
exit(0); |
150 |
|
|
break; |
151 |
|
|
default: |
152 |
|
|
WARNING("unknown option %s ignored", argv[1]); |
153 |
|
|
break; |
154 |
|
|
} |
155 |
|
71 |
argc--; |
156 |
|
71 |
argv++; |
157 |
|
|
} |
158 |
|
|
|
159 |
✗✓ |
981 |
if (safe) { |
160 |
|
|
if (pledge("stdio rpath flock cpath wpath", NULL) == -1) { |
161 |
|
|
fprintf(stderr, "%s: pledge: incorrect arguments\n", |
162 |
|
|
cmdname); |
163 |
|
|
exit(1); |
164 |
|
|
} |
165 |
|
|
} |
166 |
|
|
|
167 |
|
|
/* argv[1] is now the first argument */ |
168 |
✓✓ |
981 |
if (npfile == 0) { /* no -f; first argument is program */ |
169 |
✗✓ |
961 |
if (argc <= 1) { |
170 |
|
|
if (dbg) |
171 |
|
|
exit(0); |
172 |
|
|
FATAL("no program given"); |
173 |
|
|
} |
174 |
✗✓ |
961 |
dprintf( ("program = |%s|\n", argv[1]) ); |
175 |
|
961 |
lexprog = argv[1]; |
176 |
|
961 |
argc--; |
177 |
|
961 |
argv++; |
178 |
|
961 |
} |
179 |
|
981 |
recinit(recsize); |
180 |
|
981 |
syminit(); |
181 |
|
981 |
compile_time = 1; |
182 |
|
981 |
argv[0] = cmdname; /* put prog name at front of arglist */ |
183 |
✗✓ |
981 |
dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) ); |
184 |
|
981 |
arginit(argc, argv); |
185 |
✓✗ |
981 |
if (!safe) |
186 |
|
981 |
envinit(environ); |
187 |
|
981 |
yyparse(); |
188 |
|
981 |
setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */ |
189 |
✓✓ |
981 |
if (fs) |
190 |
|
51 |
*FS = qstring(fs, '\0'); |
191 |
✗✓ |
981 |
dprintf( ("errorflag=%d\n", errorflag) ); |
192 |
✓✗ |
981 |
if (errorflag == 0) { |
193 |
|
981 |
compile_time = 0; |
194 |
|
981 |
run(winner); |
195 |
|
981 |
} else |
196 |
|
|
bracecheck(); |
197 |
|
981 |
return(errorflag); |
198 |
|
|
} |
199 |
|
|
|
200 |
|
|
int pgetc(void) /* get 1 character from awk program */ |
201 |
|
|
{ |
202 |
|
|
int c; |
203 |
|
|
|
204 |
|
180522 |
for (;;) { |
205 |
✓✓ |
90271 |
if (yyin == NULL) { |
206 |
✓✓ |
40 |
if (curpfile >= npfile) |
207 |
|
20 |
return EOF; |
208 |
✗✓ |
20 |
if (strcmp(pfile[curpfile], "-") == 0) |
209 |
|
|
yyin = stdin; |
210 |
✗✓ |
20 |
else if ((yyin = fopen(pfile[curpfile], "r")) == NULL) |
211 |
|
|
FATAL("can't open file %s", pfile[curpfile]); |
212 |
|
20 |
lineno = 1; |
213 |
|
20 |
} |
214 |
✓✗✓✓ ✓✓ |
361004 |
if ((c = getc(yyin)) != EOF) |
215 |
|
90231 |
return c; |
216 |
✓✗ |
20 |
if (yyin != stdin) |
217 |
|
20 |
fclose(yyin); |
218 |
|
20 |
yyin = NULL; |
219 |
|
20 |
curpfile++; |
220 |
|
|
} |
221 |
|
90251 |
} |
222 |
|
|
|
223 |
|
|
char *cursource(void) /* current source file name */ |
224 |
|
|
{ |
225 |
|
|
if (npfile > 0) |
226 |
|
|
return pfile[curpfile]; |
227 |
|
|
else |
228 |
|
|
return NULL; |
229 |
|
|
} |