Mapper
get_apps_defaults.c
Go to the documentation of this file.
1 /* File: get_apps_defaults.c
2  *
3  * Program to resolve the value of a requested string.
4  *
5  * The requested string to be resolved is supplied as the string
6  * variable <request>, the resolved request is returned as the string
7  * variable <reply>.
8  *
9  * Request resolution occurs in one of three ways:
10  *
11  * 1. an environment variable matching in name to <request> is found;
12  * <reply> is then the value of that env. variable unless the
13  * value is null,
14  *
15  * 2. <request> is found as a match in a file that establishes
16  * token - resource (t-r) relationships. Three files may be scanned in
17  * this order:
18  * APPS_DEFAULTS_USER ..... a personal users set of tokens
19  * APPS_DEFAULTS_SITE ..... a site wide set of tokens
20  * APPS_DEFAULTS .......... a system-wide (national) set of tokens
21  * to find the first token match to get a request.
22  *
23  * 3. if <request> can not be resolved, <reply> is assigned as the
24  * null string.
25  *
26  * Each file is scanned from top to bottom looking for the first match
27  * between <request> and a defined token. The syntax needed in either
28  * file is:
29  *
30  * <token> <delimiter> <resource>
31  *
32  * where:
33  * <token> is defined as a string delimited by white space or <delimiter>,
34  * <delimiter> is the : (colon),
35  * <resource> is any string, the value returned depends
36  * on certain file conventions:
37  *
38  * 1. A valid t-r requires a valid token followed by a valid
39  * resource,
40  * 2. the t-r relationship must be contained on a single line,
41  * 3. no white space needs to surround <delimiter>,
42  * 4. comments are indicated by a #,
43  * 5. neither <token> nor <resource> can begin with a # or :,
44  * 6. a # or a : can be embedded within <resource>,
45  * 7. <resource> can contain white space if it is bounded by
46  * the ' or " characters,
47  * 8. blank lines are allowed in the file,
48  * 9. referbacks are indicated by $(...). The '...' is resolved
49  * the same way any other token is, and is substituted for
50  * the $(...) string to compose the final resource value.
51  * 10. Multiple referbacks are allowed in <resource>, but embedded
52  * referbacks are not allowed (i.e. no $($(...)) allowed).
53  * 11. First in wins. That is, first finding of <token>
54  * matching <request> uses that resource value, even if null.
55  *
56  * A sample of a t-r file:
57 #-----------------------------------------------------------------------
58 # This is a comment line; so was previous line. Blank lines are
59 # intentional and are allowed in file.
60 
61 ofs_level : testcase # this is a comment on valid t-r
62 ofs_reor_lvl : test:reor # ':' allowed in body of <resource>
63 ofs_inpt_grp : "test case" # white space allowed in <resource>
64 
65 ofs_file_grp : /home/$(ofs_level)/files # referback to prior token;
66  # returned resource will be
67  # /home/testcase/files
68 
69 ofs_xxx xxx # invalid t-r, no delimiter
70 ofs_yyy : #yyy # invalid t-r, no resource
71 
72 # This is comment line; so is following line
73 #-----------------------------------------------------------------------
74 
75  * Function written by JTOstrowski - HRL - 11/92
76  */
77 
78 #include <stdio.h>
79 #include <stdlib.h>
80 #include <string.h>
81 #include <ctype.h>
82 
83 #define LEN_TOKEN 128 /* maximum length of token in file */
84 #define LEN_REPLY 512 /* maximum length of reply in single line in file */
85 #define LEN_LINE 520 /* maximum length of line in file */
86 #define LEN_TOTREPLY 600 /* maximum length of all concatenated reply strings */
87 
88 #define RECUR_LIMIT 40 /* limit number of referback recursions */
89 
90 #define ENV_VAR_1 "APPS_DEFAULTS_USER" /* env. var. for personal t-r file */
91 #define ENV_VAR_2 "APPS_DEFAULTS_SITE" /* env. var. for local site t-r file */
92 #define ENV_VAR_3 "APPS_DEFAULTS" /* env. var. for default t-r file */
93 #define ENV_VAR_LENGTH 25 /* dflt length of env. var. */
94 #define NUM_ENV_VAR 3 /* no. of env. vars. to use */
95 
96 #define RFR_OPEN "$(" /* referback opening string */
97 #define RFR_CLOSE ")" /* referback closing string */
98 #define DELIM ':' /* delimiter character */
99 #define COMMENT '#' /* comment character */
100 #define QUOTE1 '\"' /* 1st valid quote character */
101 #define QUOTE2 '\'' /* 2nd valid quote character */
102 #define BSLASH '\\' /* back slash */
103 
104 #define QPHRASE1 (opt_line[ilast] == QUOTE1 && ilast > 0 && opt_line[ilast - 1] != BSLASH)
105 #define QPHRASE2 (opt_line[ilast] == QUOTE2 && ilast > 0 && opt_line[ilast - 1] != BSLASH)
106 #define NPHRASE2 (isspace(opt_line[ilast]) && ilast > 0 && opt_line[ilast - 1] != BSLASH)
107 
108 static int r_cou = 0; /* counter to limit recursion */
109 static int ifile = 0; /* file loop counter */
110 static int i = 0; /* miscellaneous counter */
111 static int ilast = 0; /* last character position holder */
112 static int iphrase = 0; /* conditional phrase-ending indicator */
113 static char token[LEN_TOKEN+1]; /* working token array */
114 static char *as_env_var; /* returned env. var. value */
115 static char env_var_array[NUM_ENV_VAR][ENV_VAR_LENGTH];
116 static int r_len = 0; /* length of reply in referback */
117 static int e_len = 0; /* length of end of reply after a referback */
118 
119 static FILE *in[NUM_ENV_VAR]; /* file descripter */
120 static char *opts_file[NUM_ENV_VAR]; /* file name holder */
121 
122 static FILE *gap = NULL; /* file descripter for debug output */
123 
124 /*------------------------------------------------------------------------------------------------*/
125 int get_apps_defaults(char *request, int *request_len, char *reply, int *reply_len)
126 
127 {
128  void get_apps_defaults_r(char *, char *);
129 
130  char inquest[LEN_TOKEN+1]; /* entered token string recopied */
131  char resource[LEN_TOTREPLY+1]; /* working resource array */
132 
133  /* gap = fopen("/tmp/gap_io","a"); */
134 
135 /* Place entered string into local variable; append '\0';set recursion count global */
136 
137  for (i = 0; i < *request_len; i++)
138  inquest[i] = request[i];
139  inquest[*request_len] = '\0';
140  r_cou = 0;
141 
142  if (gap != NULL) fprintf(gap,"Input: %s\n",inquest);
143 
144 /* Fill the environment variable array */
145  for (i = 0; i < NUM_ENV_VAR; i++)
146  (void)memset(env_var_array[i], '\0', ENV_VAR_LENGTH);
147  (void)strcpy(env_var_array[0], ENV_VAR_1);
148  (void)strcpy(env_var_array[1], ENV_VAR_2);
149  (void)strcpy(env_var_array[2], ENV_VAR_3);
150 
151 /* Make sure apps files are initialized as not-opened */
152 
153  for (ifile = 0; ifile < NUM_ENV_VAR; ifile++)
154  {
155  in[ifile] = NULL;
156  opts_file[ifile] = '\0';
157  }
158 
159 /* Call true "C" routine that can be recursive using global variable "r_cou" */
160 
161  get_apps_defaults_r(inquest,resource);
162 
163 /* Close any apps files that may have been opened */
164 
165  for (ifile = 0; ifile < NUM_ENV_VAR; ifile++)
166  {
167  if (in[ifile] != NULL)
168  {
169  (void)fclose(in[ifile]);
170  if (gap != NULL) fprintf(gap," Close: %2d %s\n",r_cou,opts_file[ifile]);
171  }
172  }
173 
174 /* Place local output string into returned string, get length, set error status */
175 
176  if (gap != NULL) fprintf(gap,"Output: %s %d\n",resource,r_cou);
177  if (gap != NULL) (void)fclose(gap);
178 
179  (void)strcpy(reply, &resource[0]);
180  *reply_len = strlen(reply);
181  if (!*reply || r_cou > RECUR_LIMIT) /* SAM, RTi */
182  {
183  return 1;
184  }
185  else
186  {
187  return 0;
188  }
189 }
190 
191 /*------------------------------------------------------------------------------------------------*/
192 void get_apps_defaults_r(char inquest[], char resource[])
193 
194 {
195  char *pOpen; /* referback opening position holder */
196  char *pClose; /* referback closing position holder */
197  int diff = 0; /* string comparison result */
198  char referback[LEN_TOKEN+1]; /* referback token array */
199  char refer_val[LEN_TOTREPLY+1]; /* referback value array */
200  char substitute[LEN_TOTREPLY+1]; /* expanded referback-ed resource */
201 
202 /* Initialize the result to NULL */
203 
204  (void)memset(resource, '\0', LEN_TOTREPLY+1);
205 
206 /* Check for the requested variable found as an environment variable */
207 
208  as_env_var = getenv(inquest);
209 
210  if ( as_env_var ) /* SAM, RTi */
211  (void)strcpy(resource, as_env_var);
212  else
213  {
214 
215 /* Increment recursive counter (needed to avoid referbacks calling itself) */
216 
217  r_cou += 1;
218  if (r_cou <= RECUR_LIMIT+1)
219  {
220 
221 /* The resource file to be read is indicated by the value of an
222  environment variable */
223 
224  for (ifile = 0; ifile < NUM_ENV_VAR; ifile++)
225  {
226  char opt_line[LEN_LINE+1]; /* t-r file line array */
227 
228 /* See if file can be opened for reading */
229 
230  if (in[ifile] == NULL)
231  {
232  opts_file[ifile] = getenv(env_var_array[ifile]);
233  if (ifile == 2 && opts_file[ifile] == NULL) {
234  strcpy(opts_file[ifile],"/usr/apps/.Apps_defaults"); /* a default A-D file sbs 1-99 */
235  }
236  in[ifile] = fopen(opts_file[ifile], "r");
237  if ((gap != NULL) && (in[ifile] != NULL))
238  fprintf(gap," Open file: %2d %s\n",r_cou,opts_file[ifile]);
239  }
240  else
241  {
242  /*type problem for linux, used rewind instead*/
243  fpos_t vpos;
244  rewind(in[ifile]);
245  /*vpos = 0;
246  (void)fsetpos(in[ifile], &vpos);*/
247  (void)fgetpos(in[ifile], &vpos);
248  }
249 
250  if (in[ifile] != NULL)
251  {
252 
253 /* Read file until either match is found or EOF reached */
254 
255  while (fgets(opt_line, LEN_LINE+1, in[ifile]) != NULL)
256  {
257  i = 0;
258 
259 /* Ignore blank lines (nl only) */
260 
261  if (strlen(opt_line) > 1)
262  {
263 
264 /* Only scan lines with the delimiter in them */
265 
266  if (strchr(opt_line, DELIM) != NULL)
267  {
268  i = 0;
269 
270 /* Look for first non-blank character on line */
271  while (i < strlen(opt_line)-1 && isspace(opt_line[i]) != 0)
272  i++;
273  if (i < strlen(opt_line))
274  {
275 
276 /* Discard line if first character is either delimiter or comment indicator */
277 
278  if (opt_line[i] != COMMENT && opt_line[i] != DELIM)
279  {
280  ilast = i;
281  i = 0;
282  token[0] = '\0';
283 
284 /* Look for token based on rules for delimiting tokens */
285 
286  while (isprint(opt_line[ilast]) != 0 &&
287  isspace(opt_line[ilast]) == 0 &&
288  opt_line[ilast] != DELIM)
289  {
290  token[i++] = opt_line[ilast++];
291  }
292  token[i] = '\0';
293 
294 /* See if token on line is one to be retrieved */
295 
296  if (strlen(inquest) == strlen(token) &&
297  strncmp(token, inquest, i) == 0)
298  {
299 /* Match found, now determine associated resource.
300  Resource can not start with DELIM or COMMENT characters
301  or any non-printing characters */
302 
303  i = ilast;
304  resource[0] = '\0';
305  while (i < strlen(opt_line)-1 &&
306  (isspace(opt_line[i]) != 0 ||
307  opt_line[i] == DELIM))
308  {
309  i++;
310  }
311 
312 /* Determine contents of resource until:
313  1. End of line is reached, or
314  2. White space is found for resources not quoted, or
315  3. Closing matching quote character is found for quoted strings. */
316 
317  if (i < strlen(opt_line))
318  {
319  if (opt_line[i] != COMMENT)
320  {
321  ilast = i;
322  i = 0;
323 
324 /* Check to see if resource string is quoted (single or double) */
325 
326  if (QPHRASE1)
327  iphrase = 1;
328  else if (QPHRASE2)
329  iphrase = 2;
330  else
331  iphrase = 0;
332 
333 /* Complete resource based on start character conditions */
334 
335  switch (iphrase)
336  {
337  case 0:
338  while (isprint(opt_line[ilast]) && !NPHRASE2)
339  resource[i++] = opt_line[ilast++];
340  break;
341  case 1:
342  ilast++;
343  while (isprint(opt_line[ilast]) && !QPHRASE1)
344  resource[i++] = opt_line[ilast++];
345  break;
346  case 2:
347  ilast++;
348  while (isprint(opt_line[ilast]) && !QPHRASE2)
349  resource[i++] = opt_line[ilast++];
350  break;
351  }
352  resource[i] = '\0';
353 
354 /* Now look for any embedded referbacks in the resource string */
355 
356  while ( ((pOpen = strstr(resource, RFR_OPEN)) != NULL) &&
357  ((pClose = strstr(pOpen, RFR_CLOSE)) != NULL) &&
358  ((diff = (int)(pClose - pOpen) - 2) >= 0 ) )
359  {
360  (void)memset(substitute, '\0', LEN_TOTREPLY+1);
361  if (strcmp(resource, pOpen)) /* SAM, RTi */
362  (void)strncpy(substitute, resource, (pOpen - &resource[0]));
363  if ( diff > 0)
364  {
365  (void)memset(referback, '\0', LEN_TOKEN+1);
366  (void)memset(refer_val, '\0', LEN_REPLY+1);
367  (void)strncpy(referback, pOpen + 2, diff);
368 
369  (void)get_apps_defaults_r(referback, refer_val);
370 
371  if (r_cou > RECUR_LIMIT+1)
372  break;
373 
374  e_len = (int)(strlen(resource) - (int)(pClose - &resource[0]));
375  e_len = e_len - 1;
376  r_len = (int)(strlen(refer_val));
377  if ( ((int)strlen(substitute) + r_len + e_len) > LEN_TOTREPLY)
378  break;
379  else
380  {
381  if (r_len > 0)
382  (void)strcat(substitute, refer_val);
383  }
384  }
385  (void)strcat(substitute, pClose + 1);
386  (void)strcpy(resource, substitute);
387  } /* end of referback expansion while-loop */
388  break;
389  } /* end of non-comment part of resource request if-loop */
390  } /* end of resource request characters if-loop */
391  } /* end of token-been-found if-loop */
392  } /* end of discard-if-delimiter-or-comment check if-loop */
393  } /* end of search for non-blank token char if-loop */
394  } /* end of check for line with a delimiter in it if-loop */
395  } /* end of non-blank line scan if-loop */
396  } /* end of t-r file read to EOL if-loop */
397  if (resource[0]) /* SAM, RTi */
398  break;
399  } /* end of legitimate file opening loop */
400  } /* end of loop thru files named by env vars */
401  } /* end of loop where recursion is less than limit */
402  else
403  {
404  resource[0] = '\0';
405  }
406  } /* end obtaining of resource for given token */
407  return;
408 
409 /* ============== Statements containing RCS keywords: */
410 {static char rcs_id1[] = "$Source: /usr/apps/nwsrfs/util/src/util_gen1/RCS/get_apps_defaults.c,v $";
411  static char rcs_id2[] = "$Id: get_apps_defaults.c,v 1.2 1998/10/14 17:21:09 page Exp $";}
412 /* =================================================== */
413 
414 }