summaryrefslogtreecommitdiffstats
path: root/contrib/tcl/unix/bp.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tcl/unix/bp.c')
-rw-r--r--contrib/tcl/unix/bp.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/contrib/tcl/unix/bp.c b/contrib/tcl/unix/bp.c
new file mode 100644
index 0000000..b8c7a49
--- /dev/null
+++ b/contrib/tcl/unix/bp.c
@@ -0,0 +1,127 @@
+/*
+ * bp.c --
+ *
+ * This file contains the "bp" ("binary patch") program. It is used
+ * to replace configuration strings in Tcl/Tk binaries as part of
+ * installation.
+ *
+ * Usage: bp file search replace
+ *
+ * This program searches file bp for the first occurrence of the
+ * character string given by "search". If it is found, then the
+ * first characters of that string get replaced by the string
+ * given by "replace". The replacement string is NULL-terminated.
+ *
+ * Copyright (c) 1996 Sun Microsystems, Inc.
+ * All rights reserved.
+ * This file is NOT subject to the terms described in "license.terms".
+ *
+ * SCCS: @(#) bp.c 1.2 96/03/12 09:08:26
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+extern int errno;
+
+/*
+ * The array below saves the last few bytes read from the file, so that
+ * they can be compared against a particular string that we're looking
+ * for.
+ */
+
+#define BUFFER_SIZE 200
+char buffer[BUFFER_SIZE];
+
+int
+main(argc, argv)
+ int argc; /* Number of command-line arguments. */
+ char **argv; /* Values of command-line arguments. */
+{
+ int length, matchChar, fileChar, cur, fileIndex, stringIndex;
+ char *s;
+ FILE *f;
+
+ if (argc != 4) {
+ fprintf(stderr,
+ "Wrong # args: should be \"%s fileName string replace\"\n",
+ argv[0]);
+ exit(1);
+ }
+ f = fopen(argv[1], "r+");
+ if (f == NULL) {
+ fprintf(stderr,
+ "Couldn't open \"%s\" for writing: %s\n",
+ argv[1], strerror(errno));
+ exit(1);
+ }
+
+ for (cur = 0; cur < BUFFER_SIZE; cur++) {
+ buffer[cur] = 0;
+ }
+ s = argv[2];
+ length = strlen(s);
+ if (length > BUFFER_SIZE) {
+ fprintf(stderr,
+ "String \"%s\" too long; must be %d or fewer chars.\n",
+ s, BUFFER_SIZE);
+ exit(1);
+ }
+ matchChar = s[length-1];
+
+ while (1) {
+ fileChar = getc(f);
+ if (fileChar == EOF) {
+ if (ferror(f)) {
+ goto ioError;
+ }
+ fprintf(stderr, "Couldn't find string \"%s\"\n", argv[2]);
+ exit(1);
+ }
+ buffer[cur] = fileChar;
+ if (fileChar == matchChar) {
+ /*
+ * Last character of the string matches the current character
+ * from the file. Search backwards through the buffer to
+ * see if the preceding characters from the file match the
+ * characters from the string.
+ */
+ for (fileIndex = cur-1, stringIndex = length-2;
+ stringIndex >= 0; fileIndex--, stringIndex--) {
+ if (fileIndex < 0) {
+ fileIndex = BUFFER_SIZE-1;
+ }
+ if (buffer[fileIndex] != s[stringIndex]) {
+ goto noMatch;
+ }
+ }
+
+ /*
+ * Matched! Backup to the start of the string, then
+ * overwrite it with the replacement value.
+ */
+
+ if (fseek(f, -length, SEEK_CUR) == -1) {
+ goto ioError;
+ }
+ if (fwrite(argv[3], strlen(argv[3])+1, 1, f) == 0) {
+ goto ioError;
+ }
+ exit(0);
+ }
+
+ /*
+ * No match; go on to next character of file.
+ */
+
+ noMatch:
+ cur++;
+ if (cur >= BUFFER_SIZE) {
+ cur = 0;
+ }
+ }
+
+ ioError:
+ fprintf(stderr, "I/O error: %s\n", strerror(errno));
+ exit(1);
+}
OpenPOWER on IntegriCloud