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 545916cd2Sjpk * Common Development and Distribution License (the "License"). 645916cd2Sjpk * 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 /* 22*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <ctype.h> 277c478bd9Sstevel@tonic-gate #include <stdio.h> 287c478bd9Sstevel@tonic-gate #include <stdlib.h> 297c478bd9Sstevel@tonic-gate #include <unistd.h> 307c478bd9Sstevel@tonic-gate #include <locale.h> 317c478bd9Sstevel@tonic-gate #include <syslog.h> 327c478bd9Sstevel@tonic-gate #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <stdarg.h> 357c478bd9Sstevel@tonic-gate #include <dirent.h> 36*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <limits.h> 377c478bd9Sstevel@tonic-gate #include <thread.h> 387c478bd9Sstevel@tonic-gate #include <sys/param.h> 397c478bd9Sstevel@tonic-gate #include <sys/time.h> 407c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 417c478bd9Sstevel@tonic-gate #include <sys/types.h> 427c478bd9Sstevel@tonic-gate #include <sys/stat.h> 437c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 447c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 457c478bd9Sstevel@tonic-gate #include <sys/mount.h> 467c478bd9Sstevel@tonic-gate #include <sys/signal.h> 477c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 487c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 497c478bd9Sstevel@tonic-gate #include <sys/tiuser.h> 507c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 517c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 527c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h> 53*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <rpcsvc/daemon_utils.h> 547c478bd9Sstevel@tonic-gate #include <assert.h> 557c478bd9Sstevel@tonic-gate #include "automount.h" 566012a713Spetede #include <deflt.h> 5745916cd2Sjpk #include <zone.h> 5845916cd2Sjpk #include <priv.h> 5945916cd2Sjpk #include <fcntl.h> 60*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libshare.h> 61*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libscf.h> 62*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include "smfcfg.h" 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate static char *check_hier(char *); 656012a713Spetede static int arch(char *, size_t, bool_t); 666012a713Spetede static int cpu(char *, size_t); 677c478bd9Sstevel@tonic-gate static int natisa(char *, size_t); 686012a713Spetede static int platform(char *, size_t); 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate struct mntlist *current_mounts; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate static bool_t nodirect_map = FALSE; 737c478bd9Sstevel@tonic-gate 7445916cd2Sjpk /* 7545916cd2Sjpk * If the system is labeled then we need to 7645916cd2Sjpk * have a uniquely-named auto_home map for each zone. 7745916cd2Sjpk * The maps are made unique by appending the zonename. 7845916cd2Sjpk * The home directory is made unique by prepending /zone/<zonename> 7945916cd2Sjpk * for each zone that is dominated by the current zone. 8045916cd2Sjpk * The current zone's home directory mount point is not changed. 8145916cd2Sjpk * 8245916cd2Sjpk * For each auto_home_<zonename> a default template map is created 8345916cd2Sjpk * only if it doesn't exist yet. The default entry is used to declare 8445916cd2Sjpk * local home directories created within each zone. For example: 8545916cd2Sjpk * 8645916cd2Sjpk * +auto_home_public 8745916cd2Sjpk * * -fstype=lofs :/zone/public/export/home/& 8845916cd2Sjpk */ 8945916cd2Sjpk static void 9045916cd2Sjpk loadzone_maps(char *mntpnt, char *map, char *opts, char **stack, char ***stkptr) 9145916cd2Sjpk { 9245916cd2Sjpk zoneid_t *zids = NULL; 9345916cd2Sjpk zoneid_t my_zoneid; 9445916cd2Sjpk uint_t nzents_saved; 9545916cd2Sjpk uint_t nzents; 9645916cd2Sjpk int i; 9745916cd2Sjpk 9845916cd2Sjpk if (!priv_ineffect(PRIV_SYS_MOUNT)) 9945916cd2Sjpk return; 10045916cd2Sjpk 10145916cd2Sjpk if (zone_list(NULL, &nzents) != 0) { 10245916cd2Sjpk return; 10345916cd2Sjpk } 10445916cd2Sjpk my_zoneid = getzoneid(); 10545916cd2Sjpk again: 10645916cd2Sjpk if (nzents == 0) 10745916cd2Sjpk return; 10845916cd2Sjpk 10945916cd2Sjpk zids = malloc(nzents * sizeof (zoneid_t)); 11045916cd2Sjpk nzents_saved = nzents; 11145916cd2Sjpk 11245916cd2Sjpk if (zone_list(zids, &nzents) != 0) { 11345916cd2Sjpk free(zids); 11445916cd2Sjpk return; 11545916cd2Sjpk } 11645916cd2Sjpk if (nzents != nzents_saved) { 11745916cd2Sjpk /* list changed, try again */ 11845916cd2Sjpk free(zids); 11945916cd2Sjpk goto again; 12045916cd2Sjpk } 12145916cd2Sjpk 12245916cd2Sjpk for (i = 0; i < nzents; i++) { 12345916cd2Sjpk char zonename[ZONENAME_MAX]; 12445916cd2Sjpk char zoneroot[MAXPATHLEN]; 12545916cd2Sjpk 12645916cd2Sjpk if (getzonenamebyid(zids[i], zonename, ZONENAME_MAX) != -1) { 12745916cd2Sjpk char appended_map[MAXPATHLEN]; 12845916cd2Sjpk char prepended_mntpnt[MAXPATHLEN]; 12945916cd2Sjpk char map_path[MAXPATHLEN]; 13045916cd2Sjpk int fd; 13145916cd2Sjpk 13245916cd2Sjpk (void) snprintf(appended_map, sizeof (appended_map), 13345916cd2Sjpk "%s_%s", map, zonename); 13445916cd2Sjpk 13545916cd2Sjpk /* for current zone, leave mntpnt alone */ 13645916cd2Sjpk if (zids[i] != my_zoneid) { 13745916cd2Sjpk (void) snprintf(prepended_mntpnt, 13845916cd2Sjpk sizeof (prepended_mntpnt), 13945916cd2Sjpk "/zone/%s%s", zonename, mntpnt); 14045916cd2Sjpk if (zone_getattr(zids[i], ZONE_ATTR_ROOT, 14145916cd2Sjpk zoneroot, sizeof (zoneroot)) == -1) 14245916cd2Sjpk continue; 14345916cd2Sjpk } else { 14445916cd2Sjpk (void) strcpy(prepended_mntpnt, mntpnt); 14545916cd2Sjpk zoneroot[0] = '\0'; 14645916cd2Sjpk } 14745916cd2Sjpk 14845916cd2Sjpk dirinit(prepended_mntpnt, appended_map, opts, 0, stack, 14945916cd2Sjpk stkptr); 15045916cd2Sjpk /* 15145916cd2Sjpk * Next create auto_home_<zone> maps for each zone 15245916cd2Sjpk */ 15345916cd2Sjpk 15445916cd2Sjpk (void) snprintf(map_path, sizeof (map_path), 15545916cd2Sjpk "/etc/%s", appended_map); 15645916cd2Sjpk /* 15745916cd2Sjpk * If the map file doesn't exist create a template 15845916cd2Sjpk */ 15945916cd2Sjpk if ((fd = open(map_path, O_RDWR | O_CREAT | O_EXCL, 16045916cd2Sjpk S_IRUSR | S_IWUSR | S_IRGRP| S_IROTH)) != -1) { 16145916cd2Sjpk int len; 16245916cd2Sjpk char map_rec[MAXPATHLEN]; 16345916cd2Sjpk 16445916cd2Sjpk len = snprintf(map_rec, sizeof (map_rec), 16545916cd2Sjpk "+%s\n*\t-fstype=lofs\t:%s/export/home/&\n", 16645916cd2Sjpk appended_map, zoneroot); 16745916cd2Sjpk if (len <= sizeof (map_rec)) 16845916cd2Sjpk (void) write(fd, map_rec, len); 16945916cd2Sjpk (void) close(fd); 17045916cd2Sjpk } 17145916cd2Sjpk } 17245916cd2Sjpk } 17345916cd2Sjpk free(zids); 17445916cd2Sjpk } 17545916cd2Sjpk 1767c478bd9Sstevel@tonic-gate void 1777c478bd9Sstevel@tonic-gate dirinit(char *mntpnt, char *map, char *opts, int direct, char **stack, 1787c478bd9Sstevel@tonic-gate char ***stkptr) 1797c478bd9Sstevel@tonic-gate { 1807c478bd9Sstevel@tonic-gate struct autodir *dir; 1817c478bd9Sstevel@tonic-gate char *p; 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate if (strcmp(map, "-null") == 0) { 1847c478bd9Sstevel@tonic-gate if (strcmp(mntpnt, "/-") == 0) 1857c478bd9Sstevel@tonic-gate nodirect_map = TRUE; 1867c478bd9Sstevel@tonic-gate goto enter; 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate p = mntpnt + (strlen(mntpnt) - 1); 1907c478bd9Sstevel@tonic-gate if (*p == '/') 1917c478bd9Sstevel@tonic-gate *p = '\0'; /* trim trailing / */ 1927c478bd9Sstevel@tonic-gate if (*mntpnt != '/') { 1937c478bd9Sstevel@tonic-gate pr_msg("dir %s must start with '/'", mntpnt); 1947c478bd9Sstevel@tonic-gate return; 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate if (p = check_hier(mntpnt)) { 1977c478bd9Sstevel@tonic-gate pr_msg("hierarchical mountpoint: %s and %s", 1987c478bd9Sstevel@tonic-gate p, mntpnt); 1997c478bd9Sstevel@tonic-gate return; 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * If it's a direct map then call dirinit 2047c478bd9Sstevel@tonic-gate * for every map entry. 2057c478bd9Sstevel@tonic-gate */ 2067c478bd9Sstevel@tonic-gate if ((strcmp(mntpnt, "/-") == 0) && !(nodirect_map)) { 2077c478bd9Sstevel@tonic-gate (void) loaddirect_map(map, map, opts, stack, stkptr); 2087c478bd9Sstevel@tonic-gate return; 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 21145916cd2Sjpk /* 21245916cd2Sjpk * Home directories are polyinstantiated on 21345916cd2Sjpk * labeled systems. 21445916cd2Sjpk */ 21545916cd2Sjpk if (is_system_labeled() && 21645916cd2Sjpk (strcmp(mntpnt, "/home") == 0) && 21745916cd2Sjpk (strcmp(map, "auto_home") == 0)) { 21845916cd2Sjpk (void) loadzone_maps(mntpnt, map, opts, stack, stkptr); 21945916cd2Sjpk return; 22045916cd2Sjpk } 2217c478bd9Sstevel@tonic-gate enter: 2227c478bd9Sstevel@tonic-gate dir = (struct autodir *)malloc(sizeof (*dir)); 2237c478bd9Sstevel@tonic-gate if (dir == NULL) 2247c478bd9Sstevel@tonic-gate goto alloc_failed; 2257c478bd9Sstevel@tonic-gate dir->dir_name = strdup(mntpnt); 2267c478bd9Sstevel@tonic-gate if (dir->dir_name == NULL) 2277c478bd9Sstevel@tonic-gate goto alloc_failed; 2287c478bd9Sstevel@tonic-gate dir->dir_map = strdup(map); 2297c478bd9Sstevel@tonic-gate if (dir->dir_map == NULL) 2307c478bd9Sstevel@tonic-gate goto alloc_failed; 2317c478bd9Sstevel@tonic-gate dir->dir_opts = strdup(opts); 2327c478bd9Sstevel@tonic-gate if (dir->dir_opts == NULL) 2337c478bd9Sstevel@tonic-gate goto alloc_failed; 2347c478bd9Sstevel@tonic-gate dir->dir_direct = direct; 2357c478bd9Sstevel@tonic-gate dir->dir_remount = 0; 2367c478bd9Sstevel@tonic-gate dir->dir_next = NULL; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * Append to dir chain 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate if (dir_head == NULL) 2427c478bd9Sstevel@tonic-gate dir_head = dir; 2437c478bd9Sstevel@tonic-gate else 2447c478bd9Sstevel@tonic-gate dir_tail->dir_next = dir; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate dir->dir_prev = dir_tail; 2477c478bd9Sstevel@tonic-gate dir_tail = dir; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate return; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate alloc_failed: 2527c478bd9Sstevel@tonic-gate if (dir != NULL) { 2537c478bd9Sstevel@tonic-gate if (dir->dir_opts) 2547c478bd9Sstevel@tonic-gate free(dir->dir_opts); 2557c478bd9Sstevel@tonic-gate if (dir->dir_map) 2567c478bd9Sstevel@tonic-gate free(dir->dir_map); 2577c478bd9Sstevel@tonic-gate if (dir->dir_name) 2587c478bd9Sstevel@tonic-gate free(dir->dir_name); 2597c478bd9Sstevel@tonic-gate free(dir); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate pr_msg("dirinit: memory allocation failed"); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate /* 2657c478bd9Sstevel@tonic-gate * Check whether the mount point is a 2667c478bd9Sstevel@tonic-gate * subdirectory or a parent directory 2677c478bd9Sstevel@tonic-gate * of any previously mounted automount 2687c478bd9Sstevel@tonic-gate * mount point. 2697c478bd9Sstevel@tonic-gate */ 2707c478bd9Sstevel@tonic-gate static char * 2717c478bd9Sstevel@tonic-gate check_hier(mntpnt) 2727c478bd9Sstevel@tonic-gate char *mntpnt; 2737c478bd9Sstevel@tonic-gate { 2747c478bd9Sstevel@tonic-gate register struct autodir *dir; 2757c478bd9Sstevel@tonic-gate register char *p, *q; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate for (dir = dir_head; dir; dir = dir->dir_next) { 2787c478bd9Sstevel@tonic-gate p = dir->dir_name; 2797c478bd9Sstevel@tonic-gate q = mntpnt; 2807c478bd9Sstevel@tonic-gate for (; *p == *q; p++, q++) 2817c478bd9Sstevel@tonic-gate if (*p == '\0') 2827c478bd9Sstevel@tonic-gate break; 2837c478bd9Sstevel@tonic-gate if (*p == '/' && *q == '\0') 2847c478bd9Sstevel@tonic-gate return (dir->dir_name); 2857c478bd9Sstevel@tonic-gate if (*p == '\0' && *q == '/') 2867c478bd9Sstevel@tonic-gate return (dir->dir_name); 2877c478bd9Sstevel@tonic-gate if (*p == '\0' && *q == '\0') 2887c478bd9Sstevel@tonic-gate return (NULL); 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate return (NULL); /* it's not a subdir or parent */ 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2946a6d3e5eSjs195444 * Gets the next token from the string "p" and copies it into "w". The "wq" is 2956a6d3e5eSjs195444 * a quote vector for "w" and is derived from "pq", which is a quote vector for 2966a6d3e5eSjs195444 * "p". Delim is the character to be used as a delimiter for the scan. A space 2976a6d3e5eSjs195444 * means "whitespace". The call to getword must provide buffers w and wq of size 2986a6d3e5eSjs195444 * at least wordsz. getword() will pass strings of maximum length (wordsz-1), 2996a6d3e5eSjs195444 * since it needs to null terminate the string. 3007c478bd9Sstevel@tonic-gate * Returns 0 on ok and -1 on error. 3017c478bd9Sstevel@tonic-gate */ 3027c478bd9Sstevel@tonic-gate int 3037c478bd9Sstevel@tonic-gate getword(char *w, char *wq, char **p, char **pq, char delim, int wordsz) 3047c478bd9Sstevel@tonic-gate { 3057c478bd9Sstevel@tonic-gate char *tmp = w; 3067c478bd9Sstevel@tonic-gate char *tmpq = wq; 3077c478bd9Sstevel@tonic-gate int count = wordsz; 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate if (wordsz <= 0) { 3107c478bd9Sstevel@tonic-gate if (verbose) 3117c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3127c478bd9Sstevel@tonic-gate "getword: input word size %d must be > 0", wordsz); 3137c478bd9Sstevel@tonic-gate return (-1); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate while ((delim == ' ' ? isspace(**p) : **p == delim) && **pq == ' ') 3177c478bd9Sstevel@tonic-gate (*p)++, (*pq)++; 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate while (**p && 3207c478bd9Sstevel@tonic-gate !((delim == ' ' ? isspace(**p) : **p == delim) && 3217c478bd9Sstevel@tonic-gate **pq == ' ')) { 3227c478bd9Sstevel@tonic-gate if (--count <= 0) { 3237c478bd9Sstevel@tonic-gate *tmp = '\0'; 3247c478bd9Sstevel@tonic-gate *tmpq = '\0'; 3257c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3267c478bd9Sstevel@tonic-gate "maximum word length (%d) exceeded", wordsz); 3277c478bd9Sstevel@tonic-gate return (-1); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate *w++ = *(*p)++; 3307c478bd9Sstevel@tonic-gate *wq++ = *(*pq)++; 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate *w = '\0'; 3337c478bd9Sstevel@tonic-gate *wq = '\0'; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate return (0); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate /* 3397c478bd9Sstevel@tonic-gate * get_line attempts to get a line from the map, upto LINESZ. A line in 3407c478bd9Sstevel@tonic-gate * the map is a concatenation of lines if the continuation symbol '\' 3417c478bd9Sstevel@tonic-gate * is used at the end of the line. Returns line on success, a NULL on 3427c478bd9Sstevel@tonic-gate * EOF, and an empty string on lines > linesz. 3437c478bd9Sstevel@tonic-gate */ 3447c478bd9Sstevel@tonic-gate char * 3457c478bd9Sstevel@tonic-gate get_line(FILE *fp, char *map, char *line, int linesz) 3467c478bd9Sstevel@tonic-gate { 3477c478bd9Sstevel@tonic-gate register char *p = line; 3487c478bd9Sstevel@tonic-gate register int len; 3497c478bd9Sstevel@tonic-gate int excess = 0; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate *p = '\0'; 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate for (;;) { 3547c478bd9Sstevel@tonic-gate if (fgets(p, linesz - (p-line), fp) == NULL) { 3557c478bd9Sstevel@tonic-gate return (*line ? line : NULL); /* EOF */ 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate len = strlen(line); 3597c478bd9Sstevel@tonic-gate if (len <= 0) { 3607c478bd9Sstevel@tonic-gate p = line; 3617c478bd9Sstevel@tonic-gate continue; 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate p = &line[len - 1]; 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* 3667c478bd9Sstevel@tonic-gate * Is input line too long? 3677c478bd9Sstevel@tonic-gate */ 3687c478bd9Sstevel@tonic-gate if (*p != '\n') { 3697c478bd9Sstevel@tonic-gate excess = 1; 3707c478bd9Sstevel@tonic-gate /* 3717c478bd9Sstevel@tonic-gate * Perhaps last char read was '\'. Reinsert it 3727c478bd9Sstevel@tonic-gate * into the stream to ease the parsing when we 3737c478bd9Sstevel@tonic-gate * read the rest of the line to discard. 3747c478bd9Sstevel@tonic-gate */ 3757c478bd9Sstevel@tonic-gate (void) ungetc(*p, fp); 3767c478bd9Sstevel@tonic-gate break; 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate trim: 3797c478bd9Sstevel@tonic-gate /* trim trailing white space */ 3807c478bd9Sstevel@tonic-gate while (p >= line && isspace(*(uchar_t *)p)) 3817c478bd9Sstevel@tonic-gate *p-- = '\0'; 3827c478bd9Sstevel@tonic-gate if (p < line) { /* empty line */ 3837c478bd9Sstevel@tonic-gate p = line; 3847c478bd9Sstevel@tonic-gate continue; 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate if (*p == '\\') { /* continuation */ 3887c478bd9Sstevel@tonic-gate *p = '\0'; 3897c478bd9Sstevel@tonic-gate continue; 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate /* 3937c478bd9Sstevel@tonic-gate * Ignore comments. Comments start with '#' 3947c478bd9Sstevel@tonic-gate * which must be preceded by a whitespace, unless 3957c478bd9Sstevel@tonic-gate * if '#' is the first character in the line. 3967c478bd9Sstevel@tonic-gate */ 3977c478bd9Sstevel@tonic-gate p = line; 3987c478bd9Sstevel@tonic-gate while (p = strchr(p, '#')) { 3997c478bd9Sstevel@tonic-gate if (p == line || isspace(*(p-1))) { 4007c478bd9Sstevel@tonic-gate *p-- = '\0'; 4017c478bd9Sstevel@tonic-gate goto trim; 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate p++; 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate break; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate if (excess) { 4087c478bd9Sstevel@tonic-gate int c; 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate /* 4117c478bd9Sstevel@tonic-gate * discard rest of line and return an empty string. 4127c478bd9Sstevel@tonic-gate * done to set the stream to the correct place when 4137c478bd9Sstevel@tonic-gate * we are done with this line. 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) { 4167c478bd9Sstevel@tonic-gate *p = c; 4177c478bd9Sstevel@tonic-gate if (*p == '\n') /* end of the long line */ 4187c478bd9Sstevel@tonic-gate break; 4197c478bd9Sstevel@tonic-gate else if (*p == '\\') { /* continuation */ 4207c478bd9Sstevel@tonic-gate if (getc(fp) == EOF) /* ignore next char */ 4217c478bd9Sstevel@tonic-gate break; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 4257c478bd9Sstevel@tonic-gate "map %s: line too long (max %d chars)", 4267c478bd9Sstevel@tonic-gate map, linesz-1); 4277c478bd9Sstevel@tonic-gate *line = '\0'; 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate return (line); 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate /* 4347c478bd9Sstevel@tonic-gate * Gets the retry=n entry from opts. 4357c478bd9Sstevel@tonic-gate * Returns 0 if retry=n is not present in option string, 4367c478bd9Sstevel@tonic-gate * retry=n is invalid, or when option string is NULL. 4377c478bd9Sstevel@tonic-gate */ 4387c478bd9Sstevel@tonic-gate int 4397c478bd9Sstevel@tonic-gate get_retry(char *opts) 4407c478bd9Sstevel@tonic-gate { 4417c478bd9Sstevel@tonic-gate int retry = 0; 4427c478bd9Sstevel@tonic-gate char buf[MAXOPTSLEN]; 4437c478bd9Sstevel@tonic-gate char *p, *pb, *lasts; 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate if (opts == NULL) 4467c478bd9Sstevel@tonic-gate return (retry); 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate (void) strcpy(buf, opts); 4497c478bd9Sstevel@tonic-gate pb = buf; 4507c478bd9Sstevel@tonic-gate while (p = (char *)strtok_r(pb, ",", &lasts)) { 4517c478bd9Sstevel@tonic-gate pb = NULL; 4527c478bd9Sstevel@tonic-gate if (strncmp(p, "retry=", 6) == 0) 4537c478bd9Sstevel@tonic-gate retry = atoi(p+6); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate return (retry > 0 ? retry : 0); 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate /* 4597c478bd9Sstevel@tonic-gate * Returns zero if "opt" is found in mnt->mnt_opts, setting 4607c478bd9Sstevel@tonic-gate * *sval to whatever follows the equal sign after "opt". 4617c478bd9Sstevel@tonic-gate * str_opt allocates a string long enough to store the value of 4627c478bd9Sstevel@tonic-gate * "opt" plus a terminating null character and returns it as *sval. 4637c478bd9Sstevel@tonic-gate * It is the responsability of the caller to deallocate *sval. 4647c478bd9Sstevel@tonic-gate * *sval will be equal to NULL upon return if either "opt=" is not found, 4657c478bd9Sstevel@tonic-gate * or "opt=" has no value associated with it. 4667c478bd9Sstevel@tonic-gate * 4677c478bd9Sstevel@tonic-gate * stropt will return -1 on error. 4687c478bd9Sstevel@tonic-gate */ 4697c478bd9Sstevel@tonic-gate int 4707c478bd9Sstevel@tonic-gate str_opt(struct mnttab *mnt, char *opt, char **sval) 4717c478bd9Sstevel@tonic-gate { 4727c478bd9Sstevel@tonic-gate char *str, *comma; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * is "opt" in the options field? 4767c478bd9Sstevel@tonic-gate */ 4777c478bd9Sstevel@tonic-gate if (str = hasmntopt(mnt, opt)) { 4787c478bd9Sstevel@tonic-gate str += strlen(opt); 4797c478bd9Sstevel@tonic-gate if (*str++ != '=' || 4807c478bd9Sstevel@tonic-gate (*str == ',' || *str == '\0')) { 4817c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Bad option field"); 4827c478bd9Sstevel@tonic-gate return (-1); 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate comma = strchr(str, ','); 4857c478bd9Sstevel@tonic-gate if (comma != NULL) 4867c478bd9Sstevel@tonic-gate *comma = '\0'; 4877c478bd9Sstevel@tonic-gate *sval = strdup(str); 4887c478bd9Sstevel@tonic-gate if (comma != NULL) 4897c478bd9Sstevel@tonic-gate *comma = ','; 4907c478bd9Sstevel@tonic-gate if (*sval == NULL) 4917c478bd9Sstevel@tonic-gate return (-1); 4927c478bd9Sstevel@tonic-gate } else 4937c478bd9Sstevel@tonic-gate *sval = NULL; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate return (0); 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate /* 4997c478bd9Sstevel@tonic-gate * Performs text expansions in the string "pline". 5007c478bd9Sstevel@tonic-gate * "plineq" is the quote vector for "pline". 5017c478bd9Sstevel@tonic-gate * An identifier prefixed by "$" is replaced by the 5027c478bd9Sstevel@tonic-gate * corresponding environment variable string. A "&" 5037c478bd9Sstevel@tonic-gate * is replaced by the key string for the map entry. 5047c478bd9Sstevel@tonic-gate * 5057c478bd9Sstevel@tonic-gate * This routine will return an error (non-zero) if *size* would be 5067c478bd9Sstevel@tonic-gate * exceeded after expansion, indicating that the macro_expand failed. 5077c478bd9Sstevel@tonic-gate * This is to prevent writing past the end of pline and plineq. 5087c478bd9Sstevel@tonic-gate * Both pline and plineq are left untouched in such error case. 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate int 5117c478bd9Sstevel@tonic-gate macro_expand(key, pline, plineq, size) 5127c478bd9Sstevel@tonic-gate char *key, *pline, *plineq; 5137c478bd9Sstevel@tonic-gate int size; 5147c478bd9Sstevel@tonic-gate { 5157c478bd9Sstevel@tonic-gate register char *p, *q; 5167c478bd9Sstevel@tonic-gate register char *bp, *bq; 5177c478bd9Sstevel@tonic-gate register char *s; 5187c478bd9Sstevel@tonic-gate char buffp[LINESZ], buffq[LINESZ]; 5197c478bd9Sstevel@tonic-gate char namebuf[64], *pn; 5207c478bd9Sstevel@tonic-gate int expand = 0; 5217c478bd9Sstevel@tonic-gate struct utsname name; 5226012a713Spetede char procbuf[SYS_NMLN]; 5237c478bd9Sstevel@tonic-gate char isaname[64]; 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate p = pline; q = plineq; 5267c478bd9Sstevel@tonic-gate bp = buffp; bq = buffq; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate while (*p) { 5297c478bd9Sstevel@tonic-gate if (*p == '&' && *q == ' ') { /* insert key */ 5307c478bd9Sstevel@tonic-gate /* 5317c478bd9Sstevel@tonic-gate * make sure we don't overflow buffer 5327c478bd9Sstevel@tonic-gate */ 5337c478bd9Sstevel@tonic-gate if ((int)((bp - buffp) + strlen(key)) < size) { 5347c478bd9Sstevel@tonic-gate for (s = key; *s; s++) { 5357c478bd9Sstevel@tonic-gate *bp++ = *s; 5367c478bd9Sstevel@tonic-gate *bq++ = ' '; 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate expand++; 5397c478bd9Sstevel@tonic-gate p++; q++; 5407c478bd9Sstevel@tonic-gate continue; 5417c478bd9Sstevel@tonic-gate } else { 5427c478bd9Sstevel@tonic-gate /* 5437c478bd9Sstevel@tonic-gate * line too long... 5447c478bd9Sstevel@tonic-gate */ 5457c478bd9Sstevel@tonic-gate return (1); 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate if (*p == '$' && *q == ' ') { /* insert env var */ 5507c478bd9Sstevel@tonic-gate p++; q++; 5517c478bd9Sstevel@tonic-gate pn = namebuf; 5527c478bd9Sstevel@tonic-gate if (*p == '{') { 5537c478bd9Sstevel@tonic-gate p++; q++; 5547c478bd9Sstevel@tonic-gate while (*p && *p != '}') { 5557c478bd9Sstevel@tonic-gate *pn++ = *p++; 5567c478bd9Sstevel@tonic-gate q++; 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate if (*p) { 5597c478bd9Sstevel@tonic-gate p++; q++; 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate } else { 5627c478bd9Sstevel@tonic-gate while (*p && (*p == '_' || isalnum(*p))) { 5637c478bd9Sstevel@tonic-gate *pn++ = *p++; 5647c478bd9Sstevel@tonic-gate q++; 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate *pn = '\0'; 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate s = getenv(namebuf); 5707c478bd9Sstevel@tonic-gate if (!s) { 5717c478bd9Sstevel@tonic-gate /* not found in env */ 5726012a713Spetede if (strcmp(namebuf, "ARCH") == 0) { 5736012a713Spetede if (arch(procbuf, sizeof (procbuf), 5746012a713Spetede FALSE)) 5756012a713Spetede s = procbuf; 5766012a713Spetede } else if (strcmp(namebuf, "CPU") == 0) { 5776012a713Spetede if (cpu(procbuf, sizeof (procbuf))) 5786012a713Spetede s = procbuf; 5796012a713Spetede } else if (strcmp(namebuf, "HOST") == 0) { 5807c478bd9Sstevel@tonic-gate (void) uname(&name); 5817c478bd9Sstevel@tonic-gate s = name.nodename; 5826012a713Spetede } else if (strcmp(namebuf, "KARCH") == 0) { 5836012a713Spetede if (arch(procbuf, sizeof (procbuf), 5846012a713Spetede TRUE)) 5856012a713Spetede s = procbuf; 5867c478bd9Sstevel@tonic-gate } else if (strcmp(namebuf, "OSREL") == 0) { 5877c478bd9Sstevel@tonic-gate (void) uname(&name); 5887c478bd9Sstevel@tonic-gate s = name.release; 5897c478bd9Sstevel@tonic-gate } else if (strcmp(namebuf, "OSNAME") == 0) { 5907c478bd9Sstevel@tonic-gate (void) uname(&name); 5917c478bd9Sstevel@tonic-gate s = name.sysname; 5927c478bd9Sstevel@tonic-gate } else if (strcmp(namebuf, "OSVERS") == 0) { 5937c478bd9Sstevel@tonic-gate (void) uname(&name); 5947c478bd9Sstevel@tonic-gate s = name.version; 5957c478bd9Sstevel@tonic-gate } else if (strcmp(namebuf, "NATISA") == 0) { 5967c478bd9Sstevel@tonic-gate if (natisa(isaname, sizeof (isaname))) 5977c478bd9Sstevel@tonic-gate s = isaname; 5986012a713Spetede } else if (strcmp(namebuf, "PLATFORM") == 0) { 5996012a713Spetede if (platform(procbuf, sizeof (procbuf))) 6006012a713Spetede s = procbuf; 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate if (s) { 6057c478bd9Sstevel@tonic-gate if ((int)((bp - buffp) + strlen(s)) < size) { 6067c478bd9Sstevel@tonic-gate while (*s) { 6077c478bd9Sstevel@tonic-gate *bp++ = *s++; 6087c478bd9Sstevel@tonic-gate *bq++ = ' '; 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate } else { 6117c478bd9Sstevel@tonic-gate /* 6127c478bd9Sstevel@tonic-gate * line too long... 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate return (1); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate expand++; 6187c478bd9Sstevel@tonic-gate continue; 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate /* 6217c478bd9Sstevel@tonic-gate * Since buffp needs to be null terminated, we need to 6227c478bd9Sstevel@tonic-gate * check that there's still room in the buffer to 6237c478bd9Sstevel@tonic-gate * place at least two more characters, *p and the 6247c478bd9Sstevel@tonic-gate * terminating null. 6257c478bd9Sstevel@tonic-gate */ 6267c478bd9Sstevel@tonic-gate if (bp - buffp == size - 1) { 6277c478bd9Sstevel@tonic-gate /* 6287c478bd9Sstevel@tonic-gate * There was not enough room for at least two more 6297c478bd9Sstevel@tonic-gate * characters, return with an error. 6307c478bd9Sstevel@tonic-gate */ 6317c478bd9Sstevel@tonic-gate return (1); 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate /* 6347c478bd9Sstevel@tonic-gate * The total number of characters so far better be less 6357c478bd9Sstevel@tonic-gate * than the size of buffer passed in. 6367c478bd9Sstevel@tonic-gate */ 6377c478bd9Sstevel@tonic-gate *bp++ = *p++; 6387c478bd9Sstevel@tonic-gate *bq++ = *q++; 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate if (!expand) 6427c478bd9Sstevel@tonic-gate return (0); 6437c478bd9Sstevel@tonic-gate *bp = '\0'; 6447c478bd9Sstevel@tonic-gate *bq = '\0'; 6457c478bd9Sstevel@tonic-gate /* 6467c478bd9Sstevel@tonic-gate * We know buffp/buffq will fit in pline/plineq since we 6477c478bd9Sstevel@tonic-gate * processed at most size characters. 6487c478bd9Sstevel@tonic-gate */ 6497c478bd9Sstevel@tonic-gate (void) strcpy(pline, buffp); 6507c478bd9Sstevel@tonic-gate (void) strcpy(plineq, buffq); 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate return (0); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate /* 6566a6d3e5eSjs195444 * Removes backslashes, quotes and brackets from the string "str" 6576a6d3e5eSjs195444 * and returns the quoting information in "qbuf". Character is 6586a6d3e5eSjs195444 * considered escaped when it is 6596a6d3e5eSjs195444 * 6606a6d3e5eSjs195444 * preceded with '\' e.g. \a 6616a6d3e5eSjs195444 * within quotes e.g. "string" 6626a6d3e5eSjs195444 * a ':' in brackets e.g. [an:ip:6::ad::d:re:s:s] 6636a6d3e5eSjs195444 * 6646a6d3e5eSjs195444 * original str: 'the "brown" f\ox said: [fe80::20a:e4ff:fe35:8b0d]' 6656a6d3e5eSjs195444 * unquoted str: 'the brown fox said: [fe80::20a:e4ff:fe35:8b0d]' 6666a6d3e5eSjs195444 * and the qbuf: ' ^^^^^ ^ ^^ ^ ^ ^ ' 6677c478bd9Sstevel@tonic-gate */ 6687c478bd9Sstevel@tonic-gate void 6697c478bd9Sstevel@tonic-gate unquote(str, qbuf) 6707c478bd9Sstevel@tonic-gate char *str, *qbuf; 6717c478bd9Sstevel@tonic-gate { 6726a6d3e5eSjs195444 register int escaped, inquote, inbracket, quoted; 6737c478bd9Sstevel@tonic-gate register char *ip, *bp, *qp; 6747c478bd9Sstevel@tonic-gate char buf[LINESZ]; 6757c478bd9Sstevel@tonic-gate 6766a6d3e5eSjs195444 escaped = inquote = inbracket = quoted = 0; 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate for (ip = str, bp = buf, qp = qbuf; *ip; ip++) { 6797c478bd9Sstevel@tonic-gate if (!escaped) { 6807c478bd9Sstevel@tonic-gate if (*ip == '\\') { 6817c478bd9Sstevel@tonic-gate escaped = 1; 6827c478bd9Sstevel@tonic-gate quoted++; 6837c478bd9Sstevel@tonic-gate continue; 6847c478bd9Sstevel@tonic-gate } else 6857c478bd9Sstevel@tonic-gate if (*ip == '"') { 6867c478bd9Sstevel@tonic-gate inquote = !inquote; 6877c478bd9Sstevel@tonic-gate quoted++; 6887c478bd9Sstevel@tonic-gate continue; 6896a6d3e5eSjs195444 } else 6906a6d3e5eSjs195444 if (*ip == '[') { 6916a6d3e5eSjs195444 inbracket++; 6926a6d3e5eSjs195444 quoted++; 6936a6d3e5eSjs195444 } else 6946a6d3e5eSjs195444 if (*ip == ']') { 6956a6d3e5eSjs195444 if (inbracket > 0) inbracket--; 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate *bp++ = *ip; 7006a6d3e5eSjs195444 *qp++ = (inquote || escaped) ? '^' 7016a6d3e5eSjs195444 : ((inbracket && (*ip == ':')) ? '^' : ' '); 7027c478bd9Sstevel@tonic-gate escaped = 0; 7037c478bd9Sstevel@tonic-gate } 7046a6d3e5eSjs195444 7057c478bd9Sstevel@tonic-gate *bp = '\0'; 7067c478bd9Sstevel@tonic-gate *qp = '\0'; 7076a6d3e5eSjs195444 7087c478bd9Sstevel@tonic-gate if (quoted) 7097c478bd9Sstevel@tonic-gate (void) strcpy(str, buf); 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate /* 7136a6d3e5eSjs195444 * If str is enclosed in [brackets], trim them off. 7146a6d3e5eSjs195444 */ 7156a6d3e5eSjs195444 void 7166a6d3e5eSjs195444 unbracket(s) 7176a6d3e5eSjs195444 char **s; 7186a6d3e5eSjs195444 { 7196a6d3e5eSjs195444 char *b = *s + strlen(*s) - 1; 7206a6d3e5eSjs195444 7216a6d3e5eSjs195444 if (*b == ']') 7226a6d3e5eSjs195444 *b = '\0'; 7236a6d3e5eSjs195444 if (**s == '[') 7246a6d3e5eSjs195444 (*s)++; 7256a6d3e5eSjs195444 } 7266a6d3e5eSjs195444 7276a6d3e5eSjs195444 /* 7287c478bd9Sstevel@tonic-gate * Removes trailing spaces from string "s". 7297c478bd9Sstevel@tonic-gate */ 7307c478bd9Sstevel@tonic-gate void 7317c478bd9Sstevel@tonic-gate trim(s) 7327c478bd9Sstevel@tonic-gate char *s; 7337c478bd9Sstevel@tonic-gate { 7347c478bd9Sstevel@tonic-gate char *p = &s[strlen(s) - 1]; 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate while (p >= s && isspace(*(uchar_t *)p)) 7377c478bd9Sstevel@tonic-gate *p-- = '\0'; 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate /* 7417c478bd9Sstevel@tonic-gate * try to allocate memory using malloc, if malloc fails, then flush the 7427c478bd9Sstevel@tonic-gate * rddir caches, and retry. If the second allocation after the readdir 7437c478bd9Sstevel@tonic-gate * caches have been flushed fails too, then return NULL to indicate 7447c478bd9Sstevel@tonic-gate * memory could not be allocated. 7457c478bd9Sstevel@tonic-gate */ 7467c478bd9Sstevel@tonic-gate char * 7477c478bd9Sstevel@tonic-gate auto_rddir_malloc(unsigned nbytes) 7487c478bd9Sstevel@tonic-gate { 7497c478bd9Sstevel@tonic-gate char *p; 7507c478bd9Sstevel@tonic-gate int again = 0; 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate if ((p = malloc(nbytes)) == NULL) { 7537c478bd9Sstevel@tonic-gate /* 7547c478bd9Sstevel@tonic-gate * No memory, free rddir caches and try again 7557c478bd9Sstevel@tonic-gate */ 7567c478bd9Sstevel@tonic-gate mutex_lock(&cleanup_lock); 7577c478bd9Sstevel@tonic-gate cond_signal(&cleanup_start_cv); 7587c478bd9Sstevel@tonic-gate if (cond_wait(&cleanup_done_cv, &cleanup_lock)) { 7597c478bd9Sstevel@tonic-gate mutex_unlock(&cleanup_lock); 7607c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "auto_rddir_malloc interrupted\n"); 7617c478bd9Sstevel@tonic-gate } else { 7627c478bd9Sstevel@tonic-gate mutex_unlock(&cleanup_lock); 7637c478bd9Sstevel@tonic-gate again = 1; 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate if (again) 7687c478bd9Sstevel@tonic-gate p = malloc(nbytes); 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate return (p); 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate /* 7747c478bd9Sstevel@tonic-gate * try to strdup a string, if it fails, then flush the rddir caches, 7757c478bd9Sstevel@tonic-gate * and retry. If the second strdup fails, return NULL to indicate failure. 7767c478bd9Sstevel@tonic-gate */ 7777c478bd9Sstevel@tonic-gate char * 7787c478bd9Sstevel@tonic-gate auto_rddir_strdup(const char *s1) 7797c478bd9Sstevel@tonic-gate { 7807c478bd9Sstevel@tonic-gate char *s2; 7817c478bd9Sstevel@tonic-gate int again = 0; 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate if ((s2 = strdup(s1)) == NULL) { 7847c478bd9Sstevel@tonic-gate /* 7857c478bd9Sstevel@tonic-gate * No memory, free rddir caches and try again 7867c478bd9Sstevel@tonic-gate */ 7877c478bd9Sstevel@tonic-gate mutex_lock(&cleanup_lock); 7887c478bd9Sstevel@tonic-gate cond_signal(&cleanup_start_cv); 7897c478bd9Sstevel@tonic-gate if (cond_wait(&cleanup_done_cv, &cleanup_lock)) { 7907c478bd9Sstevel@tonic-gate mutex_unlock(&cleanup_lock); 7917c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "auto_rddir_strdup interrupted\n"); 7927c478bd9Sstevel@tonic-gate } else { 7937c478bd9Sstevel@tonic-gate mutex_unlock(&cleanup_lock); 7947c478bd9Sstevel@tonic-gate again = 1; 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate if (again) 7997c478bd9Sstevel@tonic-gate s2 = strdup(s1); 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate return (s2); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate /* 8057c478bd9Sstevel@tonic-gate * Returns a pointer to the entry corresponding to 'name' if found, 8067c478bd9Sstevel@tonic-gate * otherwise it returns NULL. 8077c478bd9Sstevel@tonic-gate */ 8087c478bd9Sstevel@tonic-gate struct dir_entry * 8097c478bd9Sstevel@tonic-gate btree_lookup(struct dir_entry *head, char *name) 8107c478bd9Sstevel@tonic-gate { 8117c478bd9Sstevel@tonic-gate register struct dir_entry *p; 8127c478bd9Sstevel@tonic-gate register int direction; 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate for (p = head; p != NULL; ) { 8157c478bd9Sstevel@tonic-gate direction = strcmp(name, p->name); 8167c478bd9Sstevel@tonic-gate if (direction == 0) 8177c478bd9Sstevel@tonic-gate return (p); 8187c478bd9Sstevel@tonic-gate if (direction > 0) 8197c478bd9Sstevel@tonic-gate p = p->right; 8207c478bd9Sstevel@tonic-gate else p = p->left; 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate return (NULL); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate /* 8267c478bd9Sstevel@tonic-gate * Add entry to binary tree 8277c478bd9Sstevel@tonic-gate * Duplicate entries are not added 8287c478bd9Sstevel@tonic-gate */ 8297c478bd9Sstevel@tonic-gate void 8307c478bd9Sstevel@tonic-gate btree_enter(struct dir_entry **head, struct dir_entry *ent) 8317c478bd9Sstevel@tonic-gate { 8327c478bd9Sstevel@tonic-gate register struct dir_entry *p, *prev = NULL; 8337c478bd9Sstevel@tonic-gate register int direction; 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate ent->right = ent->left = NULL; 8367c478bd9Sstevel@tonic-gate if (*head == NULL) { 8377c478bd9Sstevel@tonic-gate *head = ent; 8387c478bd9Sstevel@tonic-gate return; 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate for (p = *head; p != NULL; ) { 8427c478bd9Sstevel@tonic-gate prev = p; 8437c478bd9Sstevel@tonic-gate direction = strcmp(ent->name, p->name); 8447c478bd9Sstevel@tonic-gate if (direction == 0) { 8457c478bd9Sstevel@tonic-gate /* 8467c478bd9Sstevel@tonic-gate * entry already in btree 8477c478bd9Sstevel@tonic-gate */ 8487c478bd9Sstevel@tonic-gate return; 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate if (direction > 0) 8517c478bd9Sstevel@tonic-gate p = p->right; 8527c478bd9Sstevel@tonic-gate else p = p->left; 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate assert(prev != NULL); 8557c478bd9Sstevel@tonic-gate if (direction > 0) 8567c478bd9Sstevel@tonic-gate prev->right = ent; 8577c478bd9Sstevel@tonic-gate else prev->left = ent; 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* 8617c478bd9Sstevel@tonic-gate * If entry doesn't exist already, add it to the linear list 8627c478bd9Sstevel@tonic-gate * after '*last' and to the binary tree list. 8637c478bd9Sstevel@tonic-gate * If '*last == NULL' then the list is walked till the end. 8647c478bd9Sstevel@tonic-gate * *last is always set to the new element after successful completion. 8657c478bd9Sstevel@tonic-gate * if entry already exists '*last' is only updated if not previously 8667c478bd9Sstevel@tonic-gate * provided. 8677c478bd9Sstevel@tonic-gate */ 8687c478bd9Sstevel@tonic-gate int 8697c478bd9Sstevel@tonic-gate add_dir_entry(char *name, struct dir_entry **list, struct dir_entry **last) 8707c478bd9Sstevel@tonic-gate { 8717c478bd9Sstevel@tonic-gate struct dir_entry *e, *l; 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate if ((*list != NULL) && (*last == NULL)) { 8747c478bd9Sstevel@tonic-gate /* 8757c478bd9Sstevel@tonic-gate * walk the list to find last element 8767c478bd9Sstevel@tonic-gate */ 8777c478bd9Sstevel@tonic-gate for (l = *list; l != NULL; l = l->next) 8787c478bd9Sstevel@tonic-gate *last = l; 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate if (btree_lookup(*list, name) == NULL) { 8827c478bd9Sstevel@tonic-gate /* 8837c478bd9Sstevel@tonic-gate * not a duplicate, add it to list 8847c478bd9Sstevel@tonic-gate */ 8857c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 8867c478bd9Sstevel@tonic-gate e = (struct dir_entry *) 8877c478bd9Sstevel@tonic-gate auto_rddir_malloc(sizeof (struct dir_entry)); 8887c478bd9Sstevel@tonic-gate if (e == NULL) 8897c478bd9Sstevel@tonic-gate return (ENOMEM); 8907c478bd9Sstevel@tonic-gate (void) memset((char *)e, 0, sizeof (*e)); 8917c478bd9Sstevel@tonic-gate e->name = auto_rddir_strdup(name); 8927c478bd9Sstevel@tonic-gate if (e->name == NULL) { 8937c478bd9Sstevel@tonic-gate free(e); 8947c478bd9Sstevel@tonic-gate return (ENOMEM); 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate e->next = NULL; 8977c478bd9Sstevel@tonic-gate if (*list == NULL) { 8987c478bd9Sstevel@tonic-gate /* 8997c478bd9Sstevel@tonic-gate * list is empty 9007c478bd9Sstevel@tonic-gate */ 9017c478bd9Sstevel@tonic-gate *list = *last = e; 9027c478bd9Sstevel@tonic-gate } else { 9037c478bd9Sstevel@tonic-gate /* 9047c478bd9Sstevel@tonic-gate * append to end of list 9057c478bd9Sstevel@tonic-gate */ 9067c478bd9Sstevel@tonic-gate assert(*last != NULL); 9077c478bd9Sstevel@tonic-gate (*last)->next = e; 9087c478bd9Sstevel@tonic-gate *last = e; 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate /* 9117c478bd9Sstevel@tonic-gate * add to binary tree 9127c478bd9Sstevel@tonic-gate */ 9137c478bd9Sstevel@tonic-gate btree_enter(list, e); 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate return (0); 9167c478bd9Sstevel@tonic-gate } 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate /* 9197c478bd9Sstevel@tonic-gate * Print trace output. 9207c478bd9Sstevel@tonic-gate * Like fprintf(stderr, fmt, ...) except that if "id" is nonzero, the output 9217c478bd9Sstevel@tonic-gate * is preceeded by the ID of the calling thread. 9227c478bd9Sstevel@tonic-gate */ 9237c478bd9Sstevel@tonic-gate #define FMT_BUFSIZ 1024 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate void 9267c478bd9Sstevel@tonic-gate trace_prt(int id, char *fmt, ...) 9277c478bd9Sstevel@tonic-gate { 9287c478bd9Sstevel@tonic-gate va_list args; 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate char buf[FMT_BUFSIZ]; 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate if (id) { 9337c478bd9Sstevel@tonic-gate (void) sprintf(buf, "t%u\t%s", thr_self(), fmt); 9347c478bd9Sstevel@tonic-gate fmt = buf; 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate va_start(args, fmt); 9377c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, args); 9387c478bd9Sstevel@tonic-gate va_end(args); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate /* 9427c478bd9Sstevel@tonic-gate * Extract the isalist(5) for userland from the kernel. 9437c478bd9Sstevel@tonic-gate */ 9447c478bd9Sstevel@tonic-gate static char * 9457c478bd9Sstevel@tonic-gate isalist(void) 9467c478bd9Sstevel@tonic-gate { 9477c478bd9Sstevel@tonic-gate char *buf; 9487c478bd9Sstevel@tonic-gate size_t bufsize = BUFSIZ; /* wild guess */ 9497c478bd9Sstevel@tonic-gate long ret; 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate buf = malloc(bufsize); 9527c478bd9Sstevel@tonic-gate do { 9537c478bd9Sstevel@tonic-gate ret = sysinfo(SI_ISALIST, buf, bufsize); 9547c478bd9Sstevel@tonic-gate if (ret == -1l) 9557c478bd9Sstevel@tonic-gate return (NULL); 9567c478bd9Sstevel@tonic-gate if (ret > bufsize) { 9577c478bd9Sstevel@tonic-gate bufsize = ret; 9587c478bd9Sstevel@tonic-gate buf = realloc(buf, bufsize); 9597c478bd9Sstevel@tonic-gate } else 9607c478bd9Sstevel@tonic-gate break; 9617c478bd9Sstevel@tonic-gate } while (buf != NULL); 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate return (buf); 9647c478bd9Sstevel@tonic-gate } 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate /* 9677c478bd9Sstevel@tonic-gate * Classify isa's as to bitness of the corresponding ABIs. 9687c478bd9Sstevel@tonic-gate * isa's which have no "official" system ABI are returned 9697c478bd9Sstevel@tonic-gate * unrecognised i.e. zero bits. 9707c478bd9Sstevel@tonic-gate */ 9717c478bd9Sstevel@tonic-gate static int 9727c478bd9Sstevel@tonic-gate bitness(char *isaname) 9737c478bd9Sstevel@tonic-gate { 9747c478bd9Sstevel@tonic-gate if (strcmp(isaname, "sparc") == 0 || 9757c478bd9Sstevel@tonic-gate strcmp(isaname, "i386") == 0) 9767c478bd9Sstevel@tonic-gate return (32); 9777c478bd9Sstevel@tonic-gate 97852d1efeeSmaheshvs if (strcmp(isaname, "sparcv9") == 0 || 97952d1efeeSmaheshvs strcmp(isaname, "amd64") == 0) 9807c478bd9Sstevel@tonic-gate return (64); 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate return (0); 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate /* 9866012a713Spetede * Determine the application architecture (derived from uname -m) to expand 9876012a713Spetede * the $ARCH and $KARCH macros. 9886012a713Spetede * 9896012a713Spetede * Like arch(1), we need to substitute "sun4" for "sun4u", "sun4v", ... for 9906012a713Spetede * backward compatibility. When kflag is set (like arch -k), the unmodifed 9916012a713Spetede * value is returned instead. 9926012a713Spetede */ 9936012a713Spetede static int 9946012a713Spetede arch(char *buf, size_t bufsize, bool_t karch) 9956012a713Spetede { 9966012a713Spetede long ret; 9976012a713Spetede 9986012a713Spetede ret = sysinfo(SI_MACHINE, buf, bufsize); 9996012a713Spetede if (ret == -1L) 10006012a713Spetede return (0); 10016012a713Spetede if (!karch && strncmp(buf, "sun4", 4) == 0) 10026012a713Spetede (void) strlcpy(buf, "sun4", bufsize); 10036012a713Spetede return (1); 10046012a713Spetede } 10056012a713Spetede 10066012a713Spetede /* 10076012a713Spetede * Determine the basic ISA (uname -p) to expand the $CPU macro. 10086012a713Spetede */ 10096012a713Spetede static int 10106012a713Spetede cpu(char *buf, size_t bufsize) 10116012a713Spetede { 10126012a713Spetede long ret; 10136012a713Spetede 10146012a713Spetede ret = sysinfo(SI_ARCHITECTURE, buf, bufsize); 10156012a713Spetede if (ret == -1L) 10166012a713Spetede return (0); 10176012a713Spetede else 10186012a713Spetede return (1); 10196012a713Spetede } 10206012a713Spetede 10216012a713Spetede /* 10227c478bd9Sstevel@tonic-gate * Find the left-most element in the isalist that matches our idea of a 10237c478bd9Sstevel@tonic-gate * system ABI. 10247c478bd9Sstevel@tonic-gate * 10257c478bd9Sstevel@tonic-gate * On machines with only one ABI, this is usually the same as uname -p. 10267c478bd9Sstevel@tonic-gate */ 10277c478bd9Sstevel@tonic-gate static int 10287c478bd9Sstevel@tonic-gate natisa(char *buf, size_t bufsize) 10297c478bd9Sstevel@tonic-gate { 10307c478bd9Sstevel@tonic-gate int bits; 10317c478bd9Sstevel@tonic-gate char *isa, *list; 10327c478bd9Sstevel@tonic-gate char *lasts; 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate if ((list = isalist()) == NULL) 10357c478bd9Sstevel@tonic-gate return (0); 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate for (isa = strtok_r(list, " ", &lasts); 10387c478bd9Sstevel@tonic-gate isa; isa = strtok_r(0, " ", &lasts)) 10397c478bd9Sstevel@tonic-gate if ((bits = bitness(isa)) != 0) 10407c478bd9Sstevel@tonic-gate break; /* ignore "extension" architectures */ 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate if (isa == 0 || bits == 0) { 10437c478bd9Sstevel@tonic-gate free(list); 10447c478bd9Sstevel@tonic-gate return (0); /* can't figure it out :( */ 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate (void) strncpy(buf, isa, bufsize); 10487c478bd9Sstevel@tonic-gate free(list); 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate return (1); 10517c478bd9Sstevel@tonic-gate } 10526012a713Spetede 10536012a713Spetede /* 10546012a713Spetede * Determine the platform (uname -i) to expand the $PLATFORM macro. 10556012a713Spetede */ 10566012a713Spetede static int 10576012a713Spetede platform(char *buf, size_t bufsize) 10586012a713Spetede { 10596012a713Spetede long ret; 10606012a713Spetede 10616012a713Spetede ret = sysinfo(SI_PLATFORM, buf, bufsize); 10626012a713Spetede if (ret == -1L) 10636012a713Spetede return (0); 10646012a713Spetede else 10656012a713Spetede return (1); 10666012a713Spetede } 10676012a713Spetede 10686012a713Spetede /* 1069*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Set environment variables 10706012a713Spetede */ 10716012a713Spetede void 10726012a713Spetede put_automountd_env(void) 10736012a713Spetede { 1074*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char defval[PATH_MAX], *p, *a, *c; 1075*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States int ret = 0, bufsz = PATH_MAX; 10766012a713Spetede 1077*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = autofs_smf_get_prop("environment", defval, DEFAULT_INSTANCE, 1078*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States SCF_TYPE_ASTRING, AUTOMOUNTD, &bufsz); 1079*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (ret == SA_OK) { 1080*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States a = c = defval; 1081*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (*a == NULL) 1082*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States return; 1083*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States /* 1084*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Environment variables can have more than one value 1085*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * seperated by a comma and there can be multiple 1086*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * environment variables. * a=b\,c,d=e. For multiple 1087*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * valued environment variable, values are seperated 1088*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * with an escape character. 1089*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States */ 1090*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States while ((p = strchr(c, ',')) != NULL) { 1091*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (*(p - 1) == '\\') { 1092*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States c = p + 1; 1093*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States continue; 1094*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States } 1095*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States *p = '\0'; 1096*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if ((c = strchr(a, '=')) != NULL) 1097*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States putenv(strdup(a)); 1098*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States a = c = p + 1; 1099*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States } 1100*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (*a != NULL) { 1101*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if ((c = strchr(a, '=')) != NULL) 1102*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States putenv(strdup(a)); 1103*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States } 11046012a713Spetede } 11056012a713Spetede } 1106