subst.c revision 913c4e9f1445cd8e10b9342def39eee2a29dcfd0
144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o/*
244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o * subst.c --- substitution program
344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o *
444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o * Subst is used as a quicky program to do @ substitutions
544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o *
644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o */
744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#include <stdio.h>
944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#include <errno.h>
1044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#include <stdlib.h>
1144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#include <unistd.h>
1244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#include <string.h>
1344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#include <ctype.h>
1444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
1544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#ifdef HAVE_GETOPT_H
1644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#include <getopt.h>
17691d3353c21a9c8c38d57440808ad7a53827b7dcTheodore Ts'o#else
18691d3353c21a9c8c38d57440808ad7a53827b7dcTheodore Ts'oextern char *optarg;
19691d3353c21a9c8c38d57440808ad7a53827b7dcTheodore Ts'oextern int optind;
2044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#endif
2144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
2244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
2344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostruct subst_entry {
2444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char *name;
2544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char *value;
2644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	struct subst_entry *next;
2744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o};
2844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
2944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostruct subst_entry *subst_table = 0;
3044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
3144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostatic int add_subst(char *name, char *value)
3244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
3344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	struct subst_entry	*ent = 0;
3444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	int	retval;
3544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
3644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	retval = ENOMEM;
3745d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	ent = (struct subst_entry *) malloc(sizeof(struct subst_entry));
3844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (!ent)
3944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		goto fail;
4045d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	ent->name = (char *) malloc(strlen(name)+1);
4144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (!ent->name)
4244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		goto fail;
4345d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	ent->value = (char *) malloc(strlen(value)+1);
4444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (!ent->value)
4544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		goto fail;
4644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	strcpy(ent->name, name);
4744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	strcpy(ent->value, value);
4844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	ent->next = subst_table;
4944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	subst_table = ent;
5044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	return 0;
5144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ofail:
5244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (ent) {
5344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (ent->name)
5444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			free(ent->name);
5544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (ent->value)
5644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			free(ent->value);
5744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		free(ent);
5844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
5944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	return retval;
6044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
6144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
6244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostatic struct subst_entry *fetch_subst_entry(char *name)
6344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
6444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	struct subst_entry *ent;
6544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
6644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	for (ent = subst_table; ent; ent = ent->next) {
6744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (strcmp(name, ent->name) == 0)
6844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
6944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
7044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	return ent;
7144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
7244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
73e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o/*
74e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o * Given the starting and ending position of the replacement name,
75e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o * check to see if it is valid, and pull it out if it is.
76e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o */
77e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'ostatic char *get_subst_symbol(const char *begin, int len, char prefix)
78e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o{
79e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	static char replace_name[128];
80e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	char *cp, *start;
81e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
82e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	start = replace_name;
83e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	if (prefix)
84e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		*start++ = prefix;
85e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
86e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	if (len > sizeof(replace_name)-2)
87e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		return NULL;
88e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	memcpy(start, begin, len);
89e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	start[len] = 0;
90e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
91e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	/*
927822c1d410a1c6e98f8367de7593ca6e52df1f37Theodore Ts'o	 * The substitution variable must all be in the of [0-9A-Za-z_].
93e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 * If it isn't, this must be an invalid symbol name.
94e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 */
95e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	for (cp = start; *cp; cp++) {
96e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!(*cp >= 'a' && *cp <= 'z') &&
97e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		    !(*cp >= 'A' && *cp <= 'Z') &&
987822c1d410a1c6e98f8367de7593ca6e52df1f37Theodore Ts'o		    !(*cp >= '0' && *cp <= '9') &&
99e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		    !(*cp == '_'))
100e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			return NULL;
101e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	}
102e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	return (replace_name);
103e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o}
104e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
105e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'ostatic void replace_string(char *begin, char *end, char *newstr)
106e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o{
107e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	int	replace_len, len;
108e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
109e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	replace_len = strlen(newstr);
110e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	len = end - begin;
111913c4e9f1445cd8e10b9342def39eee2a29dcfd0Theodore Ts'o	if (replace_len == 0)
112913c4e9f1445cd8e10b9342def39eee2a29dcfd0Theodore Ts'o		memmove(begin, end+1, strlen(end)+1);
113913c4e9f1445cd8e10b9342def39eee2a29dcfd0Theodore Ts'o	else if (replace_len != len+1)
114e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		memmove(end+(replace_len-len-1), end,
115e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			strlen(end)+1);
116e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	memcpy(begin, newstr, replace_len);
117e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o}
118e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
11944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostatic void substitute_line(char *line)
12044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
121cdceb0496f7ae23f685a409ab070f3431bcad520Theodore Ts'o	char	*ptr, *name_ptr, *end_ptr;
12244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	struct subst_entry *ent;
123e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	char	*replace_name;
124cdceb0496f7ae23f685a409ab070f3431bcad520Theodore Ts'o	int	len;
12544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
126e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	/*
127e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 * Expand all @FOO@ substitutions
128e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 */
12944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	ptr = line;
13044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	while (ptr) {
13144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		name_ptr = strchr(ptr, '@');
13244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!name_ptr)
133e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			break;	/* No more */
134e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (*(++name_ptr) == '@') {
135e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			/*
136e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			 * Handle tytso@@mit.edu --> tytso@mit.edu
137e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			 */
138e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			memmove(name_ptr-1, name_ptr, strlen(name_ptr)+1);
139e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			ptr = name_ptr+1;
140e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			continue;
141e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		}
142e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		end_ptr = strchr(name_ptr, '@');
14344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!end_ptr)
14444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
145e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		len = end_ptr - name_ptr;
146e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		replace_name = get_subst_symbol(name_ptr, len, 0);
147e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!replace_name) {
148e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			ptr = name_ptr;
149e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			continue;
150e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		}
15144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		ent = fetch_subst_entry(replace_name);
15244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!ent) {
15344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			fprintf(stderr, "Unfound expansion: '%s'\n",
15444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				replace_name);
15544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			ptr = end_ptr + 1;
15644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			continue;
15744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
15844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#if 0
15944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		fprintf(stderr, "Replace name = '%s' with '%s'\n",
16044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		       replace_name, ent->value);
16144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#endif
162e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		ptr = name_ptr-1;
163e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		replace_string(ptr, end_ptr, ent->value);
164e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	}
165e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	/*
166e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 * Now do a second pass to expand ${FOO}
167e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 */
168e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	ptr = line;
169e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	while (ptr) {
170e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		name_ptr = strchr(ptr, '$');
171e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!name_ptr)
172e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			break;	/* No more */
173e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (*(++name_ptr) != '{') {
174e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			ptr = name_ptr;
175e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			continue;
176e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		}
177e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		name_ptr++;
178e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		end_ptr = strchr(name_ptr, '}');
179e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!end_ptr)
180e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			break;
181e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		len = end_ptr - name_ptr;
182e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		replace_name = get_subst_symbol(name_ptr, len, '$');
183e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!replace_name) {
184e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			ptr = name_ptr;
185e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			continue;
186e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		}
187e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		ent = fetch_subst_entry(replace_name);
188e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!ent) {
189e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			ptr = end_ptr + 1;
190e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			continue;
191e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		}
192e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o#if 0
193e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		fprintf(stderr, "Replace name = '%s' with '%s'\n",
194e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		       replace_name, ent->value);
195e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o#endif
196e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		ptr = name_ptr-2;
197e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		replace_string(ptr, end_ptr, ent->value);
19844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
19944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
20044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
20144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostatic void parse_config_file(FILE *f)
20244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
20344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char	line[2048];
20444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char	*cp, *ptr;
20544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
20644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	while (!feof(f)) {
20744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		memset(line, 0, sizeof(line));
20844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (fgets(line, sizeof(line), f) == NULL)
20944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
21044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		/*
21144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 * Strip newlines and comments.
21244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 */
21344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		cp = strchr(line, '\n');
21444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (cp)
21544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			*cp = 0;
21644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		cp = strchr(line, '#');
21744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (cp)
21844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			*cp = 0;
21944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		/*
22044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 * Skip trailing and leading whitespace
22144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 */
22244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		for (cp = line + strlen(line) - 1; cp >= line; cp--) {
22344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (*cp == ' ' || *cp == '\t')
22444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				*cp = 0;
22544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			else
22644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				break;
22744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
22844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		cp = line;
22944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		while (*cp && isspace(*cp))
23044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			cp++;
23144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		ptr = cp;
23244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		/*
23344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 * Skip empty lines
23444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 */
23544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (*ptr == 0)
23644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			continue;
23744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		/*
23844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 * Ignore future extensions
23944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 */
240e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (*ptr == '@')
24144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			continue;
24244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		/*
24344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 * Parse substitutions
24444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 */
24544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		for (cp = ptr; *cp; cp++)
24644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (isspace(*cp))
24744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				break;
24844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		*cp = 0;
24944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		for (cp++; *cp; cp++)
25044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (!isspace(*cp))
25144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				break;
25244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#if 0
253913c4e9f1445cd8e10b9342def39eee2a29dcfd0Theodore Ts'o		printf("Substitute: '%s' for '%s'\n", ptr, cp ? cp : "<NULL>");
25444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#endif
25544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		add_subst(ptr, cp);
25644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
25744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
25844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
25944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o/*
26044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o * Return 0 if the files are different, 1 if the files are the same.
26144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o */
26244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostatic int compare_file(const char *outfn, const char *newfn)
26344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
26445d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	FILE	*old_f, *new_f;
26544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char	oldbuf[2048], newbuf[2048], *oldcp, *newcp;
26644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	int	retval;
26744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
26845d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	old_f = fopen(outfn, "r");
26945d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	if (!old_f)
27044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		return 0;
27145d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	new_f = fopen(newfn, "r");
27245d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	if (!new_f)
27344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		return 0;
27444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
27544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	while (1) {
27645d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o		oldcp = fgets(oldbuf, sizeof(oldbuf), old_f);
27745d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o		newcp = fgets(newbuf, sizeof(newbuf), new_f);
27844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!oldcp && !newcp) {
27944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			retval = 1;
28044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
28144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
28244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!oldcp || !newcp || strcmp(oldbuf, newbuf)) {
28344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			retval = 0;
28444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
28544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
28644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
28745d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	fclose(old_f);
28845d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	fclose(new_f);
28944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	return retval;
29044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
29144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
29244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
29344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
29444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
29544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'oint main(int argc, char **argv)
29644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
29744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char	line[2048];
29844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	int	c;
29944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	FILE	*in, *out;
30044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char	*outfn = NULL, *newfn = NULL;
30144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	int	verbose = 0;
30244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
30344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	while ((c = getopt (argc, argv, "f:v")) != EOF) {
30444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		switch (c) {
30544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		case 'f':
30644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			in = fopen(optarg, "r");
30744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (!in) {
30844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				perror(optarg);
30944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				exit(1);
31044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			}
31144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			parse_config_file(in);
31244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			fclose(in);
31344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
31444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		case 'v':
31544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			verbose++;
31644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
31744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		default:
31844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			fprintf(stderr, "%s: [-f config-file] [file]\n",
31944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				argv[0]);
32044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
32144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
32244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
32344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (optind < argc) {
32444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		in = fopen(argv[optind], "r");
32544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!in) {
32644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			perror(argv[optind]);
32744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			exit(1);
32844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
32944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		optind++;
33044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	} else
33144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		in = stdin;
33244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
33344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (optind < argc) {
33444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		outfn = argv[optind];
33545d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o		newfn = (char *) malloc(strlen(outfn)+20);
33644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!newfn) {
33744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			fprintf(stderr, "Memory error!  Exiting.\n");
33844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			exit(1);
33944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
34044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		strcpy(newfn, outfn);
34144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		strcat(newfn, ".new");
34244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		out = fopen(newfn, "w");
34344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!out) {
34444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			perror(newfn);
34544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			exit(1);
34644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
34744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	} else {
34844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		out = stdout;
34944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		outfn = 0;
35044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
35144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
35244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	while (!feof(in)) {
35344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (fgets(line, sizeof(line), in) == NULL)
35444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
35544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		substitute_line(line);
35644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		fputs(line, out);
35744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
35844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	fclose(in);
35944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	fclose(out);
36044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (outfn) {
36144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (compare_file(outfn, newfn)) {
36244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (verbose)
36344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				printf("No change, keeping %s.\n", outfn);
36444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			unlink(newfn);
36544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		} else {
36644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (verbose)
36744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				printf("Creating or replacing %s.\n", outfn);
36844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			rename(newfn, outfn);
36944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
37044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
37144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	return (0);
37244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
37344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
37444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
375