/* * ex_edit -- :e[dit][!] [+cmd] [file] * :ex[!] [+cmd] [file] * :vi[sual][!] [+cmd] [file] * * Edit a file; if none specified, re-edit the current file. The third * form of the command can only be executed while in vi mode. See the * hack in ex.c:ex_cmd(). * * !!! * Historic vi didn't permit the '+' command form without specifying * a file name as well. This seems unreasonable, so we support it * regardless. * * PUBLIC: int ex_edit __P((SCR *, EXCMD *)); */ int ex_edit(SCR *sp, EXCMD *cmdp) { FREF *frp; int attach, setalt; const char *np; size_t nlen; switch (cmdp->argc) { case 0: /* * If the name has been changed, we edit that file, not the * original name. If the user was editing a temporary file * (or wasn't editing any file), create another one. The * reason for not reusing temporary files is that there is * special exit processing of them, and reuse is tricky. */ frp = sp->frp; if (sp->ep == NULL || F_ISSET(frp, FR_TMPFILE)) { if ((frp = file_add(sp, NULL)) == NULL) return (1); attach = 0; } else attach = 1; setalt = 0; break; case 1: INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, np, nlen); if ((frp = file_add(sp, np)) == NULL) return (1); attach = 0; setalt = 1; set_alt_name(sp, np); break; default: abort(); } if (F_ISSET(cmdp, E_NEWSCREEN) || cmdp->cmd == &cmds[C_VSPLIT]) return (ex_N_edit(sp, cmdp, frp, attach)); /* * Check for modifications. * * !!! * Contrary to POSIX 1003.2-1992, autowrite did not affect :edit. */ if (file_m2(sp, FL_ISSET(cmdp->iflags, E_C_FORCE))) return (1); /* Switch files. */ if (file_init(sp, frp, NULL, (setalt ? FS_SETALT : 0) | (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) return (1); F_SET(sp, SC_FSWITCH); return (0); }
/* * ex_tag_nswitch -- * Switch context to the specified TAG. * * PUBLIC: int ex_tag_nswitch __P((SCR *, TAG *, int)); */ int ex_tag_nswitch(SCR *sp, TAG *tp, int force) { /* Get a file structure. */ if (tp->frp == NULL && (tp->frp = file_add(sp, tp->fname)) == NULL) return (1); /* If not changing files, return, we're done. */ if (tp->frp == sp->frp) return (0); /* Check for permission to leave. */ if (file_m1(sp, force, FS_ALL | FS_POSSIBLE)) return (1); /* Initialize the new file. */ if (file_init(sp, tp->frp, NULL, FS_SETALT)) return (1); /* Display tags in the center of the screen. */ F_CLR(sp, SC_SCR_TOP); F_SET(sp, SC_SCR_CENTER); /* Switch. */ F_SET(sp, SC_FSWITCH); return (0); }
void extract_files(struct tailq *queue, char *infile) { char html_fname[MAX_FILENAME]; char *file; int newLineIndex = 0, length = 0; unsigned long fileLen; file = mmap_file(infile); if (!file) return; fileLen = strlen(file); // Read each line into the queue for (int i = 0; i<fileLen+1; i++) { if (file[i] == '\n' || (i > 0 && file[i] == '\0' && file[i-1] != '\n')) { length = i-newLineIndex; strncpy(html_fname, file+newLineIndex, length); html_fname[length] = '\0'; file_add(queue, html_fname); newLineIndex = i+1; } } }
int main(int argc, char **argv) { char infile[MAX_FILENAME]; struct tailq queue; struct tailq_node *node; if (argc == 1) { file_add(&queue, "index.html"); } else if (argc == 2) { strncpy(infile, argv[1], MAX_FILENAME-1); extract_files(&queue, infile); } else { printf("usage: ./cr [in file]\n"); exit(-1); } node = queue.head; for (int i = 0; node; i++) { if (!populate_ref(&queue, node)) tailq_remove(&queue, node); node = node->next; } print_results(&queue); getchar(); printf("Bye!\n"); return 0; }
/* * editor -- * Main editor routine. * * PUBLIC: int editor(GS *, int, char *[]); */ int editor(GS *gp, int argc, char *argv[]) { extern int optind; extern char *optarg; const char *p; EVENT ev; FREF *frp; SCR *sp; size_t len; u_int flags; int ch, flagchk, lflag, secure, startup, readonly, rval, silent; char *tag_f, *wsizearg, path[256]; CHAR_T *w; size_t wlen; /* Initialize the busy routine, if not defined by the screen. */ if (gp->scr_busy == NULL) gp->scr_busy = vs_busy; /* Initialize the message routine, if not defined by the screen. */ if (gp->scr_msg == NULL) gp->scr_msg = vs_msg; gp->catd = (nl_catd)-1; /* Common global structure initialization. */ TAILQ_INIT(gp->dq); TAILQ_INIT(gp->hq); SLIST_INIT(gp->ecq); SLIST_INSERT_HEAD(gp->ecq, &gp->excmd, q); gp->noprint = DEFAULT_NOPRINT; /* Structures shared by screens so stored in the GS structure. */ TAILQ_INIT(gp->frefq); TAILQ_INIT(gp->dcb_store.textq); SLIST_INIT(gp->cutq); SLIST_INIT(gp->seqq); /* Set initial screen type and mode based on the program name. */ readonly = 0; if (!strcmp(getprogname(), "ex") || !strcmp(getprogname(), "nex")) LF_INIT(SC_EX); else { /* Nview, view are readonly. */ if (!strcmp(getprogname(), "nview") || !strcmp(getprogname(), "view")) readonly = 1; /* Vi is the default. */ LF_INIT(SC_VI); } /* Convert old-style arguments into new-style ones. */ if (v_obsolete(argv)) return (1); /* Parse the arguments. */ flagchk = '\0'; tag_f = wsizearg = NULL; lflag = secure = silent = 0; startup = 1; /* Set the file snapshot flag. */ F_SET(gp, G_SNAPSHOT); #ifdef DEBUG while ((ch = getopt(argc, argv, "c:D:eFlRrSsT:t:vw:")) != EOF) #else while ((ch = getopt(argc, argv, "c:eFlRrSst:vw:")) != EOF) #endif switch (ch) { case 'c': /* Run the command. */ /* * XXX * We should support multiple -c options. */ if (gp->c_option != NULL) { warnx("only one -c command may be specified."); return (1); } gp->c_option = optarg; break; #ifdef DEBUG case 'D': switch (optarg[0]) { case 's': startup = 0; break; case 'w': attach(gp); break; default: warnx("usage: -D requires s or w argument."); return (1); } break; #endif case 'e': /* Ex mode. */ LF_CLR(SC_VI); LF_SET(SC_EX); break; case 'F': /* No snapshot. */ F_CLR(gp, G_SNAPSHOT); break; case 'l': /* Set lisp, showmatch options. */ lflag = 1; break; case 'R': /* Readonly. */ readonly = 1; break; case 'r': /* Recover. */ if (flagchk == 't') { warnx("only one of -r and -t may be specified."); return (1); } flagchk = 'r'; break; case 'S': secure = 1; break; case 's': silent = 1; break; #ifdef DEBUG case 'T': /* Trace. */ if ((gp->tracefp = fopen(optarg, "w")) == NULL) { warn("%s", optarg); goto err; } (void)fprintf(gp->tracefp, "\n===\ntrace: open %s\n", optarg); break; #endif case 't': /* Tag. */ if (flagchk == 'r') { warnx("only one of -r and -t may be specified."); return (1); } if (flagchk == 't') { warnx("only one tag file may be specified."); return (1); } flagchk = 't'; tag_f = optarg; break; case 'v': /* Vi mode. */ LF_CLR(SC_EX); LF_SET(SC_VI); break; case 'w': wsizearg = optarg; break; case '?': default: (void)gp->scr_usage(); return (1); } argc -= optind; argv += optind; /* * -s option is only meaningful to ex. * * If not reading from a terminal, it's like -s was specified. */ if (silent && !LF_ISSET(SC_EX)) { warnx("-s option is only applicable to ex."); goto err; } if (LF_ISSET(SC_EX) && F_ISSET(gp, G_SCRIPTED)) silent = 1; /* * Build and initialize the first/current screen. This is a bit * tricky. If an error is returned, we may or may not have a * screen structure. If we have a screen structure, put it on a * display queue so that the error messages get displayed. * * !!! * Everything we do until we go interactive is done in ex mode. */ if (screen_init(gp, NULL, &sp)) { if (sp != NULL) TAILQ_INSERT_HEAD(gp->dq, sp, q); goto err; } F_SET(sp, SC_EX); TAILQ_INSERT_HEAD(gp->dq, sp, q); if (v_key_init(sp)) /* Special key initialization. */ goto err; { int oargs[5], *oargp = oargs; if (lflag) { /* Command-line options. */ *oargp++ = O_LISP; *oargp++ = O_SHOWMATCH; } if (readonly) *oargp++ = O_READONLY; if (secure) *oargp++ = O_SECURE; *oargp = -1; /* Options initialization. */ if (opts_init(sp, oargs)) goto err; } if (wsizearg != NULL) { ARGS *av[2], a, b; (void)snprintf(path, sizeof(path), "window=%s", wsizearg); a.bp = (CHAR_T *)path; a.len = strlen(path); b.bp = NULL; b.len = 0; av[0] = &a; av[1] = &b; (void)opts_set(sp, av, NULL); } if (silent) { /* Ex batch mode option values. */ O_CLR(sp, O_AUTOPRINT); O_CLR(sp, O_PROMPT); O_CLR(sp, O_VERBOSE); O_CLR(sp, O_WARN); F_SET(sp, SC_EX_SILENT); } sp->rows = O_VAL(sp, O_LINES); /* Make ex formatting work. */ sp->cols = O_VAL(sp, O_COLUMNS); if (!silent && startup) { /* Read EXINIT, exrc files. */ if (ex_exrc(sp)) goto err; if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) { if (screen_end(sp)) goto err; goto done; } } /* * List recovery files if -r specified without file arguments. * Note, options must be initialized and startup information * read before doing this. */ if (flagchk == 'r' && argv[0] == NULL) { if (rcv_list(sp)) goto err; if (screen_end(sp)) goto err; goto done; } /* * !!! * Initialize the default ^D, ^U scrolling value here, after the * user has had every opportunity to set the window option. * * It's historic practice that changing the value of the window * option did not alter the default scrolling value, only giving * a count to ^D/^U did that. */ sp->defscroll = (O_VAL(sp, O_WINDOW) + 1) / 2; /* * If we don't have a command-line option, switch into the right * editor now, so that we position default files correctly, and * so that any tags file file-already-locked messages are in the * vi screen, not the ex screen. * * XXX * If we have a command-line option, the error message can end * up in the wrong place, but I think that the combination is * unlikely. */ if (gp->c_option == NULL) { F_CLR(sp, SC_EX | SC_VI); F_SET(sp, LF_ISSET(SC_EX | SC_VI)); } /* Open a tag file if specified. */ if (tag_f != NULL) { CHAR2INT(sp, tag_f, strlen(tag_f) + 1, w, wlen); if (ex_tag_first(sp, w)) goto err; } /* * Append any remaining arguments as file names. Files are recovery * files if -r specified. If the tag option or ex startup commands * loaded a file, then any file arguments are going to come after it. */ if (*argv != NULL) { if (sp->frp != NULL) { /* Cheat -- we know we have an extra argv slot. */ *--argv = strdup(sp->frp->name); if (*argv == NULL) { warn(NULL); goto err; } } sp->argv = sp->cargv = argv; F_SET(sp, SC_ARGNOFREE); if (flagchk == 'r') F_SET(sp, SC_ARGRECOVER); } /* * If the ex startup commands and or/the tag option haven't already * created a file, create one. If no command-line files were given, * use a temporary file. */ if (sp->frp == NULL) { if (sp->argv == NULL) { if ((frp = file_add(sp, NULL)) == NULL) goto err; } else { if ((frp = file_add(sp, sp->argv[0])) == NULL) goto err; if (F_ISSET(sp, SC_ARGRECOVER)) F_SET(frp, FR_RECOVER); } if (file_init(sp, frp, NULL, 0)) goto err; if (EXCMD_RUNNING(gp)) { (void)ex_cmd(sp); if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) { if (screen_end(sp)) goto err; goto done; } } } /* * Check to see if we need to wait for ex. If SC_SCR_EX is set, ex * was forced to initialize the screen during startup. We'd like to * wait for a single character from the user, but we can't because * we're not in raw mode. We can't switch to raw mode because the * vi initialization will switch to xterm's alternate screen, causing * us to lose the messages we're pausing to make sure the user read. * So, wait for a complete line. */ if (F_ISSET(sp, SC_SCR_EX)) { p = msg_cmsg(sp, CMSG_CONT_R, &len); (void)write(STDOUT_FILENO, p, len); for (;;) { if (v_event_get(sp, &ev, 0, 0)) goto err; if (ev.e_event == E_INTERRUPT || (ev.e_event == E_CHARACTER && (ev.e_value == K_CR || ev.e_value == K_NL))) break; (void)gp->scr_bell(sp); } } /* Switch into the right editor, regardless. */ F_CLR(sp, SC_EX | SC_VI); F_SET(sp, LF_ISSET(SC_EX | SC_VI) | SC_STATUS_CNT); /* * Main edit loop. Vi handles split screens itself, we only return * here when switching editor modes or restarting the screen. */ while (sp != NULL) if (F_ISSET(sp, SC_EX) ? ex(&sp) : vi(&sp)) goto err; done: rval = 0; if (0) err: rval = 1; /* Clean out the global structure. */ v_end(gp); return (rval); }
void vm_process(VM *vm) { int a, b, opcode; opcode = vm->image[vm->ip]; switch(opcode) { case VM_NOP: break; case VM_LIT: vm->sp++; vm->ip++; TOS = vm->image[vm->ip]; break; case VM_DUP: vm->sp++; vm->data[vm->sp] = NOS; break; case VM_DROP: DROP break; case VM_SWAP: a = TOS; TOS = NOS; NOS = a; break; case VM_PUSH: vm->rsp++; TORS = TOS; DROP break; case VM_POP: vm->sp++; TOS = TORS; vm->rsp--; break; case VM_CALL: vm->ip++; vm->rsp++; TORS = vm->ip; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; case VM_JUMP: vm->ip++; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; case VM_RETURN: vm->ip = TORS; vm->rsp--; break; case VM_GT_JUMP: vm->ip++; if(NOS > TOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_LT_JUMP: vm->ip++; if(NOS < TOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_NE_JUMP: vm->ip++; if(TOS != NOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_EQ_JUMP: vm->ip++; if(TOS == NOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_FETCH: TOS = vm->image[TOS]; break; case VM_STORE: vm->image[TOS] = NOS; DROP DROP break; case VM_ADD: NOS += TOS; DROP break; case VM_SUB: NOS -= TOS; DROP break; case VM_MUL: NOS *= TOS; DROP break; case VM_DIVMOD: a = TOS; b = NOS; TOS = b / a; NOS = b % a; break; case VM_AND: a = TOS; b = NOS; DROP TOS = a & b; break; case VM_OR: a = TOS; b = NOS; DROP TOS = a | b; break; case VM_XOR: a = TOS; b = NOS; DROP TOS = a ^ b; break; case VM_SHL: a = TOS; b = NOS; DROP TOS = b << a; break; case VM_SHR: a = TOS; b = NOS; DROP TOS = b >>= a; break; case VM_ZERO_EXIT: if (TOS == 0) { DROP vm->ip = TORS; vm->rsp--; } break; case VM_INC: TOS += 1; break; case VM_DEC: TOS -= 1; break; case VM_IN: a = TOS; TOS = vm->ports[a]; vm->ports[a] = 0; break; case VM_OUT: vm->ports[0] = 0; vm->ports[TOS] = NOS; DROP DROP break; case VM_WAIT: if (vm->ports[0] == 1) break; /* Input */ if (vm->ports[0] == 0 && vm->ports[1] == 1) { vm->ports[1] = dev_getch(); vm->ports[0] = 1; } /* Output (character generator) */ if (vm->ports[2] == 1) { dev_putch(TOS); DROP vm->ports[2] = 0; vm->ports[0] = 1; } if (vm->ports[4] != 0) { vm->ports[0] = 1; switch (vm->ports[4]) { case 1: vm_save_image(vm, vm->filename); vm->ports[4] = 0; break; case 2: file_add(vm); vm->ports[4] = 0; break; case -1: vm->ports[4] = file_handle(vm); break; case -2: vm->ports[4] = file_readc(vm); break; case -3: vm->ports[4] = file_writec(vm); break; case -4: vm->ports[4] = file_closehandle(vm); break; case -5: vm->ports[4] = file_getpos(vm); break; case -6: vm->ports[4] = file_seek(vm); break; case -7: vm->ports[4] = file_size(vm); break; default: vm->ports[4] = 0; } } /* Capabilities */ if (vm->ports[5] != 0) { vm->ports[0] = 1; switch(vm->ports[5]) { case -1: vm->ports[5] = IMAGE_SIZE; break; case -2: vm->ports[5] = 0; break; case -3: vm->ports[5] = 0; break; case -4: vm->ports[5] = 0; break; case -5: vm->ports[5] = vm->sp; break; case -6: vm->ports[5] = vm->rsp; break; case -7: vm->ports[5] = 0; break; case -8: vm->ports[5] = time(NULL); break; case -9: vm->ports[5] = 0; vm->ip = IMAGE_SIZE; break; default: vm->ports[5] = 0; } } if (vm->ports[8] != 0) { vm->ports[0] = 1; switch (vm->ports[8]) { case -1: rsocket(vm); vm->ports[8] = 0; break; case -2: rbind(vm); vm->ports[8] = 0; break; case -3: rlisten(vm); vm->ports[8] = 0; break; case -4: raccept(vm); vm->ports[8] = 0; break; case -5: rclose(vm); vm->ports[8] = 0; break; case -6: rsend(vm); vm->ports[8] = 0; break; case -7: rrecv(vm); vm->ports[8] = 0; break; case -8: rconnect(vm); vm->ports[8] = 0; break; default: vm->ports[8] = 0; } vm->ports[8] = 0; } break; default: vm->rsp++; TORS = vm->ip; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; } vm->ports[3] = 1; }
/* * ex_read -- :read [file] * :read [!cmd] * Read from a file or utility. * * !!! * Historical vi wouldn't undo a filter read, for no apparent reason. * * PUBLIC: int ex_read __P((SCR *, EXCMD *)); */ int ex_read(SCR *sp, EXCMD *cmdp) { enum { R_ARG, R_EXPANDARG, R_FILTER } which; struct stat sb; CHAR_T *arg; char *name; size_t nlen; EX_PRIVATE *exp; FILE *fp; FREF *frp; GS *gp; MARK rm; db_recno_t nlines; size_t arglen; int argc, rval; char *p; char *np; gp = sp->gp; /* * 0 args: read the current pathname. * 1 args: check for "read !arg". */ switch (cmdp->argc) { case 0: which = R_ARG; break; case 1: arg = cmdp->argv[0]->bp; arglen = cmdp->argv[0]->len; if (*arg == '!') { ++arg; --arglen; which = R_FILTER; /* Secure means no shell access. */ if (O_ISSET(sp, O_SECURE)) { ex_wemsg(sp, cmdp->cmd->name, EXM_SECURE_F); return (1); } } else which = R_EXPANDARG; break; default: abort(); /* NOTREACHED */ } /* Load a temporary file if no file being edited. */ if (sp->ep == NULL) { if ((frp = file_add(sp, NULL)) == NULL) return (1); if (file_init(sp, frp, NULL, 0)) return (1); } switch (which) { case R_FILTER: /* * File name and bang expand the user's argument. If * we don't get an additional argument, it's illegal. */ argc = cmdp->argc; if (argv_exp1(sp, cmdp, arg, arglen, 1)) return (1); if (argc == cmdp->argc) { ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE); return (1); } argc = cmdp->argc - 1; /* Set the last bang command. */ exp = EXP(sp); if (exp->lastbcomm != NULL) free(exp->lastbcomm); if ((exp->lastbcomm = v_wstrdup(sp, cmdp->argv[argc]->bp, cmdp->argv[argc]->len)) == NULL) { msgq(sp, M_SYSERR, NULL); return (1); } /* * Vi redisplayed the user's argument if it changed, ex * always displayed a !, plus the user's argument if it * changed. */ if (F_ISSET(sp, SC_VI)) { if (F_ISSET(cmdp, E_MODIFY)) (void)vs_update(sp, "!", cmdp->argv[argc]->bp); } else { if (F_ISSET(cmdp, E_MODIFY)) (void)ex_printf(sp, "!%s\n", cmdp->argv[argc]->bp); else (void)ex_puts(sp, "!\n"); (void)ex_fflush(sp); } /* * Historically, filter reads as the first ex command didn't * wait for the user. If SC_SCR_EXWROTE not already set, set * the don't-wait flag. */ if (!F_ISSET(sp, SC_SCR_EXWROTE)) F_SET(sp, SC_EX_WAIT_NO); /* * Switch into ex canonical mode. The reason to restore the * original terminal modes for read filters is so that users * can do things like ":r! cat /dev/tty". * * !!! * We do not output an extra <newline>, so that we don't touch * the screen on a normal read. */ if (F_ISSET(sp, SC_VI)) { if (gp->scr_screen(sp, SC_EX)) { ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON_F); return (1); } /* * !!! * Historically, the read command doesn't switch to * the alternate X11 xterm screen, if doing a filter * read -- don't set SA_ALTERNATE. */ F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE); } if (ex_filter(sp, cmdp, &cmdp->addr1, NULL, &rm, cmdp->argv[argc]->bp, FILTER_READ)) return (1); /* The filter version of read set the autoprint flag. */ F_SET(cmdp, E_AUTOPRINT); /* * If in vi mode, move to the first nonblank. Might have * switched into ex mode, so saved the original SC_VI value. */ sp->lno = rm.lno; if (F_ISSET(sp, SC_VI)) { sp->cno = 0; (void)nonblank(sp, sp->lno, &sp->cno); } return (0); case R_ARG: name = sp->frp->name; break; case R_EXPANDARG: if (argv_exp2(sp, cmdp, arg, arglen)) return (1); /* * 0 args: impossible. * 1 args: impossible (I hope). * 2 args: read it. * >2 args: object, too many args. * * The 1 args case depends on the argv_sexp() function refusing * to return success without at least one non-blank character. */ switch (cmdp->argc) { case 0: case 1: abort(); /* NOTREACHED */ case 2: INT2CHAR(sp, cmdp->argv[1]->bp, cmdp->argv[1]->len + 1, name, nlen); /* * !!! * Historically, the read and write commands renamed * "unnamed" files, or, if the file had a name, set * the alternate file name. */ if (F_ISSET(sp->frp, FR_TMPFILE) && !F_ISSET(sp->frp, FR_EXNAMED)) { if ((p = strdup(name)) != NULL) { free(sp->frp->name); sp->frp->name = p; } /* * The file has a real name, it's no longer a * temporary, clear the temporary file flags. */ F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE); F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED); /* Notify the screen. */ (void)sp->gp->scr_rename(sp, sp->frp->name, 1); name = sp->frp->name; } else { set_alt_name(sp, name); name = sp->alt_name; } break; default: ex_wemsg(sp, cmdp->argv[0]->bp, EXM_FILECOUNT); return (1); } break; } /* * !!! * Historically, vi did not permit reads from non-regular files, nor * did it distinguish between "read !" and "read!", so there was no * way to "force" it. We permit reading from named pipes too, since * they didn't exist when the original implementation of vi was done * and they seem a reasonable addition. */ if ((fp = fopen(name, "r")) == NULL || fstat(fileno(fp), &sb)) { msgq_str(sp, M_SYSERR, name, "%s"); return (1); } if (!S_ISFIFO(sb.st_mode) && !S_ISREG(sb.st_mode)) { (void)fclose(fp); msgq(sp, M_ERR, "145|Only regular files and named pipes may be read"); return (1); } /* Try and get a lock. */ if (file_lock(sp, NULL, NULL, fileno(fp), 0) == LOCK_UNAVAIL) msgq(sp, M_ERR, "146|%s: read lock was unavailable", name); rval = ex_readfp(sp, name, fp, &cmdp->addr1, &nlines, 0); /* * In vi, set the cursor to the first line read in, if anything read * in, otherwise, the address. (Historic vi set it to the line after * the address regardless, but since that line may not exist we don't * bother.) * * In ex, set the cursor to the last line read in, if anything read in, * otherwise, the address. */ if (F_ISSET(sp, SC_VI)) { sp->lno = cmdp->addr1.lno; if (nlines) ++sp->lno; } else sp->lno = cmdp->addr1.lno + nlines; return (rval); }
/* * ex_next -- :next [+cmd] [files] * Edit the next file, optionally setting the list of files. * * !!! * The :next command behaved differently from the :rewind command in * historic vi. See nvi/docs/autowrite for details, but the basic * idea was that it ignored the force flag if the autowrite flag was * set. This implementation handles them all identically. * * PUBLIC: int ex_next __P((SCR *, EXCMD *)); */ int ex_next(SCR *sp, EXCMD *cmdp) { ARGS **argv; FREF *frp; int noargs; char **ap; const CHAR_T *wp; size_t wlen; const char *np; size_t nlen; /* Check for file to move to. */ if (cmdp->argc == 0 && (sp->cargv == NULL || sp->cargv[1] == NULL)) { msgq(sp, M_ERR, "111|No more files to edit"); return (1); } if (F_ISSET(cmdp, E_NEWSCREEN)) { /* By default, edit the next file in the old argument list. */ if (cmdp->argc == 0) { CHAR2INT(sp, sp->cargv[1], strlen(sp->cargv[1]) + 1, wp, wlen); if (argv_exp0(sp, cmdp, wp, wlen - 1)) return (1); return (ex_edit(sp, cmdp)); } return (ex_N_next(sp, cmdp)); } /* Check modification. */ if (file_m1(sp, FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE)) return (1); /* Any arguments are a replacement file list. */ if (cmdp->argc) { /* Free the current list. */ if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) { for (ap = sp->argv; *ap != NULL; ++ap) free(*ap); free(sp->argv); } F_CLR(sp, SC_ARGNOFREE | SC_ARGRECOVER); sp->cargv = NULL; /* Create a new list. */ CALLOC_RET(sp, sp->argv, char **, cmdp->argc + 1, sizeof(char *)); for (ap = sp->argv, argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv) { INT2CHAR(sp, argv[0]->bp, argv[0]->len, np, nlen); if ((*ap = v_strdup(sp, np, nlen)) == NULL) return (1); } *ap = NULL; /* Switch to the first file. */ sp->cargv = sp->argv; if ((frp = file_add(sp, *sp->cargv)) == NULL) return (1); noargs = 0; /* Display a file count with the welcome message. */ F_SET(sp, SC_STATUS_CNT); } else { if ((frp = file_add(sp, sp->cargv[1])) == NULL)
int main(int argc, char **argv) { DOS_FS fs; int salvage_files, verify, c; uint32_t free_clusters = 0; memset(&fs, 0, sizeof(fs)); salvage_files = verify = 0; rw = interactive = 1; check_atari(); while ((c = getopt(argc, argv, "Aac:d:bflnprtu:vVwy")) != -1) switch (c) { case 'A': /* toggle Atari format */ atari_format = !atari_format; break; case 'a': case 'p': case 'y': rw = 1; interactive = 0; salvage_files = 1; break; case 'b': rw = 0; interactive = 0; boot_only = 1; break; case 'c': set_dos_codepage(atoi(optarg)); break; case 'd': file_add(optarg, fdt_drop); break; case 'f': salvage_files = 1; break; case 'l': list = 1; break; case 'n': rw = 0; interactive = 0; break; case 'r': rw = 1; interactive = 1; break; case 't': test = 1; break; case 'u': file_add(optarg, fdt_undelete); break; case 'v': verbose = 1; break; case 'V': verify = 1; break; case 'w': write_immed = 1; break; default: usage(argv[0]); } set_dos_codepage(-1); /* set default codepage if none was given in command line */ if ((test || write_immed) && !rw) { fprintf(stderr, "-t and -w can not be used in read only mode\n"); exit(2); } if (optind != argc - 1) usage(argv[0]); printf("fsck.fat " VERSION " (" VERSION_DATE ")\n"); fs_open(argv[optind], rw); read_boot(&fs); if (boot_only) goto exit; if (verify) printf("Starting check/repair pass.\n"); while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue); if (test) fix_bad(&fs); if (salvage_files) reclaim_file(&fs); else reclaim_free(&fs); free_clusters = update_free(&fs); file_unused(); qfree(&mem_queue); if (verify) { n_files = 0; printf("Starting verification pass.\n"); read_fat(&fs); scan_root(&fs); reclaim_free(&fs); qfree(&mem_queue); } exit: if (fs_changed()) { if (rw) { if (interactive) rw = get_key("yn", "Perform changes ? (y/n)") == 'y'; else printf("Performing changes.\n"); } else printf("Leaving filesystem unchanged.\n"); } if (!boot_only) printf("%s: %u files, %lu/%lu clusters\n", argv[optind], n_files, (unsigned long)fs.clusters - free_clusters, (unsigned long)fs.clusters); return fs_close(rw) ? 1 : 0; }
cList *open_file(cStr * name, cStr * smode, Obj * obj) { char mode[4]; Int rw = 0; char *s = NULL; filec_t *fnew = file_new(); struct stat sbuf; /* parse the mode first, if the string pointer is NULL, set it readable */ if (smode != NULL) { s = smode->s; if (*s == '+') { rw = 1; fnew->f.readable = fnew->f.writable = 1; s++; } if (*s == '>') { s++; if (*s == '>') { s++; mode[0] = 'a'; } else { mode[0] = 'w'; } fnew->f.writable = 1; } else { if (*s == '<') s++; mode[0] = 'r'; fnew->f.readable = 1; } /* here is where we branch from perl, '-' is used to specify it as a 'binary' file (i.e. use buffers not cold strings) */ if (*s == '-') { s++; fnew->f.binary = 1; } } else { mode[0] = 'r'; fnew->f.readable = 1; } /* most systems ignore this, some need it */ mode[1] = 'b'; if (rw) { mode[2] = '+'; mode[3] = '\0'; } else { mode[2] = '\0'; } fnew->path = build_path(name->s, NULL, DISALLOW_DIR); if (fnew->path == NULL) return NULL; /* redundant, as build_path could have done this, but we have a special case which we need to handle differently */ if (stat(fnew->path->s, &sbuf) == F_SUCCESS) { /* Patch #6 -- Bruce Mitchener */ if (S_ISDIR(sbuf.st_mode)) { cthrow(directory_id, "\"%s\" is a directory.", fnew->path->s); file_discard(fnew, NULL); return NULL; } } fnew->fp = fopen(fnew->path->s, mode); if (fnew->fp == NULL) { if (GETERR() == ERR_NOMEM) panic("open_file(): %s", strerror(GETERR())); cthrow(file_id, "%s (%s)", strerror(GETERR()), name->s); file_discard(fnew, NULL); return NULL; } file_add(fnew); obj->file = fnew; fnew->objnum = obj->objnum; return statbuf_to_list(&sbuf); }
int main(int argc,char **argv) { DOS_FS fs; int rw,salvage_files,verify,c; unsigned n_files_check=0, n_files_verify=0; unsigned long free_clusters; rw = salvage_files = verify = 0; interactive = 1; check_atari(); while ((c = getopt(argc,argv,"Aad:flnprtu:vVwy")) != EOF) switch (c) { case 'A': /* toggle Atari format */ atari_format = !atari_format; break; case 'a': case 'p': case 'y': rw = 1; interactive = 0; salvage_files = 1; break; case 'd': file_add(optarg,fdt_drop); break; case 'f': salvage_files = 1; break; case 'l': list = 1; break; case 'n': rw = 0; interactive = 0; break; case 'r': rw = 1; interactive = 1; break; case 't': test = 1; break; case 'u': file_add(optarg,fdt_undelete); break; case 'v': verbose = 1; printf("dosfsck " VERSION " (" VERSION_DATE ")\n"); break; case 'V': verify = 1; break; case 'w': write_immed = 1; break; default: usage(argv[0]); } if ((test || write_immed) && !rw) { fprintf(stderr,"-t and -w require -a or -r\n"); exit(2); } if (optind != argc-1) usage(argv[0]); printf( "dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n" ); fs_open(argv[optind],rw); read_boot(&fs); if (verify) printf("Starting check/repair pass.\n"); while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue); if (test) fix_bad(&fs); if (salvage_files) reclaim_file(&fs); else reclaim_free(&fs); free_clusters = update_free(&fs); file_unused(); qfree(&mem_queue); n_files_check = n_files; if (verify) { n_files = 0; printf("Starting verification pass.\n"); read_fat(&fs); scan_root(&fs); reclaim_free(&fs); qfree(&mem_queue); n_files_verify = n_files; } if (fs_changed()) { if (rw) { if (interactive) rw = get_key("yn","Perform changes ? (y/n)") == 'y'; else printf("Performing changes.\n"); } else printf("Leaving file system unchanged.\n"); } printf( "%s: %u files, %lu/%lu clusters\n", argv[optind], n_files, fs.clusters - free_clusters, fs.clusters ); return fs_close(rw) ? 1 : 0; }
/* Open the file, load metadata and so on */ bg_db_file_t * bg_db_file_create_from_object(bg_db_t * db, bg_db_object_t * obj, int scan_flags, bg_db_scan_item_t * item, int64_t scan_dir_id) { int i; bg_track_info_t * ti; bg_plugin_handle_t * h = NULL; bg_input_plugin_t * plugin = NULL; bg_db_file_t * file; bg_db_object_type_t type; gavl_time_t duration; bg_db_object_set_type(obj, BG_DB_OBJECT_FILE); file = (bg_db_file_t *)obj; file->path = item->path; item->path = NULL; file->mtime = item->mtime; file->scan_dir_id = scan_dir_id; bg_db_object_update_size(db, file, item->size); bg_db_object_set_label_nocpy(file, bg_db_path_to_label(file->path)); /* Load all infos */ if(!bg_input_plugin_load(db->plugin_reg, file->path, NULL, &h, NULL, 0)) goto fail; plugin = (bg_input_plugin_t *)h->plugin; /* Only one track supported */ if(plugin->get_num_tracks && (plugin->get_num_tracks(h->priv) < 1)) goto fail; ti = plugin->get_track_info(h->priv, 0); /* Detect file type */ if((ti->num_audio_streams == 1) && !ti->num_video_streams) type = BG_DB_OBJECT_AUDIO_FILE; else if(ti->num_video_streams == 1) { if(!ti->num_audio_streams && (ti->num_video_streams == 1) && (ti->video_streams[0].format.framerate_mode = GAVL_FRAMERATE_STILL)) type = BG_DB_OBJECT_IMAGE_FILE; else type = BG_DB_OBJECT_VIDEO_FILE; } file->mimetype = gavl_strdup(gavl_metadata_get(&ti->metadata, GAVL_META_MIMETYPE)); /* Check if we want to add this file */ switch(type) { case BG_DB_OBJECT_AUDIO_FILE: if(!(scan_flags & BG_DB_SCAN_AUDIO)) goto fail; break; case BG_DB_OBJECT_VIDEO_FILE: if(!(scan_flags & BG_DB_SCAN_VIDEO)) goto fail; break; case BG_DB_OBJECT_IMAGE_FILE: // Images can also be movie poster and album covers break; default: break; } /* */ if(plugin->set_track && !plugin->set_track(h->priv, 0)) goto fail; /* Start everything */ if(plugin->set_audio_stream) { for(i = 0; i < ti->num_audio_streams; i++) plugin->set_audio_stream(h->priv, i, BG_STREAM_ACTION_DECODE); } if(plugin->set_video_stream) { for(i = 0; i < ti->num_video_streams; i++) plugin->set_video_stream(h->priv, i, BG_STREAM_ACTION_DECODE); } if(plugin->set_text_stream) { for(i = 0; i < ti->num_text_streams; i++) plugin->set_text_stream(h->priv, i, BG_STREAM_ACTION_DECODE); } if(plugin->set_overlay_stream) { for(i = 0; i < ti->num_overlay_streams; i++) plugin->set_overlay_stream(h->priv, i, BG_STREAM_ACTION_DECODE); } if(plugin->start && !plugin->start(h->priv)) goto fail; if(gavl_metadata_get_long(&ti->metadata, GAVL_META_APPROX_DURATION, &duration)) bg_db_object_update_duration(db, file, duration); /* Create derived type */ switch(type) { case BG_DB_OBJECT_AUDIO_FILE: bg_db_audio_file_create(db, file, ti); break; case BG_DB_OBJECT_VIDEO_FILE: break; case BG_DB_OBJECT_IMAGE_FILE: bg_db_image_file_create_from_ti(db, file, ti); break; default: break; } fail: if(plugin) plugin->close(h->priv); if(h) bg_plugin_unref(h); file_add(db, file); return file; }