xref: /plan9/sys/src/ape/cmd/pax/replace.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 /* $Source: /u/mark/src/pax/RCS/replace.c,v $
2  *
3  * $Revision: 1.2 $
4  *
5  * replace.c - regular expression pattern replacement functions
6  *
7  * DESCRIPTION
8  *
9  *	These routines provide for regular expression file name replacement
10  *	as required by pax.
11  *
12  * AUTHORS
13  *
14  *	Mark H. Colburn, NAPS International
15  *
16  * Sponsored by The USENIX Association for public distribution.
17  *
18  * Copyright (c) 1989 Mark H. Colburn.
19  * All rights reserved.
20  *
21  * Redistribution and use in source and binary forms are permitted
22  * provided that the above copyright notice is duplicated in all such
23  * forms and that any documentation, advertising materials, and other
24  * materials related to such distribution and use acknowledge that the
25  * software was developed * by Mark H. Colburn and sponsored by The
26  * USENIX Association.
27  *
28  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31  *
32  * $Log:	replace.c,v $
33  * Revision 1.2  89/02/12  10:05:59  mark
34  * 1.2 release fixes
35  *
36  * Revision 1.1  88/12/23  18:02:36  mark
37  * Initial revision
38  *
39  */
40 
41 #ifndef lint
42 static char *ident = "$Id: replace.c,v 1.2 89/02/12 10:05:59 mark Exp $";
43 static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
44 #endif /* not lint */
45 
46 /* Headers */
47 
48 #include "pax.h"
49 
50 
51 /* add_replstr - add a replacement string to the replacement string list
52  *
53  * DESCRIPTION
54  *
55  *	Add_replstr adds a replacement string to the replacement string
56  *	list which is applied each time a file is about to be processed.
57  *
58  * PARAMETERS
59  *
60  *	char	*pattern	- A regular expression which is to be parsed
61  */
62 
63 #ifdef __STDC__
64 
add_replstr(char * pattern)65 void add_replstr(char *pattern)
66 
67 #else
68 
69 void add_replstr(pattern)
70 char           *pattern;
71 
72 #endif
73 {
74     char           *p;
75     char            sep;
76     Replstr        *rptr;
77     int             len;
78 
79     if ((len = strlen(pattern)) < 4) {
80 	warn("Replacement string not added",
81 		 "Malformed substitution syntax");
82 	return;
83     }
84     if ((rptr = (Replstr *) malloc(sizeof(Replstr))) == (Replstr *)NULL) {
85 	warn("Replacement string not added", "No space");
86 	return;
87     }
88 
89     /* First character is the delimeter... */
90     sep = *pattern;
91 
92     /* Get trailing g and/or p */
93     p = pattern + len - 1;
94     while (*p != sep) {
95 	if (*p == 'g') {
96             rptr->global = 1;
97 	} else if (*p == 'p') {
98 	    rptr->print = 1;
99 	} else {
100 	    warn(p, "Invalid RE modifier");
101 	}
102 	p--;
103     }
104 
105     if (*p != sep) {
106 	warn("Replacement string not added", "Bad delimeters");
107 	free(rptr);
108 	return;
109     }
110     /* strip off leading and trailing delimeter */
111     *p = '\0';
112     pattern++;
113 
114     /* find the separating '/' in the pattern */
115     p = pattern;
116     while (*p) {
117 	if (*p == sep) {
118 	    break;
119 	}
120 	if (*p == '\\' && *(p + 1) != '\0') {
121 	    p++;
122 	}
123 	p++;
124     }
125     if (*p != sep) {
126 	warn("Replacement string not added", "Bad delimeters");
127 	free(rptr);
128 	return;
129     }
130     *p++ = '\0';
131 
132     /*
133      * Now pattern points to 'old' and p points to 'new' and both are '\0'
134      * terminated
135      */
136     if ((rptr->comp = regcomp(pattern)) == (regexp *)NULL) {
137 	warn("Replacement string not added", "Invalid RE");
138 	free(rptr);
139 	return;
140     }
141     rptr->replace = p;
142     rptr->next = (Replstr *)NULL;
143     if (rplhead == (Replstr *)NULL) {
144 	rplhead = rptr;
145 	rpltail = rptr;
146     } else {
147 	rpltail->next = rptr;
148 	rpltail = rptr;
149     }
150 }
151 
152 
153 
154 /* rpl_name - possibly replace a name with a regular expression
155  *
156  * DESCRIPTION
157  *
158  *	The string name is searched for in the list of regular expression
159  *	substituions.  If the string matches any of the regular expressions
160  *	then the string is modified as specified by the user.
161  *
162  * PARAMETERS
163  *
164  *	char	*name	- name to search for and possibly modify
165  */
166 
167 #ifdef __STDC__
168 
rpl_name(char * name)169 void rpl_name(char *name)
170 
171 #else
172 
173 void rpl_name(name)
174 char           *name;
175 
176 #endif
177 {
178     int             found = 0;
179     int             ret;
180     Replstr        *rptr;
181     char            buff[PATH_MAX + 1];
182     char            buff1[PATH_MAX + 1];
183     char            buff2[PATH_MAX + 1];
184     char           *p;
185     char           *b;
186 
187     strcpy(buff, name);
188     for (rptr = rplhead; !found && rptr != (Replstr *)NULL; rptr = rptr->next) {
189 	do {
190 	    if ((ret = regexec(rptr->comp, buff)) != 0) {
191 		p = buff;
192 		b = buff1;
193 		while (p < rptr->comp->startp[0]) {
194 		    *b++ = *p++;
195 		}
196 		p = rptr->replace;
197 		while (*p) {
198 		    *b++ = *p++;
199 		}
200 		strcpy(b, rptr->comp->endp[0]);
201 		found = 1;
202 		regsub(rptr->comp, buff1, buff2);
203 		strcpy(buff, buff2);
204 	    }
205 	} while (ret && rptr->global);
206 	if (found) {
207 	    if (rptr->print) {
208 		fprintf(stderr, "%s >> %s\n", name, buff);
209 	    }
210 	    strcpy(name, buff);
211 	}
212     }
213 }
214 
215 
216 /* get_disposition - get a file disposition
217  *
218  * DESCRIPTION
219  *
220  *	Get a file disposition from the user.  If the user enters 'y'
221  *	the the file is processed, anything else and the file is ignored.
222  *	If the user enters EOF, then the PAX exits with a non-zero return
223  *	status.
224  *
225  * PARAMETERS
226  *
227  *	char	*mode	- string signifying the action to be taken on file
228  *	char	*name	- the name of the file
229  *
230  * RETURNS
231  *
232  *	Returns 1 if the file should be processed, 0 if it should not.
233  */
234 
235 #ifdef __STDC__
236 
get_disposition(char * mode,char * name)237 int get_disposition(char *mode, char *name)
238 
239 #else
240 
241 int get_disposition(mode, name)
242 char	*mode;
243 char	*name;
244 
245 #endif
246 {
247     char	ans[2];
248     char	buf[PATH_MAX + 10];
249 
250     if (f_disposition) {
251 	sprintf(buf, "%s %s? ", mode, name);
252 	if (nextask(buf, ans, sizeof(ans)) == -1 || ans[0] == 'q') {
253 	    exit(0);
254 	}
255 	if (strlen(ans) == 0 || ans[0] != 'y') {
256 	    return(1);
257 	}
258     }
259     return(0);
260 }
261 
262 
263 /* get_newname - prompt the user for a new filename
264  *
265  * DESCRIPTION
266  *
267  *	The user is prompted with the name of the file which is currently
268  *	being processed.  The user may choose to rename the file by
269  *	entering the new file name after the prompt; the user may press
270  *	carriage-return/newline, which will skip the file or the user may
271  *	type an 'EOF' character, which will cause the program to stop.
272  *
273  * PARAMETERS
274  *
275  *	char	*name		- filename, possibly modified by user
276  *	int	size		- size of allowable new filename
277  *
278  * RETURNS
279  *
280  *	Returns 0 if successfull, or -1 if an error occurred.
281  *
282  */
283 
284 #ifdef __STDC__
285 
get_newname(char * name,int size)286 int get_newname(char *name, int size)
287 
288 #else
289 
290 int get_newname(name, size)
291 char	*name;
292 int	size;
293 
294 #endif
295 {
296     char	buf[PATH_MAX + 10];
297 
298     if (f_interactive) {
299 	sprintf(buf, "rename %s? ", name);
300 	if (nextask(buf, name, size) == -1) {
301 	    exit(0);
302 	}
303 	if (strlen(name) == 0) {
304 	    return(1);
305 	}
306     }
307     return(0);
308 }
309