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