8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / fs.d / nfs / lib / nfslog_config.c
blobaff081912b2c5e7b529208ea796ce5f6a4d41edc
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((void *)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((void *) &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((void *)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 if (config->nc_name)
610 free(config->nc_name);
611 if (config->nc_defaultdir)
612 free(config->nc_defaultdir);
613 if (config->nc_bufferpath)
614 free(config->nc_bufferpath);
615 if (config->nc_rpclogpath)
616 free(config->nc_rpclogpath);
617 if (config->nc_fhpath)
618 free(config->nc_fhpath);
619 if (config->nc_logpath)
620 free(config->nc_logpath);
621 if (config == global)
622 global = NULL;
623 if (config == global_raw)
624 global_raw = NULL;
625 free(config);
628 void
629 nfsl_freeconfig_list(nfsl_config_t **listpp)
631 nfsl_config_t *next;
633 if (*listpp == NULL)
634 return;
636 do {
637 next = (*listpp)->nc_next;
638 free_config(*listpp);
639 *listpp = next;
640 } while (*listpp);
642 free_config(global_raw);
646 * Returns a pointer to the first instance of 'tag' in the list.
647 * If 'remove' is true, then the entry is removed from the list and
648 * a pointer to it is returned.
649 * If '*tail' is not NULL, then it will point to the last element of
650 * the list. Note that this function assumes that *tail already
651 * points at the last element of the list.
652 * Returns NULL if the entry does not exist.
654 static nfsl_config_t *
655 findconfig(
656 nfsl_config_t **listpp,
657 char *tag, boolean_t remove,
658 nfsl_config_t **tail)
660 nfsl_config_t *p, *prev;
662 prev = *listpp;
663 for (p = *listpp; p != NULL; p = p->nc_next) {
664 if (strcmp(p->nc_name, tag) == 0) {
665 if (remove) {
666 if (p == prev) {
668 * first element of the list
670 *listpp = prev->nc_next;
671 } else
672 prev->nc_next = p->nc_next;
674 if (tail != NULL && p == *tail) {
676 * Only update *tail if we removed
677 * the last element of the list, and we
678 * requested *tail to be updated.
680 *tail = prev;
683 return (p);
685 prev = p;
688 return (NULL);
691 static nfsl_config_t *
692 getlastconfig(nfsl_config_t *listp)
694 nfsl_config_t *lastp = NULL;
696 for (; listp != NULL; listp = listp->nc_next)
697 lastp = listp;
699 return (lastp);
703 * Returns a pointer to the first instance of 'tag' in the list.
704 * Returns NULL if the entry does not exist.
705 * Sets 'error' if the update of the list failed if necessary, and
706 * returns NULL.
708 nfsl_config_t *
709 nfsl_findconfig(nfsl_config_t *listp, char *tag, int *error)
711 nfsl_config_t *config;
712 boolean_t updated;
714 *error = 0;
715 config = findconfig(&listp, tag, B_FALSE, (nfsl_config_t **)NULL);
716 if (config == NULL) {
718 * Rebuild our list if the file has changed.
720 if (*error = nfsl_checkconfig_list(&listp, &updated)) {
722 * List may be corrupted, notify caller.
724 return (NULL);
726 if (updated) {
728 * Search for tag again.
730 config = findconfig(&listp, tag, B_FALSE,
731 (nfsl_config_t **)NULL);
735 return (config);
739 * Use the raw global values if any of the parameters is not defined.
741 static void
742 complete_with_global(
743 char **defaultdir,
744 char **bufferpath,
745 char **rpclogpath,
746 char **fhpath,
747 char **logpath,
748 int *logformat)
750 if (*defaultdir == NULL)
751 *defaultdir = global_raw->nc_defaultdir;
752 if (*bufferpath == NULL)
753 *bufferpath = global_raw->nc_bufferpath;
754 if (*rpclogpath == NULL)
755 *rpclogpath = global_raw->nc_rpclogpath;
756 if (*fhpath == NULL)
757 *fhpath = global_raw->nc_fhpath;
758 if (*logpath == NULL)
759 *logpath = global_raw->nc_logpath;
760 if (*logformat == 0)
761 *logformat = global_raw->nc_logformat;
765 * Parses 'linebuf'. Returns 0 if a valid tag is found, otherwise non-zero.
766 * Unknown tokens are silently ignored.
767 * It is the responsibility of the caller to make a copy of the non-NULL
768 * parameters if they need to be used before linebuf is freed.
770 static int
771 get_info(
772 char *linebuf,
773 char **tag,
774 char **defaultdir,
775 char **bufferpath,
776 char **rpclogpath,
777 char **fhpath,
778 char **logpath,
779 int *logformat)
781 char *tok;
782 char *tmp;
784 /* tag */
785 *tag = NULL;
786 tok = strtok(linebuf, whitespace);
787 if (tok == NULL)
788 goto badtag;
789 if (!is_legal_tag(tok))
790 goto badtag;
791 *tag = tok;
793 *defaultdir = *bufferpath = *rpclogpath = NULL;
794 *fhpath = *logpath = NULL;
795 *logformat = 0;
797 while (tok = strtok(NULL, whitespace)) {
798 if (strncmp(tok, "defaultdir=", strlen("defaultdir=")) == 0) {
799 *defaultdir = tok + strlen("defaultdir=");
800 } else if (strncmp(tok, "buffer=", strlen("buffer=")) == 0) {
801 *bufferpath = tok + strlen("buffer=");
802 } else if (strncmp(tok, "rpclog=", strlen("rpclog=")) == 0) {
803 *rpclogpath = tok + strlen("rpclog=");
804 } else if (strncmp(tok, "fhtable=", strlen("fhtable=")) == 0) {
805 *fhpath = tok + strlen("fhtable=");
806 } else if (strncmp(tok, "log=", strlen("log=")) == 0) {
807 *logpath = tok + strlen("log=");
808 } else if (strncmp(tok, "logformat=",
809 strlen("logformat=")) == 0) {
810 tmp = tok + strlen("logformat=");
811 if (strncmp(tmp, "extended", strlen("extended")) == 0) {
812 *logformat = TRANSLOG_EXTENDED;
813 } else {
815 * Use transaction log basic format if
816 * 'extended' was not specified.
818 *logformat = TRANSLOG_BASIC;
823 if (strcmp(*tag, DEFAULTTAG) != 0) {
825 * Use global values for fields not specified if
826 * this tag is not the global tag.
828 complete_with_global(defaultdir, bufferpath,
829 rpclogpath, fhpath, logpath, logformat);
832 return (0);
834 badtag:
835 if (nfsl_errs_to_syslog) {
836 syslog(LOG_ERR, gettext(
837 "Bad tag found in config file."));
838 } else {
839 (void) fprintf(stderr, gettext(
840 "Bad tag found in config file.\n"));
842 return (-1);
846 * Returns True if we have all the elements of a complete configuration
847 * entry. A complete configuration has tag, bufferpath, fhpath and logpath
848 * defined to non-zero strings.
850 static boolean_t
851 is_complete_config(
852 char *tag,
853 char *bufferpath,
854 char *fhpath,
855 char *logpath)
857 assert(tag != NULL);
858 assert(strlen(tag) > 0);
860 if ((bufferpath != NULL && strlen(bufferpath) > 0) &&
861 (fhpath != NULL && strlen(fhpath) > 0) &&
862 (logpath != NULL && strlen(logpath) > 0))
863 return (B_TRUE);
864 return (B_FALSE);
867 #ifdef DEBUG
869 * Prints the configuration entry to stdout.
871 void
872 nfsl_printconfig(nfsl_config_t *config)
874 if (config->nc_name)
875 (void) printf("tag=%s\t", config->nc_name);
876 if (config->nc_defaultdir)
877 (void) printf("defaultdir=%s\t", config->nc_defaultdir);
878 if (config->nc_logpath)
879 (void) printf("logpath=%s\t", config->nc_logpath);
880 if (config->nc_fhpath)
881 (void) printf("fhpath=%s\t", config->nc_fhpath);
882 if (config->nc_bufferpath)
883 (void) printf("bufpath=%s\t", config->nc_bufferpath);
884 if (config->nc_rpclogpath)
885 (void) printf("rpclogpath=%s\t", config->nc_rpclogpath);
886 if (config->nc_logformat == TRANSLOG_BASIC)
887 (void) printf("logformat=basic");
888 else if (config->nc_logformat == TRANSLOG_EXTENDED)
889 (void) printf("logformat=extended");
890 else
891 (void) printf("config->nc_logformat=UNKNOWN");
893 if (config->nc_flags & NC_UPDATED)
894 (void) printf("\tflags=NC_UPDATED");
895 (void) printf("\n");
899 * Prints the configuration list to stdout.
901 void
902 nfsl_printconfig_list(nfsl_config_t *listp)
904 for (; listp != NULL; listp = listp->nc_next) {
905 nfsl_printconfig(listp);
906 (void) printf("\n");
909 #endif /* DEBUG */
912 * Returns non-zero if the given string is allowable for a tag, zero if
913 * not.
915 static int
916 is_legal_tag(char *tag)
918 int i;
919 int len;
921 if (tag == NULL)
922 return (0);
923 len = strlen(tag);
924 if (len == 0)
925 return (0);
927 for (i = 0; i < len; i++) {
928 char c;
930 c = tag[i];
931 if (!(isalnum((unsigned char)c) || c == '_'))
932 return (0);
935 return (1);
939 * gataline attempts to get a line from the configuration file,
940 * upto LINESZ. A line in the file is a concatenation of lines if the
941 * continuation symbol '\' is used at the end of the line. Returns
942 * line on success, a NULL on EOF, and an empty string on lines > linesz.
944 static char *
945 gataline(FILE *fp, char *path, char *line, int linesz) {
946 register char *p = line;
947 register int len;
948 int excess = 0;
950 *p = '\0';
952 for (;;) {
953 if (fgets(p, linesz - (p-line), fp) == NULL) {
954 return (*line ? line : NULL); /* EOF */
957 len = strlen(line);
958 if (len <= 0) {
959 p = line;
960 continue;
962 p = &line[len - 1];
965 * Is input line too long?
967 if (*p != '\n') {
968 excess = 1;
970 * Perhaps last char read was '\'. Reinsert it
971 * into the stream to ease the parsing when we
972 * read the rest of the line to discard.
974 (void) ungetc(*p, fp);
975 break;
977 trim:
979 /* trim trailing white space */
980 while (p >= line && isspace(*(uchar_t *)p))
981 *p-- = '\0';
982 if (p < line) { /* empty line */
983 p = line;
984 continue;
987 if (*p == '\\') { /* continuation */
988 *p = '\0';
989 continue;
993 * Ignore comments. Comments start with '#'
994 * which must be preceded by a whitespace, unless
995 * '#' is the first character in the line.
997 p = line;
999 while (p = strchr(p, '#')) {
1000 if (p == line || isspace(*(p-1))) {
1001 *p-- = '\0';
1002 goto trim;
1004 p++;
1007 break;
1009 if (excess) {
1010 int c;
1013 * discard rest of line and return an empty string.
1014 * done to set the stream to the correct place when
1015 * we are done with this line.
1017 while ((c = getc(fp)) != EOF) {
1018 *p = c;
1019 if (*p == '\n') /* end of the long line */
1020 break;
1021 else if (*p == '\\') { /* continuation */
1022 if (getc(fp) == EOF) /* ignore next char */
1023 break;
1026 if (nfsl_errs_to_syslog) {
1027 syslog(LOG_ERR, gettext(
1028 "%s: line too long - ignored (max %d chars)"),
1029 path, linesz-1);
1030 } else {
1031 (void) fprintf(stderr, gettext(
1032 "%s: line too long - ignored (max %d chars)\n"),
1033 path, linesz-1);
1035 *line = '\0';
1038 return (line);