1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 #include "cs.h"
8 #include <string.h>
9 
10 #define BLEN 40960
11 
12 /*------------------ 18 Nov 1999: utility routines --------------------*/
13 
tokenize_string(char * sin,int * ntok,char *** stok)14 static void tokenize_string( char * sin , int * ntok , char *** stok )
15 {
16    int     n_tok , ii ;
17    char ** s_tok , *cpt , *sss ;
18 
19    if( stok == NULL ) return ;
20    if( ntok == NULL || sin == NULL || sin[0] == '\0' ){ *stok = NULL; return; }
21 
22    n_tok = 0 ;
23    s_tok = (char **) malloc( sizeof(char *) ) ;
24 
25    /* break input into tokens, copy them in the new arg list */
26 
27    cpt = strtok( sin , " \t\n\r\f\v" ) ;
28    if( cpt == NULL ){ free(s_tok); *stok = NULL; return; }     /* do nothing */
29 
30    while( cpt != NULL ){
31       ii  = strlen(cpt) ;
32       sss = (char *) malloc( sizeof(char) * (ii+1) ) ;
33       strcpy(sss,cpt) ;
34       n_tok++ ;
35       s_tok = (char **) realloc( s_tok , sizeof(char *) * n_tok ) ;
36       s_tok[n_tok-1] = sss ;
37 
38       cpt = strtok( NULL , " \t\n\r\f\v" ) ;
39    }
40 
41    *ntok = n_tok ; *stok = s_tok ; return ;
42 }
43 
duplicate_string_list(int nin,char ** sin,char *** sout)44 static void duplicate_string_list( int nin , char ** sin , char *** sout )
45 {
46    int ii , ll ;
47    char ** s_out = NULL ;
48 
49    if( sout == NULL ) return ;
50    if( nin < 1 || sin == NULL ){ *sout = NULL ; return ; }
51 
52    s_out = (char **) malloc( sizeof(char *) * nin ) ;
53    for( ii=0 ; ii < nin ; ii++ ){
54       ll = strlen(sin[ii]) ;
55       s_out[ii] = (char *) malloc( sizeof(char) * (ll+1) );
56       strcpy( s_out[ii] , sin[ii] ) ;
57    }
58 
59    *sout = s_out ; return ;
60 }
61 
free_string_list(int nin,char ** sin)62 static void free_string_list( int nin , char ** sin )
63 {
64    int ii ;
65    if( sin == NULL ) return ;
66    for( ii=0 ; ii < nin ; ii++ ) if( sin[ii] != NULL ) free(sin[ii]) ;
67    free(sin) ; return ;
68 }
69 
appendto_string_list(int * nfirst,char *** sfirst,int nsecond,char ** ssecond)70 static void appendto_string_list( int *nfirst , char *** sfirst ,
71                                   int nsecond , char ** ssecond  )
72 {
73    int     nf=*nfirst , ii , ll ;
74    char ** sf ;
75 
76    if( nsecond < 1 || ssecond == NULL ) return ;  /* nothing to do */
77 
78    if( *sfirst == NULL || nf == 0 )
79       sf = (char **) malloc( sizeof(char *) * nsecond ) ;
80    else
81       sf = (char **) realloc( *sfirst , sizeof(char *)*(nf+nsecond) ) ;
82 
83    for( ii=0 ; ii < nsecond ; ii++ ){
84       ll = strlen(ssecond[ii]) ;
85       sf[nf+ii] = (char *) malloc( sizeof(char) * (ll+1) ) ;
86       strcpy( sf[nf+ii] , ssecond[ii] ) ;
87    }
88 
89    *nfirst = nf+nsecond ;
90    *sfirst = sf         ; return ;
91 }
92 
93 /*----------------------------------------------------------------------------
94    18 Nov 1999: Take the input string (sin) and put its pieces at the
95                 front of the arg list, just after argv[0].
96                 If *new_argv is returned as NULL, then there are no new args.
97 ------------------------------------------------------------------------------*/
98 
prepend_string_to_args(char * sin,int argc,char * argv[],int * new_argc,char *** new_argv)99 void prepend_string_to_args( char * sin ,
100                              int argc , char * argv[] ,
101                              int * new_argc , char *** new_argv )
102 {
103    int     n_argc , ii , ntok=0    ;
104    char ** n_argv ,   ** stok=NULL ;
105    char * cpt , * sss ;
106 
107    if( new_argc == NULL || new_argv == NULL ) return ;              /* error */
108 
109    if( sin == NULL || sin[0] == '\0' ){ *new_argv = NULL; return; } /* do nothing */
110 
111    /*-- if no inputs after argv[0], prepend and append are identical --*/
112 
113    if( argc < 2 ){
114       append_string_to_args( sin , argc , argv , new_argc , new_argv ) ;
115       return ;
116    }
117 
118    /*-- OK, must do it my way --*/
119 
120    tokenize_string( sin , &ntok , &stok ) ;
121    if( stok == NULL || ntok < 1 ){ *new_argv = NULL; return; }      /* do nothing */
122 
123    /* copy first input arg to output */
124 
125    duplicate_string_list( 1 , argv , &n_argv ) ;
126    n_argc = 1 ;
127 
128    /* append token list to output */
129 
130    appendto_string_list( &n_argc , &n_argv , ntok , stok ) ;
131    free_string_list( ntok , stok ) ;
132 
133    /* append rest of input args to output */
134 
135    appendto_string_list( &n_argc , &n_argv , argc-1 , argv+1 ) ;
136 
137    *new_argc = n_argc ;  /* the results! */
138    *new_argv = n_argv ;
139    return ;
140 }
141 
142 /*----------------------------------------------------------------------------
143    18 Nov 1999: Take the input string (sin) and append its pieces to
144                 the existing command line arguments.
145                 If *new_argv is returned as NULL, then there are no new args.
146 ------------------------------------------------------------------------------*/
147 
append_string_to_args(char * sin,int argc,char * argv[],int * new_argc,char *** new_argv)148 void append_string_to_args( char * sin ,
149                             int argc , char * argv[] ,
150                             int * new_argc , char *** new_argv )
151 {
152    int     n_argc , ii , ntok=0    ;
153    char ** n_argv ,   ** stok=NULL ;
154    char * cpt , * sss ;
155 
156    if( new_argc == NULL || new_argv == NULL ) return ;              /* error */
157 
158    if( sin == NULL || sin[0] == '\0' ){ *new_argv = NULL; return; } /* do nothing */
159 
160    tokenize_string( sin , &ntok , &stok ) ;
161    if( stok == NULL || ntok < 1 ){ *new_argv = NULL; return; }      /* do nothing */
162 
163    /* copy input args to output */
164 
165    if( argc > 0 ){
166       duplicate_string_list( argc , argv , &n_argv ) ;
167       n_argc = argc ;
168    } else {                                                    /* shouldn't happen */
169       n_argv = NULL ;
170       n_argc = 0 ;
171    }
172 
173    /* append token list to output */
174 
175    appendto_string_list( &n_argc , &n_argv , ntok , stok ) ;
176    free_string_list( ntok , stok ) ;
177 
178    *new_argc = n_argc ;  /* the results! */
179    *new_argv = n_argv ;
180    return ;
181 }
182 
183 /*-------------------------------------------------------------------------------
184    Copy stdin to the command line arguments if the last argument on the
185    command line is '-@'.
186    18 Nov 1999: modified to put the actual args mangling in the routine above.
187 ---------------------------------------------------------------------------------*/
188 
addto_args(int argc,char * argv[],int * new_argc,char *** new_argv)189 void addto_args( int argc , char * argv[] , int * new_argc , char *** new_argv )
190 {
191    int  ii , nsin , nall ;
192    char lbuf[4096] ;
193    char * sin , * cpt ;
194 
195    /*-- sanity checks --*/
196 
197    if( new_argc == NULL || new_argv == NULL ) return ;
198 
199    if( strcmp(argv[argc-1],"-@") != 0 ){ *new_argv = NULL; return; } /* do nothing */
200 
201    /* suck the standard input in */
202 
203    nall = BLEN ;
204    sin  = (char *) malloc( sizeof(char) * nall ) ;  /* will hold stdin */
205    nsin = 0 ;
206 
207    sin[0] = '\0';  /* 'terminate' this empty string    18 Apr 2006 [rickr] */
208 
209    do{
210       cpt = afni_fgets( lbuf , BLEN , stdin ) ; /* read line */
211       if( cpt == NULL ) break ;            /* end of file */
212       ii = strlen(lbuf) ;
213       if( ii+nsin >= nall-4 ){             /* make more sin space */
214          nall += BLEN ;
215          sin   = (char *) realloc( sin , sizeof(char) * nall ) ;
216       }
217       strcat(sin,lbuf) ; nsin = strlen(sin) ;  /* add to sin array */
218    } while(1) ;
219 
220    if( nsin == 0 ){ *new_argv = NULL; free(sin); return; }  /* nothing was read */
221 
222    append_string_to_args( sin , argc-1 , argv , new_argc , new_argv ) ;  /* real work */
223 
224    free(sin) ; return ;
225 }
226