1%{
2/*
3 * Copyright (c) 1997-2014 Erez Zadok
4 * Copyright (c) 2005 Daniel P. Ottavio
5 * Copyright (c) 1990 Jan-Simon Pendry
6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7 * Copyright (c) 1990 The Regents of the University of California.
8 * All rights reserved.
9 *
10 * This code is derived from software contributed to Berkeley by
11 * Jan-Simon Pendry at Imperial College, London.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 *
38 * File: am-utils/amd/sun_map_parse.y
39 *
40 */
41
42#ifdef HAVE_CONFIG_H
43# include <config.h>
44#endif /* HAVE_CONFIG_H */
45#include <am_defs.h>
46#include <amd.h>
47#include <sun_map.h>
48
49
50#define SUN_FSTYPE_STR  "fstype="
51
52
53extern int sun_map_lex(void);
54extern int sun_map_error(const char *);
55extern void sun_map_tok_setbuff(const char *);
56extern int sun_map_parse(void);
57
58struct sun_entry *sun_map_parse_read(const char *);
59
60static struct sun_list *sun_entry_list = NULL;
61static struct sun_list *sun_opt_list = NULL;
62static struct sun_list *sun_host_list = NULL;
63static struct sun_list *sun_location_list = NULL;
64static struct sun_list *mountpt_list = NULL;
65static char *tmpFsType = NULL;
66
67
68/*
69 * Each get* function returns a pointer to the corresponding global
70 * list structure.  If the structure is NULL than a new instance is
71 * returned.
72 */
73static struct sun_list *get_sun_opt_list(void);
74static struct sun_list *get_sun_host_list(void);
75static struct sun_list *get_sun_location_list(void);
76static struct sun_list *get_mountpt_list(void);
77static struct sun_list *get_sun_entry_list(void);
78
79%}
80
81%union {
82  char strval[2048];
83}
84
85%token NEWLINE COMMENT WSPACE
86%token <strval> WORD
87
88%%
89
90amap : file
91     ;
92
93file : new_lines entries
94     | entries
95     ;
96
97entries : entry
98        | entry new_lines
99        | entry new_lines entries
100        ;
101
102new_lines : NEWLINE
103          | NEWLINE new_lines
104          ;
105
106entry : locations {
107
108  struct sun_list *list;
109  struct sun_entry *entry;
110
111  /* allocate an entry */
112  entry = CALLOC(struct sun_entry);
113
114  /*
115   * Assign the global location list to this entry and reset the
116   * global pointer.  Reseting the global pointer will create a new
117   * list instance next time get_sun_location_list() is called.
118   */
119  list = get_sun_location_list();
120  entry->location_list = (struct sun_location *)list->first;
121  sun_location_list = NULL;
122
123   /* Add this entry to the entry list. */
124  sun_list_add(get_sun_entry_list(), (qelem *)entry);
125}
126
127| '-' options WSPACE locations {
128
129  struct sun_list *list;
130  struct sun_entry *entry;
131
132  entry = CALLOC(struct sun_entry);
133
134  /* An fstype may have been defined in the 'options'. */
135  if (tmpFsType != NULL) {
136    entry->fstype = tmpFsType;
137    tmpFsType = NULL;
138  }
139
140  /*
141   * Assign the global location list to this entry and reset the
142   * global pointer.  Reseting the global pointer will create a new
143   * list instance next time get_sun_location_list() is called.
144   */
145  list = get_sun_location_list();
146  entry->location_list = (struct sun_location *)list->first;
147  sun_location_list = NULL;
148
149  /*
150   * Assign the global opt list to this entry and reset the global
151   * pointer.  Reseting the global pointer will create a new list
152   * instance next time get_sun_opt_list() is called.
153   */
154  list = get_sun_opt_list();
155  entry->opt_list = (struct sun_opt *)list->first;
156  sun_opt_list = NULL;
157
158  /* Add this entry to the entry list. */
159  sun_list_add(get_sun_entry_list(), (qelem *)entry);
160}
161
162| mountpoints {
163
164  struct sun_list *list;
165  struct sun_entry *entry;
166
167  /* allocate an entry */
168  entry = CALLOC(struct sun_entry);
169
170  /*
171   * Assign the global mountpt list to this entry and reset the global
172   * pointer.  Reseting the global pointer will create a new list
173   * instance next time get_mountpt_list() is called.
174   */
175  list = get_mountpt_list();
176  entry->mountpt_list = (struct sun_mountpt *)list->first;
177  mountpt_list = NULL;
178
179  /* Add this entry to the entry list. */
180  sun_list_add(get_sun_entry_list(), (qelem *)entry);
181}
182
183| '-' options WSPACE mountpoints {
184
185  struct sun_list *list;
186  struct sun_entry *entry;
187
188  /* allocate an entry */
189  entry = CALLOC(struct sun_entry);
190
191  /* An fstype may have been defined in the 'options'. */
192  if (tmpFsType != NULL) {
193    entry->fstype = tmpFsType;
194    tmpFsType = NULL;
195  }
196
197  /*
198   * Assign the global mountpt list to this entry and reset the global
199   * pointer.  Reseting the global pointer will create a new list
200   * instance next time get_mountpt_list() is called.
201   */
202  list = get_mountpt_list();
203  entry->mountpt_list = (struct sun_mountpt *)list->first;
204  mountpt_list = NULL;
205
206  /*
207   * Assign the global opt list to this entry and reset the global
208   * pointer.  Reseting the global pointer will create a new list
209   * instance next time get_sun_opt_list() is called.
210   */
211  list = get_sun_opt_list();
212  entry->opt_list = (struct sun_opt *)list->first;
213  sun_opt_list = NULL;
214
215  /* Add this entry to the entry list. */
216  sun_list_add(get_sun_entry_list(), (qelem *)entry);
217}
218;
219
220mountpoints : mountpoint
221            | mountpoint WSPACE mountpoints
222            ;
223
224mountpoint : WORD WSPACE location {
225
226  struct sun_list *list;
227  struct sun_mountpt *mountpt;
228
229  /* allocate a mountpt */
230  mountpt = CALLOC(struct sun_mountpt);
231
232  /*
233   * Assign the global loaction list to this entry and reset the
234   * global pointer.  Reseting the global pointer will create a new
235   * list instance next time get_sun_location_list() is called.
236   */
237  list = get_sun_location_list();
238  mountpt->location_list = (struct sun_location *)list->first;
239  sun_location_list = NULL;
240
241  mountpt->path = xstrdup($1);
242
243  /* Add this mountpt to the mountpt list. */
244  sun_list_add(get_mountpt_list(), (qelem *)mountpt);
245}
246
247| WORD WSPACE '-' options WSPACE location {
248
249  struct sun_list *list;
250  struct sun_mountpt *mountpt;
251
252  /* allocate a mountpt */
253  mountpt = CALLOC(struct sun_mountpt);
254
255  /* An fstype may have been defined in the 'options'. */
256  if (tmpFsType != NULL) {
257    mountpt->fstype = tmpFsType;
258    tmpFsType = NULL;
259  }
260
261  /*
262   * Assign the global location list to this entry and reset the
263   * global pointer.  Reseting the global pointer will create a new
264   * list instance next time get_sun_location_list() is called.
265   */
266  list = get_sun_location_list();
267  mountpt->location_list = (struct sun_location *)list->first;
268  sun_location_list = NULL;
269
270  /*
271   * Assign the global opt list to this entry and reset the global
272   * pointer.  Reseting the global pointer will create a new list
273   * instance next time get_sun_opt_list() is called.
274   */
275  list = get_sun_opt_list();
276  mountpt->opt_list = (struct sun_opt *)list->first;
277  sun_opt_list = NULL;
278
279  mountpt->path = xstrdup($1);
280
281  /* Add this mountpt to the mountpt list. */
282  sun_list_add(get_mountpt_list(), (qelem *)mountpt);
283}
284;
285
286locations : location
287          | location WSPACE locations
288          ;
289
290location : hosts ':' WORD {
291
292  struct sun_list *list;
293  struct sun_location *location;
294
295  /* allocate a new location */
296  location = CALLOC(struct sun_location);
297
298  /*
299   * Assign the global opt list to this entry and reset the global
300   * pointer.  Reseting the global pointer will create a new list
301   * instance next time get_sun_opt_list() is called.
302   */
303  list = get_sun_host_list();
304  location->host_list = (struct sun_host *)list->first;
305  sun_host_list = NULL;
306
307  location->path = xstrdup($3);
308
309  /* Add this location to the location list. */
310  sun_list_add(get_sun_location_list(), (qelem *)location);
311}
312
313| ':' WORD {
314
315  struct sun_location *location;
316
317  /* allocate a new location */
318  location = CALLOC(struct sun_location);
319
320  location->path = xstrdup($2);
321
322  /* Add this location to the location list. */
323  sun_list_add(get_sun_location_list(), (qelem *)location);
324}
325;
326
327hosts : host
328      | host ',' hosts
329      ;
330
331host : WORD {
332
333  /* allocate a new host */
334  struct sun_host *host = CALLOC(struct sun_host);
335
336  host->name = xstrdup($1);
337
338  /* Add this host to the host list. */
339  sun_list_add(get_sun_host_list(),(qelem *)host);
340}
341
342| WORD weight {
343
344  /*
345   * It is assumed that the host for this rule was allocated by the
346   * 'weight' rule and assigned to be the last host item on the host
347   * list.
348   */
349  struct sun_host *host = (struct sun_host *)sun_host_list->last;
350
351  host->name = xstrdup($1);
352}
353;
354
355weight : '(' WORD ')' {
356
357  int val;
358  /* allocate a new host */
359  struct sun_host *host = CALLOC(struct sun_host);
360
361  val = atoi($2);
362
363  host->weight = val;
364
365  /* Add this host to the host list. */
366  sun_list_add(get_sun_host_list(), (qelem *)host);
367}
368;
369
370options : option
371        | option ',' options
372        ;
373
374option : WORD {
375
376  char *type;
377
378  /* check if this is an fstype option */
379  if ((type = strstr($1,SUN_FSTYPE_STR)) != NULL) {
380    /* parse out the fs type from the Sun fstype keyword  */
381    if ((type = type + strlen(SUN_FSTYPE_STR)) != NULL) {
382      /*
383       * This global fstype str will be assigned to the current being
384       * parsed later in the parsing.
385       */
386      tmpFsType = xstrdup(type);
387    }
388  }
389  else {
390    /*
391     * If it is not an fstype option allocate an opt struct and assign
392     * the value.
393     */
394    struct sun_opt *opt = CALLOC(struct sun_opt);
395    opt->str = xstrdup($1);
396    /* Add this opt to the opt list. */
397    sun_list_add(get_sun_opt_list(), (qelem *)opt);
398  }
399}
400
401;
402
403%%
404
405/*
406 * Parse 'map_data' which is assumed to be a Sun-syle map.  If
407 * successful a sun_entry is returned.
408 *
409 * The parser is designed to parse map entries with out the keys.  For
410 * example the entry:
411 *
412 * usr -ro pluto:/usr/local
413 *
414 * should be passed to the parser as:
415 *
416 * -ro pluto:/usr/local
417 *
418 * The reason for this is that the Amd info services already strip off
419 * the key when they read map info.
420 */
421struct sun_entry *
422sun_map_parse_read(const char *map_data)
423{
424  struct sun_entry *retval = NULL;
425
426  /* pass map_data to lex */
427  sun_map_tok_setbuff(map_data);
428
429  /* call yacc */
430  sun_map_parse();
431
432  if (sun_entry_list != NULL) {
433    /* return the first Sun entry in the list */
434    retval = (struct sun_entry*)sun_entry_list->first;
435    sun_entry_list = NULL;
436  }
437  else {
438    plog(XLOG_ERROR, "Sun map parser did not produce data structs.");
439  }
440
441  return retval;
442}
443
444
445static struct sun_list *
446get_sun_entry_list(void)
447{
448  if (sun_entry_list == NULL) {
449    sun_entry_list = CALLOC(struct sun_list);
450  }
451  return sun_entry_list;
452}
453
454
455static struct sun_list *
456get_mountpt_list(void)
457{
458  if (mountpt_list == NULL) {
459    mountpt_list = CALLOC(struct sun_list);
460  }
461  return mountpt_list;
462}
463
464
465static struct sun_list *
466get_sun_location_list(void)
467{
468  if (sun_location_list == NULL) {
469    sun_location_list = CALLOC(struct sun_list);
470  }
471  return sun_location_list;
472}
473
474
475static struct sun_list *
476get_sun_host_list(void)
477{
478  if (sun_host_list == NULL) {
479    sun_host_list = CALLOC(struct sun_list);
480  }
481  return sun_host_list;
482}
483
484
485static struct sun_list *
486get_sun_opt_list(void)
487{
488  if (sun_opt_list == NULL) {
489    sun_opt_list = CALLOC(struct sun_list);
490  }
491  return sun_opt_list;
492}
493