static void logfile_mod_stdio_rotate(Logfile * lf) { #ifdef S_ISREG struct stat sb; #endif int i; char from[MAXPATHLEN]; char to[MAXPATHLEN]; l_stdio_t *ll = (l_stdio_t *) lf->data; assert(lf->path); #ifdef S_ISREG if (stat(lf->path, &sb) == 0) if (S_ISREG(sb.st_mode) == 0) return; #endif debug(0, 1) ("logfileRotate (stdio): %s\n", lf->path); /* Rotate numbers 0 through N up one */ for (i = Config.Log.rotateNumber; i > 1;) { i--; snprintf(from, MAXPATHLEN, "%s.%d", lf->path, i - 1); snprintf(to, MAXPATHLEN, "%s.%d", lf->path, i); xrename(from, to); } /* Rotate the current log to .0 */ logfileFlush(lf); file_close(ll->fd); /* always close */ if (Config.Log.rotateNumber > 0) { snprintf(to, MAXPATHLEN, "%s.%d", lf->path, 0); xrename(lf->path, to); } /* Reopen the log. It may have been renamed "manually" */ ll->fd = file_open(lf->path, O_WRONLY | O_CREAT | O_TEXT); if (DISK_ERROR == ll->fd && lf->flags.fatal) { debug(50, 1) ("logfileRotate (stdio): %s: %s\n", lf->path, xstrerror()); fatalf("Cannot open %s: %s", lf->path, xstrerror()); } }
void exit_command (Widget w, XtPointer client_data, XtPointer call_data) { string font_name = client_data; close_font (font_name); if (true_gf_output_name != NULL) xrename (gf_output_name, true_gf_output_name); if (true_tfm_output_name != NULL) xrename (tfm_output_name, true_tfm_output_name); exit (0); }
void storeLogRotate(void) { char *fname = NULL; int i; LOCAL_ARRAY(char, from, MAXPATHLEN); LOCAL_ARRAY(char, to, MAXPATHLEN); #ifdef S_ISREG struct stat sb; #endif if (storelog_fd > -1) { file_close(storelog_fd); storelog_fd = -1; } if ((fname = Config.Log.store) == NULL) return; if (strcmp(fname, "none") == 0) return; #ifdef S_ISREG if (stat(fname, &sb) == 0) if (S_ISREG(sb.st_mode) == 0) return; #endif debug(20, 1) ("storeLogRotate: Rotating.\n"); /* Rotate numbers 0 through N up one */ for (i = Config.Log.rotateNumber; i > 1;) { i--; snprintf(from, MAXPATHLEN, "%s.%d", fname, i - 1); snprintf(to, MAXPATHLEN, "%s.%d", fname, i); xrename(from, to); } /* Rotate the current log to .0 */ if (Config.Log.rotateNumber > 0) { snprintf(to, MAXPATHLEN, "%s.%d", fname, 0); xrename(fname, to); } storelog_fd = file_open(fname, O_WRONLY | O_CREAT); if (storelog_fd < 0) { debug(50, 0) ("storeLogRotate: %s: %s\n", fname, xstrerror()); debug(20, 1) ("Store logging disabled\n"); } }
static int write_ar_archive(archive_handle_t *handle) { struct stat st; archive_handle_t *out_handle; char *temp_fn = NULL; xfstat(handle->src_fd, &st, handle->ar__name); /* if archive exists, create a new handle for output. * we create it in place of the old one. */ if (st.st_size != 0) { out_handle = init_handle(); #if !ENABLE_PLATFORM_MINGW32 xunlink(handle->ar__name); out_handle->src_fd = xopen(handle->ar__name, O_WRONLY | O_CREAT | O_TRUNC); #else /* can't unlink open file, create temporary output file */ temp_fn = xasprintf("%sXXXXXX", handle->ar__name); out_handle->src_fd = xmkstemp(temp_fn); #endif out_handle->accept = handle->accept; } else { out_handle = handle; } handle->ar__out = out_handle; xwrite(out_handle->src_fd, AR_MAGIC "\n", AR_MAGIC_LEN + 1); out_handle->offset += AR_MAGIC_LEN + 1; /* skip to the end of the archive if we have to append stuff */ if (st.st_size != 0) { handle->filter = filter_replaceable; handle->action_data = copy_data; unpack_ar_archive(handle); } while (write_ar_header(out_handle) == 0) continue; /* optional, since we exit right after we return */ if (ENABLE_FEATURE_CLEAN_UP || ENABLE_PLATFORM_MINGW32) { close(handle->src_fd); if (out_handle->src_fd != handle->src_fd) close(out_handle->src_fd); } #if ENABLE_PLATFORM_MINGW32 if ( temp_fn != NULL ) { xrename(temp_fn, handle->ar__name); free(temp_fn); } #endif return EXIT_SUCCESS; }
void useragentRotateLog(void) { #if USE_USERAGENT_LOG char *fname = NULL; int i; LOCAL_ARRAY(char, from, MAXPATHLEN); LOCAL_ARRAY(char, to, MAXPATHLEN); struct stat sb; if ((fname = Config.Log.useragent) == NULL) return; if (strcmp(fname, "none") == 0) return; #ifdef S_ISREG if (stat(fname, &sb) == 0) if (S_ISREG(sb.st_mode) == 0) return; #endif debug(40, 1) ("useragentRotateLog: Rotating.\n"); /* Rotate numbers 0 through N up one */ for (i = Config.Log.rotateNumber; i > 1;) { i--; snprintf(from, MAXPATHLEN, "%s.%d", fname, i - 1); snprintf(to, MAXPATHLEN, "%s.%d", fname, i); xrename(from, to); } if (cache_useragent_log) { file_close(fileno(cache_useragent_log)); fclose(cache_useragent_log); cache_useragent_log = NULL; } /* Rotate the current log to .0 */ if (Config.Log.rotateNumber > 0) { snprintf(to, MAXPATHLEN, "%s.%d", fname, 0); xrename(fname, to); } useragentOpenLog(); #endif }
/* if fn is NULL then input is stdin and output is stdout */ static void convert(char *fn, int conv_type) { FILE *in, *out; int ch; char *temp_fn = temp_fn; /* for compiler */ char *resolved_fn = resolved_fn; in = stdin; out = stdout; if (fn != NULL) { struct stat st; int fd; resolved_fn = xmalloc_follow_symlinks(fn); if (resolved_fn == NULL) bb_simple_perror_msg_and_die(fn); in = xfopen_for_read(resolved_fn); xfstat(fileno(in), &st, resolved_fn); temp_fn = xasprintf("%sXXXXXX", resolved_fn); fd = xmkstemp(temp_fn); if (fchmod(fd, st.st_mode) == -1) bb_simple_perror_msg_and_die(temp_fn); fchown(fd, st.st_uid, st.st_gid); out = xfdopen_for_write(fd); } while ((ch = fgetc(in)) != EOF) { if (ch == '\r') continue; if (ch == '\n') if (conv_type == CT_UNIX2DOS) fputc('\r', out); fputc(ch, out); } if (fn != NULL) { if (fclose(in) < 0 || fclose(out) < 0) { unlink(temp_fn); bb_perror_nomsg_and_die(); } xrename(temp_fn, resolved_fn); free(temp_fn); free(resolved_fn); } }
int add_remove_shell_main(int argc UNUSED_PARAM, char **argv) { FILE *orig_fp; char *orig_fn; char *new_fn; struct stat sb; sb.st_mode = 0666; argv++; orig_fn = xmalloc_follow_symlinks(SHELLS_FILE); if (!orig_fn) return EXIT_FAILURE; orig_fp = fopen_for_read(orig_fn); if (orig_fp) xfstat(fileno(orig_fp), &sb, orig_fn); new_fn = xasprintf("%s.tmp", orig_fn); /* * O_TRUNC or O_EXCL? At the first glance, O_EXCL looks better, * since it prevents races. But: (1) it requires a retry loop, * (2) if /etc/shells.tmp is *stale*, then retry loop * with O_EXCL will never succeed - it should have a timeout, * after which it should revert to O_TRUNC. * For now, I settle for O_TRUNC instead. */ xmove_fd(xopen3(new_fn, O_WRONLY | O_CREAT | O_TRUNC, sb.st_mode), STDOUT_FILENO); /* TODO? xfchown(STDOUT_FILENO, sb.st_uid, sb.st_gid); */ if (orig_fp) { /* Copy old file, possibly skipping removed shell names */ char *line; while ((line = xmalloc_fgetline(orig_fp)) != NULL) { char **cpp = argv; while (*cpp) { if (*cpp != dont_add && strcmp(*cpp, line) == 0) { /* Old file has this shell name */ if (REMOVE_SHELL) { /* we are remove-shell */ /* delete this name by not copying it */ goto next_line; } /* we are add-shell */ /* mark this name as "do not add" */ *cpp = dont_add; } cpp++; } /* copy shell name from old to new file */ puts(line); next_line: free(line); } if (ENABLE_FEATURE_CLEAN_UP) fclose(orig_fp); } if (ADD_SHELL) { char **cpp = argv; while (*cpp) { if (*cpp != dont_add) puts(*cpp); cpp++; } } /* Ensure we wrote out everything */ if (fclose(stdout) != 0) { xunlink(new_fn); bb_perror_msg_and_die("%s: write error", new_fn); } /* Small hole: if rename fails, /etc/shells.tmp is not removed */ xrename(new_fn, orig_fn); if (ENABLE_FEATURE_CLEAN_UP) { free(orig_fn); free(new_fn); } return EXIT_SUCCESS; }
int crontab_main(int argc UNUSED_PARAM, char **argv) { const struct passwd *pas; const char *crontab_dir = CRONTABS; char *tmp_fname; char *new_fname; char *user_name; /* -u USER */ int fd; int src_fd; int opt_ler; /* file [opts] Replace crontab from file * - [opts] Replace crontab from stdin * -u user User * -c dir Crontab directory * -l List crontab for user * -e Edit crontab for user * -r Delete crontab for user * bbox also supports -d == -r, but most other crontab * implementations do not. Deprecated. */ enum { OPT_u = (1 << 0), OPT_c = (1 << 1), OPT_l = (1 << 2), OPT_e = (1 << 3), OPT_r = (1 << 4), OPT_ler = OPT_l + OPT_e + OPT_r, }; opt_complementary = "?1:dr"; /* max one argument; -d implies -r */ opt_ler = getopt32(argv, "u:c:lerd", &user_name, &crontab_dir); argv += optind; if (sanitize_env_if_suid()) { /* Clears dangerous stuff, sets PATH */ /* run by non-root? */ if (opt_ler & (OPT_u|OPT_c)) bb_error_msg_and_die("only root can use -c or -u"); } if (opt_ler & OPT_u) { pas = getpwnam(user_name); if (!pas) bb_error_msg_and_die("user %s is not known", user_name); } else { /* XXX: xgetpwuid */ uid_t my_uid = getuid(); pas = getpwuid(my_uid); if (!pas) bb_perror_msg_and_die("unknown uid %d", (int)my_uid); } #define user_name DONT_USE_ME_BEYOND_THIS_POINT /* From now on, keep only -l, -e, -r bits */ opt_ler &= OPT_ler; if ((opt_ler - 1) & opt_ler) /* more than one bit set? */ bb_show_usage(); /* Read replacement file under user's UID/GID/group vector */ src_fd = STDIN_FILENO; if (!opt_ler) { /* Replace? */ if (!argv[0]) bb_show_usage(); if (NOT_LONE_DASH(argv[0])) { src_fd = open_as_user(pas, argv[0]); if (src_fd < 0) bb_error_msg_and_die("user %s cannot read %s", pas->pw_name, argv[0]); } } /* cd to our crontab directory */ xchdir(crontab_dir); tmp_fname = NULL; /* Handle requested operation */ switch (opt_ler) { default: /* case OPT_r: Delete */ unlink(pas->pw_name); break; case OPT_l: /* List */ { char *args[2] = { pas->pw_name, NULL }; return bb_cat(args); /* list exits, * the rest go play with cron update file */ } case OPT_e: /* Edit */ tmp_fname = xasprintf("%s.%u", crontab_dir, (unsigned)getpid()); /* No O_EXCL: we don't want to be stuck if earlier crontabs * were killed, leaving stale temp file behind */ src_fd = xopen3(tmp_fname, O_RDWR|O_CREAT|O_TRUNC, 0600); fchown(src_fd, pas->pw_uid, pas->pw_gid); fd = open(pas->pw_name, O_RDONLY); if (fd >= 0) { bb_copyfd_eof(fd, src_fd); close(fd); xlseek(src_fd, 0, SEEK_SET); } close_on_exec_on(src_fd); /* don't want editor to see this fd */ edit_file(pas, tmp_fname); /* fall through */ case 0: /* Replace (no -l, -e, or -r were given) */ new_fname = xasprintf("%s.new", pas->pw_name); fd = open(new_fname, O_WRONLY|O_CREAT|O_TRUNC|O_APPEND, 0600); if (fd >= 0) { bb_copyfd_eof(src_fd, fd); close(fd); xrename(new_fname, pas->pw_name); } else { bb_error_msg("cannot create %s/%s", crontab_dir, new_fname); } if (tmp_fname) unlink(tmp_fname); /*free(tmp_fname);*/ /*free(new_fname);*/ } /* switch */ /* Bump notification file. Handle window where crond picks file up * before we can write our entry out. */ while ((fd = open(CRONUPDATE, O_WRONLY|O_CREAT|O_APPEND, 0600)) >= 0) { struct stat st; fdprintf(fd, "%s\n", pas->pw_name); if (fstat(fd, &st) != 0 || st.st_nlink != 0) { /*close(fd);*/ break; } /* st.st_nlink == 0: * file was deleted, maybe crond missed our notification */ close(fd); /* loop */ } if (fd < 0) { bb_error_msg("cannot append to %s/%s", crontab_dir, CRONUPDATE); } return 0; }
static void compile_dex_with_dexopt(const char* dex_file_name, const char* odex_file_name) { SCOPED_RESLIST(rl); int dex_file = xopen(dex_file_name, O_RDONLY, 0); const char* odex_temp_filename = xaprintf( "%s.tmp.%s", odex_file_name, gen_hex_random(ENOUGH_ENTROPY)); cleanup_commit(cleanup_allocate(), cleanup_tmpfile, odex_temp_filename); int odex_temp_file = xopen(odex_temp_filename, O_RDWR | O_CREAT | O_EXCL, 0644); allow_inherit(dex_file); allow_inherit(odex_temp_file); struct child_start_info csi = { .io[0] = CHILD_IO_DEV_NULL, .io[1] = CHILD_IO_PIPE, .io[2] = CHILD_IO_DUP_TO_STDOUT, .exename = "dexopt", .argv = ARGV( "dexopt", "--zip", xaprintf("%d", dex_file), xaprintf("%d", odex_temp_file), dex_file_name, "v=ao=fm=y"), }; struct child* dexopt = child_start(&csi); struct growable_buffer output = slurp_fd_buf(dexopt->fd[1]->fd); int status = child_status_to_exit_code(child_wait(dexopt)); if (status != 0) die(EINVAL, "dexopt failed: %s", massage_output_buf(output)); xrename(odex_temp_filename, odex_file_name); } static void compile_dex(const char* dex_file_name, const char* odex_file_name) { if (api_level() < 21) compile_dex_with_dexopt(dex_file_name, odex_file_name); } int rdex_main(const struct cmd_rdex_info* info) { const char* dex_file_name = info->dexfile; struct stat dex_stat = xstat(dex_file_name); const char* odex_file_name = make_odex_name(dex_file_name); bool need_recompile = true; struct stat odex_stat; if (stat(odex_file_name, &odex_stat) == 0 && dex_stat.st_mtime <= odex_stat.st_mtime) { need_recompile = false; } (void) need_recompile; (void) odex_file_name; (void) compile_dex; if (need_recompile) compile_dex(dex_file_name, odex_file_name); if (setenv("CLASSPATH", dex_file_name, 1) == -1) die_errno("setenv"); if (info->classname[0] == '-') die(EINVAL, "class name cannot begin with '-'"); execvp("app_process", (char* const*) ARGV_CONCAT( ARGV("app_process", xdirname(dex_file_name), info->classname), info->args ?: empty_argv)); die_errno("execvp(\"app_process\", ..."); }
int sed_main(int argc UNUSED_PARAM, char **argv) { unsigned opt; llist_t *opt_e, *opt_f; char *opt_i; #if ENABLE_LONG_OPTS static const char sed_longopts[] ALIGN1 = /* name has_arg short */ "in-place\0" Optional_argument "i" "regexp-extended\0" No_argument "r" "quiet\0" No_argument "n" "silent\0" No_argument "n" "expression\0" Required_argument "e" "file\0" Required_argument "f"; #endif INIT_G(); /* destroy command strings on exit */ if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff); /* Lie to autoconf when it starts asking stupid questions. */ if (argv[1] && strcmp(argv[1], "--version") == 0) { puts("This is not GNU sed version 4.0"); return 0; } /* do normal option parsing */ opt_e = opt_f = NULL; opt_i = NULL; /* -i must be first, to match OPT_in_place definition */ /* -E is a synonym of -r: * GNU sed 4.2.1 mentions it in neither --help * nor manpage, but does recognize it. */ opt = getopt32long(argv, "^" "i::rEne:*f:*" "\0" "nn"/*count -n*/, sed_longopts, &opt_i, &opt_e, &opt_f, &G.be_quiet); /* counter for -n */ //argc -= optind; argv += optind; if (opt & OPT_in_place) { // -i die_func = cleanup_outname; } if (opt & (2|4)) G.regex_type |= REG_EXTENDED; // -r or -E //if (opt & 8) // G.be_quiet++; // -n (implemented with a counter instead) while (opt_e) { // -e add_cmd_block(llist_pop(&opt_e)); } while (opt_f) { // -f char *line; FILE *cmdfile; cmdfile = xfopen_stdin(llist_pop(&opt_f)); while ((line = xmalloc_fgetline(cmdfile)) != NULL) { add_cmd(line); free(line); } fclose_if_not_stdin(cmdfile); } /* if we didn't get a pattern from -e or -f, use argv[0] */ if (!(opt & 0x30)) { if (!*argv) bb_show_usage(); add_cmd_block(*argv++); } /* Flush any unfinished commands. */ add_cmd(""); /* By default, we write to stdout */ G.nonstdout = stdout; /* argv[0..(argc-1)] should be names of file to process. If no * files were specified or '-' was specified, take input from stdin. * Otherwise, we process all the files specified. */ G.input_file_list = argv; if (!argv[0]) { if (opt & OPT_in_place) bb_error_msg_and_die(bb_msg_requires_arg, "-i"); argv[0] = (char*)bb_msg_standard_input; /* G.last_input_file = 0; - already is */ } else { goto start; for (; *argv; argv++) { struct stat statbuf; int nonstdoutfd; sed_cmd_t *sed_cmd; G.last_input_file++; start: if (!(opt & OPT_in_place)) { if (LONE_DASH(*argv)) { *argv = (char*)bb_msg_standard_input; process_files(); } continue; } /* -i: process each FILE separately: */ if (stat(*argv, &statbuf) != 0) { bb_simple_perror_msg(*argv); G.exitcode = EXIT_FAILURE; G.current_input_file++; continue; } G.outname = xasprintf("%sXXXXXX", *argv); nonstdoutfd = xmkstemp(G.outname); G.nonstdout = xfdopen_for_write(nonstdoutfd); /* Set permissions/owner of output file */ /* chmod'ing AFTER chown would preserve suid/sgid bits, * but GNU sed 4.2.1 does not preserve them either */ fchmod(nonstdoutfd, statbuf.st_mode); fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid); process_files(); fclose(G.nonstdout); G.nonstdout = stdout; if (opt_i) { char *backupname = xasprintf("%s%s", *argv, opt_i); xrename(*argv, backupname); free(backupname); } /* else unlink(*argv); - rename below does this */ xrename(G.outname, *argv); //TODO: rollback backup on error? free(G.outname); G.outname = NULL; /* Fix disabled range matches and mangled ",+N" ranges */ for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) { sed_cmd->beg_line = sed_cmd->beg_line_orig; sed_cmd->end_line = sed_cmd->end_line_orig; } } /* Here, to handle "sed 'cmds' nonexistent_file" case we did: * if (G.current_input_file[G.current_input_file] == NULL) * return G.exitcode; * but it's not needed since process_files() works correctly * in this case too. */ } process_files(); return G.exitcode; }
int sysbef (char *befbuf) //************************************************************************* // //************************************************************************* { static char shutdown_reason[23]; char xbuf[20]; static char *beftab[] = { "CONNECT", "LOGIN", "CALL", "OSHELL", #ifdef __DOS16__ #ifdef _TNC "TNC", #endif "W2", "UWIN", "TWIN", #ifdef _AUTOTRCWIN "TRWIN", #endif #endif "RTEXT", "CAT", "RPRG", "WTEXT", "WPRG", "RBIN", "WBIN", "SLR", "CLOG", "REORG", "LIFETIME", "MKBOARD", "RMBOARD", "MVBOARD", "SHUTDOWN", "NEW", "KILL", "TEST", "IMPORT", "DISABLE", "ENABLE", #ifdef DIEBOX_UIMPORT "UIMPORT", #endif #ifdef OLDMAILIMPORT "OLDMAILIMPORT", #endif "SETUSER", "BEACON", "GREP", "TGREP", "TAIL", "BEGIN", "BATCH", "EXPORT", "PWGEN", "POSTFWD", "MONITOR", "NOTE", "MACRO", "CFGFLEX", "ORM", "OMV", "OCP", "OMD", "APPEND", #ifdef DF3VI_EXTRACT "EXTRACT", #endif "HOLD", "SETPW", #ifdef FEATURE_YAPP "WYAPP", "RYAPP", #endif #ifdef FEATURE_DIDADIT "WDIDADIT", "RDIDADIT", #endif #if defined FEATURE_SERIAL || defined _TELEPHONE "TTYINIT", #endif #ifdef _TELEPHONE // JJ "TTYCMD", "TTYDIAL", "TTYHANGUP", "TTYSTATUS", "TTYWIN", "TTYCOUNTERRESET", #endif #ifdef _AUTOFWD "AFWDLIST", #endif #ifdef FEATURE_MDPW "MD2SUM", "MD5SUM", #endif #ifdef FEATURE_EDITOR "EDIT", "FEDIT", "REDIT", #else #ifdef DF3VI_FWD_EDIT "FEDIT", "FWDEDIT", #endif #ifdef DF3VI_REJ_EDIT "REDIT", "REJECTEDIT", #endif #ifdef DF3VI_CONV_EDIT "CEDIT", "CONVEDIT", #endif #endif #ifdef _FILEFWD "FWDIMPORT", "FWDEXPORT", #endif "YMBTEST", "SCMDLIST", // Dies ist immer das letzte Kommando! NULL }; enum befnum { unsinn, connect_, login, call_, oshell_, #ifdef __DOS16__ #ifdef _TNC tnc, #endif w2, uwin, twin, #ifdef _AUTOTRCWIN trwin, #endif #endif rtext, rtext_, rprg, wtext, wprg, rbin, wbin, slr, clog, reorg, life_, mkb, rmb, mvb, shutdown_, new_, kill_, test, import, disable_, enable_, #ifdef DIEBOX_UIMPORT uimport_, #endif #ifdef OLDMAILIMPORT oldmailimport_, #endif setuser, beacon, grep_, tgrep, tail, begin, batch, export_, pwgen, postfwd_, monitor_, note, macro, cfgflex_, orm, omv, ocp, omd, _append, #ifdef DF3VI_EXTRACT extract_, #endif hold, setpw, #ifdef FEATURE_YAPP wyapp, ryapp, #endif #ifdef FEATURE_DIDADIT wdidadit, rdidadit, #endif #if defined FEATURE_SERIAL || defined _TELEPHONE ttyinit, #endif #ifdef _TELEPHONE // JJ ttycmd, ttydial, ttyhangup, ttystatus, ttywin_, ttycounterreset, #endif #ifdef _AUTOFWD afwdlist_, #endif #ifdef FEATURE_MDPW md2sum, md5sum, #endif #ifdef FEATURE_EDITOR edit, fedit, redit, #else #ifdef DF3VI_FWD_EDIT fedit, fwdedit, #endif #ifdef DF3VI_REJ_EDIT redit, rejectedit, #endif #ifdef DF3VI_CONV_EDIT cedit, convedit_, #endif #endif #ifdef _FILEFWD fwdimport, fwdexport, #endif ymbtest, scmdlist // Dies ist immer das letzte Kommando! } cmd = unsinn; befbuf += blkill(befbuf); cmd = (befnum) readcmd(beftab, &befbuf, 0); switch (cmd) { #ifdef FEATURE_YAPP case ryapp: #endif #ifdef FEATURE_DIDADIT case rdidadit: #endif #if defined(FEATURE_YAPP) || defined(FEATURE_DIDADIT) break; #endif default: if (u->lf != 6) putv(LF); leerzeile(); // Sends the number of CRs stored in "ALTER LF" } switch (cmd) { case unsinn: if ( mbinitbef(befbuf, 0) #ifdef _TELEPHONE // JJ || ttyinitbef(befbuf, 0) #endif ) { strcpy(xbuf, "^"); mbparsave(); #ifdef _TELEPHONE // JJ ttyparsave(); #endif strncpy(xbuf + 1, befbuf, 18); xbuf[19] = 0; subst1(xbuf, ' ', 0); subst1(xbuf, '=', 0); grep(MBINITNAME, xbuf, o_i); #ifdef _TELEPHONE // JJ grep(INITTTYNAME, xbuf, o_i); #endif return OK; } else return NO; case note: trace(replog, "note", "%s", befbuf); break; #ifdef DF3VI_EXTRACT case extract_: mbchange(befbuf, w_extract, 1); break; #endif case hold: mbchange(befbuf, w_hold, 1); break; case omv: { char f1[50], f2[50]; befbuf = nexttoken(befbuf, f1, 49); befbuf = nexttoken(befbuf, f2, 49); if (! *f1 || ! *f2 || xrename(f1, f2)) putf(ms(m_error)); else { putf(ms(m_moving)); putf(ms(m_nach), f1, f2); } break; } case ocp: { char f1[50], f2[50]; befbuf = nexttoken(befbuf, f1, 49); befbuf = nexttoken(befbuf, f2, 49); if (! *f1 || ! *f2 || filecopy(f1, f2)) putf(ms(m_error)); else { putf(ms(m_copying)); putf(ms(m_nach), f1, f2); } break; } case orm: { char f1[50]; befbuf = nexttoken(befbuf, f1, 49); if (! *f1 || xunlink(f1)) putf(ms(m_filecantdeleted), f1); else putf(ms(m_filedeleted), f1); break; } case omd: { char f1[50]; befbuf = nexttoken(befbuf, f1, 49); killbackslash(f1); if (! *f1 || xmkdir(f1)) putf(ms(m_directorycantcreated), f1); else putf(ms(m_directorycreated), f1); break; } case _append: { char textline[LINELEN+1]; befbuf = nexttoken(befbuf, textline, LINELEN); if (! *befbuf) { putf("Syntax: APPEND <textline> <filename>\n"); break; } FILE *f = s_fopen(befbuf, "sat"); if (f) { fprintf(f, "%s\n", textline); s_fclose(f); } else putf(ms(m_filenotfound), befbuf); } break; case macro: { mk_start(befbuf); } break; case setuser: { char call[CALLEN+1]; befbuf = nexttoken(befbuf, call, CALLEN+1); strupr(call); if (mbcallok(call) && *befbuf) { trace(report, "setuser", "%s", befbuf); { if (! mbalter(NULL, befbuf, call)) putf(ms(m_isunknown), call); b->msg_loadnum = 0; //reload msg loaduser(b->logincall, u, 1); } } else putf("Syntax: SETUSER <call> <option> <value>\n"); } break; case setpw: //automatisierte Passwort-Vergabe { char call[CALLEN+1]; char passwd[40]; int i, pwline = 0; FILE *upwf; befbuf = nexttoken(befbuf, call, CALLEN+1); strupr(call); pwline = atoi(befbuf); if (! mbcallok(call) || ! pwline) { putf("Syntax: SETPW <call> <number>\n"); break; } if (! loaduser(call, u, 0)) { putf(ms(m_isunknown), call); break; } upwf = s_fopen("userpw.bcm", "sr"); if (! upwf) { putf(ms(m_filenotfound), "userpw.bcm"); break; } for (i = 0; i < pwline && ! feof(upwf); i++) fgets(passwd, sizeof(passwd) - 1, upwf); s_fclose(upwf); if (i < pwline) { putf(ms(m_userpwlines), i - 1); break; } strcpy(u->password, passwd); saveuser(u); pwline = strlen(u->password); putf(ms(m_loginpw), pwtypestr(u->loginpwtype), pwtypestr(u->sfpwtype)); putf(" "); putf(ms(m_pwdlength), pwline); sprintf(passwd, "pw set to %i char", pwline); pwlog(call, b->logincall, passwd); b->msg_loadnum = 0; //reload msg loaduser(b->logincall, u, 1); } break; #ifdef DIEBOX_UIMPORT case uimport_: { putf(ms(m_dieboximport)); uimport(); } break; #endif #ifdef OLDMAILIMPORT case oldmailimport_: { scanoptions(befbuf); formoptions(); befbuf += blkill(befbuf); if (isdir(befbuf)) { putf(ms(m_omi_started), befbuf); putflush(); oldmailimport(befbuf); } else putf(ms(m_dirunknown), befbuf); } break; #endif case disable_: { putf(ms(m_boxdisabled)); m.disable = 1; mbparsave(); } break; case enable_: { putf(ms(m_boxenabled)); m.disable = 0; mbparsave(); } break; case test: { if (*befbuf == 'W') { while (1); } // for testing watchdog else if (*befbuf == 'S') { trace(fatal, "test", "abort"); } else if (*befbuf == 'V') { *(char *)0 = 1; } else mk_start(befbuf); } break; case batch: { runbatch(befbuf); } break; case rtext: case rtext_: { fileio_text fio; fio.usefile(befbuf); fio.tx(); putf("\032\n"); // CTRL-Z } break; case wtext: { fileio_text fio; fio.usefile(befbuf); fio.rx(); } break; case rbin: case rprg: { fileio_abin fio; fio.usefile(befbuf); fio.tx(); } break; case wbin: case wprg: { fileio_abin fio; fio.usefile(befbuf); fio.rx(); } break; #ifdef FEATURE_YAPP case ryapp: { fileio_yapp fio; fio.usefile(befbuf); fio.tx(); } break; case wyapp: { fileio_yapp fio; fio.usefile(befbuf); fio.rx(); } break; #endif // FEATURE_YAPP #ifdef FEATURE_DIDADIT case rdidadit: { fileio_dida fio; fio.usefile(befbuf); fio.tx(); } break; case wdidadit: { fileio_dida fio; if (! *befbuf) fio.usefile("dummy"); else { if (befbuf[strlen(befbuf) - 1] != '/') strcat(befbuf, "/"); strcat(befbuf, "dummy"); fio.usefile(befbuf); } fio.rx(); } break; #endif // FEATURE_DIDADIT case slr: { scanoptions(befbuf); putlog(TRACEPATH "/" SYSLOGRNAME, befbuf); } break; case clog: { scanoptions(befbuf); putlog(TRACEPATH "/" CMDLOGNAME, befbuf); } break; case tail: { scanoptions(befbuf); befbuf += blkill(befbuf); if (b->optplus&o_f && *befbuf) { int a; FILE *f = s_fopen(befbuf, "lrt"); if (f) { fseek(f, 0, SEEK_END); do { while ((a = fgetc(f)) != EOF) putv(a); wdelay(349); } while (! testabbruch()); s_fclose(f); } } else { fileio_text fio; fio.usefile(befbuf); fio.settail(-2000); fio.tx(); } } break; case begin: { fileio_text fio; fio.usefile(befbuf); fio.settail(2000); fio.tx(); } break; case monitor_: { if (*befbuf) { scanoptions(befbuf); b->continous = 1; monitor(atoi(befbuf), b->optplus); } else putf("Syntax: MONITOR [-iords] <task-id>\n"); } break; case tgrep: { char string[61]; char name[40]; scanoptions(befbuf); if (b->optminus & o_i) b->optplus |= o_i; //wenn nicht explizit "-i-", ist "-i" default b->usermail = 0; if (! *befbuf) { putf("Syntax: TGREP [pattern] <fwd-bbs>\n"); break; } befbuf = nexttoken(befbuf, string, 60); if (*befbuf) { sprintf(name, TRACEPATH "/t_%s.bcm", befbuf); grep(name, string, b->optplus); } else { sprintf(name, TRACEPATH "/t_%s.bcm", string); putlog(name, ""); } } break; case grep_: { char string[61]; scanoptions(befbuf); if (b->optminus & o_i) b->optplus |= o_i; //wenn nicht explizit "-i-", ist "-i" default b->usermail = 0; befbuf = nexttoken(befbuf, string, 60); grep(befbuf, string, b->optplus); } break; #ifdef _AUTOFWD case afwdlist_: { afwdlist(befbuf); } break; #endif case life_: { if (*befbuf) { strupr(befbuf); char *life = skip(befbuf); int board = finddir(befbuf, b->sysop); if (board > 0) { board -= 1; if (life && *life) { tree[board].lifetime_max = atoi(life); tree[board].lifetime_min = 1; if (tree[board].lifetime_max > 999) tree[board].lifetime_max = 999; if (tree[board].lifetime_max < 1) tree[board].lifetime_max = 1; char *life_min = skip(life); if (life_min && *life_min) { tree[board].lifetime_min = atoi(life_min); if (tree[board].lifetime_min > 999) tree[board].lifetime_min = 999; if (tree[board].lifetime_min < 1) tree[board].lifetime_min = 1; } mbtreesave(); } putf(ms(m_lifetimestat), b->boardfullname, tree[board].lifetime_max, tree[board].lifetime_min); } else putf(ms(m_notfound), befbuf); } else putf("Syntax: LIFETIME <board> <days_maximum> [<days_minimum>]\n" " (with 1 <= days_maximum/days_minimum <= 999)\n\n"); } break; #ifdef _TNC case tnc: { control_tnc(befbuf); } break; #endif case connect_: { termqso(befbuf); } break; case login: { if (mbcallok(befbuf)) { mblogin(befbuf, login_standard, b->uplink); cmdlog("login changed"); putf(ms(m_loginchanged)); } else putf("Syntax: LOGIN <new logincall>\n"); } break; case call_: { if (mbcallok(befbuf)) { mblogin(befbuf, login_silent, b->uplink); b->msg_loadnum--; //Sonst wird falsche Sprache benutzt cmdlog("call changed"); } else putf("Syntax: CALL <new logincall>\n"); } break; case oshell_: { if (t->input == io_file || t->output == io_file) oshell(befbuf, sh_noinput); else oshell(befbuf, m.dosinput ? sh_forceinput : sh_ifmultitask); } break; case reorg: { if (sema_test("purgereorg") == 1) putf(ms(m_purgeallstarted)); else { putf(ms(m_reorginvoked)); fork(P_BACK | P_MAIL, 0, mbreorg, befbuf); } } break; case postfwd_: { putf(ms(m_postfwdinvoked)); fork(P_BACK | P_MAIL, 0, postfwd, "Postfwd"); } break; #ifdef FEATURE_EDITOR case edit: { fork(P_WIND | P_KEYB, 0, editfile, befbuf); } break; case fedit: { fork(P_WIND | P_KEYB, 0, editfile, FWDLISTNAME); } break; case redit: { fork(P_WIND | P_KEYB, 0, editfile, REJECTNAME); } break; #else #ifdef DF3VI_FWD_EDIT case fedit: //wenn kein editor vorhanden remote-editor aufrufen case fwdedit: { fwdlistedit(befbuf); } break; #endif #ifdef DF3VI_REJ_EDIT case redit: case rejectedit: { rejectlistedit(befbuf); } break; #endif #ifdef DF3VI_CONV_EDIT case cedit: case convedit_: { convedit(befbuf); } break; #endif #endif case new_: { scanoptions(befbuf); mbinit(); initfwdlist(); #ifdef _AUTOFWD initafwdlist(); #endif if (! (b->optplus & o_q)) // skip statistics on "new -q" { b->optplus = o_s | o_f | o_c; putf(ms(m_hadrstat)); browse_hadr(""); } mbcvtload(); #ifdef RUNUTILS read_runfile(); #endif msg_dealloc(1); mk_read_jobs(); } break; case kill_: { if (atoi(befbuf)) { while (atoi(befbuf)) { if (! killtask(nextdez(&befbuf), 1)) putf(ms(m_cantkilltask)); } } else putf("Syntax: KILL <task-id>\n"); } break; #ifdef __DOS16__ case w2: { fork(P_WIND | P_KEYB|P_MAIL, 0, mbwin2, m.sysopcall); } break; case uwin: { fork(P_WIND | P_KEYB|P_MAIL, 0, userwin, "Users"); } break; case twin: { fork(P_WIND | P_MAIL, 0, taskwin, befbuf); } break; #ifdef _AUTOTRCWIN case trwin: { if (*befbuf) fork(P_WIND | P_MAIL, 0, trcwin, befbuf); else putf("Syntax: TRWIN [-iords] <task-id>\n"); } break; #endif #endif //__DOS16__ case mkb: { char mainboard[30]; char newboard[20]; char *slash; befbuf = nexttoken(befbuf, mainboard, 29); befbuf = nexttoken(befbuf, newboard, 19); slash = strchr(mainboard + 1, '/'); if (slash && (! *newboard)) { *slash = 0; strcpy(newboard, slash + 1); } if (! *newboard && *mainboard == '/') { strcpy(newboard, mainboard + 1); mainboard[1] = 0; } if (*mainboard && *newboard) { switch (mkboard(mainboard, newboard, 0)) { case 0: putf(ms(m_boardcreated)); break; case 1: putf(ms(m_mainboardnotfound)); break; case 2: putf(ms(m_toomanyboards)); break; case 3: putf(ms(m_boardnameexist)); break; case 4: putf(ms(m_invalidboardname)); break; } } else putf("Syntax: MKBOARD <mainboard> <subboard>\n"); } break; case rmb: { if (*befbuf) { subst1(befbuf, ' ', '/'); if (*befbuf == '/' && befbuf[1] == '/') befbuf++; switch (rmboard(befbuf)) { case 0: putf(ms(m_boardremoved)); break; case 1: putf(ms(m_boardnotfound)); break; case 2: putf(ms(m_boardnotempty)); break; } } else putf("Syntax: RMBOARD <mainboard> <subboard>\n"); } break; case mvb: { char oldboard[20]; char subboard[20]; char neuboard[20]; befbuf = nexttoken(befbuf, oldboard, 19); befbuf = nexttoken(befbuf, subboard, 19); befbuf = nexttoken(befbuf, neuboard, 19); if (*oldboard && *subboard && *neuboard) { switch (mvboard(oldboard, subboard, neuboard)) { case 0: putf(ms(m_boardmoved)); break; case 1: putf(ms(m_newboardnotfound)); break; case 2: putf(ms(m_toomanyboards)); break; case 4: putf(ms(m_oldboardnotfound)); break; } } else putf("Syntax: MVBOARD <oldboard> <subboard> <newboard>\n"); } break; case shutdown_: { scanoptions(befbuf); #ifdef __DOS16__ if (b->optplus & o_r) atexit((void(*)()) MK_FP(0xffff, 0x0000)); #endif runterfahren = 1; sprintf(shutdown_reason, "shutdown by %s", b->logincall); stopreason = shutdown_reason; } break; case cfgflex_: { if (*befbuf && file_isreg("cfgflex.bcm")) { putf(ms(m_flexstarted)); fork(P_BACK | P_MAIL, 0, cfgflex, befbuf); } else putf("Syntax: CFGFLEX <flexcall> (cfgflex.bcm must exist)\n"); } break; case import: { sysimport(befbuf); } break; case export_: { if (*befbuf) { if ((t->input != io_file || t->output == io_dummy) && t->output != io_file) { char fname[51]; scanoptions(befbuf); befbuf = nexttoken(befbuf, fname, 50); if (b->optplus & o_a) // neue Option -b fuer binaer { if (b->optplus & o_b) b->outputfile = s_fopen(fname, "sab"); else b->outputfile = s_fopen(fname, "sat"); } else { if (b->optplus & o_b) b->outputfile = s_fopen(fname, "swb"); else b->outputfile = s_fopen(fname, "swt"); } if (b->outputfile) { s_fsetopt(b->outputfile, 1); b->oldinput = t->input; b->oldoutput = t->output; t->input = io_dummy; t->output = io_file; b->continous = 1; if (b->optplus & o_u) b->sysop = 0; if (*befbuf) mailbef(befbuf, 0); b->sysop = 1; } else putf(ms(m_filenotopen), fname); } } else putf("Syntax: EXPORT <filename> <box-command>\n"); } break; case beacon: { if (*befbuf) { FILE *f = s_fopen(BEACONNAME, "srt"); unsigned int i = 0; char s[LINELEN+1]; if (f) { while (fgets(s, LINELEN, f)) { if (*s) { s[strlen(s) - 1] = 0; putbeacon_tnc(s, befbuf); i++; } } s_fclose(f); } putf(ms(m_beaconframes), i); } else { fork(P_BACK | P_MAIL, 0, sendmailbake, "Beacon"); putf(ms(m_beaconstarted)); } } break; case pwgen: { FILE *f; if (*befbuf && (f = s_fopen(befbuf, "swt")) != 0) { unsigned int i; int upw; upw = ! stricmp(befbuf, "userpw.bcm"); // file fuer setpw for (i = 0; i < 1620; i++) { char c = 0; while (! isalnum(c)) c = random_max('z'); fputc(c, f); //pw-file fuer setpw erzeugen (81 Zeilen mit je 20 Zeichen) if (upw && (i % 20) == 19) fputc(LF, f); } trace(report, "pwgen", "%s created", befbuf); s_fclose(f); } else //ohne Parameter immer userpw.bcm erzeugen if (! *befbuf && (f = s_fopen("userpw.bcm", "swt")) != 0) { unsigned int i; for (i = 0; i < 1620; i++) { char c = 0; while (! isalnum(c)) c = random_max('z'); fputc(c, f); //pw-file fuer setpw erzeugen (81 Zeilen mit je 20 Zeichen) if ((i % 20) == 19) fputc(LF, f); } trace(report, "pwgen", "userpw.bcm created"); s_fclose(f); } } break; case scmdlist: // DH3MB { unsigned int i = 0; while (beftab[i]) putf("(%02d) %s\n", ++i, beftab[i]); } break; #ifdef FEATURE_MDPW case md2sum: { if (! *befbuf) { putf("Syntax: MD2SUM <filename>\n"); break; } if (! file_isreg(befbuf)) putf(ms(m_filenotfound), befbuf); else { MD2 md2; md2.readfile(befbuf, 0L); md2.gethexdigest(b->line); putf("%s %s\n", b->line, befbuf); } } break; case md5sum: { if (! *befbuf) { putf("Syntax: MD5SUM <filename>\n"); break; } if (! file_isreg(befbuf)) putf(ms(m_filenotfound), befbuf); else { MD5 md5; md5.readfile(befbuf, 0L); md5.gethexdigest(b->line); putf("%s %s\n", b->line, befbuf); } } break; #endif #if defined FEATURE_SERIAL || defined _TELEPHONE case ttyinit: { if (eingelogt("getty", 0, 0)) putf(ms(m_ttyactive)); else init_tty(); } break; #endif #ifdef _TELEPHONE // JJ case ttycmd: { if (*befbuf) { if (m.ttydevice > 1) putf_tty("%s\r", befbuf); else putf(ms(m_nomodem)); } else putf("Syntax: TTYCMD <command>\n"); } break; case ttydial: { strupr(befbuf); char *nummer; char call[8]; nummer = nexttoken(befbuf, call, 8); if (*befbuf && mbcallok(call)) { if (m.ttydevice && (get_ufwd(call)[0] || isforwardpartner(call) >= 0)) { putf(ms(m_startphonefwd), call, nummer); sprintf(befbuf, "%s TTY %s", call, nummer); fork(P_BACK | P_MAIL, 0, fwdsend, befbuf); } else putf(ms(m_nottyactive)); } else putf("Syntax: TTYDIAL <call> <number>\n"); } break; case ttyhangup: { tty_hangup(); putf(ms(m_hangupmodem)); } break; case ttystatus: { tty_statustext(); putv(LF); } break; case ttywin_: { fork(P_WIND | P_MAIL, 0, tty_win, befbuf); } break; case ttycounterreset: { tty_counterreset(); putv(LF); } break; #endif #ifdef _FILEFWD case fwdimport: { if (*befbuf) fwd_import(befbuf); } break; case fwdexport: { if (*befbuf) fwd_export(befbuf); } break; #endif case ymbtest: { #ifdef _USERCOMP if (u->comp == 1) { /* char output[256] = { 0 }; char output2[256] = { 0 }; int i, il = 0; */ putf("//COMP 1\n\n"); putflush(); /* il = comp_sp_stat_huff(befbuf, strlen(befbuf), output); // printf("il: %d strlen: %d\n",il,strlen(befbuf)); // printf("befbuf:\n-%s-\nOut:\n-%s-\n",befbuf,output); //putflush(); for (i = 1; i < il ; i++) bputv(output[i]); putv(LF); putflush(); output[0] = '\0'; strcpy(befbuf, "dies ist noch ein laengerer text 2"); il = comp_sp_stat_huff(befbuf, strlen(befbuf), output); for (i = 1; i < il ; i++) bputv(output[i]); putv(LF); putflush(); output[0] = '\0'; strcpy(befbuf, "dies ist ein noch laengerer text 3"); il = comp_sp_stat_huff(befbuf, strlen(befbuf), output); for (i = 1; i < il ; i++) bputv(output[i]); putv(LF); putflush(); putf("\n"); il = decomp_sp_stat_huff(output, strlen(output), output2); printf("il: %d strlen: %d\n",il,strlen(output)); printf("Out2:\n-%s-\n",output2); */ /* #include "ahuf.h" // TOP-Huffman class AHUF; AHUF *ahuf; ahuf = new AHUF(); il = ahuf->Komprimieren(true, befbuf, output, strlen(befbuf) ); printf("il: %d strlen: %d\n",il,strlen(befbuf)); printf("befbuf:\n-%s-\nOut:\n-%s-\n",befbuf,output); putflush(); putf("%s",output); putflush(); putf("\n"); */ } #endif } break; } return OK;
static void do_xfer_recv(const struct xfer_opts xfer_opts, const char* filename, const char* desired_basename, int from_peer) { struct xfer_msg statm = recv_xfer_msg(from_peer); if (statm.type != XFER_MSG_STAT) die(ECOMM, "expected stat msg"); struct cleanup* error_cl = cleanup_allocate(); struct stat st; const char* parent_directory = NULL; const char* rename_to = NULL; const char* write_mode = NULL; int dest_fd; if (stat(filename, &st) == 0) { if (S_ISDIR(st.st_mode)) { if (desired_basename == NULL) die(EISDIR, "\"%s\" is a directory", filename); parent_directory = filename; filename = xaprintf("%s/%s", parent_directory, desired_basename); } else if (S_ISREG(st.st_mode)) { if (st.st_nlink > 1) write_mode = "inplace"; } else { write_mode = "inplace"; } } if (parent_directory == NULL) parent_directory = xdirname(filename); if (write_mode == NULL) write_mode = xfer_opts.write_mode; bool atomic; bool automatic_mode = false; if (write_mode == NULL) { automatic_mode = true; atomic = true; } else if (strcmp(write_mode, "atomic") == 0) { atomic = true; } else if (strcmp(write_mode, "inplace") == 0) { atomic = false; } else { die(EINVAL, "unknown write mode \"%s\"", write_mode); } bool regular_file = true; bool preallocated = false; bool chmod_explicit = false; mode_t chmod_explicit_modes = 0; if (xfer_opts.preserve) { chmod_explicit = true; chmod_explicit_modes = statm.u.stat.ugo_bits; } if (xfer_opts.mode) { char* endptr = NULL; errno = 0; unsigned long omode = strtoul(xfer_opts.mode, &endptr, 8); if (errno != 0 || *endptr != '\0' || (omode &~ 0777) != 0) die(EINVAL, "invalid mode bits: %s", xfer_opts.mode); chmod_explicit = true; chmod_explicit_modes = (mode_t) omode; } mode_t creat_mode = (chmod_explicit_modes ? 0200 : 0666); if (atomic) { rename_to = filename; filename = xaprintf("%s.fb-adb-%s", filename, gen_hex_random(ENOUGH_ENTROPY)); dest_fd = try_xopen( filename, O_CREAT | O_WRONLY | O_EXCL, creat_mode); if (dest_fd == -1) { if (errno == EACCES && automatic_mode) { atomic = false; filename = rename_to; rename_to = NULL; } else { die_errno("open(\"%s\")", filename); } } } if (!atomic) { dest_fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, creat_mode); if (!S_ISREG(xfstat(dest_fd).st_mode)) regular_file = false; } if (regular_file) cleanup_commit(error_cl, unlink_cleanup, filename); if (regular_file && statm.u.stat.size > 0) preallocated = fallocate_if_supported( dest_fd, statm.u.stat.size); uint64_t total_written = copy_loop_posix_recv(from_peer, dest_fd); if (preallocated && total_written < statm.u.stat.size) xftruncate(dest_fd, total_written); if (xfer_opts.preserve) { struct timeval times[2] = { { statm.u.stat.atime, statm.u.stat.atime_ns / 1000 }, { statm.u.stat.mtime, statm.u.stat.mtime_ns / 1000 }, }; #ifdef HAVE_FUTIMES if (futimes(dest_fd, times) == -1) die_errno("futimes"); #else if (utimes(filename, times) == -1) die_errno("times"); #endif } if (chmod_explicit) if (fchmod(dest_fd, chmod_explicit_modes) == -1) die_errno("fchmod"); if (xfer_opts.sync) xfsync(dest_fd); if (rename_to) xrename(filename, rename_to); if (xfer_opts.sync) xfsync(xopen(parent_directory, O_DIRECTORY|O_RDONLY, 0)); cleanup_forget(error_cl); }
int sed_main(int argc UNUSED_PARAM, char **argv) { unsigned opt; llist_t *opt_e, *opt_f; char *opt_i; #if ENABLE_LONG_OPTS static const char sed_longopts[] ALIGN1 = /* name has_arg short */ "in-place\0" Optional_argument "i" "regexp-extended\0" No_argument "r" "quiet\0" No_argument "n" "silent\0" No_argument "n" "expression\0" Required_argument "e" "file\0" Required_argument "f"; #endif int status = EXIT_SUCCESS; INIT_G(); /* destroy command strings on exit */ if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff); /* Lie to autoconf when it starts asking stupid questions. */ if (argv[1] && strcmp(argv[1], "--version") == 0) { puts("This is not GNU sed version 4.0"); return 0; } /* do normal option parsing */ opt_e = opt_f = NULL; opt_i = NULL; opt_complementary = "e::f::" /* can occur multiple times */ "nn"; /* count -n */ IF_LONG_OPTS(applet_long_options = sed_longopts); /* -i must be first, to match OPT_in_place definition */ opt = getopt32(argv, "i::rne:f:", &opt_i, &opt_e, &opt_f, &G.be_quiet); /* counter for -n */ //argc -= optind; argv += optind; if (opt & OPT_in_place) { // -i atexit(cleanup_outname); } if (opt & 0x2) G.regex_type |= REG_EXTENDED; // -r //if (opt & 0x4) G.be_quiet++; // -n while (opt_e) { // -e add_cmd_block(llist_pop(&opt_e)); } while (opt_f) { // -f char *line; FILE *cmdfile; cmdfile = xfopen_for_read(llist_pop(&opt_f)); while ((line = xmalloc_fgetline(cmdfile)) != NULL) { add_cmd(line); free(line); } fclose(cmdfile); } /* if we didn't get a pattern from -e or -f, use argv[0] */ if (!(opt & 0x18)) { if (!*argv) bb_show_usage(); add_cmd_block(*argv++); } /* Flush any unfinished commands. */ add_cmd(""); /* By default, we write to stdout */ G.nonstdout = stdout; /* argv[0..(argc-1)] should be names of file to process. If no * files were specified or '-' was specified, take input from stdin. * Otherwise, we process all the files specified. */ if (argv[0] == NULL) { if (opt & OPT_in_place) bb_error_msg_and_die(bb_msg_requires_arg, "-i"); add_input_file(stdin); } else { int i; for (i = 0; argv[i]; i++) { struct stat statbuf; int nonstdoutfd; FILE *file; sed_cmd_t *sed_cmd; if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) { add_input_file(stdin); process_files(); continue; } file = fopen_or_warn(argv[i], "r"); if (!file) { status = EXIT_FAILURE; continue; } add_input_file(file); if (!(opt & OPT_in_place)) { continue; } /* -i: process each FILE separately: */ G.outname = xasprintf("%sXXXXXX", argv[i]); nonstdoutfd = xmkstemp(G.outname); G.nonstdout = xfdopen_for_write(nonstdoutfd); /* Set permissions/owner of output file */ fstat(fileno(file), &statbuf); /* chmod'ing AFTER chown would preserve suid/sgid bits, * but GNU sed 4.2.1 does not preserve them either */ fchmod(nonstdoutfd, statbuf.st_mode); fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid); process_files(); fclose(G.nonstdout); G.nonstdout = stdout; if (opt_i) { char *backupname = xasprintf("%s%s", argv[i], opt_i); xrename(argv[i], backupname); free(backupname); } /* else unlink(argv[i]); - rename below does this */ xrename(G.outname, argv[i]); //TODO: rollback backup on error? free(G.outname); G.outname = NULL; /* Re-enable disabled range matches */ for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) { sed_cmd->beg_line = sed_cmd->beg_line_orig; } } /* Here, to handle "sed 'cmds' nonexistent_file" case we did: * if (G.current_input_file >= G.input_file_count) * return status; * but it's not needed since process_files() works correctly * in this case too. */ } process_files(); return status; }
void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) { file_header_t *file_header = archive_handle->file_header; int dst_fd; int res; #if ENABLE_FEATURE_TAR_SELINUX char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE]; #ifdef __BIONIC__ matchpathcon_init(NULL); #endif if (!sctx) sctx = archive_handle->tar__sctx[PAX_GLOBAL]; if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ setfscreatecon(sctx); free(archive_handle->tar__sctx[PAX_NEXT_FILE]); archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL; } #endif if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) { char *slash = strrchr(file_header->name, '/'); if (slash) { *slash = '\0'; bb_make_directory(file_header->name, -1, FILEUTILS_RECUR); *slash = '/'; } } if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) { /* Remove the entry if it exists */ if (!S_ISDIR(file_header->mode)) { /* Is it hardlink? * We encode hard links as regular files of size 0 with a symlink */ if (S_ISREG(file_header->mode) && file_header->link_target && file_header->size == 0 ) { /* Ugly special case: * tar cf t.tar hardlink1 hardlink2 hardlink1 * results in this tarball structure: * hardlink1 * hardlink2 -> hardlink1 * hardlink1 -> hardlink1 <== !!! */ if (strcmp(file_header->link_target, file_header->name) == 0) goto ret; } /* Proceed with deleting */ if (unlink(file_header->name) == -1 && errno != ENOENT ) { bb_perror_msg_and_die("can't remove old file %s", file_header->name); } } } else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) { /* Remove the existing entry if its older than the extracted entry */ struct stat existing_sb; if (lstat(file_header->name, &existing_sb) == -1) { if (errno != ENOENT) { bb_perror_msg_and_die("can't stat old file"); } } else if ((time_t) existing_sb.st_mtime >= (time_t) file_header->mtime) { if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) && !S_ISDIR(file_header->mode) ) { bb_error_msg("%s not created: newer or " "same age file exists", file_header->name); } data_skip(archive_handle); goto ret; } else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) { bb_perror_msg_and_die("can't remove old file %s", file_header->name); } } /* Handle hard links separately * We encode hard links as regular files of size 0 with a symlink */ if (S_ISREG(file_header->mode) && file_header->link_target && file_header->size == 0 ) { /* hard link */ res = link(file_header->link_target, file_header->name); if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { bb_perror_msg("can't create %slink " "from %s to %s", "hard", file_header->name, file_header->link_target); } /* Hardlinks have no separate mode/ownership, skip chown/chmod */ goto ret; } /* Create the filesystem entry */ switch (file_header->mode & S_IFMT) { case S_IFREG: { /* Regular file */ char *dst_name; int flags = O_WRONLY | O_CREAT | O_EXCL; if (archive_handle->ah_flags & ARCHIVE_O_TRUNC) flags = O_WRONLY | O_CREAT | O_TRUNC; dst_name = file_header->name; #ifdef ARCHIVE_REPLACE_VIA_RENAME if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) /* rpm-style temp file name */ dst_name = xasprintf("%s;%x", dst_name, (int)getpid()); #endif dst_fd = xopen3(dst_name, flags, file_header->mode ); bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size); close(dst_fd); #ifdef ARCHIVE_REPLACE_VIA_RENAME if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) { xrename(dst_name, file_header->name); free(dst_name); } #endif break; } case S_IFDIR: res = mkdir(file_header->name, file_header->mode); if ((res == -1) && (errno != EISDIR) /* btw, Linux doesn't return this */ && (errno != EEXIST) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) ) { bb_perror_msg("can't make dir %s", file_header->name); } break; case S_IFLNK: /* Symlink */ //TODO: what if file_header->link_target == NULL (say, corrupted tarball?) res = symlink(file_header->link_target, file_header->name); if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) ) { bb_perror_msg("can't create %slink " "from %s to %s", "sym", file_header->name, file_header->link_target); } break; case S_IFSOCK: case S_IFBLK: case S_IFCHR: case S_IFIFO: res = mknod(file_header->name, file_header->mode, file_header->device); if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) ) { bb_perror_msg("can't create node %s", file_header->name); } break; default: bb_error_msg_and_die("unrecognized file type"); } if (!S_ISLNK(file_header->mode)) { if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) { uid_t uid = file_header->uid; gid_t gid = file_header->gid; #if ENABLE_FEATURE_TAR_UNAME_GNAME if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) { if (file_header->tar__uname) { //TODO: cache last name/id pair? struct passwd *pwd = getpwnam(file_header->tar__uname); if (pwd) uid = pwd->pw_uid; } if (file_header->tar__gname) { struct group *grp = getgrnam(file_header->tar__gname); if (grp) gid = grp->gr_gid; } } #endif /* GNU tar 1.15.1 uses chown, not lchown */ chown(file_header->name, uid, gid); } /* uclibc has no lchmod, glibc is even stranger - * it has lchmod which seems to do nothing! * so we use chmod... */ if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) { chmod(file_header->name, file_header->mode); } if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) { struct timeval t[2]; t[1].tv_sec = t[0].tv_sec = file_header->mtime; t[1].tv_usec = t[0].tv_usec = 0; utimes(file_header->name, t); } } ret: ; #if ENABLE_FEATURE_TAR_SELINUX if (sctx) { /* reset the context after creating an entry */ setfscreatecon(NULL); } #endif }
int patch_main(int argc UNUSED_PARAM, char **argv) { struct stat saved_stat; char *patch_line; FILE *patch_file; int patch_level; int ret = 0; char plus = '+'; unsigned opt; enum { OPT_R = (1 << 2), OPT_N = (1 << 3), /*OPT_f = (1 << 4), ignored */ /*OPT_E = (1 << 5), ignored, this is the default */ /*OPT_g = (1 << 6), ignored */ OPT_dry_run = (1 << 7) * ENABLE_LONG_OPTS, }; xfunc_error_retval = 2; { const char *p = "-1"; const char *i = "-"; /* compat */ #if ENABLE_LONG_OPTS static const char patch_longopts[] ALIGN1 = "strip\0" Required_argument "p" "input\0" Required_argument "i" "reverse\0" No_argument "R" "forward\0" No_argument "N" /* "Assume user knows what [s]he is doing, do not ask any questions": */ "force\0" No_argument "f" /*ignored*/ # if ENABLE_DESKTOP "remove-empty-files\0" No_argument "E" /*ignored*/ /* "Controls actions when a file is under RCS or SCCS control, * and does not exist or is read-only and matches the default version, * or when a file is under ClearCase control and does not exist..." * IOW: rather obscure option. * But Gentoo's portage does use -g0 */ "get\0" Required_argument "g" /*ignored*/ # endif "dry-run\0" No_argument "\xfd" # if ENABLE_DESKTOP "backup-if-mismatch\0" No_argument "\xfe" /*ignored*/ "no-backup-if-mismatch\0" No_argument "\xff" /*ignored*/ # endif ; applet_long_options = patch_longopts; #endif /* -f,-E,-g are ignored */ opt = getopt32(argv, "p:i:RN""fEg:", &p, &i, NULL); if (opt & OPT_R) plus = '-'; patch_level = xatoi(p); /* can be negative! */ patch_file = xfopen_stdin(i); } patch_line = xmalloc_fgetline(patch_file); while (patch_line) { FILE *src_stream; FILE *dst_stream; //char *old_filename; char *new_filename; char *backup_filename = NULL; unsigned src_cur_line = 1; unsigned dst_cur_line = 0; unsigned dst_beg_line; unsigned bad_hunk_count = 0; unsigned hunk_count = 0; smallint copy_trailing_lines_flag = 0; /* Skip everything upto the "---" marker * No need to parse the lines "Only in <dir>", and "diff <args>" */ do { /* Extract the filename ugsed before the patch was generated */ new_filename = extract_filename(patch_line, patch_level, "--- "); // was old_filename above patch_line = xmalloc_fgetline(patch_file); if (!patch_line) goto quit; } while (!new_filename); free(new_filename); // "source" filename is irrelevant new_filename = extract_filename(patch_line, patch_level, "+++ "); if (!new_filename) { bb_error_msg_and_die("invalid patch"); } /* Get access rights from the file to be patched */ if (stat(new_filename, &saved_stat) != 0) { char *slash = strrchr(new_filename, '/'); if (slash) { /* Create leading directories */ *slash = '\0'; bb_make_directory(new_filename, -1, FILEUTILS_RECUR); *slash = '/'; } src_stream = NULL; saved_stat.st_mode = 0644; } else if (!(opt & OPT_dry_run)) { backup_filename = xasprintf("%s.orig", new_filename); xrename(new_filename, backup_filename); src_stream = xfopen_for_read(backup_filename); } else src_stream = xfopen_for_read(new_filename); if (opt & OPT_dry_run) { dst_stream = xfopen_for_write("/dev/null"); } else { dst_stream = xfopen_for_write(new_filename); fchmod(fileno(dst_stream), saved_stat.st_mode); } printf("patching file %s\n", new_filename); /* Handle all hunks for this file */ patch_line = xmalloc_fgets(patch_file); while (patch_line) { unsigned count; unsigned src_beg_line; unsigned hunk_offset_start; unsigned src_last_line = 1; unsigned dst_last_line = 1; if ((sscanf(patch_line, "@@ -%u,%u +%u,%u", &src_beg_line, &src_last_line, &dst_beg_line, &dst_last_line) < 3) && (sscanf(patch_line, "@@ -%u +%u,%u", &src_beg_line, &dst_beg_line, &dst_last_line) < 2) ) { /* No more hunks for this file */ break; } if (plus != '+') { /* reverse patch */ unsigned tmp = src_last_line; src_last_line = dst_last_line; dst_last_line = tmp; tmp = src_beg_line; src_beg_line = dst_beg_line; dst_beg_line = tmp; } hunk_count++; if (src_beg_line && dst_beg_line) { /* Copy unmodified lines upto start of hunk */ /* src_beg_line will be 0 if it's a new file */ count = src_beg_line - src_cur_line; if (copy_lines(src_stream, dst_stream, count)) { bb_error_msg_and_die("bad src file"); } src_cur_line += count; dst_cur_line += count; copy_trailing_lines_flag = 1; } src_last_line += hunk_offset_start = src_cur_line; dst_last_line += dst_cur_line; while (1) { free(patch_line); patch_line = xmalloc_fgets(patch_file); if (patch_line == NULL) break; /* EOF */ if (!*patch_line) { /* whitespace-damaged patch with "" lines */ free(patch_line); patch_line = xstrdup(" "); } if ((*patch_line != '-') && (*patch_line != '+') && (*patch_line != ' ') ) { break; /* End of hunk */ } if (*patch_line != plus) { /* '-' or ' ' */ char *src_line = NULL; if (src_cur_line == src_last_line) break; if (src_stream) { src_line = xmalloc_fgets(src_stream); if (src_line) { int diff = strcmp(src_line, patch_line + 1); src_cur_line++; free(src_line); if (diff) src_line = NULL; } } /* Do not patch an already patched hunk with -N */ if (src_line == 0 && (opt & OPT_N)) { continue; } if (!src_line) { bb_error_msg("hunk #%u FAILED at %u", hunk_count, hunk_offset_start); bad_hunk_count++; break; } if (*patch_line != ' ') { /* '-' */ continue; } } if (dst_cur_line == dst_last_line) break; fputs(patch_line + 1, dst_stream); dst_cur_line++; } /* end of while loop handling one hunk */ } /* end of while loop handling one file */ /* Cleanup last patched file */ if (copy_trailing_lines_flag) { copy_lines(src_stream, dst_stream, (unsigned)(-1)); } if (src_stream) { fclose(src_stream); } fclose(dst_stream); if (bad_hunk_count) { ret = 1; bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count); } else { /* It worked, we can remove the backup */ if (backup_filename) { unlink(backup_filename); } if (!(opt & OPT_dry_run) && ((dst_cur_line == 0) || (dst_beg_line == 0)) ) { /* The new patched file is empty, remove it */ xunlink(new_filename); // /* old_filename and new_filename may be the same file */ // unlink(old_filename); } } free(backup_filename); //free(old_filename); free(new_filename); } /* end of "while there are patch lines" */ quit: /* 0 = SUCCESS * 1 = Some hunks failed * 2 = More serious problems (exited earlier) */ return ret; }
int patch_main(int argc UNUSED_PARAM, char **argv) { struct stat saved_stat; char *patch_line; FILE *patch_file; int patch_level; int ret = 0; char plus = '+'; xfunc_error_retval = 2; { const char *p = "-1"; const char *i = "-"; /* compat */ if (getopt32(argv, "p:i:R", &p, &i) & 4) plus = '-'; patch_level = xatoi(p); /* can be negative! */ patch_file = xfopen_stdin(i); } patch_line = xmalloc_fgetline(patch_file); while (patch_line) { FILE *src_stream; FILE *dst_stream; //char *old_filename; char *new_filename; char *backup_filename; unsigned src_cur_line = 1; unsigned dst_cur_line = 0; unsigned dst_beg_line; unsigned bad_hunk_count = 0; unsigned hunk_count = 0; smallint copy_trailing_lines_flag = 0; /* Skip everything upto the "---" marker * No need to parse the lines "Only in <dir>", and "diff <args>" */ do { /* Extract the filename used before the patch was generated */ new_filename = extract_filename(patch_line, patch_level, "--- "); // was old_filename above patch_line = xmalloc_fgetline(patch_file); if (!patch_line) goto quit; } while (!new_filename); free(new_filename); // "source" filename is irrelevant new_filename = extract_filename(patch_line, patch_level, "+++ "); if (!new_filename) { bb_error_msg_and_die("invalid patch"); } /* Get access rights from the file to be patched */ if (stat(new_filename, &saved_stat) != 0) { char *slash = strrchr(new_filename, '/'); if (slash) { /* Create leading directories */ *slash = '\0'; bb_make_directory(new_filename, -1, FILEUTILS_RECUR); *slash = '/'; } backup_filename = NULL; src_stream = NULL; saved_stat.st_mode = 0644; } else { backup_filename = xasprintf("%s.orig", new_filename); xrename(new_filename, backup_filename); src_stream = xfopen_for_read(backup_filename); } dst_stream = xfopen_for_write(new_filename); fchmod(fileno(dst_stream), saved_stat.st_mode); printf("patching file %s\n", new_filename); /* Handle all hunks for this file */ patch_line = xmalloc_fgets(patch_file); while (patch_line) { unsigned count; unsigned src_beg_line; unsigned hunk_offset_start; unsigned src_last_line = 1; unsigned dst_last_line = 1; if ((sscanf(patch_line, "@@ -%d,%d +%d,%d", &src_beg_line, &src_last_line, &dst_beg_line, &dst_last_line) < 3) && (sscanf(patch_line, "@@ -%d +%d,%d", &src_beg_line, &dst_beg_line, &dst_last_line) < 2) ) { /* No more hunks for this file */ break; } if (plus != '+') { /* reverse patch */ unsigned tmp = src_last_line; src_last_line = dst_last_line; dst_last_line = tmp; tmp = src_beg_line; src_beg_line = dst_beg_line; dst_beg_line = tmp; } hunk_count++; if (src_beg_line && dst_beg_line) { /* Copy unmodified lines upto start of hunk */ /* src_beg_line will be 0 if it's a new file */ count = src_beg_line - src_cur_line; if (copy_lines(src_stream, dst_stream, count)) { bb_error_msg_and_die("bad src file"); } src_cur_line += count; dst_cur_line += count; copy_trailing_lines_flag = 1; } src_last_line += hunk_offset_start = src_cur_line; dst_last_line += dst_cur_line; while (1) { free(patch_line); patch_line = xmalloc_fgets(patch_file); if (patch_line == NULL) break; /* EOF */ if ((*patch_line != '-') && (*patch_line != '+') && (*patch_line != ' ') ) { break; /* End of hunk */ } if (*patch_line != plus) { /* '-' or ' ' */ char *src_line = NULL; if (src_cur_line == src_last_line) break; if (src_stream) { src_line = xmalloc_fgets(src_stream); if (src_line) { int diff = strcmp(src_line, patch_line + 1); src_cur_line++; free(src_line); if (diff) src_line = NULL; } } if (!src_line) { bb_error_msg("hunk #%u FAILED at %u", hunk_count, hunk_offset_start); bad_hunk_count++; break; } if (*patch_line != ' ') { /* '-' */ continue; } } if (dst_cur_line == dst_last_line) break; fputs(patch_line + 1, dst_stream); dst_cur_line++; } /* end of while loop handling one hunk */ } /* end of while loop handling one file */ /* Cleanup last patched file */ if (copy_trailing_lines_flag) { copy_lines(src_stream, dst_stream, (unsigned)(-1)); } if (src_stream) { fclose(src_stream); } fclose(dst_stream); if (bad_hunk_count) { ret = 1; bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count); } else { /* It worked, we can remove the backup */ if (backup_filename) { unlink(backup_filename); } if ((dst_cur_line == 0) || (dst_beg_line == 0)) { /* The new patched file is empty, remove it */ xunlink(new_filename); // /* old_filename and new_filename may be the same file */ // unlink(old_filename); } } free(backup_filename); //free(old_filename); free(new_filename); } /* end of "while there are patch lines" */ quit: /* 0 = SUCCESS * 1 = Some hunks failed * 2 = More serious problems (exited earlier) */ return ret; }
int sed_main(int argc ATTRIBUTE_UNUSED, char **argv) { enum { OPT_in_place = 1 << 0, }; unsigned opt; llist_t *opt_e, *opt_f; int status = EXIT_SUCCESS; INIT_G(); /* destroy command strings on exit */ if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff); /* Lie to autoconf when it starts asking stupid questions. */ if (argv[1] && !strcmp(argv[1], "--version")) { puts("This is not GNU sed version 4.0"); return 0; } /* do normal option parsing */ opt_e = opt_f = NULL; opt_complementary = "e::f::" /* can occur multiple times */ "nn"; /* count -n */ opt = getopt32(argv, "irne:f:", &opt_e, &opt_f, &G.be_quiet); /* counter for -n */ //argc -= optind; argv += optind; if (opt & OPT_in_place) { // -i atexit(cleanup_outname); } if (opt & 0x2) G.regex_type |= REG_EXTENDED; // -r //if (opt & 0x4) G.be_quiet++; // -n while (opt_e) { // -e add_cmd_block(llist_pop(&opt_e)); } while (opt_f) { // -f char *line; FILE *cmdfile; cmdfile = xfopen(llist_pop(&opt_f), "r"); while ((line = xmalloc_fgetline(cmdfile)) != NULL) { add_cmd(line); free(line); } fclose(cmdfile); } /* if we didn't get a pattern from -e or -f, use argv[0] */ if (!(opt & 0x18)) { if (!*argv) bb_show_usage(); add_cmd_block(*argv++); } /* Flush any unfinished commands. */ add_cmd(""); /* By default, we write to stdout */ G.nonstdout = stdout; /* argv[0..(argc-1)] should be names of file to process. If no * files were specified or '-' was specified, take input from stdin. * Otherwise, we process all the files specified. */ if (argv[0] == NULL) { if (opt & OPT_in_place) bb_error_msg_and_die(bb_msg_requires_arg, "-i"); add_input_file(stdin); process_files(); } else { int i; FILE *file; for (i = 0; argv[i]; i++) { struct stat statbuf; int nonstdoutfd; if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) { add_input_file(stdin); process_files(); continue; } file = fopen_or_warn(argv[i], "r"); if (!file) { status = EXIT_FAILURE; continue; } if (!(opt & OPT_in_place)) { add_input_file(file); continue; } G.outname = xasprintf("%sXXXXXX", argv[i]); nonstdoutfd = mkstemp(G.outname); if (-1 == nonstdoutfd) bb_perror_msg_and_die("cannot create temp file %s", G.outname); G.nonstdout = fdopen(nonstdoutfd, "w"); /* Set permissions of output file */ fstat(fileno(file), &statbuf); fchmod(nonstdoutfd, statbuf.st_mode); add_input_file(file); process_files(); fclose(G.nonstdout); G.nonstdout = stdout; /* unlink(argv[i]); */ xrename(G.outname, argv[i]); free(G.outname); G.outname = NULL; } if (G.input_file_count > G.current_input_file) process_files(); } return status; }