diff options
author | bk@work.mysql.com <> | 2000-07-31 21:29:14 +0200 |
---|---|---|
committer | bk@work.mysql.com <> | 2000-07-31 21:29:14 +0200 |
commit | f4c589ff6c653d1d2a09c26e46ead3c8a15655d8 (patch) | |
tree | d253a359142dfc1ed247d5d4365d86972ea31109 /extra | |
parent | 7eec25e393727b16bb916b50d82b0aa3084e065c (diff) | |
download | mariadb-git-f4c589ff6c653d1d2a09c26e46ead3c8a15655d8.tar.gz |
Import changeset
Diffstat (limited to 'extra')
-rw-r--r-- | extra/.cvsignore | 10 | ||||
-rw-r--r-- | extra/Attic/print_defaults.c | 125 | ||||
-rw-r--r-- | extra/Makefile.am | 29 | ||||
-rw-r--r-- | extra/comp_err.c | 275 | ||||
-rw-r--r-- | extra/my_print_defaults.c | 125 | ||||
-rw-r--r-- | extra/perror.c | 207 | ||||
-rw-r--r-- | extra/replace.c | 1080 | ||||
-rw-r--r-- | extra/resolveip.c | 204 |
8 files changed, 2055 insertions, 0 deletions
diff --git a/extra/.cvsignore b/extra/.cvsignore new file mode 100644 index 00000000000..e0042c405cc --- /dev/null +++ b/extra/.cvsignore @@ -0,0 +1,10 @@ +.deps +.libs +Makefile +Makefile.in +comp_err +my_print_defaults +perror +print_defaults +replace +resolveip diff --git a/extra/Attic/print_defaults.c b/extra/Attic/print_defaults.c new file mode 100644 index 00000000000..a6e67e4949e --- /dev/null +++ b/extra/Attic/print_defaults.c @@ -0,0 +1,125 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* +** print_default.c: +** Print all parameters in a default file that will be given to some program. +** +** Written by Monty +*/ + +#include <global.h> +#include <my_sys.h> +#include <getopt.h> + +const char *config_file="my"; /* Default config file */ + +static struct option long_options[] = +{ + {"config-file", required_argument, 0, 'c'}, + {"defaults-file", required_argument, 0, 'c'}, + {"no-defaults", no_argument, 0, 'd'}, + {"help", no_argument, 0, '?'}, + {"version", no_argument, 0, 'V'}, + {0, 0, 0, 0} +}; + +static void usage(my_bool version) +{ + printf("%s Ver 1.1 for %s at %s\n",my_progname,SYSTEM_TYPE, + MACHINE_TYPE); + if (version) + return; + puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); + puts("Prints all arguments that is give to some program using the default files"); + printf("Usage: %s [OPTIONS] groups\n",my_progname); + printf("\n\ + -c, --config-file=# --defaults-file=#\n\ + The config file to use (default '%s')\n\ + --no-defaults Return an empty string (useful for scripts)\n\ + -?, --help Display this help message and exit.\n\ + -V, --version Output version information and exit.\n", + config_file); + printf("\nExample usage: %s --config-file=my client mysql\n",my_progname); +} + +static int get_options(int *argc,char ***argv) +{ + int c,option_index; + + while ((c=getopt_long(*argc,*argv,"c:V?I", + long_options, &option_index)) != EOF) + { + switch (c) { + case 'c': + config_file=optarg; + break; + case 'n': + exit(0); + case 'I': + case '?': + usage(0); + exit(0); + case 'V': + usage(1); + exit(0); + } + } + (*argc)-=optind; + (*argv)+=optind; + if (*argc < 1) + { + usage(0); + return 1; + } + return 0; +} + +int main(int argc, char **argv) +{ + int count; + char **load_default_groups, *tmp_arguments[2], + **argument, **arguments; + MY_INIT(argv[0]); + + /* + ** Check out the args + */ + if (get_options(&argc,&argv)) + exit(1); + if (!(load_default_groups=(char**) my_malloc((argc+2)*sizeof(char*), + MYF(MY_WME)))) + exit(1); + + for (count=0; *argv ; argv++,count++) + load_default_groups[count]= *argv; + load_default_groups[count]=0; + + count=1; + arguments=tmp_arguments; + arguments[0]=my_progname; + arguments[1]=0; + load_defaults(config_file, (const char **) load_default_groups, + &count, &arguments); + + for (argument= arguments+1 ; *argument ; argument++) + puts(*argument); + my_free((char*) load_default_groups,MYF(0)); + free_defaults(arguments); + + exit(0); +} diff --git a/extra/Makefile.am b/extra/Makefile.am new file mode 100644 index 00000000000..8fd41221cfe --- /dev/null +++ b/extra/Makefile.am @@ -0,0 +1,29 @@ +# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I.. +LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \ + ../dbug/libdbug.a ../strings/libmystrings.a +bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults + +OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\ + __math.h time.h __time.h unistd.h __unistd.h types.h \ + xtypes.h ac-types.h posix.h string.h __string.h \ + errno.h socket.h inet.h dirent.h netdb.h \ + cleanup.h cond.h debug_out.h fd.h kernel.h mutex.h \ + prio_queue.h pthread_attr.h pthread_once.h queue.h\ + sleep.h specific.h version.h pwd.h timers.h uio.h \ + cdefs.h machdep.h signal.h __signal.h diff --git a/extra/comp_err.c b/extra/comp_err.c new file mode 100644 index 00000000000..198bdffb0db --- /dev/null +++ b/extra/comp_err.c @@ -0,0 +1,275 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Saves all errmesg in a header file, updated by me, in a compact file */ + +#include <global.h> +#include <m_ctype.h> +#include <my_sys.h> +#include <m_string.h> + +#define MAXLENGTH 1000 +#define MAX_ROWS 1000 +#define MAX_FILES 10 + +int row_count; +uint file_pos[MAX_ROWS],file_row_pos[MAX_FILES]; +my_string saved_row[MAX_ROWS]; +uchar file_head[]= { 254,254,2,1 }; + +static void get_options(int *argc,char **argv[]); +static int count_rows(FILE *from,pchar c, pchar c2); +static int remember_rows(FILE *from,pchar c); +static int copy_rows(FILE *to); + + + /* Functions defined in this file */ + +int main(int argc,char *argv[]) +{ + int i,error,files,length; + uchar head[32]; + FILE *from,*to; + MY_INIT(argv[0]); + + get_options(&argc,&argv); + error=1; + row_count=files=0; + + to=0; + for ( ; argc-- > 1 ; argv++) + { + file_row_pos[files++] = row_count; + + if ((from = fopen(*argv,"r")) == NULL) + { + fprintf(stderr,"Can't open file '%s'\n",*argv); + return(1); + } + + VOID(count_rows(from,'"','}')); /* Calculate start-info */ + if (remember_rows(from,'}') < 0) /* Remember rows */ + { + fprintf(stderr,"Can't find textrows in '%s'\n",*argv); + fclose(from); + goto end; + } + fclose(from); + } + + if ((to=my_fopen(*argv,O_WRONLY | FILE_BINARY,MYF(0))) == NULL) + { + fprintf(stderr,"Can't create file '%s'\n",*argv); + return(1); + } + + fseek(to,(long) (32+row_count*2),0); + if (copy_rows(to)) + goto end; + + length=ftell(to)-32-row_count*2; + + bzero((gptr) head,32); /* Save Header & pointers */ + bmove((byte*) head,(byte*) file_head,4); + head[4]=files; + int2store(head+6,length); + int2store(head+8,row_count); + for (i=0 ; i<files ; i++) + { + int2store(head+10+i+i,file_row_pos[i]); + } + + fseek(to,0l,0); + if (fwrite(head,1,32,to) != 32) + goto end; + + for (i=0 ; i<row_count ; i++) + { + int2store(head,file_pos[i]); + if (fwrite(head,1,2,to) != 2) + goto end; + } + error=0; + printf("Found %d messages in language file %s\n",row_count,*argv); + + end: + if (to) + fclose(to); + if (error) + fprintf(stderr,"Can't uppdate messagefile %s, errno: %d\n",*argv,errno); + + exit(error); + return(0); +} /* main */ + + + /* Read options */ + +static void get_options(argc,argv) +register int *argc; +register char **argv[]; +{ + int help=0; + char *pos,*progname; + + progname= (*argv)[0]; + while (--*argc >0 && *(pos = *(++*argv)) == '-' ) { + while (*++pos) + switch(*pos) { + case '#': + DBUG_PUSH (++pos); + *(pos--) = '\0'; /* Skippa argument */ + break; + case 'V': + printf("%s (Compile errormessage) Ver 1.3\n",progname); + break; + case 'I': + case '?': + printf(" %s (Compile errormessage) Ver 1.3\n",progname); + puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); + printf("Usage: %s [-?] [-I] [-V] fromfile[s] tofile\n",progname); + puts("Options: -Info -Version\n"); + help=1; + break; + default: + fprintf(stderr,"illegal option: -%c\n",*pos); + fprintf(stderr,"legal options: -?IV\n"); + break; + } + } + if (*argc < 2) + { + if (!help) + printf("Usage: %s [-?] [-I] [-V] fromfile[s] tofile\n",progname); + exit(-1); + } + return; +} /* get_options */ + + + /* Count rows in from-file until row that start with char is found */ + +static int count_rows(from,c,c2) +FILE *from; +pchar c,c2; +{ + int count; + long pos; + char rad[MAXLENGTH]; + DBUG_ENTER("count_rows"); + + pos=ftell(from); count=0; + while (fgets(rad,MAXLENGTH,from) != NULL) + { + if (rad[0] == c || rad[0] == c2) + break; + count++; + pos=ftell(from); + } + fseek(from,pos,0); /* Position to beginning of last row */ + DBUG_PRINT("exit",("count: %d",count)); + DBUG_RETURN(count); +} /* count_rows */ + + + /* Read rows and remember them until row that start with char */ + /* Converts row as a C-compiler would convert a textstring */ + +static int remember_rows(from,c) +FILE *from; +pchar c; +{ + int i,nr,start_count,found_end; + char row[MAXLENGTH],*pos; + DBUG_ENTER("remember_rows"); + + start_count=row_count; found_end=0; + while (fgets(row,MAXLENGTH,from) != NULL) + { + if (row[0] == c) + { + found_end=1; + break; + } + for (pos=row ; *pos ;) + { + if (*pos == '\\') + { + switch (*++pos) { + case '\\': + case '"': + VOID(strmov(pos-1,pos)); + break; + case 'n': + pos[-1]='\n'; + VOID(strmov(pos,pos+1)); + break; + default: + if (*pos >= '0' && *pos <'8') + { + nr=0; + for (i=0 ; i<3 && (*pos >= '0' && *pos <'8' ) ; i++) + nr=nr*8+ (*(pos++) -'0'); + pos-=i; + pos[-1]=nr; + VOID(strmov(pos,pos+i)); + } + else if (*pos) + VOID(strmov(pos-1,pos)); /* Remove '\' */ + } + } + else pos++; + } + while (pos >row+1 && *pos != '"') + pos--; + + if (!(saved_row[row_count] = (my_string) my_malloc((uint) (pos-row), + MYF(MY_WME)))) + DBUG_RETURN(-1); + *pos=0; + VOID(strmov(saved_row[row_count],row+1)); + row_count++; + } + if (row_count-start_count == 0 && ! found_end) + DBUG_RETURN(-1); /* Found nothing */ + DBUG_RETURN(row_count-start_count); +} /* remember_rows */ + + + /* Copy rows from memory to file and remember position */ + + +static int copy_rows(to) +FILE *to; +{ + int row_nr; + long start_pos; + DBUG_ENTER("copy_rows"); + + start_pos=ftell(to); + for (row_nr =0 ; row_nr < row_count; row_nr++) + { + file_pos[row_nr]= (int) (ftell(to)-start_pos); + if (fputs(saved_row[row_nr],to) == EOF || fputc('\0',to) == EOF) + { + fprintf(stderr,"Can't write to outputfile\n"); + DBUG_RETURN(1); + } + my_free((gptr) saved_row[row_nr],MYF(0)); + } + DBUG_RETURN(0); +} /* copy_rows */ diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c new file mode 100644 index 00000000000..a6e67e4949e --- /dev/null +++ b/extra/my_print_defaults.c @@ -0,0 +1,125 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* +** print_default.c: +** Print all parameters in a default file that will be given to some program. +** +** Written by Monty +*/ + +#include <global.h> +#include <my_sys.h> +#include <getopt.h> + +const char *config_file="my"; /* Default config file */ + +static struct option long_options[] = +{ + {"config-file", required_argument, 0, 'c'}, + {"defaults-file", required_argument, 0, 'c'}, + {"no-defaults", no_argument, 0, 'd'}, + {"help", no_argument, 0, '?'}, + {"version", no_argument, 0, 'V'}, + {0, 0, 0, 0} +}; + +static void usage(my_bool version) +{ + printf("%s Ver 1.1 for %s at %s\n",my_progname,SYSTEM_TYPE, + MACHINE_TYPE); + if (version) + return; + puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); + puts("Prints all arguments that is give to some program using the default files"); + printf("Usage: %s [OPTIONS] groups\n",my_progname); + printf("\n\ + -c, --config-file=# --defaults-file=#\n\ + The config file to use (default '%s')\n\ + --no-defaults Return an empty string (useful for scripts)\n\ + -?, --help Display this help message and exit.\n\ + -V, --version Output version information and exit.\n", + config_file); + printf("\nExample usage: %s --config-file=my client mysql\n",my_progname); +} + +static int get_options(int *argc,char ***argv) +{ + int c,option_index; + + while ((c=getopt_long(*argc,*argv,"c:V?I", + long_options, &option_index)) != EOF) + { + switch (c) { + case 'c': + config_file=optarg; + break; + case 'n': + exit(0); + case 'I': + case '?': + usage(0); + exit(0); + case 'V': + usage(1); + exit(0); + } + } + (*argc)-=optind; + (*argv)+=optind; + if (*argc < 1) + { + usage(0); + return 1; + } + return 0; +} + +int main(int argc, char **argv) +{ + int count; + char **load_default_groups, *tmp_arguments[2], + **argument, **arguments; + MY_INIT(argv[0]); + + /* + ** Check out the args + */ + if (get_options(&argc,&argv)) + exit(1); + if (!(load_default_groups=(char**) my_malloc((argc+2)*sizeof(char*), + MYF(MY_WME)))) + exit(1); + + for (count=0; *argv ; argv++,count++) + load_default_groups[count]= *argv; + load_default_groups[count]=0; + + count=1; + arguments=tmp_arguments; + arguments[0]=my_progname; + arguments[1]=0; + load_defaults(config_file, (const char **) load_default_groups, + &count, &arguments); + + for (argument= arguments+1 ; *argument ; argument++) + puts(*argument); + my_free((char*) load_default_groups,MYF(0)); + free_defaults(arguments); + + exit(0); +} diff --git a/extra/perror.c b/extra/perror.c new file mode 100644 index 00000000000..b6d32d50868 --- /dev/null +++ b/extra/perror.c @@ -0,0 +1,207 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Return error-text for system error messages and nisam messages */ + +#define PERROR_VERSION "2.2" + +#include <global.h> +#include <my_sys.h> +#include <m_string.h> +#include <errno.h> +#include <getopt.h> + + +static struct option long_options[] = +{ + {"help", no_argument, 0, '?'}, + {"info", no_argument, 0, 'I'}, + {"all", no_argument, 0, 'a'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {0, 0, 0, 0} +}; + +typedef struct ha_errors { + int errcode; + const char *msg; +} HA_ERRORS; + +static int verbose=0,print_all_codes=0; + +static HA_ERRORS ha_errlist[]= +{ + { 120,"Didn't find key on read or update" }, + { 121,"Duplicate key on write or update" }, + { 123,"Someone has changed the row since it was read; Update with is recoverable" }, + { 124,"Wrong index given to function" }, + { 126,"Index file is crashed / Wrong file format" }, + { 127,"Record-file is crashed" }, + { 131,"Command not supported by database" }, + { 132,"Old database file" }, + { 133,"No record read before update" }, + { 134,"Record was already deleted (or record file crashed)" }, + { 135,"No more room in record file" }, + { 136,"No more room in index file" }, + { 137,"No more records (read after end of file)" }, + { 138,"Unsupported extension used for table" }, + { 139,"Too big row (>= 24 M)"}, + { 140,"Wrong create options"}, + { 141,"Dupplicate unique on write or update"}, + { 0,NullS }, +}; + + +static void print_version(void) +{ + printf("%s Ver %s, for %s (%s)\n",my_progname,PERROR_VERSION, + SYSTEM_TYPE,MACHINE_TYPE); +} + +static void usage(void) +{ + print_version(); + puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); + printf("Usage: %s [OPTIONS] [ERRORCODES]\n",my_progname); + printf("\n\ + -?, --help Displays this help and exits.\n\ + -I, --info Synonym for the above."); +#ifdef HAVE_SYS_ERRLIST + printf("\n\ + -a, --all Print all the error messages and the number."); +#endif + printf("\n\ + -v, --verbose Print info about various stages.\n\ + -V, --version Displays version information and exits.\n"); +} + + +static int get_options(int *argc,char ***argv) +{ + int c,option_index; + + while ((c=getopt_long(*argc,*argv,"avVI?",long_options, + &option_index)) != EOF) + { + switch (c) { +#ifdef HAVE_SYS_ERRLIST + case 'a': + print_all_codes=1; + break; +#endif + case 'v': + verbose=1; + break; + case 'V': + print_version(); + exit(0); + break; + case 'I': + case '?': + usage(); + exit(0); + break; + default: + fprintf(stderr,"%s: Illegal option character '%c'\n", + my_progname,opterr); + return(1); + break; + } + } + (*argc)-=optind; + (*argv)+=optind; + if (!*argc && !print_all_codes) + { + usage(); + return 1; + } + return 0; +} /* get_options */ + + +static const char *get_ha_error_msg(int code) +{ + HA_ERRORS *ha_err_ptr; + + for (ha_err_ptr=ha_errlist ; ha_err_ptr->errcode ;ha_err_ptr++) + if (ha_err_ptr->errcode == code) + return ha_err_ptr->msg; + return NullS; +} + + +int main(int argc,char *argv[]) +{ + int error,code,found; + const char *msg; + MY_INIT(argv[0]); + + if (get_options(&argc,&argv)) + exit(1); + + error=0; +#ifdef HAVE_SYS_ERRLIST + if (print_all_codes) + { + HA_ERRORS *ha_err_ptr; + for (code=1 ; code < sys_nerr ; code++) + { + if (sys_errlist[code][0]) + { /* Skipp if no error-text */ + printf("%3d = %s\n",code,sys_errlist[code]); + } + } + for (ha_err_ptr=ha_errlist ; ha_err_ptr->errcode ;ha_err_ptr++) + printf("%3d = %s\n",ha_err_ptr->errcode,ha_err_ptr->msg); + } + else +#endif + { + for ( ; argc-- > 0 ; argv++) + { + found=0; + code=atoi(*argv); + msg = strerror(code); + if (msg) + { + found=1; + if (verbose) + printf("%3d = %s\n",code,msg); + else + puts(msg); + } + if (!(msg=get_ha_error_msg(code))) + { + if (!found) + { + fprintf(stderr,"Illegal error code: %d\n",code); + error=1; + } + } + else + { + if (verbose) + printf("%3d = %s\n",code,msg); + else + puts(msg); + } + } + } + exit(error); + return error; +} + diff --git a/extra/replace.c b/extra/replace.c new file mode 100644 index 00000000000..44f117c7969 --- /dev/null +++ b/extra/replace.c @@ -0,0 +1,1080 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Replace strings in textfile + This program replace strings in a file or on stdin/stdout. + It accepts a list of from-strings and to-strings and replaces all + occurents of from-strings to to-strings. + The first occurents of a found string is matched. If there are more than + one possibly replace the longer from-string is replaced. + Special characters in from string: + \^ Match start of line. + \$ Match end of line. + \b Match space-character, start of line or end of line. + For end \b the next replace starts locking at the end space-character. + An \b alone or in a string matches only a space-character. + \r, \t, \v as in C. + The programs make a DFA-state-machine of the strings and the speed isn't + dependent on the count of replace-strings (only of the number of replaces). + A line is assumed ending with \n or \0. + There are no limit exept memory on length of strings. + + Written by Monty. + fill_buffer_retaining() is taken from gnu-grep and modified. +*/ + +#define DONT_USE_RAID +#include <global.h> +#include <m_ctype.h> +#include <my_sys.h> +#include <m_string.h> +#include <errno.h> + +#define PC_MALLOC 256 /* Bytes for pointers */ +#define PS_MALLOC 512 /* Bytes for data */ + +typedef struct st_pointer_array { /* when using array-strings */ + TYPELIB typelib; /* Pointer to strings */ + byte *str; /* Strings is here */ + int7 *flag; /* Flag about each var. */ + uint array_allocs,max_count,length,max_length; +} POINTER_ARRAY; + +#define SPACE_CHAR 256 +#define START_OF_LINE 257 +#define END_OF_LINE 258 +#define LAST_CHAR_CODE 259 + +typedef struct st_replace { + bool found; + struct st_replace *next[256]; +} REPLACE; + +typedef struct st_replace_found { + bool found; + char *replace_string; + uint to_offset; + int from_offset; +} REPLACE_STRING; + +#ifndef WORD_BIT +#define WORD_BIT (8*sizeof(uint)) +#endif + + /* functions defined in this file */ + +extern int main(int argc,char * *argv); +static int static_get_options(int *argc,char * * *argv); +static int get_replace_strings(int *argc,char * * *argv, + POINTER_ARRAY *from_array, + POINTER_ARRAY *to_array); +int insert_pointer_name(POINTER_ARRAY *pa, my_string name); +void free_pointer_array(POINTER_ARRAY *pa); +static int convert_pipe(REPLACE *,FILE *,FILE *); +static int convert_file(REPLACE *, my_string); +REPLACE *init_replace(my_string *from, my_string *to,uint count, my_string + word_end_chars); +uint replace_strings(REPLACE *rep, my_string *start,uint *max_length, + my_string from); +static int initialize_buffer(void); +static void reset_buffer(void); +static void free_buffer(void); + +static int silent=0,verbose=0,updated=0; + + /* The main program */ + +int main(argc,argv) +int argc; +char *argv[]; +{ + int i,error; + char word_end_chars[256],*pos; + POINTER_ARRAY from,to; + REPLACE *replace; + MY_INIT(argv[0]); + + if (static_get_options(&argc,&argv)) + exit(1); + if (get_replace_strings(&argc,&argv,&from,&to)) + exit(1); + + for (i=1,pos=word_end_chars ; i < 256 ; i++) + if (isspace(i)) + *pos++=i; + *pos=0; + if (!(replace=init_replace((char**) from.typelib.type_names, + (char**) to.typelib.type_names, + (uint) from.typelib.count,word_end_chars))) + exit(1); + free_pointer_array(&from); + free_pointer_array(&to); + if (initialize_buffer()) + return 1; + + error=0; + if (argc == 0) + error=convert_pipe(replace,stdin,stdout); + else + { + while (argc--) + { + error=convert_file(replace,*(argv++)); + } + } + free_buffer(); + my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); + exit(error ? 2 : 0); + return 0; /* No compiler warning */ +} /* main */ + + + /* reads options */ + /* Initiates DEBUG - but no debugging here ! */ + +static int static_get_options(argc,argv) +register int *argc; +register char **argv[]; +{ + int help,version,opt; + char *pos; + + silent=verbose=help=0; + + while (--*argc > 0 && *(pos = *(++*argv)) == '-' && pos[1] != '-') { + while (*++pos) + { + version=0; + switch((opt= *pos)) { + case 's': + silent=1; + break; + case 'v': + verbose=1; + break; + case '#': + DBUG_PUSH (++pos); + pos= (char*) " "; /* Skipp rest of arguments */ + break; + case 'V': + version=1; + case 'I': + case '?': + help=1; /* Help text written */ + printf("%s Ver 1.3 for %s at %s\n",my_progname,SYSTEM_TYPE, + MACHINE_TYPE); + if (version) + break; + puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); + puts("This program replace strings in a file or on stdin/stdout.\n" + "It accepts a list of from-strings and to-strings and replaces\n" + "all occurents of from-strings to to-strings.\n" + "The first occurents of a found string is matched. Longer matches\n" + "are prefered before shorter matches.\n\n" + "Special characters in from string:\n" + " \\^ Match start of line.\n" + " \\$ Match end of line.\n" + " \\b Match space-character, start of line or end of line.\n" + " For a end \\b the next replace starts locking at the end\n" + " space-character. A \\b alone in a string matches only a\n" + " space-character.\n"); + printf("Usage: %s [-?svIV] from to from to ... -- [files]\n", my_progname); + puts("or"); + printf("Usage: %s [-?svIV] from to from to ... < fromfile > tofile\n", my_progname); + puts(""); + puts("Options: -? or -I \"Info\" -s \"silent\" -v \"verbose\""); + break; + default: + fprintf(stderr,"illegal option: -%c\n",*pos); + break; + } + } + } + if (*argc == 0) + { + if (!help) + my_message(0,"No replace options given",MYF(ME_BELL)); + exit(0); /* Don't use as pipe */ + } + return(0); +} /* static_get_options */ + + +static int get_replace_strings(argc,argv,from_array,to_array) +register int *argc; +register char **argv[]; +POINTER_ARRAY *from_array,*to_array; +{ + char *pos; + + bzero((char*) from_array,sizeof(from_array[0])); + bzero((char*) to_array,sizeof(to_array[0])); + while (*argc > 0 && (*(pos = *(*argv)) != '-' || pos[1] != '-' || pos[2])) + { + insert_pointer_name(from_array,pos); + (*argc)--; + (*argv)++; + if (!*argc || !strcmp(**argv,"--")) + { + my_message(0,"No to-string for last from-string",MYF(ME_BELL)); + return 1; + } + insert_pointer_name(to_array,**argv); + (*argc)--; + (*argv)++; + } + if (*argc) + { /* Skipp "--" argument */ + (*argc)--; + (*argv)++; + } + return 0; +} + +int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name) +{ + uint i,length,old_count; + byte *new_pos; + const char **new_array; + DBUG_ENTER("insert_pointer_name"); + + if (! pa->typelib.count) + { + if (!(pa->typelib.type_names=(const char **) + my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/ + (sizeof(my_string)+sizeof(*pa->flag))* + (sizeof(my_string)+sizeof(*pa->flag))),MYF(MY_WME)))) + DBUG_RETURN(-1); + if (!(pa->str= (byte*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD), + MYF(MY_WME)))) + { + my_free((gptr) pa->typelib.type_names,MYF(0)); + DBUG_RETURN (-1); + } + pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(byte*)+ + sizeof(*pa->flag)); + pa->flag= (int7*) (pa->typelib.type_names+pa->max_count); + pa->length=0; + pa->max_length=PS_MALLOC-MALLOC_OVERHEAD; + pa->array_allocs=1; + } + length=strlen(name)+1; + if (pa->length+length >= pa->max_length) + { + if (!(new_pos= (byte*) my_realloc((gptr) pa->str, + (uint) (pa->max_length+PS_MALLOC), + MYF(MY_WME)))) + DBUG_RETURN(1); + if (new_pos != pa->str) + { + my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str); + for (i=0 ; i < pa->typelib.count ; i++) + pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff, + char*); + pa->str=new_pos; + } + pa->max_length+=PS_MALLOC; + } + if (pa->typelib.count >= pa->max_count-1) + { + int len; + pa->array_allocs++; + len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD); + if (!(new_array=(const char **) my_realloc((gptr) pa->typelib.type_names, + (uint) len/ + (sizeof(byte*)+sizeof(*pa->flag))* + (sizeof(byte*)+sizeof(*pa->flag)), + MYF(MY_WME)))) + DBUG_RETURN(1); + pa->typelib.type_names=new_array; + old_count=pa->max_count; + pa->max_count=len/(sizeof(byte*) + sizeof(*pa->flag)); + pa->flag= (int7*) (pa->typelib.type_names+pa->max_count); + memcpy((byte*) pa->flag,(my_string) (pa->typelib.type_names+old_count), + old_count*sizeof(*pa->flag)); + } + pa->flag[pa->typelib.count]=0; /* Reset flag */ + pa->typelib.type_names[pa->typelib.count++]= pa->str+pa->length; + pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */ + VOID(strmov(pa->str+pa->length,name)); + pa->length+=length; + DBUG_RETURN(0); +} /* insert_pointer_name */ + + + /* free pointer array */ + +void free_pointer_array(pa) +reg1 POINTER_ARRAY *pa; +{ + if (pa->typelib.count) + { + pa->typelib.count=0; + my_free((gptr) pa->typelib.type_names,MYF(0)); + pa->typelib.type_names=0; + my_free((gptr) pa->str,MYF(0)); + } + return; +} /* free_pointer_array */ + + + /* Code for replace rutines */ + +#define SET_MALLOC_HUNC 64 + +typedef struct st_rep_set { + uint *bits; /* Pointer to used sets */ + short next[LAST_CHAR_CODE]; /* Pointer to next sets */ + uint found_len; /* Best match to date */ + int found_offset; + uint table_offset; + uint size_of_bits; /* For convinience */ +} REP_SET; + +typedef struct st_rep_sets { + uint count; /* Number of sets */ + uint extra; /* Extra sets in buffer */ + uint invisible; /* Sets not chown */ + uint size_of_bits; + REP_SET *set,*set_buffer; + uint *bit_buffer; +} REP_SETS; + +typedef struct st_found_set { + uint table_offset; + int found_offset; +} FOUND_SET; + +typedef struct st_follow { + int chr; + uint table_offset; + uint len; +} FOLLOWS; + + +static int init_sets(REP_SETS *sets,uint states); +static REP_SET *make_new_set(REP_SETS *sets); +static void make_sets_invisible(REP_SETS *sets); +static void free_last_set(REP_SETS *sets); +static void free_sets(REP_SETS *sets); +static void set_bit(REP_SET *set, uint bit); +static void clear_bit(REP_SET *set, uint bit); +static void or_bits(REP_SET *to,REP_SET *from); +static void copy_bits(REP_SET *to,REP_SET *from); +static int cmp_bits(REP_SET *set1,REP_SET *set2); +static int get_next_bit(REP_SET *set,uint lastpos); +static int find_set(REP_SETS *sets,REP_SET *find); +static int find_found(FOUND_SET *found_set,uint table_offset, + int found_offset); +static uint start_at_word(my_string pos); +static uint end_of_word(my_string pos); +static uint replace_len(my_string pos); + +static uint found_sets=0; + + + /* Init a replace structure for further calls */ + +REPLACE *init_replace(my_string *from, my_string *to,uint count, + my_string word_end_chars) +{ + uint i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr; + int used_sets,chr,default_state; + char used_chars[LAST_CHAR_CODE],is_word_end[256]; + my_string pos,to_pos,*to_array; + REP_SETS sets; + REP_SET *set,*start_states,*word_states,*new_set; + FOLLOWS *follow,*follow_ptr; + REPLACE *replace; + FOUND_SET *found_set; + REPLACE_STRING *rep_str; + DBUG_ENTER("init_replace"); + + /* Count number of states */ + for (i=result_len=max_length=0 , states=2 ; i < count ; i++) + { + len=replace_len(from[i]); + if (!len) + { + errno=EINVAL; + my_message(0,"No to-string for last from-string",MYF(ME_BELL)); + DBUG_RETURN(0); + } + states+=len+1; + result_len+=strlen(to[i])+1; + if (len > max_length) + max_length=len; + } + bzero((char*) is_word_end,sizeof(is_word_end)); + for (i=0 ; word_end_chars[i] ; i++) + is_word_end[(uchar) word_end_chars[i]]=1; + + if (init_sets(&sets,states)) + DBUG_RETURN(0); + found_sets=0; + if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count, + MYF(MY_WME)))) + { + free_sets(&sets); + DBUG_RETURN(0); + } + VOID(make_new_set(&sets)); /* Set starting set */ + make_sets_invisible(&sets); /* Hide previus sets */ + used_sets=-1; + word_states=make_new_set(&sets); /* Start of new word */ + start_states=make_new_set(&sets); /* This is first state */ + if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME)))) + { + free_sets(&sets); + my_free((gptr) found_set,MYF(0)); + DBUG_RETURN(0); + } + + /* Init follow_ptr[] */ + for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++) + { + if (from[i][0] == '\\' && from[i][1] == '^') + { + set_bit(start_states,states+1); + if (!from[i][2]) + { + start_states->table_offset=i; + start_states->found_offset=1; + } + } + else if (from[i][0] == '\\' && from[i][1] == '$') + { + set_bit(start_states,states); + set_bit(word_states,states); + if (!from[i][2] && start_states->table_offset == (uint) ~0) + { + start_states->table_offset=i; + start_states->found_offset=0; + } + } + else + { + set_bit(word_states,states); + if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2])) + set_bit(start_states,states+1); + else + set_bit(start_states,states); + } + for (pos=from[i], len=0; *pos ; pos++) + { + if (*pos == '\\' && *(pos+1)) + { + pos++; + switch (*pos) { + case 'b': + follow_ptr->chr = SPACE_CHAR; + break; + case '^': + follow_ptr->chr = START_OF_LINE; + break; + case '$': + follow_ptr->chr = END_OF_LINE; + break; + case 'r': + follow_ptr->chr = '\r'; + break; + case 't': + follow_ptr->chr = '\t'; + break; + case 'v': + follow_ptr->chr = '\v'; + break; + default: + follow_ptr->chr = (uchar) *pos; + break; + } + } + else + follow_ptr->chr= (uchar) *pos; + follow_ptr->table_offset=i; + follow_ptr->len= ++len; + follow_ptr++; + } + follow_ptr->chr=0; + follow_ptr->table_offset=i; + follow_ptr->len=len; + follow_ptr++; + states+=(uint) len+1; + } + + + for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++) + { + set=sets.set+set_nr; + default_state= 0; /* Start from beginning */ + + /* If end of found-string not found or start-set with current set */ + + for (i= (uint) ~0; (i=get_next_bit(set,i)) ;) + { + if (!follow[i].chr) + { + if (! default_state) + default_state= find_found(found_set,set->table_offset, + set->found_offset+1); + } + } + copy_bits(sets.set+used_sets,set); /* Save set for changes */ + if (!default_state) + or_bits(sets.set+used_sets,sets.set); /* Can restart from start */ + + /* Find all chars that follows current sets */ + bzero((char*) used_chars,sizeof(used_chars)); + for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;) + { + used_chars[follow[i].chr]=1; + if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr && + follow[i].len > 1) || follow[i].chr == END_OF_LINE) + used_chars[0]=1; + } + + /* Mark word_chars used if \b is in state */ + if (used_chars[SPACE_CHAR]) + for (pos= word_end_chars ; *pos ; pos++) + used_chars[(int) (uchar) *pos] = 1; + + /* Handle other used characters */ + for (chr= 0 ; chr < 256 ; chr++) + { + if (! used_chars[chr]) + set->next[chr]= chr ? default_state : -1; + else + { + new_set=make_new_set(&sets); + set=sets.set+set_nr; /* if realloc */ + new_set->table_offset=set->table_offset; + new_set->found_len=set->found_len; + new_set->found_offset=set->found_offset+1; + found_end=0; + + for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; ) + { + if (!follow[i].chr || follow[i].chr == chr || + (follow[i].chr == SPACE_CHAR && + (is_word_end[chr] || + (!chr && follow[i].len > 1 && ! follow[i+1].chr))) || + (follow[i].chr == END_OF_LINE && ! chr)) + { + if ((! chr || (follow[i].chr && !follow[i+1].chr)) && + follow[i].len > found_end) + found_end=follow[i].len; + if (chr && follow[i].chr) + set_bit(new_set,i+1); /* To next set */ + else + set_bit(new_set,i); + } + } + if (found_end) + { + new_set->found_len=0; /* Set for testing if first */ + bits_set=0; + for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;) + { + if ((follow[i].chr == SPACE_CHAR || + follow[i].chr == END_OF_LINE) && ! chr) + bit_nr=i+1; + else + bit_nr=i; + if (follow[bit_nr-1].len < found_end || + (new_set->found_len && + (chr == 0 || !follow[bit_nr].chr))) + clear_bit(new_set,i); + else + { + if (chr == 0 || !follow[bit_nr].chr) + { /* best match */ + new_set->table_offset=follow[bit_nr].table_offset; + if (chr || (follow[i].chr == SPACE_CHAR || + follow[i].chr == END_OF_LINE)) + new_set->found_offset=found_end; /* New match */ + new_set->found_len=found_end; + } + bits_set++; + } + } + if (bits_set == 1) + { + set->next[chr] = find_found(found_set, + new_set->table_offset, + new_set->found_offset); + free_last_set(&sets); + } + else + set->next[chr] = find_set(&sets,new_set); + } + else + set->next[chr] = find_set(&sets,new_set); + } + } + } + + /* Alloc replace structure for the replace-state-machine */ + + if ((replace=(REPLACE*) my_malloc(sizeof(REPLACE)*(sets.count)+ + sizeof(REPLACE_STRING)*(found_sets+1)+ + sizeof(my_string)*count+result_len, + MYF(MY_WME | MY_ZEROFILL)))) + { + rep_str=(REPLACE_STRING*) (replace+sets.count); + to_array=(my_string*) (rep_str+found_sets+1); + to_pos=(my_string) (to_array+count); + for (i=0 ; i < count ; i++) + { + to_array[i]=to_pos; + to_pos=strmov(to_pos,to[i])+1; + } + rep_str[0].found=1; + rep_str[0].replace_string=0; + for (i=1 ; i <= found_sets ; i++) + { + pos=from[found_set[i-1].table_offset]; + rep_str[i].found= !bcmp(pos,"\\^",3) ? 2 : 1; + rep_str[i].replace_string=to_array[found_set[i-1].table_offset]; + rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos); + rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+ + end_of_word(pos); + } + for (i=0 ; i < sets.count ; i++) + { + for (j=0 ; j < 256 ; j++) + if (sets.set[i].next[j] >= 0) + replace[i].next[j]=replace+sets.set[i].next[j]; + else + replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1)); + } + } + my_free((gptr) follow,MYF(0)); + free_sets(&sets); + my_free((gptr) found_set,MYF(0)); + DBUG_PRINT("exit",("Replace table has %d states",sets.count)); + DBUG_RETURN(replace); +} + + +static int init_sets(REP_SETS *sets,uint states) +{ + bzero((char*) sets,sizeof(*sets)); + sets->size_of_bits=((states+7)/8); + if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC, + MYF(MY_WME)))) + return 1; + if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits* + SET_MALLOC_HUNC,MYF(MY_WME)))) + { + my_free((gptr) sets->set,MYF(0)); + return 1; + } + return 0; +} + + /* Make help sets invisible for nicer codeing */ + +static void make_sets_invisible(REP_SETS *sets) +{ + sets->invisible=sets->count; + sets->set+=sets->count; + sets->count=0; +} + +static REP_SET *make_new_set(REP_SETS *sets) +{ + uint i,count,*bit_buffer; + REP_SET *set; + if (sets->extra) + { + sets->extra--; + set=sets->set+ sets->count++; + bzero((char*) set->bits,sizeof(uint)*sets->size_of_bits); + bzero((char*) &set->next[0],sizeof(set->next[0])*LAST_CHAR_CODE); + set->found_offset=0; + set->found_len=0; + set->table_offset= (uint) ~0; + set->size_of_bits=sets->size_of_bits; + return set; + } + count=sets->count+sets->invisible+SET_MALLOC_HUNC; + if (!(set=(REP_SET*) my_realloc((gptr) sets->set_buffer, + sizeof(REP_SET)*count, + MYF(MY_WME)))) + return 0; + sets->set_buffer=set; + sets->set=set+sets->invisible; + if (!(bit_buffer=(uint*) my_realloc((gptr) sets->bit_buffer, + (sizeof(uint)*sets->size_of_bits)*count, + MYF(MY_WME)))) + return 0; + sets->bit_buffer=bit_buffer; + for (i=0 ; i < count ; i++) + { + sets->set_buffer[i].bits=bit_buffer; + bit_buffer+=sets->size_of_bits; + } + sets->extra=SET_MALLOC_HUNC; + return make_new_set(sets); +} + +static void free_last_set(REP_SETS *sets) +{ + sets->count--; + sets->extra++; + return; +} + +static void free_sets(REP_SETS *sets) +{ + my_free((gptr)sets->set_buffer,MYF(0)); + my_free((gptr)sets->bit_buffer,MYF(0)); + return; +} + +static void set_bit(REP_SET *set, uint bit) +{ + set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT); + return; +} + +static void clear_bit(REP_SET *set, uint bit) +{ + set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT)); + return; +} + + +static void or_bits(REP_SET *to,REP_SET *from) +{ + reg1 uint i; + for (i=0 ; i < to->size_of_bits ; i++) + to->bits[i]|=from->bits[i]; + return; +} + +static void copy_bits(REP_SET *to,REP_SET *from) +{ + memcpy((byte*) to->bits,(byte*) from->bits, + (size_t) (sizeof(uint) * to->size_of_bits)); +} + +static int cmp_bits(REP_SET *set1,REP_SET *set2) +{ + return bcmp((byte*) set1->bits,(byte*) set2->bits, + sizeof(uint) * set1->size_of_bits); +} + + + /* Get next set bit from set. */ + +static int get_next_bit(REP_SET *set,uint lastpos) +{ + uint pos,*start,*end,bits; + + start=set->bits+ ((lastpos+1) / WORD_BIT); + end=set->bits + set->size_of_bits; + bits=start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1); + + while (! bits && ++start < end) + bits=start[0]; + if (!bits) + return 0; + pos=(uint) (start-set->bits)*WORD_BIT; + while (! (bits & 1)) + { + bits>>=1; + pos++; + } + return pos; +} + + /* find if there is a same set in sets. If there is, use it and + free given set, else put in given set in sets and return it's + position */ + +static int find_set(REP_SETS *sets,REP_SET *find) +{ + uint i; + for (i=0 ; i < sets->count-1 ; i++) + { + if (!cmp_bits(sets->set+i,find)) + { + free_last_set(sets); + return i; + } + } + return i; /* return new postion */ +} + + /* find if there is a found_set with same table_offset & found_offset + If there is return offset to it, else add new offset and return pos. + Pos returned is -offset-2 in found_set_structure because it's is + saved in set->next and set->next[] >= 0 points to next set and + set->next[] == -1 is reserved for end without replaces. + */ + +static int find_found(FOUND_SET *found_set,uint table_offset, int found_offset) +{ + int i; + for (i=0 ; (uint) i < found_sets ; i++) + if (found_set[i].table_offset == table_offset && + found_set[i].found_offset == found_offset) + return -i-2; + found_set[i].table_offset=table_offset; + found_set[i].found_offset=found_offset; + found_sets++; + return -i-2; /* return new postion */ +} + + /* Return 1 if regexp starts with \b or ends with \b*/ + +static uint start_at_word(my_string pos) +{ + return (((!bcmp(pos,"\\b",2) && pos[2]) || !bcmp(pos,"\\^",2)) ? 1 : 0); +} + +static uint end_of_word(my_string pos) +{ + my_string end=strend(pos); + return ((end > pos+2 && !bcmp(end-2,"\\b",2)) || + (end >= pos+2 && !bcmp(end-2,"\\$",2))) ? + 1 : 0; +} + + +static uint replace_len(my_string str) +{ + uint len=0; + while (*str) + { + if (str[0] == '\\' && str[1]) + str++; + str++; + len++; + } + return len; +} + + + /* The actual loop */ + +uint replace_strings(REPLACE *rep, my_string *start,uint *max_length, my_string from) +{ + reg1 REPLACE *rep_pos; + reg2 REPLACE_STRING *rep_str; + my_string to,end,pos,new; + + end=(to= *start) + *max_length-1; + rep_pos=rep+1; + for(;;) + { + while (!rep_pos->found) + { + rep_pos= rep_pos->next[(uchar) *from]; + if (to == end) + { + (*max_length)+=8192; + if (!(new=my_realloc(*start,*max_length,MYF(MY_WME)))) + return (uint) -1; + to=new+(to - *start); + end=(*start=new)+ *max_length-1; + } + *to++= *from++; + } + if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string) + return (uint) (to - *start)-1; + updated=1; /* Some my_string is replaced */ + to-=rep_str->to_offset; + for (pos=rep_str->replace_string; *pos ; pos++) + { + if (to == end) + { + (*max_length)*=2; + if (!(new=my_realloc(*start,*max_length,MYF(MY_WME)))) + return (uint) -1; + to=new+(to - *start); + end=(*start=new)+ *max_length-1; + } + *to++= *pos; + } + if (!*(from-=rep_str->from_offset) && rep_pos->found != 2) + return (uint) (to - *start); + rep_pos=rep; + } +} + +static char *buffer; /* The buffer itself, grown as needed. */ +static int bufbytes; /* Number of bytes in the buffer. */ +static int bufread,my_eof; /* Number of bytes to get with each read(). */ +static uint bufalloc; +static char *out_buff; +static uint out_length; + +static int initialize_buffer() +{ + bufread = 8192; + bufalloc = bufread + bufread / 2; + if (!(buffer = my_malloc(bufalloc+1,MYF(MY_WME)))) + return 1; + bufbytes=my_eof=0; + out_length=bufread; + if (!(out_buff=my_malloc(out_length,MYF(MY_WME)))) + return(1); + return 0; +} + +static void reset_buffer() +{ + bufbytes=my_eof=0; +} + +static void free_buffer() +{ + my_free(buffer,MYF(MY_WME)); + my_free(out_buff,MYF(MY_WME)); +} + + +/* Fill the buffer retaining the last n bytes at the beginning of the + newly filled buffer (for backward context). Returns the number of new + bytes read from disk. */ + +static int fill_buffer_retaining(fd,n) +File fd; +int n; +{ + int i; + + /* See if we need to grow the buffer. */ + if ((int) bufalloc - n <= bufread) + { + while ((int) bufalloc - n <= bufread) + { + bufalloc *= 2; + bufread *= 2; + } + buffer = my_realloc(buffer, bufalloc+1, MYF(MY_WME)); + if (! buffer) + return(-1); + } + + /* Shift stuff down. */ + bmove(buffer,buffer+bufbytes-n,(uint) n); + bufbytes = n; + + if (my_eof) + return 0; + + /* Read in new stuff. */ + if ((i=(int) my_read(fd, buffer + bufbytes, (uint) bufread,MYF(MY_WME))) < 0) + return -1; + + /* Kludge to pretend every nonempty file ends with a newline. */ + if (i == 0 && bufbytes > 0 && buffer[bufbytes - 1] != '\n') + { + my_eof = i = 1; + buffer[bufbytes] = '\n'; + } + + bufbytes += i; + return i; +} + + /* Return 0 if convert is ok */ + /* Global variable update is set if something was changed */ + +static int convert_pipe(rep,in,out) +REPLACE *rep; +FILE *in,*out; +{ + int retain,error; + uint length; + char save_char,*end_of_line,*start_of_line; + DBUG_ENTER("convert_pipe"); + + updated=retain=0; + reset_buffer(); + + while ((error=fill_buffer_retaining(fileno(in),retain)) > 0) + { + end_of_line=buffer ; + buffer[bufbytes]=0; /* Sentinel */ + for (;;) + { + start_of_line=end_of_line; + while (end_of_line[0] != '\n' && end_of_line[0]) + end_of_line++; + if (end_of_line == buffer+bufbytes) + { + retain=end_of_line - start_of_line; + break; /* No end of line, read more */ + } + save_char=end_of_line[0]; + end_of_line[0]=0; + end_of_line++; + if ((length=replace_strings(rep,&out_buff,&out_length,start_of_line)) == + (uint) -1) + return 1; + if (!my_eof) + out_buff[length++]=save_char; /* Don't write added newline */ + if (my_fwrite(out,out_buff,length,MYF(MY_WME | MY_NABP))) + DBUG_RETURN(1); + } + } + DBUG_RETURN(error); +} + + +static int convert_file(rep,name) +REPLACE *rep; +my_string name; +{ + int error; + FILE *in,*out; + char dir_buff[FN_REFLEN],*tempname; + DBUG_ENTER("convert_file"); + + if (!(in=my_fopen(name,O_RDONLY,MYF(MY_WME)))) + DBUG_RETURN(1); + dirname_part(dir_buff,name); + tempname=my_tempnam(dir_buff,"PR",MYF(MY_WME)); + if (!(out=my_fopen(tempname,(int) (O_WRONLY | O_CREAT), + MYF(MY_WME)))) + { + (*free)(tempname); + my_fclose(in,MYF(0)); + DBUG_RETURN(1); + } + + error=convert_pipe(rep,in,out); + my_fclose(in,MYF(0)); my_fclose(out,MYF(0)); + + if (updated && ! error) + my_redel(name,tempname,MYF(MY_WME | MY_LINK_WARNING)); + else + my_delete(tempname,MYF(MY_WME)); + (*free)(tempname); + if (!silent && ! error) + { + if (updated) + printf("%s converted\n",name); + else if (verbose) + printf("%s left unchanged\n",name); + } + DBUG_RETURN(error); +} diff --git a/extra/resolveip.c b/extra/resolveip.c new file mode 100644 index 00000000000..d739f8de244 --- /dev/null +++ b/extra/resolveip.c @@ -0,0 +1,204 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Resolves IP's to hostname and hostnames to IP's */ + +#define RESOLVE_VERSION "2.0" + +#include <global.h> +#include <sys/types.h> +#include <sys/socket.h> +#ifndef HAVE_BROKEN_NETINET_INCLUDES +#include <netinet/in.h> +#endif +#include <arpa/inet.h> +#include <netdb.h> +#include <m_ctype.h> +#include <my_sys.h> +#include <getopt.h> + +#if !defined(_AIX) && !defined(HAVE_UNIXWARE7_THREADS) && !defined(HAVE_UNIXWARE7_POSIX) && !defined(h_errno) +extern int h_errno; +#endif + +static int silent=0; + +static struct option long_options[] = +{ + {"help", no_argument, 0, '?'}, + {"info", no_argument, 0, 'I'}, + {"silent", no_argument, 0, 's'}, + {"version", no_argument, 0, 'V'}, + {0, 0, 0, 0} +}; + + +static void print_version(void) +{ + printf("%s Ver %s, for %s (%s)\n",my_progname,RESOLVE_VERSION, + SYSTEM_TYPE,MACHINE_TYPE); +} + + +static void usage(void) +{ + print_version(); + puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); + puts("Get hostname based on IP-address or IP-address based on hostname.\n"); + printf("Usage: %s [OPTIONS] hostname or IP-address\n",my_progname); + printf("\n\ + -?, --help Displays this help and exits.\n\ + -I, --info Synonym for the above.\n\ + -s, --silent Be more silent.\n\ + -V, --version Displays version information and exits.\n"); +} + +/*static my_string load_default_groups[]= { "resolveip","client",0 }; */ + +static int get_options(int *argc,char ***argv) +{ + int c,option_index; + + /* load_defaults("my",load_default_groups,argc,argv); */ + while ((c=getopt_long(*argc,*argv,"?IsV", + long_options, &option_index)) != EOF) + { + switch (c) { + case 's': + silent=1; + break; + case 'V': print_version(); exit(0); + case 'I': + case '?': + usage(); + exit(0); + default: + fprintf(stderr,"%s: Illegal option character '%c'\n", + my_progname,opterr); + return(1); + break; + } + } + (*argc)-=optind; + (*argv)+=optind; + if (*argc == 0) + { + usage(); + return 1; + } + return 0; +} /* get_options */ + + + +int main(int argc, char **argv) +{ + struct hostent *hpaddr; + u_long taddr; + char *ip,**q; + int error=0; + + MY_INIT(argv[0]); + + if (get_options(&argc,&argv)) + exit(1); + + while (argc--) + { + ip = *argv++; + + if (isdigit(ip[0])) + { + taddr = inet_addr(ip); + if (taddr == htonl(INADDR_BROADCAST)) + { + puts("Broadcast"); + continue; + } + if (taddr == htonl(INADDR_ANY)) + { + if (!taddr) + puts("Null-IP-Addr"); + else + puts("Old-Bcast"); + continue; + } + + hpaddr = gethostbyaddr((char*) &(taddr), sizeof(struct in_addr),AF_INET); + if (hpaddr) + { + if (silent) + puts(hpaddr->h_name); + else + { + printf ("Host name of %s is %s", ip,hpaddr->h_name); + for (q = hpaddr->h_aliases; *q != 0; q++) + (void) printf(", %s", *q); + puts(""); + } + } + else + { + error=2; + fprintf(stderr,"%s: Unable to find hostname for '%s'\n",my_progname, + ip); + } + } + else + { + hpaddr = gethostbyname(ip); + if (!hpaddr) + { + const char *err; + fprintf(stderr,"%s: Unable to find hostid for '%s'",my_progname,ip); + switch (h_errno) { + case HOST_NOT_FOUND: err="host not found"; break; + case TRY_AGAIN: err="try again"; break; + case NO_RECOVERY: err="no recovery"; break; + case NO_DATA: err="no_data"; break; + default: err=0; + } + if (err) + fprintf(stderr,": %s\n",err); + else + fprintf(stderr,"\n"); + error=2; + } + else if (silent) + { + struct in_addr in; + memcpy((char*) &in.s_addr, (char*) *hpaddr->h_addr_list, + sizeof (in.s_addr)); + puts(inet_ntoa(in)); + } + else + { + char **p; + for (p = hpaddr->h_addr_list; *p != 0; p++) + { + struct in_addr in; + memcpy(&in.s_addr, *p, sizeof (in.s_addr)); + printf ("IP address of %s is %s\n",ip,inet_ntoa(in)); + } + } + } + } + exit(error); +} + + + |