dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fs.d / nfs / lib / nfslog_config.c
blob263b5b4fbf3d7b16903d0429ac4b9deef812295d
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <ctype.h>
27 #include <errno.h>
28 #include <locale.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <string.h>
34 #include <syslog.h>
35 #include <nfs/nfs.h>
36 #include <assert.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41 #include "nfslog_config.h"
43 #define ERROR_BUFSZ 100
46 * This flag controls where error messages go.
47 * Zero means that messages go to stderr.
48 * Non-zero means that messages go to syslog.
50 boolean_t nfsl_errs_to_syslog;
53 * Pointer to the global entry in the list
55 static nfsl_config_t *global = NULL;
58 * Pointer to the raw global entry in the list, this is the
59 * global entry without the expanded paths. This is used to
60 * complete configurations.
62 static nfsl_config_t *global_raw = NULL;
65 * Last modification time to config file.
67 static timestruc_t config_last_modification = { 0 };
70 * Whitespace characters to delimit fields in a line.
72 static const char *whitespace = " \t";
74 static int getconfiglist(nfsl_config_t **, boolean_t);
75 static nfsl_config_t *create_config(char *, char *, char *, char *, char *,
76 char *, int, boolean_t, int *);
77 static nfsl_config_t *create_global_raw(int *);
78 static int update_config(nfsl_config_t *, char *, char *, char *,
79 char *, char *, char *, int, boolean_t, boolean_t);
80 static int update_field(char **, char *, char *, boolean_t *);
81 static nfsl_config_t *findconfig(nfsl_config_t **, char *, boolean_t,
82 nfsl_config_t **);
83 static nfsl_config_t *getlastconfig(nfsl_config_t *);
84 static void complete_with_global(char **, char **, char **, char **,
85 char **, int *);
86 #ifdef DEBUG
87 static void remove_config(nfsl_config_t **, nfsl_config_t *, nfsl_config_t **);
88 void nfsl_printconfig(nfsl_config_t *);
89 #endif /* DEBUG */
90 static char *gataline(FILE *, char *, char *, int);
91 static int get_info(char *, char **, char **, char **, char **, char **,
92 char **, int *);
93 static void free_config(nfsl_config_t *);
94 static int is_legal_tag(char *);
95 static boolean_t is_complete_config(char *, char *, char *, char *);
98 * Read the configuration file and create a list of configuration
99 * parameters. Returns zero for success or an errno value.
100 * The caller is responsible for freeing the returned configlist by calling
101 * nfsl_freeconfig_list().
103 * If the configuration file does not exist, *listpp points to a config entry
104 * containing the hardwired defaults.
107 nfsl_getconfig_list(nfsl_config_t **listpp)
109 int error = 0;
110 char *locale;
113 * Set the locale correctly so that we can correctly identify
114 * alphabetic characters.
116 if ((locale = getenv("LC_ALL")) != NULL)
117 (void) setlocale(LC_ALL, locale);
118 else if ((locale = getenv("LC_CTYPE")) != NULL)
119 (void) setlocale(LC_CTYPE, locale);
120 else if ((locale = getenv("LANG")) != NULL)
121 (void) setlocale(LC_CTYPE, locale);
124 * Allocate 'global_raw' structure, its contents are
125 * indirectly allocated by create_config().
127 assert(global_raw == NULL);
128 global_raw = create_global_raw(&error);
129 if (global_raw == NULL)
130 return (error);
133 * Build global entry with hardwired defaults first.
135 assert(global == NULL);
136 global = create_config(DEFAULTTAG, DEFAULTDIR, BUFFERPATH, NULL,
137 FHPATH, LOGPATH, TRANSLOG_BASIC, B_TRUE, &error);
138 *listpp = global;
139 if (global == NULL) {
140 free_config(global_raw);
141 return (error);
144 if (error = getconfiglist(listpp, B_FALSE))
145 nfsl_freeconfig_list(listpp);
146 else {
147 assert(global != NULL);
149 * The global entry was replaced with the one in the file,
150 * clear the UPDATED flag
152 global->nc_flags &= ~NC_UPDATED;
154 return (error);
158 * Allocates memory for the 'global_raw' structure.
159 * The actual allocation of values for its components happens in
160 * update_config().
162 static nfsl_config_t *
163 create_global_raw(int *error)
165 nfsl_config_t *p;
167 *error = 0;
168 if (p = (nfsl_config_t *)malloc(sizeof (*p)))
169 (void) memset(p, 0, sizeof (*p));
170 else
171 *error = ENOMEM;
173 return (p);
177 * Checks if the the configuration file has been modified since we last
178 * read it, if not simply returns, otherwise it re-reads it adding new
179 * configuration entries. Note that existing entries that no longer
180 * exist in the configuration file are not removed. Existing entries
181 * that are modified in the configuration file are updated in the list
182 * as well.
183 * if 'updated' is defined then it is set to TRUE if the list was modified.
185 * Note that if an error occurs, the list may be corrupted.
186 * It is the responsibility of the caller to free the list.
187 * If the configuration file does not exist, we simply return the list
188 * that we previously had, log a message and return success.
191 nfsl_checkconfig_list(nfsl_config_t **listpp, boolean_t *updated)
193 struct stat st;
194 int error = 0;
196 if (updated != NULL)
197 *updated = B_FALSE;
199 if (stat(NFSL_CONFIG_FILE_PATH, &st) == -1) {
200 error = errno;
201 if (nfsl_errs_to_syslog) {
202 syslog(LOG_ERR, gettext(
203 "Can't stat %s - %s"), NFSL_CONFIG_FILE_PATH,
204 strerror(error));
205 } else {
206 (void) fprintf(stderr, gettext(
207 "Can't stat %s - %s\n"), NFSL_CONFIG_FILE_PATH,
208 strerror(error));
210 return (0);
213 if (config_last_modification.tv_sec == st.st_mtim.tv_sec &&
214 config_last_modification.tv_nsec == st.st_mtim.tv_nsec)
215 return (0);
217 if (updated != NULL)
218 *updated = B_TRUE;
220 return (getconfiglist(listpp, B_TRUE));
224 * Does the real work. Reads the configuration file and creates the
225 * list of entries. Assumes that *listpp contains at least one entry.
226 * The caller is responsible for freeing any config entries added to
227 * the list whether this routine returns an error or not.
229 * Returns 0 on success and updates the '*listpp' config list,
230 * Returns non-zero error value otherwise.
232 static int
233 getconfiglist(nfsl_config_t **listpp, boolean_t updating)
235 FILE *fp;
236 int error = 0;
237 nfsl_config_t *listp = NULL, *tail = NULL;
238 char linebuf[MAX_LINESZ];
239 char errorbuf[ERROR_BUFSZ];
240 char *tag, *defaultdir, *bufferpath, *rpclogpath, *fhpath, *logpath;
241 int logformat;
242 flock_t flock;
243 struct stat st;
245 fp = fopen(NFSL_CONFIG_FILE_PATH, "r");
246 if (fp == NULL) {
247 if (updating) {
248 (void) sprintf(errorbuf, "Can't open %s",
249 NFSL_CONFIG_FILE_PATH);
250 } else {
251 (void) sprintf(errorbuf,
252 "Can't open %s - using hardwired defaults",
253 NFSL_CONFIG_FILE_PATH);
257 * Use hardwired config.
259 if (nfsl_errs_to_syslog)
260 syslog(LOG_ERR, gettext("%s"), errorbuf);
261 else
262 (void) fprintf(stderr, gettext("%s\n"), errorbuf);
264 return (0);
267 (void) memset(&flock, 0, sizeof (flock));
268 flock.l_type = F_RDLCK;
269 if (fcntl(fileno(fp), F_SETLKW, &flock) == -1) {
270 error = errno;
271 if (nfsl_errs_to_syslog) {
272 syslog(LOG_ERR, gettext(
273 "Can't lock %s - %s"), NFSL_CONFIG_FILE_PATH,
274 strerror(error));
275 } else {
276 (void) fprintf(stderr, gettext(
277 "Can't lock %s - %s\n"), NFSL_CONFIG_FILE_PATH,
278 strerror(error));
280 goto done;
283 assert (*listpp != NULL);
284 tail = getlastconfig(*listpp);
286 while (gataline(fp, NFSL_CONFIG_FILE_PATH, linebuf, sizeof (linebuf))) {
287 if (linebuf[0] == '\0') {
289 * ignore lines that exceed max size
291 continue;
294 if (error = get_info(linebuf, &tag, &defaultdir, &bufferpath,
295 &rpclogpath, &fhpath, &logpath, &logformat))
296 break;
298 if (listp = findconfig(listpp, tag, B_FALSE, &tail)) {
300 * An entry with the same tag name exists,
301 * update the fields that changed.
303 error = update_config(listp, tag, defaultdir,
304 bufferpath, rpclogpath, fhpath, logpath,
305 logformat, B_TRUE, B_TRUE);
306 if (error)
307 break;
308 } else {
310 * New entry, create it.
312 listp = create_config(tag, defaultdir,
313 bufferpath, rpclogpath, fhpath,
314 logpath, logformat, B_TRUE, &error);
315 if (listp == NULL)
316 break;
318 if (*listpp == NULL)
319 *listpp = listp;
320 else
321 tail->nc_next = listp;
322 tail = listp;
325 assert(global != NULL);
328 if (!error) {
330 * Get mtime while we have file locked
332 if (error = fstat(fileno(fp), &st)) {
333 error = errno;
334 if (nfsl_errs_to_syslog) {
335 syslog(LOG_ERR, gettext(
336 "Can't stat %s - %s"), NFSL_CONFIG_FILE_PATH,
337 strerror(error));
338 } else {
339 (void) fprintf(stderr, gettext(
340 "Can't stat %s - %s\n"), NFSL_CONFIG_FILE_PATH,
341 strerror(error));
344 config_last_modification = st.st_mtim;
347 done:
348 (void) fclose(fp);
349 return (error);
353 * Creates the config structure with the values specified by the
354 * parameters. If defaultdir has been specified, all relative paths
355 * are prepended with this defaultdir.
356 * If 'complete' is set then this must represent a complete config entry
357 * as specified by is_complete_config(), otherwise no work is perfomed, and
358 * NULL is returned.
360 * Returns the newly created config structure on success.
361 * Returns NULL on failure and sets error to the appropriate error.
363 static nfsl_config_t *
364 create_config(
365 char *tag,
366 char *defaultdir,
367 char *bufferpath,
368 char *rpclogpath,
369 char *fhpath,
370 char *logpath,
371 int logformat,
372 boolean_t complete,
373 int *error)
375 nfsl_config_t *config;
377 if ((config = (nfsl_config_t *)malloc(sizeof (*config))) == NULL) {
378 *error = ENOMEM;
379 return (NULL);
381 (void) memset(config, 0, sizeof (*config));
383 *error = update_config(config, tag, defaultdir, bufferpath, rpclogpath,
384 fhpath, logpath, logformat, complete, B_TRUE);
385 if (*error) {
386 free(config);
387 return (NULL);
390 config->nc_flags &= ~NC_UPDATED; /* This is a new entry */
392 return (config);
397 * Updates the configuration entry with the new information provided,
398 * sets NC_UPDATED to indicate so. The entry is left untouched if all
399 * the fields are the same (except for 'nc_rpccookie', 'nc_transcookie'
400 * and 'nc_next').
401 * Prepends each path component with 'defauldir' if 'prepend' is set.
403 * Returns 0 on success, error otherwise.
404 * On error, the config entry is left in an inconsistent state.
405 * The only thing the caller can really do with it is free it.
407 static int
408 update_config(
409 nfsl_config_t *config,
410 char *tag,
411 char *defaultdir,
412 char *bufferpath,
413 char *rpclogpath,
414 char *fhpath,
415 char *logpath,
416 int logformat,
417 boolean_t complete,
418 boolean_t prepend)
420 boolean_t updated, config_updated = B_FALSE;
421 int error = 0;
423 if (complete && !is_complete_config(tag, bufferpath, fhpath, logpath)) {
425 * Not a complete entry
427 if (nfsl_errs_to_syslog) {
428 syslog(LOG_ERR, gettext(
429 "update_config: \"%s\" not a complete config entry."),
430 tag);
431 } else {
432 (void) fprintf(stderr, gettext(
433 "update_config: \"%s\" not a complete config entry.\n"),
434 tag);
436 return (EINVAL);
439 assert(tag != NULL);
440 if (config->nc_name == NULL) {
442 * New entry
444 if ((config->nc_name = strdup(tag)) == NULL) {
445 error = ENOMEM;
446 goto errout;
448 } else
449 assert(strcmp(config->nc_name, tag) == 0);
451 if (error = update_field(
452 &config->nc_defaultdir, defaultdir, NULL, &updated))
453 goto errout;
454 if (!prepend) {
456 * Do not prepend default directory.
458 defaultdir = NULL;
460 config_updated |= updated;
461 if (error = update_field(
462 &config->nc_bufferpath, bufferpath, defaultdir, &updated))
463 goto errout;
464 config_updated |= updated;
465 if (error = update_field(
466 &config->nc_rpclogpath, rpclogpath, defaultdir, &updated))
467 goto errout;
468 config_updated |= updated;
469 if (error = update_field(
470 &config->nc_fhpath, fhpath, defaultdir, &updated))
471 goto errout;
472 config_updated |= updated;
473 if (error = update_field(
474 &config->nc_logpath, logpath, defaultdir, &updated))
475 goto errout;
476 config_updated |= updated;
477 updated = (config->nc_logformat != logformat);
478 if (updated)
479 config->nc_logformat = logformat;
480 config_updated |= updated;
482 if (config_updated)
483 config->nc_flags |= NC_UPDATED;
485 if (strcmp(tag, DEFAULTTAG) == 0) {
487 * Have the default global config point to this entry.
489 global = config;
492 * Update the global_raw configuration entry.
493 * Make sure no expanding of paths occurs.
495 if (error = update_config(global_raw, DEFAULTRAWTAG, defaultdir,
496 bufferpath, rpclogpath, fhpath, logpath, logformat,
497 complete, B_FALSE))
498 goto errout;
501 return (error);
503 errout:
504 if (nfsl_errs_to_syslog) {
505 syslog(LOG_ERR, gettext(
506 "update_config: Can't process \"%s\" config entry: %s"),
507 tag, strerror(error));
508 } else {
509 (void) fprintf(stderr, gettext(
510 "update_config: Can't process \"%s\" config entry: %s\n"),
511 tag, strerror(error));
513 return (error);
517 * Prepends 'prependir' to 'new' if 'prependir' is defined.
518 * Compares the value of '*old' with 'new', if it has changed,
519 * then sets whatever 'old' references equal to 'new'.
520 * Returns 0 on success, error otherwise.
521 * Sets '*updated' to B_TRUE if field was modified.
522 * The value of '*updated' is undefined on error.
524 static int
525 update_field(
526 char **old, /* pointer to config field */
527 char *new, /* updated value */
528 char *prependdir, /* prepend this directory to new */
529 boolean_t *updated) /* field was modified */
531 char *tmp_new = NULL;
532 int need_update = 0;
534 if (new != NULL) {
535 if (prependdir != NULL && new[0] != '/') {
536 tmp_new = malloc(strlen(prependdir) + strlen(new) + 2);
537 if (tmp_new == NULL)
538 return (ENOMEM);
539 (void) sprintf(tmp_new, "%s/%s", prependdir, new);
540 } else {
541 if ((tmp_new = strdup(new)) == NULL)
542 return (ENOMEM);
546 if (tmp_new != NULL) {
547 if (*old == NULL)
548 need_update++;
549 else if (strcmp(tmp_new, *old) != 0) {
550 free(*old);
551 need_update++;
553 if (need_update)
554 *old = tmp_new;
555 } else if (*old != NULL) {
556 need_update++;
557 free(*old);
558 *old = NULL;
561 *updated = need_update != 0;
562 return (0);
565 #ifdef DEBUG
567 * Removes and frees the 'config' entry from the list
568 * pointed to by '*listpp'.
569 * No error is reported if the entry does not exist.
570 * Updates '*tail' to point to the last item in the list.
572 static void
573 remove_config(
574 nfsl_config_t **listpp,
575 nfsl_config_t *config,
576 nfsl_config_t **tail)
578 nfsl_config_t *p, *prev;
580 prev = *listpp;
581 for (p = *listpp; p != NULL; p = p->nc_next) {
582 if (p == config) {
583 if (p == prev) {
585 * first element of the list
587 *listpp = prev->nc_next;
588 } else
589 prev->nc_next = p->nc_next;
590 free_config(p);
591 break;
593 prev = p;
597 * Find tail of the list.
599 for (*tail = prev; (*tail)->nc_next != NULL; *tail = (*tail)->nc_next)
602 #endif /* DEBUG */
604 static void
605 free_config(nfsl_config_t *config)
607 if (config == NULL)
608 return;
609 free(config->nc_name);
610 free(config->nc_defaultdir);
611 free(config->nc_bufferpath);
612 free(config->nc_rpclogpath);
613 free(config->nc_fhpath);
614 free(config->nc_logpath);
615 if (config == global)
616 global = NULL;
617 if (config == global_raw)
618 global_raw = NULL;
619 free(config);
622 void
623 nfsl_freeconfig_list(nfsl_config_t **listpp)
625 nfsl_config_t *next;
627 if (*listpp == NULL)
628 return;
630 do {
631 next = (*listpp)->nc_next;
632 free_config(*listpp);
633 *listpp = next;
634 } while (*listpp);
636 free_config(global_raw);
640 * Returns a pointer to the first instance of 'tag' in the list.
641 * If 'remove' is true, then the entry is removed from the list and
642 * a pointer to it is returned.
643 * If '*tail' is not NULL, then it will point to the last element of
644 * the list. Note that this function assumes that *tail already
645 * points at the last element of the list.
646 * Returns NULL if the entry does not exist.
648 static nfsl_config_t *
649 findconfig(
650 nfsl_config_t **listpp,
651 char *tag, boolean_t remove,
652 nfsl_config_t **tail)
654 nfsl_config_t *p, *prev;
656 prev = *listpp;
657 for (p = *listpp; p != NULL; p = p->nc_next) {
658 if (strcmp(p->nc_name, tag) == 0) {
659 if (remove) {
660 if (p == prev) {
662 * first element of the list
664 *listpp = prev->nc_next;
665 } else
666 prev->nc_next = p->nc_next;
668 if (tail != NULL && p == *tail) {
670 * Only update *tail if we removed
671 * the last element of the list, and we
672 * requested *tail to be updated.
674 *tail = prev;
677 return (p);
679 prev = p;
682 return (NULL);
685 static nfsl_config_t *
686 getlastconfig(nfsl_config_t *listp)
688 nfsl_config_t *lastp = NULL;
690 for (; listp != NULL; listp = listp->nc_next)
691 lastp = listp;
693 return (lastp);
697 * Returns a pointer to the first instance of 'tag' in the list.
698 * Returns NULL if the entry does not exist.
699 * Sets 'error' if the update of the list failed if necessary, and
700 * returns NULL.
702 nfsl_config_t *
703 nfsl_findconfig(nfsl_config_t *listp, char *tag, int *error)
705 nfsl_config_t *config;
706 boolean_t updated;
708 *error = 0;
709 config = findconfig(&listp, tag, B_FALSE, (nfsl_config_t **)NULL);
710 if (config == NULL) {
712 * Rebuild our list if the file has changed.
714 if (*error = nfsl_checkconfig_list(&listp, &updated)) {
716 * List may be corrupted, notify caller.
718 return (NULL);
720 if (updated) {
722 * Search for tag again.
724 config = findconfig(&listp, tag, B_FALSE,
725 (nfsl_config_t **)NULL);
729 return (config);
733 * Use the raw global values if any of the parameters is not defined.
735 static void
736 complete_with_global(
737 char **defaultdir,
738 char **bufferpath,
739 char **rpclogpath,
740 char **fhpath,
741 char **logpath,
742 int *logformat)
744 if (*defaultdir == NULL)
745 *defaultdir = global_raw->nc_defaultdir;
746 if (*bufferpath == NULL)
747 *bufferpath = global_raw->nc_bufferpath;
748 if (*rpclogpath == NULL)
749 *rpclogpath = global_raw->nc_rpclogpath;
750 if (*fhpath == NULL)
751 *fhpath = global_raw->nc_fhpath;
752 if (*logpath == NULL)
753 *logpath = global_raw->nc_logpath;
754 if (*logformat == 0)
755 *logformat = global_raw->nc_logformat;
759 * Parses 'linebuf'. Returns 0 if a valid tag is found, otherwise non-zero.
760 * Unknown tokens are silently ignored.
761 * It is the responsibility of the caller to make a copy of the non-NULL
762 * parameters if they need to be used before linebuf is freed.
764 static int
765 get_info(
766 char *linebuf,
767 char **tag,
768 char **defaultdir,
769 char **bufferpath,
770 char **rpclogpath,
771 char **fhpath,
772 char **logpath,
773 int *logformat)
775 char *tok;
776 char *tmp;
778 /* tag */
779 *tag = NULL;
780 tok = strtok(linebuf, whitespace);
781 if (tok == NULL)
782 goto badtag;
783 if (!is_legal_tag(tok))
784 goto badtag;
785 *tag = tok;
787 *defaultdir = *bufferpath = *rpclogpath = NULL;
788 *fhpath = *logpath = NULL;
789 *logformat = 0;
791 while (tok = strtok(NULL, whitespace)) {
792 if (strncmp(tok, "defaultdir=", strlen("defaultdir=")) == 0) {
793 *defaultdir = tok + strlen("defaultdir=");
794 } else if (strncmp(tok, "buffer=", strlen("buffer=")) == 0) {
795 *bufferpath = tok + strlen("buffer=");
796 } else if (strncmp(tok, "rpclog=", strlen("rpclog=")) == 0) {
797 *rpclogpath = tok + strlen("rpclog=");
798 } else if (strncmp(tok, "fhtable=", strlen("fhtable=")) == 0) {
799 *fhpath = tok + strlen("fhtable=");
800 } else if (strncmp(tok, "log=", strlen("log=")) == 0) {
801 *logpath = tok + strlen("log=");
802 } else if (strncmp(tok, "logformat=",
803 strlen("logformat=")) == 0) {
804 tmp = tok + strlen("logformat=");
805 if (strncmp(tmp, "extended", strlen("extended")) == 0) {
806 *logformat = TRANSLOG_EXTENDED;
807 } else {
809 * Use transaction log basic format if
810 * 'extended' was not specified.
812 *logformat = TRANSLOG_BASIC;
817 if (strcmp(*tag, DEFAULTTAG) != 0) {
819 * Use global values for fields not specified if
820 * this tag is not the global tag.
822 complete_with_global(defaultdir, bufferpath,
823 rpclogpath, fhpath, logpath, logformat);
826 return (0);
828 badtag:
829 if (nfsl_errs_to_syslog) {
830 syslog(LOG_ERR, gettext(
831 "Bad tag found in config file."));
832 } else {
833 (void) fprintf(stderr, gettext(
834 "Bad tag found in config file.\n"));
836 return (-1);
840 * Returns True if we have all the elements of a complete configuration
841 * entry. A complete configuration has tag, bufferpath, fhpath and logpath
842 * defined to non-zero strings.
844 static boolean_t
845 is_complete_config(
846 char *tag,
847 char *bufferpath,
848 char *fhpath,
849 char *logpath)
851 assert(tag != NULL);
852 assert(strlen(tag) > 0);
854 if ((bufferpath != NULL && strlen(bufferpath) > 0) &&
855 (fhpath != NULL && strlen(fhpath) > 0) &&
856 (logpath != NULL && strlen(logpath) > 0))
857 return (B_TRUE);
858 return (B_FALSE);
861 #ifdef DEBUG
863 * Prints the configuration entry to stdout.
865 void
866 nfsl_printconfig(nfsl_config_t *config)
868 if (config->nc_name)
869 (void) printf("tag=%s\t", config->nc_name);
870 if (config->nc_defaultdir)
871 (void) printf("defaultdir=%s\t", config->nc_defaultdir);
872 if (config->nc_logpath)
873 (void) printf("logpath=%s\t", config->nc_logpath);
874 if (config->nc_fhpath)
875 (void) printf("fhpath=%s\t", config->nc_fhpath);
876 if (config->nc_bufferpath)
877 (void) printf("bufpath=%s\t", config->nc_bufferpath);
878 if (config->nc_rpclogpath)
879 (void) printf("rpclogpath=%s\t", config->nc_rpclogpath);
880 if (config->nc_logformat == TRANSLOG_BASIC)
881 (void) printf("logformat=basic");
882 else if (config->nc_logformat == TRANSLOG_EXTENDED)
883 (void) printf("logformat=extended");
884 else
885 (void) printf("config->nc_logformat=UNKNOWN");
887 if (config->nc_flags & NC_UPDATED)
888 (void) printf("\tflags=NC_UPDATED");
889 (void) printf("\n");
893 * Prints the configuration list to stdout.
895 void
896 nfsl_printconfig_list(nfsl_config_t *listp)
898 for (; listp != NULL; listp = listp->nc_next) {
899 nfsl_printconfig(listp);
900 (void) printf("\n");
903 #endif /* DEBUG */
906 * Returns non-zero if the given string is allowable for a tag, zero if
907 * not.
909 static int
910 is_legal_tag(char *tag)
912 int i;
913 int len;
915 if (tag == NULL)
916 return (0);
917 len = strlen(tag);
918 if (len == 0)
919 return (0);
921 for (i = 0; i < len; i++) {
922 char c;
924 c = tag[i];
925 if (!(isalnum((unsigned char)c) || c == '_'))
926 return (0);
929 return (1);
933 * gataline attempts to get a line from the configuration file,
934 * upto LINESZ. A line in the file is a concatenation of lines if the
935 * continuation symbol '\' is used at the end of the line. Returns
936 * line on success, a NULL on EOF, and an empty string on lines > linesz.
938 static char *
939 gataline(FILE *fp, char *path, char *line, int linesz) {
940 register char *p = line;
941 register int len;
942 int excess = 0;
944 *p = '\0';
946 for (;;) {
947 if (fgets(p, linesz - (p-line), fp) == NULL) {
948 return (*line ? line : NULL); /* EOF */
951 len = strlen(line);
952 if (len <= 0) {
953 p = line;
954 continue;
956 p = &line[len - 1];
959 * Is input line too long?
961 if (*p != '\n') {
962 excess = 1;
964 * Perhaps last char read was '\'. Reinsert it
965 * into the stream to ease the parsing when we
966 * read the rest of the line to discard.
968 (void) ungetc(*p, fp);
969 break;
971 trim:
973 /* trim trailing white space */
974 while (p >= line && isspace(*(uchar_t *)p))
975 *p-- = '\0';
976 if (p < line) { /* empty line */
977 p = line;
978 continue;
981 if (*p == '\\') { /* continuation */
982 *p = '\0';
983 continue;
987 * Ignore comments. Comments start with '#'
988 * which must be preceded by a whitespace, unless
989 * '#' is the first character in the line.
991 p = line;
993 while (p = strchr(p, '#')) {
994 if (p == line || isspace(*(p-1))) {
995 *p-- = '\0';
996 goto trim;
998 p++;
1001 break;
1003 if (excess) {
1004 int c;
1007 * discard rest of line and return an empty string.
1008 * done to set the stream to the correct place when
1009 * we are done with this line.
1011 while ((c = getc(fp)) != EOF) {
1012 *p = c;
1013 if (*p == '\n') /* end of the long line */
1014 break;
1015 else if (*p == '\\') { /* continuation */
1016 if (getc(fp) == EOF) /* ignore next char */
1017 break;
1020 if (nfsl_errs_to_syslog) {
1021 syslog(LOG_ERR, gettext(
1022 "%s: line too long - ignored (max %d chars)"),
1023 path, linesz-1);
1024 } else {
1025 (void) fprintf(stderr, gettext(
1026 "%s: line too long - ignored (max %d chars)\n"),
1027 path, linesz-1);
1029 *line = '\0';
1032 return (line);