1 #include "mrilib.h"
2 
3 /*----------------------------------------------------------------------
4    history:
5 
6    ...         [rwcox]
7      - Initial Version(s)
8 
9    24 Mar 2005 [rickr]
10      - added options: -help, -new_char, -new_string, -unescape
11   ----------------------------------------------------------------------
12 */
13 
14 
15 void help_n_exit( void );
16 int  suck_file( char *fname , char **fbuf ) ;
17 
main(int argc,char * argv[])18 int main( int argc , char * argv[] )
19 {
20    int nbuf , ntarg , ii,jj, nfind , ff , quiet = 0;
21    char *fbuf , *targ ;
22    char *jstr=strdup("AFNI-rules-") ; int njstr=strlen(jstr) ;
23 
24    int   ac, unesc = 0; /* for -unescape option    24 Mar 2005 [rickr] */
25    int   use_newstr = 0;
26    char  newchar = 'x';
27 
28    int   nfname=0 ;    /* for globbing */
29    char **fname=NULL ;
30 
31    /* help? */
32 
33    if( argc < 3 ) help_n_exit();
34 
35    /* Check for arguments.  If we don't get an exact match, continue, */
36    /* allowing the user to start a target string with '-'.            */
37    for( ac = 1; ac < argc && argv[ac][0] == '-'; ac++ ){
38       if( strcmp(argv[ac], "-help") == 0 )
39          help_n_exit();
40 
41       if( strcmp(argv[ac], "-new_char") == 0 ){
42          ac++;
43          if( ac >= argc ){
44             fprintf(stderr,"** -new_char option requires an argument\n");
45             exit(1);
46          }
47 
48          newchar = argv[ac][0];
49       }
50 
51       if ( strcmp(argv[ac], "-quiet") == 0) {
52          quiet++;
53       }
54 
55       if( strcmp(argv[ac], "-new_string") == 0 ){
56          ac++;
57          if( ac >= argc ){
58             fprintf(stderr,"** -new_string option requires an argument\n");
59             exit(1);
60          }
61 
62          jstr = strdup(argv[ac]);
63          njstr = strlen(jstr);
64          use_newstr = 1;
65       }
66 
67       if( strcmp(argv[ac], "-unescape") == 0 )
68          unesc = 1;
69    }
70 
71    if( ac > argc-2 ){
72       fprintf(stderr,"** missing target string or input files\n");
73       fprintf(stderr,"   (please see 'strblast -help')\n");
74       exit(1);
75    }
76 
77    machdep() ;
78 
79    /* load the target */
80 
81    targ = argv[ac] ; ntarg = strlen(targ) ; ac++ ;
82    if( ntarg < 1 ){
83       fprintf(stderr,"** Can't enter an empty target string!\n") ;
84       exit(1) ;
85    }
86    if( unesc ){ /* let's leave argv alone, so dup the string */
87       char * tnew = strdup(targ);
88       if( !tnew ){ fprintf(stderr,"** cannot dup targetstring?!\n"); exit(1); }
89       for(ii=0, jj = 0; ii<ntarg; ii++, jj++){
90               if(tnew[ii] == '\\' && tnew[ii+1] == 't'){tnew[jj] = '\t'; ii++;}
91          else if(tnew[ii] == '\\' && tnew[ii+1] == 'n'){tnew[jj] = '\n'; ii++;}
92          else if(tnew[ii] == '\\' && tnew[ii+1] == 'r'){tnew[jj] = '\r'; ii++;}
93          else if(ii > jj) tnew[jj] = tnew[ii];
94       }
95       tnew[jj] = '\0';  /* and terminate */
96 
97       /* now for the ol' switcheroo... */
98       targ = tnew;  ntarg = jj;
99    }
100 
101    /* if the replacement string is too long, truncate it */
102    if( ntarg < njstr ){
103       if( use_newstr ){ jstr[ntarg] = '\0' ; njstr = ntarg; }
104       else            { jstr[0] = newchar  ; njstr = 1;     }
105    }
106 
107    /* get input filenames */
108 
109    MCW_warn_expand(1) ;
110    MCW_file_expand( argc-ac , argv+ac , &nfname , &fname ) ;
111    MCW_warn_expand(0) ;
112    if( nfname == 0 ){
113       fprintf(stderr,"** No files found from command line!\n") ;
114       exit(1) ;
115    }
116 
117    /* loop over files */
118 
119    for( ff=0 ; ff < nfname ; ff++ ){
120 
121       /* read it all into memory */
122 
123       fbuf = NULL ;
124       nbuf = suck_file( fname[ff] , &fbuf ) ;
125       if( nbuf < ntarg || fbuf == NULL ){
126          fprintf(stderr,"** Can't read input file %s\n",fname[ff]) ;
127          if( fbuf != NULL ) free(fbuf) ;
128          continue ;
129       }
130 
131       /* scan for start character */
132 
133       for( nfind=ii=0 ; ii < nbuf-ntarg ; ii++ ){
134 
135          if( fbuf[ii] == targ[0] ){  /* if find it, check rest of string */
136 
137             for( jj=1; jj < ntarg && fbuf[ii+jj]==targ[jj] ; jj++ ) ; /* nada */
138 
139             if( jj == ntarg ){  /* found it */
140                nfind++ ;
141                for( jj=0 ; jj < njstr ; jj++ ) fbuf[ii+jj] = jstr[jj] ;
142                for(      ; jj < ntarg ; jj++ ) fbuf[ii+jj] = newchar ;
143                /* only if found, noted by R Notestine  28 May 2009 [rickr] */
144                ii += ntarg-1 ; /* increment past found word, shy by 1 */
145             }
146          }
147       }
148 
149       if( nfind > 0 ){
150          FILE *fp ;
151          if (quiet < 2)
152             fprintf(stderr,"++ Found %d copies of target %s in file %s\n",
153                  nfind,targ,fname[ff] ) ;
154          fp = fopen( fname[ff] , "wb" ) ;
155          if( fp == NULL ){
156             fprintf(stderr,"** Can't open file %s for output!\n",fname[ff]) ;
157             exit(1) ;
158          }
159          fwrite( fbuf , 1 , nbuf , fp ) ; fclose(fp) ;
160       } else {
161          if (!quiet)
162             fprintf(stderr,"++ Found no copies of target %s in file %s\n",
163                  targ , fname[ff] ) ;
164       }
165 
166       free(fbuf) ;
167 
168    } /* end of loop over files */
169 
170    exit(0) ;
171 }
172 
173 /*------------------------------------------------------------------*/
174 
suck_file(char * fname,char ** fbuf)175 int suck_file( char *fname , char **fbuf )
176 {
177    int len , fd , ii ;
178    char * buf ;
179 
180    if( fname == NULL || fname[0] == '\0' || fbuf == NULL ) return 0 ;
181 
182    len = THD_filesize( fname ) ;
183    if( len <= 0 ) return 0 ;
184 
185    buf = (char *) malloc( sizeof(char) * (len+4) ) ;
186    if( buf == NULL ) return 0 ;
187 
188    fd = open( fname , O_RDONLY ) ;
189    if( fd < 0 ) return 0 ;
190 
191    ii = read( fd , buf , len ) ;
192    close( fd ) ;
193    if( ii <= 0 ){ free(buf) ; return 0; }
194    *fbuf = buf ; return ii ;
195 }
196 
help_n_exit(void)197 void help_n_exit( void )
198 {
199    printf("Usage: strblast [options] TARGETSTRING filename ...\n"
200           "Finds exact copies of the target string in each of\n"
201           "the input files, and replaces all characters with\n"
202           "some junk string.\n"
203           "\n"
204           "options:\n"
205           "\n"
206           "  -help              : show this help\n"
207           "\n"
208           "  -new_char CHAR     : replace TARGETSTRING with CHAR (repeated)\n"
209           "\n"
210           "      This option is used to specify what TARGETSTRING is\n"
211           "      replaced with.  In this case, replace it with repeated\n"
212           "      copies of the character CHAR.\n"
213           "\n"
214           "  -new_string STRING : replace TARGETSTRING with STRING\n"
215           "\n"
216           "      This option is used to specify what TARGETSTRING is\n"
217           "      replaced with.  In this case, replace it with the string\n"
218           "      STRING.  If STRING is not long enough, then CHAR from the\n"
219           "      -new_char option will be used to complete the overwrite\n"
220           "      (or the character 'x', by default).\n"
221           "\n"
222           "  -unescape          : parse TARGETSTRING for escaped characters\n"
223           "                       (includes '\\t', '\\n', '\\r')\n"
224           "\n"
225           "      If this option is given, strblast will parse TARGETSTRING\n"
226           "      replacing any escaped characters with their encoded ASCII\n"
227           "      values.\n"
228           "\n"
229           "  -quiet : Do not report files with no strings found.\n"
230           "           use -quiet -quiet to avoid any reporting.\n"
231           "\n"
232           "Examples:\n"
233           "  strings I.001 | more # see if Subject Name is present\n"
234           "  strblast 'Subject Name' I.*\n"
235           "\n"
236           "  strblast -unescape \"END OF LINE\\n\"       infile.txt\n"
237           "  strblast -new_char \" \" \"BAD STRING\"      infile.txt\n"
238           "  strblast -new_string \"GOOD\" \"BAD STRING\" infile.txt\n"
239           "\n"
240           "Notes and Warnings:\n"
241           "  * strblast will modify the input files irreversibly!\n"
242           "      You might want to test if they are still usable.\n"
243           "  * strblast reads files into memory to operate on them.\n"
244           "      If the file is too big to fit in memory, strblast\n"
245           "      will fail.\n"
246           "  * strblast  will do internal wildcard expansion, so\n"
247           "      if there are too many input files for your shell to\n"
248           "      handle, you can do something like\n"
249           "         strblast 'Subject Name' 'I.*'\n"
250           "      and strblast will expand the 'I.*' wildcard for you.\n"
251          ) ;
252    exit(0) ;
253 }
254