17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*8548bf79Snr123932 * Common Development and Distribution License (the "License"). 6*8548bf79Snr123932 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 227c478bd9Sstevel@tonic-gate * ns_files.c 237c478bd9Sstevel@tonic-gate * 24*8548bf79Snr123932 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <syslog.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <ctype.h> 357c478bd9Sstevel@tonic-gate #include <nsswitch.h> 367c478bd9Sstevel@tonic-gate #include <sys/stat.h> 377c478bd9Sstevel@tonic-gate #include <sys/param.h> 387c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 397c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h> 407c478bd9Sstevel@tonic-gate #include <thread.h> 417c478bd9Sstevel@tonic-gate #include <assert.h> 427c478bd9Sstevel@tonic-gate #include <errno.h> 437c478bd9Sstevel@tonic-gate #include <fcntl.h> 447c478bd9Sstevel@tonic-gate #include <unistd.h> 457c478bd9Sstevel@tonic-gate #include <synch.h> 467c478bd9Sstevel@tonic-gate #include <sys/types.h> 477c478bd9Sstevel@tonic-gate #include <sys/wait.h> 48*8548bf79Snr123932 #include <strings.h> 497c478bd9Sstevel@tonic-gate #include "automount.h" 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate static int read_execout(char *key, char **lp, char *fname, char *line, 527c478bd9Sstevel@tonic-gate int linesz); 53*8548bf79Snr123932 static int call_read_execout(char *key, char **lp, char *fname, char *line, 54*8548bf79Snr123932 int linesz); 557c478bd9Sstevel@tonic-gate static FILE *file_open(char *, char *, char **, char ***); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* 587c478bd9Sstevel@tonic-gate * Initialize the stack 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate void 617c478bd9Sstevel@tonic-gate init_files(char **stack, char ***stkptr) 627c478bd9Sstevel@tonic-gate { 637c478bd9Sstevel@tonic-gate /* 647c478bd9Sstevel@tonic-gate * The call is bogus for automountd since the stack is 657c478bd9Sstevel@tonic-gate * is more appropriately initialized in the thread-private 667c478bd9Sstevel@tonic-gate * routines 677c478bd9Sstevel@tonic-gate */ 687c478bd9Sstevel@tonic-gate if (stack == NULL && stkptr == NULL) 697c478bd9Sstevel@tonic-gate return; 707c478bd9Sstevel@tonic-gate (void) stack_op(INIT, NULL, stack, stkptr); 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate int 747c478bd9Sstevel@tonic-gate getmapent_files(key, mapname, ml, stack, stkptr, iswildcard, isrestricted) 757c478bd9Sstevel@tonic-gate char *key; 767c478bd9Sstevel@tonic-gate char *mapname; 777c478bd9Sstevel@tonic-gate struct mapline *ml; 787c478bd9Sstevel@tonic-gate char **stack, ***stkptr; 797c478bd9Sstevel@tonic-gate bool_t *iswildcard; 807c478bd9Sstevel@tonic-gate bool_t isrestricted; 817c478bd9Sstevel@tonic-gate { 827c478bd9Sstevel@tonic-gate int nserr; 837c478bd9Sstevel@tonic-gate FILE *fp; 847c478bd9Sstevel@tonic-gate char word[MAXPATHLEN+1], wordq[MAXPATHLEN+1]; 857c478bd9Sstevel@tonic-gate char linebuf[LINESZ], lineqbuf[LINESZ]; 867c478bd9Sstevel@tonic-gate char *lp, *lq; 877c478bd9Sstevel@tonic-gate struct stat stbuf; 887c478bd9Sstevel@tonic-gate char fname[MAXFILENAMELEN]; /* /etc prepended to mapname if reqd */ 897c478bd9Sstevel@tonic-gate int syntaxok = 1; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate if (iswildcard) 927c478bd9Sstevel@tonic-gate *iswildcard = FALSE; 937c478bd9Sstevel@tonic-gate if ((fp = file_open(mapname, fname, stack, stkptr)) == NULL) { 947c478bd9Sstevel@tonic-gate nserr = __NSW_UNAVAIL; 957c478bd9Sstevel@tonic-gate goto done; 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if (stat(fname, &stbuf) < 0) { 997c478bd9Sstevel@tonic-gate nserr = __NSW_UNAVAIL; 1007c478bd9Sstevel@tonic-gate goto done; 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * If the file has its execute bit on then 1057c478bd9Sstevel@tonic-gate * assume it's an executable map. 1067c478bd9Sstevel@tonic-gate * Execute it and pass the key as an argument. 1077c478bd9Sstevel@tonic-gate * Expect to get a map entry on the stdout. 1087c478bd9Sstevel@tonic-gate * Ignore the "x" bit on restricted maps. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate if (!isrestricted && (stbuf.st_mode & S_IXUSR)) { 1117c478bd9Sstevel@tonic-gate int rc; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate if (trace > 1) { 1147c478bd9Sstevel@tonic-gate trace_prt(1, 1157c478bd9Sstevel@tonic-gate "\tExecutable map: map=%s key=%s\n", 1167c478bd9Sstevel@tonic-gate fname, key); 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 119*8548bf79Snr123932 rc = call_read_execout(key, &lp, fname, ml->linebuf, LINESZ); 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate if (rc != 0) { 1227c478bd9Sstevel@tonic-gate nserr = __NSW_UNAVAIL; 1237c478bd9Sstevel@tonic-gate goto done; 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 126*8548bf79Snr123932 if (strlen(ml->linebuf) == 0) { 1277c478bd9Sstevel@tonic-gate nserr = __NSW_NOTFOUND; 1287c478bd9Sstevel@tonic-gate goto done; 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate unquote(ml->linebuf, ml->lineqbuf); 1327c478bd9Sstevel@tonic-gate nserr = __NSW_SUCCESS; 1337c478bd9Sstevel@tonic-gate goto done; 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * It's just a normal map file. 1397c478bd9Sstevel@tonic-gate * Search for the entry with the required key. 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate for (;;) { 1427c478bd9Sstevel@tonic-gate lp = get_line(fp, fname, linebuf, sizeof (linebuf)); 1437c478bd9Sstevel@tonic-gate if (lp == NULL) { 1447c478bd9Sstevel@tonic-gate nserr = __NSW_NOTFOUND; 1457c478bd9Sstevel@tonic-gate goto done; 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate if (verbose && syntaxok && isspace(*(uchar_t *)lp)) { 1487c478bd9Sstevel@tonic-gate syntaxok = 0; 1497c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 1507c478bd9Sstevel@tonic-gate "leading space in map entry \"%s\" in %s", 1517c478bd9Sstevel@tonic-gate lp, mapname); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate lq = lineqbuf; 1547c478bd9Sstevel@tonic-gate unquote(lp, lq); 1557c478bd9Sstevel@tonic-gate if ((getword(word, wordq, &lp, &lq, ' ', sizeof (word)) 1567c478bd9Sstevel@tonic-gate == -1) || (word[0] == '\0')) 1577c478bd9Sstevel@tonic-gate continue; 1587c478bd9Sstevel@tonic-gate if (strcmp(word, key) == 0) 1597c478bd9Sstevel@tonic-gate break; 1607c478bd9Sstevel@tonic-gate if (word[0] == '*' && word[1] == '\0') { 1617c478bd9Sstevel@tonic-gate if (iswildcard) 1627c478bd9Sstevel@tonic-gate *iswildcard = TRUE; 1637c478bd9Sstevel@tonic-gate break; 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate if (word[0] == '+') { 1667c478bd9Sstevel@tonic-gate nserr = getmapent(key, word+1, ml, stack, stkptr, 1677c478bd9Sstevel@tonic-gate iswildcard, isrestricted); 1687c478bd9Sstevel@tonic-gate if (nserr == __NSW_SUCCESS) 1697c478bd9Sstevel@tonic-gate goto done; 1707c478bd9Sstevel@tonic-gate continue; 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* 1747c478bd9Sstevel@tonic-gate * sanity check each map entry key against 1757c478bd9Sstevel@tonic-gate * the lookup key as the map is searched. 1767c478bd9Sstevel@tonic-gate */ 1777c478bd9Sstevel@tonic-gate if (verbose && syntaxok) { /* sanity check entry */ 1787c478bd9Sstevel@tonic-gate if (*key == '/') { 1797c478bd9Sstevel@tonic-gate if (*word != '/') { 1807c478bd9Sstevel@tonic-gate syntaxok = 0; 1817c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 1827c478bd9Sstevel@tonic-gate "bad key \"%s\" in direct map %s\n", 1837c478bd9Sstevel@tonic-gate word, mapname); 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate } else { 1867c478bd9Sstevel@tonic-gate if (strchr(word, '/')) { 1877c478bd9Sstevel@tonic-gate syntaxok = 0; 1887c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 1897c478bd9Sstevel@tonic-gate "bad key \"%s\" in indirect map %s\n", 1907c478bd9Sstevel@tonic-gate word, mapname); 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate (void) strcpy(ml->linebuf, lp); 1977c478bd9Sstevel@tonic-gate (void) strcpy(ml->lineqbuf, lq); 1987c478bd9Sstevel@tonic-gate nserr = __NSW_SUCCESS; 1997c478bd9Sstevel@tonic-gate done: 2007c478bd9Sstevel@tonic-gate if (fp) { 2017c478bd9Sstevel@tonic-gate (void) stack_op(POP, (char *)NULL, stack, stkptr); 2027c478bd9Sstevel@tonic-gate (void) fclose(fp); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate return (nserr); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate int 2107c478bd9Sstevel@tonic-gate getmapkeys_files(mapname, list, error, cache_time, stack, stkptr) 2117c478bd9Sstevel@tonic-gate char *mapname; 2127c478bd9Sstevel@tonic-gate struct dir_entry **list; 2137c478bd9Sstevel@tonic-gate int *error; 2147c478bd9Sstevel@tonic-gate int *cache_time; 2157c478bd9Sstevel@tonic-gate char **stack, ***stkptr; 2167c478bd9Sstevel@tonic-gate { 2177c478bd9Sstevel@tonic-gate FILE *fp = NULL; 2187c478bd9Sstevel@tonic-gate char word[MAXPATHLEN+1], wordq[MAXPATHLEN+1]; 2197c478bd9Sstevel@tonic-gate char linebuf[LINESZ], lineqbuf[LINESZ]; 2207c478bd9Sstevel@tonic-gate char *lp, *lq; 2217c478bd9Sstevel@tonic-gate struct stat stbuf; 2227c478bd9Sstevel@tonic-gate char fname[MAXFILENAMELEN]; /* /etc prepended to mapname if reqd */ 2237c478bd9Sstevel@tonic-gate int syntaxok = 1; 2247c478bd9Sstevel@tonic-gate int nserr; 2257c478bd9Sstevel@tonic-gate struct dir_entry *last = NULL; 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate if (trace > 1) 2287c478bd9Sstevel@tonic-gate trace_prt(1, "getmapkeys_files %s\n", mapname); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate *cache_time = RDDIR_CACHE_TIME; 2317c478bd9Sstevel@tonic-gate if ((fp = file_open(mapname, fname, stack, stkptr)) == NULL) { 2327c478bd9Sstevel@tonic-gate *error = ENOENT; 2337c478bd9Sstevel@tonic-gate nserr = __NSW_UNAVAIL; 2347c478bd9Sstevel@tonic-gate goto done; 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate if (fseek(fp, 0L, SEEK_SET) == -1) { 2377c478bd9Sstevel@tonic-gate *error = ENOENT; 2387c478bd9Sstevel@tonic-gate nserr = __NSW_UNAVAIL; 2397c478bd9Sstevel@tonic-gate goto done; 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate if (stat(fname, &stbuf) < 0) { 2437c478bd9Sstevel@tonic-gate *error = ENOENT; 2447c478bd9Sstevel@tonic-gate nserr = __NSW_UNAVAIL; 2457c478bd9Sstevel@tonic-gate goto done; 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * If the file has its execute bit on then 2507c478bd9Sstevel@tonic-gate * assume it's an executable map. 2517c478bd9Sstevel@tonic-gate * I don't know how to list executable maps, return 2527c478bd9Sstevel@tonic-gate * an empty map. 2537c478bd9Sstevel@tonic-gate */ 2547c478bd9Sstevel@tonic-gate if (stbuf.st_mode & S_IXUSR) { 2557c478bd9Sstevel@tonic-gate *error = 0; 2567c478bd9Sstevel@tonic-gate nserr = __NSW_SUCCESS; 2577c478bd9Sstevel@tonic-gate goto done; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate /* 2607c478bd9Sstevel@tonic-gate * It's just a normal map file. 2617c478bd9Sstevel@tonic-gate * List entries one line at a time. 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate for (;;) { 2647c478bd9Sstevel@tonic-gate lp = get_line(fp, fname, linebuf, sizeof (linebuf)); 2657c478bd9Sstevel@tonic-gate if (lp == NULL) { 2667c478bd9Sstevel@tonic-gate nserr = __NSW_SUCCESS; 2677c478bd9Sstevel@tonic-gate goto done; 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate if (syntaxok && isspace(*(uchar_t *)lp)) { 2707c478bd9Sstevel@tonic-gate syntaxok = 0; 2717c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 2727c478bd9Sstevel@tonic-gate "leading space in map entry \"%s\" in %s", 2737c478bd9Sstevel@tonic-gate lp, mapname); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate lq = lineqbuf; 2767c478bd9Sstevel@tonic-gate unquote(lp, lq); 2777c478bd9Sstevel@tonic-gate if ((getword(word, wordq, &lp, &lq, ' ', MAXFILENAMELEN) 2787c478bd9Sstevel@tonic-gate == -1) || (word[0] == '\0')) 2797c478bd9Sstevel@tonic-gate continue; 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * Wildcard entries should be ignored and this should be 2827c478bd9Sstevel@tonic-gate * the last entry read to corroborate the search through 2837c478bd9Sstevel@tonic-gate * files, i.e., search for key until a wildcard is reached. 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate if (word[0] == '*' && word[1] == '\0') 2867c478bd9Sstevel@tonic-gate break; 2877c478bd9Sstevel@tonic-gate if (word[0] == '+') { 2887c478bd9Sstevel@tonic-gate /* 2897c478bd9Sstevel@tonic-gate * Name switch here 2907c478bd9Sstevel@tonic-gate */ 2917c478bd9Sstevel@tonic-gate getmapkeys(word+1, list, error, cache_time, 2927c478bd9Sstevel@tonic-gate stack, stkptr, 0); 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * the list may have been updated, therefore 2957c478bd9Sstevel@tonic-gate * our 'last' may no longer be valid 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate last = NULL; 2987c478bd9Sstevel@tonic-gate continue; 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate if (add_dir_entry(word, list, &last) != 0) { 3027c478bd9Sstevel@tonic-gate *error = ENOMEM; 3037c478bd9Sstevel@tonic-gate goto done; 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate assert(last != NULL); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate nserr = __NSW_SUCCESS; 3097c478bd9Sstevel@tonic-gate done: 3107c478bd9Sstevel@tonic-gate if (fp) { 3117c478bd9Sstevel@tonic-gate (void) stack_op(POP, (char *)NULL, stack, stkptr); 3127c478bd9Sstevel@tonic-gate (void) fclose(fp); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate if (*list != NULL) { 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * list of entries found 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate *error = 0; 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate return (nserr); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 32411606941Sjwahlig int 3257c478bd9Sstevel@tonic-gate loadmaster_files(mastermap, defopts, stack, stkptr) 3267c478bd9Sstevel@tonic-gate char *mastermap; 3277c478bd9Sstevel@tonic-gate char *defopts; 3287c478bd9Sstevel@tonic-gate char **stack, ***stkptr; 3297c478bd9Sstevel@tonic-gate { 3307c478bd9Sstevel@tonic-gate FILE *fp; 3317c478bd9Sstevel@tonic-gate int done = 0; 3327c478bd9Sstevel@tonic-gate char *line, *dir, *map, *opts; 3337c478bd9Sstevel@tonic-gate char linebuf[LINESZ]; 3347c478bd9Sstevel@tonic-gate char lineq[LINESZ]; 3357c478bd9Sstevel@tonic-gate char fname[MAXFILENAMELEN]; /* /etc prepended to mapname if reqd */ 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate if ((fp = file_open(mastermap, fname, stack, stkptr)) == NULL) 3397c478bd9Sstevel@tonic-gate return (__NSW_UNAVAIL); 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate while ((line = get_line(fp, fname, linebuf, 3427c478bd9Sstevel@tonic-gate sizeof (linebuf))) != NULL) { 3437c478bd9Sstevel@tonic-gate unquote(line, lineq); 3447c478bd9Sstevel@tonic-gate if (macro_expand("", line, lineq, LINESZ)) { 3457c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3467c478bd9Sstevel@tonic-gate "map %s: line too long (max %d chars)", 3477c478bd9Sstevel@tonic-gate mastermap, LINESZ - 1); 3487c478bd9Sstevel@tonic-gate continue; 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate dir = line; 3517c478bd9Sstevel@tonic-gate while (*dir && isspace(*dir)) 3527c478bd9Sstevel@tonic-gate dir++; 3537c478bd9Sstevel@tonic-gate if (*dir == '\0') 3547c478bd9Sstevel@tonic-gate continue; 3557c478bd9Sstevel@tonic-gate map = dir; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate while (*map && !isspace(*map)) map++; 3587c478bd9Sstevel@tonic-gate if (*map) 3597c478bd9Sstevel@tonic-gate *map++ = '\0'; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate if (*dir == '+') { 3627c478bd9Sstevel@tonic-gate opts = map; 3637c478bd9Sstevel@tonic-gate while (*opts && isspace(*opts)) 3647c478bd9Sstevel@tonic-gate opts++; 3657c478bd9Sstevel@tonic-gate if (*opts != '-') 3667c478bd9Sstevel@tonic-gate opts = defopts; 3677c478bd9Sstevel@tonic-gate else 3687c478bd9Sstevel@tonic-gate opts++; 3697c478bd9Sstevel@tonic-gate /* 3707c478bd9Sstevel@tonic-gate * Check for no embedded blanks. 3717c478bd9Sstevel@tonic-gate */ 3727c478bd9Sstevel@tonic-gate if (strcspn(opts, " ") == strlen(opts)) { 3737c478bd9Sstevel@tonic-gate dir++; 3747c478bd9Sstevel@tonic-gate (void) loadmaster_map(dir, opts, stack, stkptr); 3757c478bd9Sstevel@tonic-gate } else { 3767c478bd9Sstevel@tonic-gate pr_msg("Warning: invalid entry for %s in %s ignored.\n", dir, fname); 3777c478bd9Sstevel@tonic-gate continue; 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate } else { 3817c478bd9Sstevel@tonic-gate while (*map && isspace(*map)) 3827c478bd9Sstevel@tonic-gate map++; 3837c478bd9Sstevel@tonic-gate if (*map == '\0') 3847c478bd9Sstevel@tonic-gate continue; 3857c478bd9Sstevel@tonic-gate opts = map; 3867c478bd9Sstevel@tonic-gate while (*opts && !isspace(*opts)) 3877c478bd9Sstevel@tonic-gate opts++; 3887c478bd9Sstevel@tonic-gate if (*opts) { 3897c478bd9Sstevel@tonic-gate *opts++ = '\0'; 3907c478bd9Sstevel@tonic-gate while (*opts && isspace(*opts)) 3917c478bd9Sstevel@tonic-gate opts++; 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate if (*opts != '-') 3947c478bd9Sstevel@tonic-gate opts = defopts; 3957c478bd9Sstevel@tonic-gate else 3967c478bd9Sstevel@tonic-gate opts++; 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * Check for no embedded blanks. 3997c478bd9Sstevel@tonic-gate */ 4007c478bd9Sstevel@tonic-gate if (strcspn(opts, " ") == strlen(opts)) { 4017c478bd9Sstevel@tonic-gate dirinit(dir, map, opts, 0, stack, stkptr); 4027c478bd9Sstevel@tonic-gate } else { 4037c478bd9Sstevel@tonic-gate pr_msg("Warning: invalid entry for %s in %s ignored.\n", dir, fname); 4047c478bd9Sstevel@tonic-gate continue; 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate done++; 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate (void) stack_op(POP, (char *)NULL, stack, stkptr); 4117c478bd9Sstevel@tonic-gate (void) fclose(fp); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate return (done ? __NSW_SUCCESS : __NSW_NOTFOUND); 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate 41611606941Sjwahlig int 4177c478bd9Sstevel@tonic-gate loaddirect_files(map, local_map, opts, stack, stkptr) 4187c478bd9Sstevel@tonic-gate char *map, *local_map, *opts; 4197c478bd9Sstevel@tonic-gate char **stack, ***stkptr; 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate FILE *fp; 4227c478bd9Sstevel@tonic-gate int done = 0; 4237c478bd9Sstevel@tonic-gate char *line, *p1, *p2; 4247c478bd9Sstevel@tonic-gate char linebuf[LINESZ]; 4257c478bd9Sstevel@tonic-gate char fname[MAXFILENAMELEN]; /* /etc prepended to mapname if reqd */ 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate if ((fp = file_open(map, fname, stack, stkptr)) == NULL) 4287c478bd9Sstevel@tonic-gate return (__NSW_UNAVAIL); 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate while ((line = get_line(fp, fname, linebuf, 4317c478bd9Sstevel@tonic-gate sizeof (linebuf))) != NULL) { 4327c478bd9Sstevel@tonic-gate p1 = line; 4337c478bd9Sstevel@tonic-gate while (*p1 && isspace(*p1)) 4347c478bd9Sstevel@tonic-gate p1++; 4357c478bd9Sstevel@tonic-gate if (*p1 == '\0') 4367c478bd9Sstevel@tonic-gate continue; 4377c478bd9Sstevel@tonic-gate p2 = p1; 4387c478bd9Sstevel@tonic-gate while (*p2 && !isspace(*p2)) 4397c478bd9Sstevel@tonic-gate p2++; 4407c478bd9Sstevel@tonic-gate *p2 = '\0'; 4417c478bd9Sstevel@tonic-gate if (*p1 == '+') { 4427c478bd9Sstevel@tonic-gate p1++; 4437c478bd9Sstevel@tonic-gate (void) loaddirect_map(p1, local_map, opts, stack, 4447c478bd9Sstevel@tonic-gate stkptr); 4457c478bd9Sstevel@tonic-gate } else { 4467c478bd9Sstevel@tonic-gate dirinit(p1, local_map, opts, 1, stack, stkptr); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate done++; 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate (void) stack_op(POP, (char *)NULL, stack, stkptr); 4527c478bd9Sstevel@tonic-gate (void) fclose(fp); 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate return (done ? __NSW_SUCCESS : __NSW_NOTFOUND); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate /* 4587c478bd9Sstevel@tonic-gate * This procedure opens the file and pushes it onto the 4597c478bd9Sstevel@tonic-gate * the stack. Only if a file is opened successfully, is 4607c478bd9Sstevel@tonic-gate * it pushed onto the stack 4617c478bd9Sstevel@tonic-gate */ 4627c478bd9Sstevel@tonic-gate static FILE * 4637c478bd9Sstevel@tonic-gate file_open(map, fname, stack, stkptr) 4647c478bd9Sstevel@tonic-gate char *map, *fname; 4657c478bd9Sstevel@tonic-gate char **stack, ***stkptr; 4667c478bd9Sstevel@tonic-gate { 4677c478bd9Sstevel@tonic-gate FILE *fp; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate if (*map != '/') { 4707c478bd9Sstevel@tonic-gate /* prepend an "/etc" */ 4717c478bd9Sstevel@tonic-gate (void) strcpy(fname, "/etc/"); 4727c478bd9Sstevel@tonic-gate (void) strcat(fname, map); 4737c478bd9Sstevel@tonic-gate } else 4747c478bd9Sstevel@tonic-gate (void) strcpy(fname, map); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate fp = fopen(fname, "r"); 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate if (fp != NULL) { 4797c478bd9Sstevel@tonic-gate if (!stack_op(PUSH, fname, stack, stkptr)) { 4807c478bd9Sstevel@tonic-gate (void) fclose(fp); 4817c478bd9Sstevel@tonic-gate return (NULL); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate return (fp); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* 4887c478bd9Sstevel@tonic-gate * reimplemnted to be MT-HOT. 4897c478bd9Sstevel@tonic-gate */ 4907c478bd9Sstevel@tonic-gate int 4917c478bd9Sstevel@tonic-gate stack_op(op, name, stack, stkptr) 4927c478bd9Sstevel@tonic-gate int op; 4937c478bd9Sstevel@tonic-gate char *name; 4947c478bd9Sstevel@tonic-gate char **stack, ***stkptr; 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate char **ptr = NULL; 4977c478bd9Sstevel@tonic-gate char **stk_top = &stack[STACKSIZ - 1]; 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * the stackptr points to the next empty slot 5017c478bd9Sstevel@tonic-gate * for PUSH: put the element and increment stkptr 5027c478bd9Sstevel@tonic-gate * for POP: decrement stkptr and free 5037c478bd9Sstevel@tonic-gate */ 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate switch (op) { 5067c478bd9Sstevel@tonic-gate case INIT: 5077c478bd9Sstevel@tonic-gate for (ptr = stack; ptr != stk_top; ptr++) 5087c478bd9Sstevel@tonic-gate *ptr = (char *)NULL; 5097c478bd9Sstevel@tonic-gate *stkptr = stack; 5107c478bd9Sstevel@tonic-gate return (1); 5117c478bd9Sstevel@tonic-gate case ERASE: 5127c478bd9Sstevel@tonic-gate for (ptr = stack; ptr != stk_top; ptr++) 5137c478bd9Sstevel@tonic-gate if (*ptr) { 5147c478bd9Sstevel@tonic-gate if (trace > 1) 5157c478bd9Sstevel@tonic-gate trace_prt(1, " ERASE %s\n", *ptr); 5167c478bd9Sstevel@tonic-gate free (*ptr); 5177c478bd9Sstevel@tonic-gate *ptr = (char *)NULL; 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate *stkptr = stack; 5207c478bd9Sstevel@tonic-gate return (1); 5217c478bd9Sstevel@tonic-gate case PUSH: 5227c478bd9Sstevel@tonic-gate if (*stkptr == stk_top) 5237c478bd9Sstevel@tonic-gate return (0); 5247c478bd9Sstevel@tonic-gate for (ptr = stack; ptr != *stkptr; ptr++) 5257c478bd9Sstevel@tonic-gate if (*ptr && (strcmp(*ptr, name) == 0)) { 5267c478bd9Sstevel@tonic-gate return (0); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate if (trace > 1) 5297c478bd9Sstevel@tonic-gate trace_prt(1, " PUSH %s\n", name); 5307c478bd9Sstevel@tonic-gate if ((**stkptr = strdup(name)) == NULL) { 5317c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "stack_op: Memory alloc failed : %m"); 5327c478bd9Sstevel@tonic-gate return (0); 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate (*stkptr)++; 5357c478bd9Sstevel@tonic-gate return (1); 5367c478bd9Sstevel@tonic-gate case POP: 5377c478bd9Sstevel@tonic-gate if (*stkptr != stack) 5387c478bd9Sstevel@tonic-gate (*stkptr)--; 5397c478bd9Sstevel@tonic-gate else 5407c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Attempt to pop empty stack\n"); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate if (*stkptr && **stkptr) { 5437c478bd9Sstevel@tonic-gate if (trace > 1) 5447c478bd9Sstevel@tonic-gate trace_prt(1, " POP %s\n", **stkptr); 5457c478bd9Sstevel@tonic-gate free (**stkptr); 5467c478bd9Sstevel@tonic-gate **stkptr = (char *)NULL; 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate return (1); 5497c478bd9Sstevel@tonic-gate default: 5507c478bd9Sstevel@tonic-gate return (0); 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate #define READ_EXECOUT_ARGS 3 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate /* 5577c478bd9Sstevel@tonic-gate * read_execout(char *key, char **lp, char *fname, char *line, int linesz) 5587c478bd9Sstevel@tonic-gate * A simpler, multithreaded implementation of popen(). Used due to 5597c478bd9Sstevel@tonic-gate * non multithreaded implementation of popen() (it calls vfork()) and a 5607c478bd9Sstevel@tonic-gate * significant bug in execl(). 5617c478bd9Sstevel@tonic-gate * Returns 0 on OK or -1 on error. 5627c478bd9Sstevel@tonic-gate */ 5637c478bd9Sstevel@tonic-gate static int 5647c478bd9Sstevel@tonic-gate read_execout(char *key, char **lp, char *fname, char *line, int linesz) 5657c478bd9Sstevel@tonic-gate { 5667c478bd9Sstevel@tonic-gate int p[2]; 5677c478bd9Sstevel@tonic-gate int status = 0; 5687c478bd9Sstevel@tonic-gate int child_pid; 5697c478bd9Sstevel@tonic-gate char *args[READ_EXECOUT_ARGS]; 5707c478bd9Sstevel@tonic-gate FILE *fp0; 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate if (pipe(p) < 0) { 5737c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "read_execout: Cannot create pipe"); 5747c478bd9Sstevel@tonic-gate return (-1); 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate /* setup args for execv */ 5787c478bd9Sstevel@tonic-gate if (((args[0] = strdup(fname)) == NULL) || 5797c478bd9Sstevel@tonic-gate ((args[1] = strdup(key)) == NULL)) { 5807c478bd9Sstevel@tonic-gate if (args[0] != NULL) 5817c478bd9Sstevel@tonic-gate free(args[0]); 5827c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "read_execout: Memory allocation failed"); 5837c478bd9Sstevel@tonic-gate return (-1); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate args[2] = NULL; 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate if (trace > 3) 5887c478bd9Sstevel@tonic-gate trace_prt(1, "\tread_execout: forking .....\n"); 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate switch ((child_pid = fork1())) { 5917c478bd9Sstevel@tonic-gate case -1: 5927c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "read_execout: Cannot fork"); 5937c478bd9Sstevel@tonic-gate return (-1); 5947c478bd9Sstevel@tonic-gate case 0: 5957c478bd9Sstevel@tonic-gate /* 5967c478bd9Sstevel@tonic-gate * Child 5977c478bd9Sstevel@tonic-gate */ 5987c478bd9Sstevel@tonic-gate close(p[0]); 5997c478bd9Sstevel@tonic-gate close(1); 6007c478bd9Sstevel@tonic-gate if (fcntl(p[1], F_DUPFD, 1) != 1) { 6017c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 6027c478bd9Sstevel@tonic-gate "read_execout: dup of stdout failed"); 6037c478bd9Sstevel@tonic-gate _exit(-1); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate close(p[1]); 6067c478bd9Sstevel@tonic-gate execv(fname, &args[0]); 6077c478bd9Sstevel@tonic-gate _exit(-1); 6087c478bd9Sstevel@tonic-gate default: 6097c478bd9Sstevel@tonic-gate /* 6107c478bd9Sstevel@tonic-gate * Parent 6117c478bd9Sstevel@tonic-gate */ 6127c478bd9Sstevel@tonic-gate close(p[1]); 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate /* 6157c478bd9Sstevel@tonic-gate * wait for child to complete. Note we read after the 6167c478bd9Sstevel@tonic-gate * child exits to guarantee a full pipe. 6177c478bd9Sstevel@tonic-gate */ 6187c478bd9Sstevel@tonic-gate while (waitpid(child_pid, &status, 0) < 0) { 6197c478bd9Sstevel@tonic-gate /* if waitpid fails with EINTR, restart */ 6207c478bd9Sstevel@tonic-gate if (errno != EINTR) { 6217c478bd9Sstevel@tonic-gate status = -1; 6227c478bd9Sstevel@tonic-gate break; 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate if (status != -1) { 6267c478bd9Sstevel@tonic-gate if ((fp0 = fdopen(p[0], "r")) != NULL) { 6277c478bd9Sstevel@tonic-gate *lp = get_line(fp0, fname, line, linesz); 6287c478bd9Sstevel@tonic-gate fclose(fp0); 6297c478bd9Sstevel@tonic-gate } else { 6307c478bd9Sstevel@tonic-gate close(p[0]); 6317c478bd9Sstevel@tonic-gate status = -1; 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate } else { 6347c478bd9Sstevel@tonic-gate close(p[0]); 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate /* free args */ 6387c478bd9Sstevel@tonic-gate free(args[0]); 6397c478bd9Sstevel@tonic-gate free(args[1]); 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate if (trace > 3) 6427c478bd9Sstevel@tonic-gate trace_prt(1, "\tread_execout: map=%s key=%s line=%s\n", 6437c478bd9Sstevel@tonic-gate fname, key, line); 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate return (status); 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate } 648*8548bf79Snr123932 649*8548bf79Snr123932 void 650*8548bf79Snr123932 automountd_do_exec_map(void *cookie, char *argp, size_t arg_size, 651*8548bf79Snr123932 door_desc_t *dfd, uint_t n_desc) 652*8548bf79Snr123932 { 653*8548bf79Snr123932 command_t *command; 654*8548bf79Snr123932 char line[LINESZ]; 655*8548bf79Snr123932 char *lp; 656*8548bf79Snr123932 int rc; 657*8548bf79Snr123932 658*8548bf79Snr123932 command = (command_t *)argp; 659*8548bf79Snr123932 660*8548bf79Snr123932 if (sizeof (*command) != arg_size) { 661*8548bf79Snr123932 rc = 0; 662*8548bf79Snr123932 syslog(LOG_ERR, "read_execout: invalid door arguments"); 663*8548bf79Snr123932 door_return((char *)&rc, sizeof (rc), NULL, 0); 664*8548bf79Snr123932 } 665*8548bf79Snr123932 666*8548bf79Snr123932 rc = read_execout(command->key, &lp, command->file, line, LINESZ); 667*8548bf79Snr123932 668*8548bf79Snr123932 if (rc != 0) { 669*8548bf79Snr123932 /* 670*8548bf79Snr123932 * read_execout returned an error, return 0 to the door_client 671*8548bf79Snr123932 * to indicate failure 672*8548bf79Snr123932 */ 673*8548bf79Snr123932 rc = 0; 674*8548bf79Snr123932 door_return((char *)&rc, sizeof (rc), NULL, 0); 675*8548bf79Snr123932 } else { 676*8548bf79Snr123932 door_return((char *)line, LINESZ, NULL, 0); 677*8548bf79Snr123932 } 678*8548bf79Snr123932 trace_prt(1, "automountd_do_exec_map, door return failed %s, %s\n", 679*8548bf79Snr123932 command->file, strerror(errno)); 680*8548bf79Snr123932 door_return(NULL, 0, NULL, 0); 681*8548bf79Snr123932 } 682*8548bf79Snr123932 683*8548bf79Snr123932 int 684*8548bf79Snr123932 call_read_execout(char *key, char **lp, char *fname, char *line, 685*8548bf79Snr123932 int linesz) 686*8548bf79Snr123932 { 687*8548bf79Snr123932 command_t command; 688*8548bf79Snr123932 door_arg_t darg; 689*8548bf79Snr123932 int ret; 690*8548bf79Snr123932 691*8548bf79Snr123932 bzero(&command, sizeof (command)); 692*8548bf79Snr123932 (void) strlcpy(command.file, fname, MAXPATHLEN); 693*8548bf79Snr123932 (void) strlcpy(command.key, key, MAXOPTSLEN); 694*8548bf79Snr123932 695*8548bf79Snr123932 if (trace >= 1) 696*8548bf79Snr123932 trace_prt(1, "call_read_execout %s %s\n", fname, key); 697*8548bf79Snr123932 darg.data_ptr = (char *)&command; 698*8548bf79Snr123932 darg.data_size = sizeof (command); 699*8548bf79Snr123932 darg.desc_ptr = NULL; 700*8548bf79Snr123932 darg.desc_num = 0; 701*8548bf79Snr123932 darg.rbuf = line; 702*8548bf79Snr123932 darg.rsize = linesz; 703*8548bf79Snr123932 704*8548bf79Snr123932 ret = door_call(did_exec_map, &darg); 705*8548bf79Snr123932 706*8548bf79Snr123932 lp = &line; 707*8548bf79Snr123932 return (ret); 708*8548bf79Snr123932 } 709