~ubuntu-branches/ubuntu/trusty/bash/trusty-security

1.5.1 by Matthias Klose
Import upstream version 4.3~rc1
1
/*
2
 * mksyntax.c - construct shell syntax table for fast char attribute lookup.
3
 */
4
5
/* Copyright (C) 2000-2009 Free Software Foundation, Inc.
6
7
   This file is part of GNU Bash, the Bourne Again SHell.
8
9
   Bash is free software: you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation, either version 3 of the License, or
12
   (at your option) any later version.
13
14
   Bash is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
19
   You should have received a copy of the GNU General Public License
20
   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
21
*/
22
23
#include "config.h"
24
25
#include <stdio.h>
26
#include "bashansi.h"
27
#include "chartypes.h"
28
#include <errno.h>
29
30
#ifdef HAVE_UNISTD_H
31
#  include <unistd.h>
32
#endif
33
34
#include "syntax.h"
35
36
extern int optind;
37
extern char *optarg;
38
39
#ifndef errno
40
extern int errno;
41
#endif
42
43
#ifndef HAVE_STRERROR
44
extern char *strerror();
45
#endif
46
47
struct wordflag {
48
	int	flag;
49
	char	*fstr;
50
} wordflags[] = {
51
	{ CWORD,	"CWORD" },
52
	{ CSHMETA,	"CSHMETA" },
53
	{ CSHBRK,	"CSHBRK" },
54
	{ CBACKQ,	"CBACKQ" },
55
	{ CQUOTE,	"CQUOTE" },
56
	{ CSPECL,	"CSPECL" },
57
	{ CEXP,		"CEXP" },
58
	{ CBSDQUOTE,	"CBSDQUOTE" },
59
	{ CBSHDOC,	"CBSHDOC" },
60
	{ CGLOB,	"CGLOB" },
61
	{ CXGLOB,	"CXGLOB" },
62
	{ CXQUOTE,	"CXQUOTE" },
63
	{ CSPECVAR,	"CSPECVAR" },
64
	{ CSUBSTOP,	"CSUBSTOP" },
65
	{ CBLANK,	"CBLANK" },
66
};
67
	
68
#define N_WFLAGS	(sizeof (wordflags) / sizeof (wordflags[0]))
69
#define SYNSIZE		256
70
71
int	lsyntax[SYNSIZE];
72
int	debug;
73
char	*progname;
74
75
char	preamble[] = "\
76
/*\n\
77
 * This file was generated by mksyntax.  DO NOT EDIT.\n\
78
 */\n\
79
\n";
80
81
char	includes[] = "\
82
#include \"config.h\"\n\
83
#include \"stdc.h\"\n\
84
#include \"syntax.h\"\n\n";
85
86
static void
87
usage()
88
{
89
  fprintf (stderr, "%s: usage: %s [-d] [-o filename]\n", progname, progname);
90
  exit (2);
91
}
92
93
#ifdef INCLUDE_UNUSED
94
static int
95
getcflag (s)
96
     char *s;
97
{
98
  int i;
99
100
  for (i = 0; i < N_WFLAGS; i++)
101
    if (strcmp (s, wordflags[i].fstr) == 0)
102
      return wordflags[i].flag;
103
  return -1;
104
}
105
#endif
106
107
static char *
108
cdesc (i)
109
     int i;
110
{
111
  static char xbuf[16];
112
113
  if (i == ' ')
114
    return "SPC";
115
  else if (ISPRINT (i))
116
    {
117
      xbuf[0] = i;
118
      xbuf[1] = '\0';
119
      return (xbuf);
120
    }
121
  else if (i == CTLESC)
122
    return "CTLESC";
123
  else if (i == CTLNUL)
124
    return "CTLNUL";
125
  else if (i == '\033')		/* ASCII */
126
    return "ESC";
127
128
  xbuf[0] = '\\';
129
  xbuf[2] = '\0';
130
    
131
  switch (i)
132
    {
133
#ifdef __STDC__
134
    case '\a': xbuf[1] = 'a'; break;
135
    case '\v': xbuf[1] = 'v'; break;
136
#else
137
    case '\007': xbuf[1] = 'a'; break;
138
    case 0x0B: xbuf[1] = 'v'; break;
139
#endif
140
    case '\b': xbuf[1] = 'b'; break;
141
    case '\f': xbuf[1] = 'f'; break;
142
    case '\n': xbuf[1] = 'n'; break;
143
    case '\r': xbuf[1] = 'r'; break;
144
    case '\t': xbuf[1] = 't'; break;
145
    default: sprintf (xbuf, "%d", i); break;
146
    }
147
148
  return xbuf;	
149
}
150
151
static char *
152
getcstr (f)
153
     int f;
154
{
155
  int i;
156
157
  for (i = 0; i < N_WFLAGS; i++)
158
    if (f == wordflags[i].flag)
159
      return (wordflags[i].fstr);
160
  return ((char *)NULL);
161
}
162
163
static void
164
addcstr (str, flag)
165
     char *str;
166
     int flag;
167
{
168
  char *s, *fstr;
169
  unsigned char uc;
170
171
  for (s = str; s && *s; s++)
172
    {
173
      uc = *s;
174
175
      if (debug)
176
	{
177
	  fstr = getcstr (flag);
178
	  fprintf(stderr, "added %s for character %s\n", fstr, cdesc(uc));
179
	}
180
	
181
      lsyntax[uc] |= flag;
182
    }
183
}
184
185
static void
186
addcchar (c, flag)
187
     unsigned char c;
188
     int flag;
189
{
190
  char *fstr;
191
192
  if (debug)
193
    {
194
      fstr = getcstr (flag);
195
      fprintf (stderr, "added %s for character %s\n", fstr, cdesc(c));
196
    }
197
  lsyntax[c] |= flag;
198
}
199
200
static void
201
addblanks ()
202
{
203
  register int i;
204
  unsigned char uc;
205
206
  for (i = 0; i < SYNSIZE; i++)
207
    {
208
      uc = i;
209
      /* Since we don't call setlocale(), this defaults to the "C" locale, and
210
	 the default blank characters will be space and tab. */
211
      if (isblank (uc))
212
	lsyntax[uc] |= CBLANK;
213
    }
214
}
215
216
/* load up the correct flag values in lsyntax */
217
static void
218
load_lsyntax ()
219
{
220
  /* shell metacharacters */
221
  addcstr (shell_meta_chars, CSHMETA);
222
223
  /* shell word break characters */
224
  addcstr (shell_break_chars, CSHBRK);
225
226
  addcchar ('`', CBACKQ);
227
228
  addcstr (shell_quote_chars, CQUOTE);
229
230
  addcchar (CTLESC, CSPECL);
231
  addcchar (CTLNUL, CSPECL);
232
233
  addcstr (shell_exp_chars, CEXP);
234
235
  addcstr (slashify_in_quotes, CBSDQUOTE);
236
  addcstr (slashify_in_here_document, CBSHDOC);
237
238
  addcstr (shell_glob_chars, CGLOB);
239
240
#if defined (EXTENDED_GLOB)
241
  addcstr (ext_glob_chars, CXGLOB);
242
#endif
243
244
  addcstr (shell_quote_chars, CXQUOTE);
245
  addcchar ('\\', CXQUOTE);
246
247
  addcstr ("@*#?-$!", CSPECVAR);	/* omits $0...$9 and $_ */
248
249
  addcstr ("-=?+", CSUBSTOP);		/* OP in ${paramOPword} */
250
251
  addblanks ();
252
}
253
254
static void
255
dump_lflags (fp, ind)
256
     FILE *fp;
257
     int ind;
258
{
259
  int xflags, first, i;
260
261
  xflags = lsyntax[ind];
262
  first = 1;
263
264
  if (xflags == 0)
265
    fputs (wordflags[0].fstr, fp);
266
  else
267
    {
268
      for (i = 1; i < N_WFLAGS; i++)
269
	if (xflags & wordflags[i].flag)
270
	  {
271
	    if (first)
272
	      first = 0;
273
	    else
274
	      putc ('|', fp);
275
	    fputs (wordflags[i].fstr, fp);
276
  	  }
277
    }
278
}
279
280
static void
281
wcomment (fp, i)
282
     FILE *fp;
283
     int i;
284
{
285
  fputs ("\t\t/* ", fp);
286
287
  fprintf (fp, "%s", cdesc(i));
288
      
289
  fputs (" */", fp);
290
}
291
292
static void
293
dump_lsyntax (fp)
294
     FILE *fp;
295
{
296
  int i;
297
298
  fprintf (fp, "int sh_syntabsiz = %d;\n", SYNSIZE);
299
  fprintf (fp, "int sh_syntaxtab[%d] = {\n", SYNSIZE);
300
301
  for (i = 0; i < SYNSIZE; i++)
302
    {
303
      putc ('\t', fp);
304
      dump_lflags (fp, i);
305
      putc (',', fp);
306
      wcomment (fp, i);
307
      putc ('\n', fp);
308
    }
309
310
  fprintf (fp, "};\n");
311
}
312
313
int
314
main(argc, argv)
315
     int argc;
316
     char **argv;
317
{
318
  int opt, i;
319
  char *filename;
320
  FILE *fp;
321
322
  if ((progname = strrchr (argv[0], '/')) == 0)
323
    progname = argv[0];
324
  else
325
    progname++;
326
327
  filename = (char *)NULL;
328
  debug = 0;
329
330
  while ((opt = getopt (argc, argv, "do:")) != EOF)
331
    {
332
      switch (opt)
333
	{
334
	case 'd':
335
	  debug = 1;
336
	  break;
337
	case 'o':
338
	  filename = optarg;
339
	  break;
340
	default:
341
	  usage();
342
	}
343
    }
344
345
  argc -= optind;
346
  argv += optind;
347
348
  if (filename)
349
    {
350
      fp = fopen (filename, "w");
351
      if (fp == 0)
352
	{
353
	  fprintf (stderr, "%s: %s: cannot open: %s\n", progname, filename, strerror(errno));
354
	  exit (1);
355
	}
356
    }
357
  else
358
    {
359
      filename = "stdout";
360
      fp = stdout;
361
    }
362
363
364
  for (i = 0; i < SYNSIZE; i++)
365
    lsyntax[i] = CWORD;
366
367
  load_lsyntax ();
368
369
  fprintf (fp, "%s\n", preamble);
370
  fprintf (fp, "%s\n", includes);
371
372
  dump_lsyntax (fp);
373
374
  if (fp != stdout)
375
    fclose (fp);
376
  exit (0);
377
}
378
379
380
#if !defined (HAVE_STRERROR)
381
382
#include <bashtypes.h>
383
#if defined (HAVE_SYS_PARAM_H)
384
#  include <sys/param.h>
385
#endif
386
387
#if defined (HAVE_UNISTD_H)
388
#  include <unistd.h>
389
#endif
390
391
/* Return a string corresponding to the error number E.  From
392
   the ANSI C spec. */
393
#if defined (strerror)
394
#  undef strerror
395
#endif
396
397
char *
398
strerror (e)
399
     int e;
400
{
401
  static char emsg[40];
402
#if defined (HAVE_SYS_ERRLIST)
403
  extern int sys_nerr;
404
  extern char *sys_errlist[];
405
406
  if (e > 0 && e < sys_nerr)
407
    return (sys_errlist[e]);
408
  else
409
#endif /* HAVE_SYS_ERRLIST */
410
    {
411
      sprintf (emsg, "Unknown system error %d", e);
412
      return (&emsg[0]);
413
    }
414
}
415
#endif /* HAVE_STRERROR */