1 /* $OpenBSD: main.c,v 1.22 2020/02/27 21:43:46 millert 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 20121220"; 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 setlocale(LC_ALL, ""); 65 setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */ 66 67 cmdname = __progname; 68 if (pledge("stdio rpath wpath cpath proc exec", NULL) == -1) { 69 fprintf(stderr, "%s: pledge: incorrect arguments\n", 70 cmdname); 71 exit(1); 72 } 73 74 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 signal(SIGFPE, fpecatch); 81 82 yyin = NULL; 83 symtab = makesymtab(NSYMTAB); 84 while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') { 85 if (strcmp(argv[1], "--") == 0) { /* explicit end of args */ 86 argc--; 87 argv++; 88 break; 89 } 90 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 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 argc--; argv++; 102 if (argc <= 1) 103 FATAL("no program filename"); 104 if (npfile >= MAX_PFILE - 1) 105 FATAL("too many -f options"); 106 pfile[npfile++] = argv[1]; 107 } 108 break; 109 case 'F': /* set field separator */ 110 if (argv[1][2] != 0) { /* arg is -Fsomething */ 111 if (argv[1][2] == 't' && argv[1][3] == 0) /* wart: t=>\t */ 112 fs = "\t"; 113 else if (argv[1][2] != 0) 114 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 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 argc--; 156 argv++; 157 } 158 159 if (safe) { 160 if (pledge("stdio rpath", 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 if (npfile == 0) { /* no -f; first argument is program */ 169 if (argc <= 1) { 170 if (dbg) 171 exit(0); 172 FATAL("no program given"); 173 } 174 DPRINTF( ("program = |%s|\n", argv[1]) ); 175 lexprog = argv[1]; 176 argc--; 177 argv++; 178 } 179 recinit(recsize); 180 syminit(); 181 compile_time = 1; 182 argv[0] = cmdname; /* put prog name at front of arglist */ 183 DPRINTF( ("argc=%d, argv[0]=%s\n", argc, argv[0]) ); 184 arginit(argc, argv); 185 if (!safe) 186 envinit(environ); 187 yyparse(); 188 setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */ 189 if (fs) 190 *FS = qstring(fs, '\0'); 191 DPRINTF( ("errorflag=%d\n", errorflag) ); 192 if (errorflag == 0) { 193 compile_time = 0; 194 run(winner); 195 } else 196 bracecheck(); 197 return(errorflag); 198 } 199 200 int pgetc(void) /* get 1 character from awk program */ 201 { 202 int c; 203 204 for (;;) { 205 if (yyin == NULL) { 206 if (curpfile >= npfile) 207 return EOF; 208 if (strcmp(pfile[curpfile], "-") == 0) 209 yyin = stdin; 210 else if ((yyin = fopen(pfile[curpfile], "r")) == NULL) 211 FATAL("can't open file %s", pfile[curpfile]); 212 lineno = 1; 213 } 214 if ((c = getc(yyin)) != EOF) 215 return c; 216 if (yyin != stdin) 217 fclose(yyin); 218 yyin = NULL; 219 curpfile++; 220 } 221 } 222 223 char *cursource(void) /* current source file name */ 224 { 225 if (npfile > 0) 226 return pfile[curpfile]; 227 else 228 return NULL; 229 } 230