1325392Strasz#!/usr/bin/awk -f
2325392Strasz#-
3325392Strasz# Copyright (c) 2017 G. Paul Ziemba
4325392Strasz# All rights reserved.
5325392Strasz#
6325392Strasz#  Redistribution and use in source and binary forms, with or without
7325392Strasz#  modification, are permitted provided that the following conditions
8325392Strasz#  are met:
9325392Strasz#  1. Redistributions of source code must retain the above copyright
10325392Strasz#     notice, this list of conditions and the following disclaimer.
11325392Strasz#  2. Redistributions in binary form must reproduce the above copyright
12325392Strasz#     notice, this list of conditions and the following disclaimer in the
13325392Strasz#     documentation and/or other materials provided with the distribution.
14325392Strasz#
15325392Strasz#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16325392Strasz#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17325392Strasz#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18325392Strasz#  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19325392Strasz#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20325392Strasz#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21325392Strasz#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22325392Strasz#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23325392Strasz#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24325392Strasz#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25325392Strasz#  SUCH DAMAGE.
26325392Strasz#
27325392Strasz# $FreeBSD: stable/11/etc/autofs/include_nis_nullfs 332587 2018-04-16 15:58:53Z trasz $
28325392Strasz#
29325392Strasz
30325392Strasz#
31326251Strasz# /etc/autofs/include_nis_nullfs
32325392Strasz#
33325392Strasz# automountd Directory Services script for NIS
34325392Strasz#
35325392Strasz# SYNOPSIS
36326251Strasz#       include_nis_nullfs <mapname>
37325392Strasz#
38326251Strasz#       include_nis_nullfs <mapname> <key>
39325392Strasz#
40325392Strasz# DESCRIPTION
41325392Strasz#
42325392Strasz#       This script provides a Directory Services map for automountd
43325392Strasz#       based on NIS. Please see auto_master(5) for general information.
44325392Strasz#
45325392Strasz#       The first form, with one argument, emits the entire named NIS map.
46325392Strasz#       The second form, with two arguments, emits the map entry for the
47325392Strasz#       key given in the second argument. 
48325392Strasz#
49325392Strasz#       This script attempts to determine the names and IP addresses
50325392Strasz#       of the local host. Map entries matching the local host are
51325392Strasz#       rewritten to specify nullfs mounts (instead of the default
52325392Strasz#       NFS) to reduce access overhead in the kernel.
53325392Strasz#
54325392Strasz#	If a map entry contains multiple location fields, it is not changed.
55325392Strasz#
56325392Strasz
57325392Strasz
58325392Strasz# Populate list of names and IP addrs thet mean "this host"
59325392Strasz# into myhostnames array
60325392StraszBEGIN {
61325392Strasz    #
62325392Strasz    # Set self hostnames
63325392Strasz    #
64325392Strasz
65325392Strasz    "hostname -s" | getline;
66325392Strasz    myhostnames[$0] = 1;
67325392Strasz
68325392Strasz    "hostname -f" | getline;
69325392Strasz    myhostnames[$0] = 1;
70325392Strasz
71325392Strasz    myhostnames["localhost"] = 1
72325392Strasz
73325392Strasz    "hostname -f" | getline;
74325392Strasz    localdomain=$0
75325392Strasz    myhostnames["localhost."localdomain] = 1
76325392Strasz
77325392Strasz    while ("ifconfig" | getline) {
78325392Strasz	if ($1 == "inet") {
79325392Strasz	    myhostnames[$2] = 1;
80325392Strasz	}
81325392Strasz    }
82325392Strasz
83325392Strasz    # debug
84325392Strasz#            print "--- hostname list start ----"
85325392Strasz#            for (i in myhostnames) {
86325392Strasz#                print i
87325392Strasz#            }
88325392Strasz#            print "--- hostname list end ----"
89325392Strasz
90325392Strasz    if (ARGC == 2) {
91325392Strasz	# mapname only
92325392Strasz	while ("ypcat -k " ARGV[1] | getline) {
93325392Strasz	    proc_mapline(1)
94325392Strasz	}
95325392Strasz    }
96325392Strasz    if (ARGC == 3) {
97325392Strasz	# mapname and keyname
98325392Strasz	while ("ypmatch " ARGV[2] " " ARGV[1] | getline) {
99325392Strasz	    proc_mapline(0)
100325392Strasz	}
101325392Strasz    }
102325392Strasz    exit 0
103325392Strasz}
104325392Strasz
105325392Straszfunction is_self(hostname)
106325392Strasz{
107325392Strasz    if (myhostnames[hostname]) {
108325392Strasz	return 1
109325392Strasz    }
110325392Strasz    return 0
111325392Strasz}
112325392Strasz
113325392Strasz#
114325392Strasz# Lines are of the form [key] [-opts] location1 [... locationN]
115325392Strasz#
116325392Strasz# indicate index of key field with first positional parameter
117325392Strasz# 1 means keyfield is the first field
118325392Strasz# 0 means keyfield is not present
119325392Strasz#
120325392Straszfunction proc_mapline(keyfield)
121325392Strasz{
122325392Strasz    optionsfield = 0
123325392Strasz    locationfield = 0
124325392Strasz    locationcount = 0
125325392Strasz
126325392Strasz    for (i=keyfield+1; i <= NF; ++i) {
127325392Strasz	if (!optionsfield) {
128325392Strasz	    if ($i ~ /^-/) {
129325392Strasz		# the first options field found on the line
130325392Strasz		optionsfield = i;
131325392Strasz		continue
132325392Strasz	    }
133325392Strasz	}
134325392Strasz	# Assumption: location contains colon (":")
135325392Strasz	if (optionsfield && ($i ~ /:/) && ($i !~ /^-/)) {
136325392Strasz	    ++locationcount
137325392Strasz	    if (!locationfield) {
138325392Strasz		# the first location field found on the line
139325392Strasz		locationfield = i
140325392Strasz	    }
141325392Strasz	}
142325392Strasz    }
143325392Strasz
144325392Strasz    #
145325392Strasz    # If location not found, do not modify.
146325392Strasz    #
147325392Strasz    # If there is more than one location, do not modify. Rationale:
148325392Strasz    # Options are applied to all locations. We ca not have "nullfs"
149325392Strasz    # for only some locations and "nfs" for others for a given
150325392Strasz    # map key (i.e., a line). The usual reason for multiple
151325392Strasz    # locations is for redundancy using replicated volumes on
152325392Strasz    # multiple hosts, so multiple hosts imply fstype=nfs (the
153325392Strasz    # FreeBSD default for automounter maps).
154325392Strasz    #
155325392Strasz    # Hypothetically there could be a map entry with multiple
156325392Strasz    # locations all with host parts matching "me". In that case,
157325392Strasz    # it would be safe to rewrite the locations and specify
158325392Strasz    # nullfs, but the code does not handle this case.
159325392Strasz    #
160325392Strasz    if (locationcount == 1) {
161325392Strasz	#
162325392Strasz	# We have a line with exactly one location field
163325392Strasz	#
164325392Strasz	# Assumption: location has no more than one colon (":")
165325392Strasz	#
166325392Strasz	n=split($locationfield,location,":")
167325392Strasz	if (is_self(location[1])) {
168325392Strasz	    $locationfield = ":" location[2]
169325392Strasz	    if (optionsfield) {
170325392Strasz		# append to existing options
171325392Strasz		$optionsfield = $optionsfield ",fstype=nullfs"
172325392Strasz	    } else {
173325392Strasz		# sneak in ahead of location
174325392Strasz		$locationfield = "-fstype=nullfs " $locationfield
175325392Strasz	    }
176325392Strasz	}
177325392Strasz    }
178325392Strasz
179325392Strasz    print
180325392Strasz}
181