1 /* GNU SED, a batch stream editor. 2 Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003,2006,2008,2009 3 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3, or (at your option) 8 any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 18 19 20 #include "sed.h" 21 22 23 #include <stdio.h> 24 #ifdef HAVE_STRINGS_H 25 # include <strings.h> 26 #else 27 # include <string.h> 28 #endif /*HAVE_STRINGS_H*/ 29 #ifdef HAVE_MEMORY_H 30 # include <memory.h> 31 #endif 32 33 #ifndef HAVE_STRCHR 34 # define strchr index 35 # define strrchr rindex 36 #endif 37 38 #ifdef HAVE_STDLIB_H 39 # include <stdlib.h> 40 #endif 41 42 #ifdef HAVE_SYS_TYPES_H 43 # include <sys/types.h> 44 #endif 45 #include "getopt.h" 46 47 #ifndef BOOTSTRAP 48 #ifndef HAVE_STDLIB_H 49 extern char *getenv P_((const char *)); 50 #endif 51 #endif 52 53 #ifndef HAVE_STRTOUL 54 # define ATOI(x) atoi(x) 55 #else 56 # define ATOI(x) strtoul(x, NULL, 0) 57 #endif 58 59 char *program_name; 60 61 int extended_regexp_flags = 0; 62 63 /* If set, fflush(stdout) on every line output. */ 64 bool unbuffered_output = false; 65 66 /* If set, don't write out the line unless explicitly told to */ 67 bool no_default_output = false; 68 69 /* If set, reset line counts on every new file. */ 70 bool separate_files = false; 71 72 /* If set, follow symlinks when processing in place */ 73 bool follow_symlinks = false; 74 75 /* How do we edit files in-place? (we don't if NULL) */ 76 char *in_place_extension = NULL; 77 78 /* The mode to use to read files, either "rt" or "rb". */ 79 char *read_mode = "rt"; 80 81 /* Do we need to be pedantically POSIX compliant? */ 82 enum posixicity_types posixicity; 83 84 /* How long should the `l' command's output line be? */ 85 countT lcmd_out_line_len = 70; 86 87 /* The complete compiled SED program that we are going to run: */ 88 static struct vector *the_program = NULL; 89 90 static void usage P_((int)); 91 static void 92 contact(errmsg) 93 int errmsg; 94 { 95 FILE *out = errmsg ? stderr : stdout; 96 #ifndef REG_PERL 97 fprintf(out, _("GNU sed home page: <http://www.gnu.org/software/sed/>.\n\ 98 General help using GNU software: <http://www.gnu.org/gethelp/>.\n")); 99 #endif 100 101 /* Only print the bug report address for `sed --help', otherwise we'll 102 get reports for other people's bugs. */ 103 if (!errmsg) 104 fprintf(out, _("E-mail bug reports to: <%s>.\n\ 105 Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"), 106 PACKAGE_BUGREPORT, PACKAGE); 107 } 108 109 static void usage P_((int)); 110 static void 111 usage(status) 112 int status; 113 { 114 FILE *out = status ? stderr : stdout; 115 116 #ifdef REG_PERL 117 #define PERL_HELP _(" -R, --regexp-perl\n use Perl 5's regular expressions syntax in the script.\n") 118 #else 119 #define PERL_HELP "" 120 #endif 121 122 fprintf(out, _("\ 123 Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n\ 124 \n"), myname); 125 126 fprintf(out, _(" -n, --quiet, --silent\n\ 127 suppress automatic printing of pattern space\n")); 128 fprintf(out, _(" -e script, --expression=script\n\ 129 add the script to the commands to be executed\n")); 130 fprintf(out, _(" -f script-file, --file=script-file\n\ 131 add the contents of script-file to the commands to be executed\n")); 132 #ifdef ENABLE_FOLLOW_SYMLINKS 133 fprintf(out, _(" --follow-symlinks\n\ 134 follow symlinks when processing in place\n")); 135 #endif 136 fprintf(out, _(" -i[SUFFIX], --in-place[=SUFFIX]\n\ 137 edit files in place (makes backup if extension supplied)\n")); 138 #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS) || defined(__EMX__) 139 fprintf(out, _(" -b, --binary\n\ 140 open files in binary mode (CR+LFs are not processed specially)\n")); 141 #endif 142 fprintf(out, _(" -l N, --line-length=N\n\ 143 specify the desired line-wrap length for the `l' command\n")); 144 fprintf(out, _(" --posix\n\ 145 disable all GNU extensions.\n")); 146 fprintf(out, _(" -r, --regexp-extended\n\ 147 use extended regular expressions in the script.\n")); 148 #ifdef REG_PERL 149 fprintf(out, PERL_HELP); 150 #endif 151 fprintf(out, _(" -s, --separate\n\ 152 consider files as separate rather than as a single continuous\n\ 153 long stream.\n")); 154 fprintf(out, _(" -u, --unbuffered\n\ 155 load minimal amounts of data from the input files and flush\n\ 156 the output buffers more often\n")); 157 fprintf(out, _(" --help display this help and exit\n")); 158 fprintf(out, _(" --version output version information and exit\n")); 159 fprintf(out, _("\n\ 160 If no -e, --expression, -f, or --file option is given, then the first\n\ 161 non-option argument is taken as the sed script to interpret. All\n\ 162 remaining arguments are names of input files; if no input files are\n\ 163 specified, then the standard input is read.\n\ 164 \n")); 165 contact (status); 166 167 ck_fclose (NULL); 168 exit (status); 169 } 170 171 int 172 main(argc, argv) 173 int argc; 174 char **argv; 175 { 176 #ifdef REG_PERL 177 #define SHORTOPTS "bsnrRuEe:f:l:i::V:" 178 #else 179 #define SHORTOPTS "bsnruEe:f:l:i::V:" 180 #endif 181 182 static struct option longopts[] = { 183 {"binary", 0, NULL, 'b'}, 184 {"regexp-extended", 0, NULL, 'r'}, 185 #ifdef REG_PERL 186 {"regexp-perl", 0, NULL, 'R'}, 187 #endif 188 {"expression", 1, NULL, 'e'}, 189 {"file", 1, NULL, 'f'}, 190 {"in-place", 2, NULL, 'i'}, 191 {"line-length", 1, NULL, 'l'}, 192 {"quiet", 0, NULL, 'n'}, 193 {"posix", 0, NULL, 'p'}, 194 {"silent", 0, NULL, 'n'}, 195 {"separate", 0, NULL, 's'}, 196 {"unbuffered", 0, NULL, 'u'}, 197 {"version", 0, NULL, 'v'}, 198 {"help", 0, NULL, 'h'}, 199 #ifdef ENABLE_FOLLOW_SYMLINKS 200 {"follow-symlinks", 0, NULL, 'F'}, 201 #endif 202 {NULL, 0, NULL, 0} 203 }; 204 205 int opt; 206 int return_code; 207 const char *cols = getenv("COLS"); 208 209 program_name = argv[0]; 210 initialize_main (&argc, &argv); 211 #if HAVE_SETLOCALE 212 /* Set locale according to user's wishes. */ 213 setlocale (LC_ALL, ""); 214 #endif 215 initialize_mbcs (); 216 217 #if ENABLE_NLS 218 219 /* Tell program which translations to use and where to find. */ 220 bindtextdomain (PACKAGE, LOCALEDIR); 221 textdomain (PACKAGE); 222 #endif 223 224 if (getenv("POSIXLY_CORRECT") != NULL) 225 posixicity = POSIXLY_CORRECT; 226 else 227 posixicity = POSIXLY_EXTENDED; 228 229 /* If environment variable `COLS' is set, use its value for 230 the baseline setting of `lcmd_out_line_len'. The "-1" 231 is to avoid gratuitous auto-line-wrap on ttys. 232 */ 233 if (cols) 234 { 235 countT t = ATOI(cols); 236 if (t > 1) 237 lcmd_out_line_len = t-1; 238 } 239 240 myname = *argv; 241 while ((opt = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != EOF) 242 { 243 switch (opt) 244 { 245 case 'n': 246 no_default_output = true; 247 break; 248 case 'e': 249 the_program = compile_string(the_program, optarg, strlen(optarg)); 250 break; 251 case 'f': 252 the_program = compile_file(the_program, optarg); 253 break; 254 255 case 'F': 256 follow_symlinks = true; 257 break; 258 259 case 'i': 260 separate_files = true; 261 if (optarg == NULL) 262 /* use no backups */ 263 in_place_extension = ck_strdup ("*"); 264 265 else if (strchr(optarg, '*') != NULL) 266 in_place_extension = ck_strdup(optarg); 267 268 else 269 { 270 in_place_extension = MALLOC (strlen(optarg) + 2, char); 271 in_place_extension[0] = '*'; 272 strcpy (in_place_extension + 1, optarg); 273 } 274 275 break; 276 277 case 'l': 278 lcmd_out_line_len = ATOI(optarg); 279 break; 280 281 case 'p': 282 posixicity = POSIXLY_BASIC; 283 break; 284 285 case 'b': 286 read_mode = "rb"; 287 break; 288 289 /* Undocumented, for compatibility with BSD sed. */ 290 case 'E': 291 case 'r': 292 if (extended_regexp_flags) 293 usage(4); 294 extended_regexp_flags = REG_EXTENDED; 295 break; 296 297 #ifdef REG_PERL 298 case 'R': 299 if (extended_regexp_flags) 300 usage(4); 301 extended_regexp_flags = REG_PERL; 302 break; 303 #endif 304 305 case 's': 306 separate_files = true; 307 break; 308 309 case 'u': 310 unbuffered_output = true; 311 break; 312 313 case 'v': 314 #ifdef REG_PERL 315 fprintf(stdout, _("super-sed version %s\n"), VERSION); 316 fprintf(stdout, _("based on GNU sed version %s\n\n"), SED_FEATURE_VERSION); 317 #else 318 fprintf(stdout, _("GNU sed version %s\n"), VERSION); 319 #endif 320 fprintf(stdout, _("Copyright (C) %d Free Software Foundation, Inc.\n\ 321 This is free software; see the source for copying conditions. There is NO\n\ 322 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n\ 323 to the extent permitted by law.\n\ 324 "), COPYRIGHT_YEAR); 325 fputc('\n', stdout); 326 contact(false); 327 328 ck_fclose (NULL); 329 exit (0); 330 case 'h': 331 usage(0); 332 default: 333 usage(4); 334 } 335 } 336 337 if (!the_program) 338 { 339 if (optind < argc) 340 { 341 char *arg = argv[optind++]; 342 the_program = compile_string(the_program, arg, strlen(arg)); 343 } 344 else 345 usage(4); 346 } 347 check_final_program(the_program); 348 349 return_code = process_files(the_program, argv+optind); 350 351 finish_program(the_program); 352 ck_fclose(NULL); 353 354 return return_code; 355 } 356