X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=util%2Fsubst.c;h=8544b6da4c0771a90e815cd5d0b4c612ec2a2a66;hb=0a05b90330d8b505469c72143964b954776be232;hp=f1f7a6e3ee25aff8c36d7d6da2e4ab52a07526c4;hpb=7822c1d410a1c6e98f8367de7593ca6e52df1f37;p=tools%2Fe2fsprogs.git diff --git a/util/subst.c b/util/subst.c index f1f7a6e..8544b6d 100644 --- a/util/subst.c +++ b/util/subst.c @@ -2,7 +2,7 @@ * subst.c --- substitution program * * Subst is used as a quicky program to do @ substitutions - * + * */ #include @@ -11,9 +11,16 @@ #include #include #include +#include +#include +#include +#include #ifdef HAVE_GETOPT_H #include +#else +extern char *optarg; +extern int optind; #endif @@ -28,9 +35,7 @@ struct subst_entry *subst_table = 0; static int add_subst(char *name, char *value) { struct subst_entry *ent = 0; - int retval; - - retval = ENOMEM; + ent = (struct subst_entry *) malloc(sizeof(struct subst_entry)); if (!ent) goto fail; @@ -47,13 +52,10 @@ static int add_subst(char *name, char *value) return 0; fail: if (ent) { - if (ent->name) - free(ent->name); - if (ent->value) - free(ent->value); + free(ent->name); free(ent); } - return retval; + return ENOMEM; } static struct subst_entry *fetch_subst_entry(char *name) @@ -71,7 +73,7 @@ static struct subst_entry *fetch_subst_entry(char *name) * Given the starting and ending position of the replacement name, * check to see if it is valid, and pull it out if it is. */ -static char *get_subst_symbol(const char *begin, int len, char prefix) +static char *get_subst_symbol(const char *begin, size_t len, char prefix) { static char replace_name[128]; char *cp, *start; @@ -84,7 +86,7 @@ static char *get_subst_symbol(const char *begin, int len, char prefix) return NULL; memcpy(start, begin, len); start[len] = 0; - + /* * The substitution variable must all be in the of [0-9A-Za-z_]. * If it isn't, this must be an invalid symbol name. @@ -105,7 +107,9 @@ static void replace_string(char *begin, char *end, char *newstr) replace_len = strlen(newstr); len = end - begin; - if (replace_len != len+1) + if (replace_len == 0) + memmove(begin, end+1, strlen(end)+1); + else if (replace_len != len+1) memmove(end+(replace_len-len-1), end, strlen(end)+1); memcpy(begin, newstr, replace_len); @@ -113,10 +117,10 @@ static void replace_string(char *begin, char *end, char *newstr) static void substitute_line(char *line) { - char *ptr, *name_ptr, *end_ptr, *cp, ch; + char *ptr, *name_ptr, *end_ptr; struct subst_entry *ent; char *replace_name; - int len, replace_len; + size_t len; /* * Expand all @FOO@ substitutions @@ -145,7 +149,7 @@ static void substitute_line(char *line) } ent = fetch_subst_entry(replace_name); if (!ent) { - fprintf(stderr, "Unfound expansion: '%s'\n", + fprintf(stderr, "Unfound expansion: '%s'\n", replace_name); ptr = end_ptr + 1; continue; @@ -156,6 +160,12 @@ static void substitute_line(char *line) #endif ptr = name_ptr-1; replace_string(ptr, end_ptr, ent->value); + if ((ent->value[0] == '@') && + (strlen(replace_name) == strlen(ent->value)-2) && + !strncmp(replace_name, ent->value+1, + strlen(ent->value)-2)) + /* avoid an infinite loop */ + ptr += strlen(ent->value); } /* * Now do a second pass to expand ${FOO} @@ -178,7 +188,7 @@ static void substitute_line(char *line) if (!replace_name) { ptr = name_ptr; continue; - } + } ent = fetch_subst_entry(replace_name); if (!ent) { ptr = end_ptr + 1; @@ -245,7 +255,7 @@ static void parse_config_file(FILE *f) if (!isspace(*cp)) break; #if 0 - printf("Substitute: '%s' for '%s'\n", ptr, cp); + printf("Substitute: '%s' for '%s'\n", ptr, cp ? cp : ""); #endif add_subst(ptr, cp); } @@ -264,8 +274,10 @@ static int compare_file(const char *outfn, const char *newfn) if (!old_f) return 0; new_f = fopen(newfn, "r"); - if (!new_f) + if (!new_f) { + fclose(old_f); return 0; + } while (1) { oldcp = fgets(oldbuf, sizeof(oldbuf), old_f); @@ -284,7 +296,6 @@ static int compare_file(const char *outfn, const char *newfn) return retval; } - int main(int argc, char **argv) @@ -294,8 +305,11 @@ int main(int argc, char **argv) FILE *in, *out; char *outfn = NULL, *newfn = NULL; int verbose = 0; - - while ((c = getopt (argc, argv, "f:v")) != EOF) { + int adjust_timestamp = 0; + struct stat stbuf; + struct utimbuf ut; + + while ((c = getopt (argc, argv, "f:tv")) != EOF) { switch (c) { case 'f': in = fopen(optarg, "r"); @@ -306,11 +320,14 @@ int main(int argc, char **argv) parse_config_file(in); fclose(in); break; + case 't': + adjust_timestamp++; + break; case 'v': verbose++; break; default: - fprintf(stderr, "%s: [-f config-file] [file]\n", + fprintf(stderr, "%s: [-f config-file] [file]\n", argv[0]); break; } @@ -324,7 +341,7 @@ int main(int argc, char **argv) optind++; } else in = stdin; - + if (optind < argc) { outfn = argv[optind]; newfn = (char *) malloc(strlen(outfn)+20); @@ -343,7 +360,7 @@ int main(int argc, char **argv) out = stdout; outfn = 0; } - + while (!feof(in)) { if (fgets(line, sizeof(line), in) == NULL) break; @@ -353,15 +370,29 @@ int main(int argc, char **argv) fclose(in); fclose(out); if (outfn) { + struct stat st; if (compare_file(outfn, newfn)) { if (verbose) printf("No change, keeping %s.\n", outfn); + if (adjust_timestamp) { + if (stat(outfn, &stbuf) == 0) { + if (verbose) + printf("Updating modtime for %s\n", outfn); + ut.actime = stbuf.st_atime; + ut.modtime = time(0); + if (utime(outfn, &ut) < 0) + perror("utime"); + } + } unlink(newfn); } else { if (verbose) printf("Creating or replacing %s.\n", outfn); rename(newfn, outfn); } + /* set read-only to alert user it is a generated file */ + if (stat(outfn, &st) == 0) + chmod(outfn, st.st_mode & ~0222); } return (0); }