subst.c revision 7822c1d410a1c6e98f8367de7593ca6e52df1f37
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>
1744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#endif
1844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
1944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
2044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostruct subst_entry {
2144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char *name;
2244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char *value;
2344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	struct subst_entry *next;
2444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o};
2544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
2644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostruct subst_entry *subst_table = 0;
2744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
2844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostatic int add_subst(char *name, char *value)
2944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
3044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	struct subst_entry	*ent = 0;
3144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	int	retval;
3244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
3344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	retval = ENOMEM;
3445d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	ent = (struct subst_entry *) malloc(sizeof(struct subst_entry));
3544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (!ent)
3644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		goto fail;
3745d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	ent->name = (char *) malloc(strlen(name)+1);
3844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (!ent->name)
3944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		goto fail;
4045d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	ent->value = (char *) malloc(strlen(value)+1);
4144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (!ent->value)
4244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		goto fail;
4344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	strcpy(ent->name, name);
4444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	strcpy(ent->value, value);
4544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	ent->next = subst_table;
4644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	subst_table = ent;
4744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	return 0;
4844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ofail:
4944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (ent) {
5044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (ent->name)
5144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			free(ent->name);
5244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (ent->value)
5344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			free(ent->value);
5444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		free(ent);
5544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
5644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	return retval;
5744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
5844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
5944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostatic struct subst_entry *fetch_subst_entry(char *name)
6044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
6144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	struct subst_entry *ent;
6244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
6344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	for (ent = subst_table; ent; ent = ent->next) {
6444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (strcmp(name, ent->name) == 0)
6544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
6644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
6744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	return ent;
6844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
6944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
70e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o/*
71e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o * Given the starting and ending position of the replacement name,
72e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o * check to see if it is valid, and pull it out if it is.
73e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o */
74e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'ostatic char *get_subst_symbol(const char *begin, int len, char prefix)
75e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o{
76e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	static char replace_name[128];
77e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	char *cp, *start;
78e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
79e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	start = replace_name;
80e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	if (prefix)
81e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		*start++ = prefix;
82e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
83e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	if (len > sizeof(replace_name)-2)
84e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		return NULL;
85e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	memcpy(start, begin, len);
86e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	start[len] = 0;
87e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
88e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	/*
897822c1d410a1c6e98f8367de7593ca6e52df1f37Theodore Ts'o	 * The substitution variable must all be in the of [0-9A-Za-z_].
90e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 * If it isn't, this must be an invalid symbol name.
91e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 */
92e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	for (cp = start; *cp; cp++) {
93e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!(*cp >= 'a' && *cp <= 'z') &&
94e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		    !(*cp >= 'A' && *cp <= 'Z') &&
957822c1d410a1c6e98f8367de7593ca6e52df1f37Theodore Ts'o		    !(*cp >= '0' && *cp <= '9') &&
96e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		    !(*cp == '_'))
97e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			return NULL;
98e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	}
99e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	return (replace_name);
100e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o}
101e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
102e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'ostatic void replace_string(char *begin, char *end, char *newstr)
103e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o{
104e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	int	replace_len, len;
105e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
106e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	replace_len = strlen(newstr);
107e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	len = end - begin;
108e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	if (replace_len != len+1)
109e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		memmove(end+(replace_len-len-1), end,
110e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			strlen(end)+1);
111e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	memcpy(begin, newstr, replace_len);
112e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o}
113e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o
11444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostatic void substitute_line(char *line)
11544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
116e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	char	*ptr, *name_ptr, *end_ptr, *cp, ch;
11744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	struct subst_entry *ent;
118e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	char	*replace_name;
11944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	int	len, replace_len;
12044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
121e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	/*
122e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 * Expand all @FOO@ substitutions
123e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 */
12444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	ptr = line;
12544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	while (ptr) {
12644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		name_ptr = strchr(ptr, '@');
12744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!name_ptr)
128e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			break;	/* No more */
129e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (*(++name_ptr) == '@') {
130e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			/*
131e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			 * Handle tytso@@mit.edu --> tytso@mit.edu
132e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			 */
133e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			memmove(name_ptr-1, name_ptr, strlen(name_ptr)+1);
134e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			ptr = name_ptr+1;
135e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			continue;
136e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		}
137e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		end_ptr = strchr(name_ptr, '@');
13844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!end_ptr)
13944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
140e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		len = end_ptr - name_ptr;
141e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		replace_name = get_subst_symbol(name_ptr, len, 0);
142e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!replace_name) {
143e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			ptr = name_ptr;
144e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			continue;
145e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		}
14644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		ent = fetch_subst_entry(replace_name);
14744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!ent) {
14844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			fprintf(stderr, "Unfound expansion: '%s'\n",
14944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				replace_name);
15044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			ptr = end_ptr + 1;
15144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			continue;
15244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
15344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#if 0
15444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		fprintf(stderr, "Replace name = '%s' with '%s'\n",
15544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		       replace_name, ent->value);
15644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#endif
157e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		ptr = name_ptr-1;
158e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		replace_string(ptr, end_ptr, ent->value);
159e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	}
160e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	/*
161e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 * Now do a second pass to expand ${FOO}
162e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	 */
163e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	ptr = line;
164e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o	while (ptr) {
165e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		name_ptr = strchr(ptr, '$');
166e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!name_ptr)
167e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			break;	/* No more */
168e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (*(++name_ptr) != '{') {
169e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			ptr = name_ptr;
170e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			continue;
171e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		}
172e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		name_ptr++;
173e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		end_ptr = strchr(name_ptr, '}');
174e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!end_ptr)
175e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			break;
176e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		len = end_ptr - name_ptr;
177e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		replace_name = get_subst_symbol(name_ptr, len, '$');
178e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!replace_name) {
179e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			ptr = name_ptr;
180e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			continue;
181e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		}
182e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		ent = fetch_subst_entry(replace_name);
183e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (!ent) {
184e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			ptr = end_ptr + 1;
185e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o			continue;
186e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		}
187e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o#if 0
188e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		fprintf(stderr, "Replace name = '%s' with '%s'\n",
189e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		       replace_name, ent->value);
190e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o#endif
191e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		ptr = name_ptr-2;
192e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		replace_string(ptr, end_ptr, ent->value);
19344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
19444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
19544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
19644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostatic void parse_config_file(FILE *f)
19744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
19844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char	line[2048];
19944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char	*cp, *ptr;
20044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
20144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	while (!feof(f)) {
20244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		memset(line, 0, sizeof(line));
20344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (fgets(line, sizeof(line), f) == NULL)
20444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
20544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		/*
20644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 * Strip newlines and comments.
20744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 */
20844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		cp = strchr(line, '\n');
20944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (cp)
21044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			*cp = 0;
21144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		cp = strchr(line, '#');
21244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (cp)
21344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			*cp = 0;
21444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		/*
21544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 * Skip trailing and leading whitespace
21644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 */
21744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		for (cp = line + strlen(line) - 1; cp >= line; cp--) {
21844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (*cp == ' ' || *cp == '\t')
21944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				*cp = 0;
22044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			else
22144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				break;
22244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
22344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		cp = line;
22444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		while (*cp && isspace(*cp))
22544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			cp++;
22644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		ptr = cp;
22744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		/*
22844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 * Skip empty lines
22944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 */
23044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (*ptr == 0)
23144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			continue;
23244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		/*
23344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 * Ignore future extensions
23444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 */
235e7549ca6280abe5ab5c1934ecfd7d132c7abeb59Theodore Ts'o		if (*ptr == '@')
23644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			continue;
23744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		/*
23844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 * Parse substitutions
23944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		 */
24044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		for (cp = ptr; *cp; cp++)
24144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (isspace(*cp))
24244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				break;
24344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		*cp = 0;
24444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		for (cp++; *cp; cp++)
24544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (!isspace(*cp))
24644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				break;
24744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#if 0
24844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		printf("Substitute: '%s' for '%s'\n", ptr, cp);
24944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o#endif
25044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		add_subst(ptr, cp);
25144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
25244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
25344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
25444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o/*
25544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o * Return 0 if the files are different, 1 if the files are the same.
25644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o */
25744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'ostatic int compare_file(const char *outfn, const char *newfn)
25844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
25945d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	FILE	*old_f, *new_f;
26044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char	oldbuf[2048], newbuf[2048], *oldcp, *newcp;
26144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	int	retval;
26244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
26345d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	old_f = fopen(outfn, "r");
26445d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	if (!old_f)
26544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		return 0;
26645d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	new_f = fopen(newfn, "r");
26745d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	if (!new_f)
26844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		return 0;
26944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
27044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	while (1) {
27145d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o		oldcp = fgets(oldbuf, sizeof(oldbuf), old_f);
27245d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o		newcp = fgets(newbuf, sizeof(newbuf), new_f);
27344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!oldcp && !newcp) {
27444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			retval = 1;
27544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
27644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
27744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!oldcp || !newcp || strcmp(oldbuf, newbuf)) {
27844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			retval = 0;
27944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
28044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
28144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
28245d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	fclose(old_f);
28345d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o	fclose(new_f);
28444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	return retval;
28544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
28644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
28744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
28844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
28944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
29044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'oint main(int argc, char **argv)
29144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o{
29244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char	line[2048];
29344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	int	c;
29444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	FILE	*in, *out;
29544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	char	*outfn = NULL, *newfn = NULL;
29644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	int	verbose = 0;
29744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
29844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	while ((c = getopt (argc, argv, "f:v")) != EOF) {
29944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		switch (c) {
30044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		case 'f':
30144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			in = fopen(optarg, "r");
30244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (!in) {
30344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				perror(optarg);
30444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				exit(1);
30544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			}
30644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			parse_config_file(in);
30744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			fclose(in);
30844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
30944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		case 'v':
31044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			verbose++;
31144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
31244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		default:
31344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			fprintf(stderr, "%s: [-f config-file] [file]\n",
31444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				argv[0]);
31544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
31644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
31744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
31844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (optind < argc) {
31944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		in = fopen(argv[optind], "r");
32044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!in) {
32144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			perror(argv[optind]);
32244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			exit(1);
32344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
32444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		optind++;
32544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	} else
32644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		in = stdin;
32744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
32844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (optind < argc) {
32944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		outfn = argv[optind];
33045d2161466e32b3e67115951ab1eb7eef25c218aTheodore Ts'o		newfn = (char *) malloc(strlen(outfn)+20);
33144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!newfn) {
33244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			fprintf(stderr, "Memory error!  Exiting.\n");
33344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			exit(1);
33444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
33544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		strcpy(newfn, outfn);
33644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		strcat(newfn, ".new");
33744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		out = fopen(newfn, "w");
33844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (!out) {
33944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			perror(newfn);
34044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			exit(1);
34144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
34244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	} else {
34344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		out = stdout;
34444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		outfn = 0;
34544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
34644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
34744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	while (!feof(in)) {
34844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (fgets(line, sizeof(line), in) == NULL)
34944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			break;
35044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		substitute_line(line);
35144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		fputs(line, out);
35244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
35344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	fclose(in);
35444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	fclose(out);
35544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	if (outfn) {
35644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		if (compare_file(outfn, newfn)) {
35744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (verbose)
35844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				printf("No change, keeping %s.\n", outfn);
35944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			unlink(newfn);
36044339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		} else {
36144339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			if (verbose)
36244339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o				printf("Creating or replacing %s.\n", outfn);
36344339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o			rename(newfn, outfn);
36444339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o		}
36544339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	}
36644339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o	return (0);
36744339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o}
36844339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
36944339bdff87584b72a2ade7d3a1426e3335f2167Theodore Ts'o
370