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 
53 extern int sun_map_lex(void);
54 extern int sun_map_error(const char *);
55 extern void sun_map_tok_setbuff(const char *);
56 extern int sun_map_parse(void);
57 
58 struct sun_entry *sun_map_parse_read(const char *);
59 
60 static struct sun_list *sun_entry_list = NULL;
61 static struct sun_list *sun_opt_list = NULL;
62 static struct sun_list *sun_host_list = NULL;
63 static struct sun_list *sun_location_list = NULL;
64 static struct sun_list *mountpt_list = NULL;
65 static 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  */
73 static struct sun_list *get_sun_opt_list(void);
74 static struct sun_list *get_sun_host_list(void);
75 static struct sun_list *get_sun_location_list(void);
76 static struct sun_list *get_mountpt_list(void);
77 static 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 
90 amap : file
91      ;
92 
93 file : new_lines entries
94      | entries
95      ;
96 
97 entries : entry
98         | entry new_lines
99         | entry new_lines entries
100         ;
101 
102 new_lines : NEWLINE
103           | NEWLINE new_lines
104           ;
105 
106 entry : 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 
220 mountpoints : mountpoint
221             | mountpoint WSPACE mountpoints
222             ;
223 
224 mountpoint : 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 
286 locations : location
287           | location WSPACE locations
288           ;
289 
290 location : 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 
327 hosts : host
328       | host ',' hosts
329       ;
330 
331 host : 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 
355 weight : '(' 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 
370 options : option
371         | option ',' options
372         ;
373 
374 option : 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  */
421 struct sun_entry *
422 sun_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 
445 static struct sun_list *
get_sun_entry_list(void)446 get_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 
455 static struct sun_list *
get_mountpt_list(void)456 get_mountpt_list(void)
457 {
458   if (mountpt_list == NULL) {
459     mountpt_list = CALLOC(struct sun_list);
460   }
461   return mountpt_list;
462 }
463 
464 
465 static struct sun_list *
get_sun_location_list(void)466 get_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 
475 static struct sun_list *
get_sun_host_list(void)476 get_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 
485 static struct sun_list *
get_sun_opt_list(void)486 get_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