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 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 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 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 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