pax_global_header00006660000000000000000000000064142304607620014516gustar00rootroot0000000000000052 comment=eab92dcaa34b66bc5182772afc9fda4ac8a27597 hexedit-1.6/000077500000000000000000000000001423046076200130165ustar00rootroot00000000000000hexedit-1.6/.github/000077500000000000000000000000001423046076200143565ustar00rootroot00000000000000hexedit-1.6/.github/workflows/000077500000000000000000000000001423046076200164135ustar00rootroot00000000000000hexedit-1.6/.github/workflows/full-check.yml000066400000000000000000000010501423046076200211470ustar00rootroot00000000000000name: full-check on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: install_dependencies run: sudo apt install libncurses5-dev - name: first_build run: | ./autogen.sh ./configure make sudo make install # sudo make uninstall # make distclean # - name: second_build_to_test_build_twice # run: | # ./autogen.sh # ./configure # make # sudo make install hexedit-1.6/.gitignore000066400000000000000000000001541423046076200150060ustar00rootroot00000000000000#output hexedit #build system dirt configure config.h* Makefile Makefile-build #compiled object files *.o hexedit-1.6/COPYING000066400000000000000000000431271423046076200140600ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. hexedit-1.6/Changes000066400000000000000000000171121423046076200143130ustar00rootroot00000000000000april 2022 - 1.6 - configure script must error-out when (n)curses isn't found - Move SIGWINCH handling from handler to NCURSES - Make configure.ac compliant with autoconf >= 2.70 - Check that malloc did not return NULL - Fix a possible memory leak in findFile() - Prevent division by zero on empty files. august 2020 - 1.5 - Fix searching very long string - Keep status of firstTime beween calls. (#35) - man page: use simple double quotes (instead of weird ```xxx''') - Properly handle off_t on non-lfs 32 bit systems. - Fixed compiler warnings. - Do not allow negative line length. (#34) - fix overflow on excessively long escape sequence. (#32) - Ignore KEY_RESIZE in main loop. (#33) - Show percentage of cursor relative to filesize. - Bug copy & paste (#29) september 2017 - 1.4.2 - fix spelling errors in manpage - fix build septembre 2017 - 1.4 - terminal resizing support - fix build novembre 2016: - mark cursor position in both HEX and ASCII - skip whitespace when parsing hex-strings march 2014: - fix small but in DIE() which was leaving the terminal in a bad state - added --linelength / -l command line option february 2013: - fix displaying sector number when above 2^31 - fix potential file descriptor leak (thanks to Rich Burridge) - add DESTDIR support to the makefiles - preprocessor flags should use CPPFLAGS, not CFLAGS - fix a small issue in mymemmem/mymemrmem when HAVE_MEMMEM/HAVE_MEMRMEM is not defined september 2005: - version 1.2.12 - colored (fruit salad) display built by default (if use_default_colors available), available through option --color (based on a patch from Yuri D'Elia) september 2005: - version 1.2.11 - add --enable-colors to build and have a colored (fruit salad) display - allow entering goto "position" and "sector" in hexadecimal or not - when prompting, propose previously entered value, and give ability to modify it - fix setting mark after scrolling - some cleanup may 2004: - version 1.2.10 - handle getnstr() not defined (needed for SGI IRIX 6.5.22) april 2004: - version 1.2.9 (brown paper bag version) - fix searching larger than 3 characters long strings january 2004: - version 1.2.8 - replace the unsafe getstr() with getnstr() (thanks to Richard Chadderton) august 2003: - version 1.2.7 - check the presence of before including it - fix build on Digital UNIX 4.0f (remove -Wall) - use the full width of the terminal (the trick is to stop relying on printing "\n", but using move() instead) - fix displaying the offsets at beginning of each line on big endian boxes (thanks to Martin Schaffner) june 2003: - version 1.2.6 - fix core dump when searching backward (thanks to Jean Delvare) (the culprit is memrmem, but also fixing provided memrchr) june 2003: - version 1.2.5 - fix build on Solaris (which doesn't have BLKGETSIZE and all compilers don't have -W) march 2003: - version 1.2.4 - use BLKGETSIZE to try to get the size of a device - do not die horribly when accessing after the end - fix provided memrchr() (thanks to Yue Luo) - fix displaying after searching >32bit files (thanks to Paul Mattal) june 2002: - version 1.2.3 - add some KEY_HOME KEY_END (^[[7~ and ^[[8~) - fix for HAVE_MEMMEM - fix my memrchr not behaving the same as libc's - fix the use of memrchr to behave as libc's - use "(void)" in prototype of functions having no parameters - call "raw()" when help() is over october 2001: - version 1.2.2 - yet again some s/int/INT/ (mainly in the "edited" list manipulation) june 2001: - version 1.2.1 - replace llseek with lseek + use of _FILE_OFFSET_BITS=64 - memrchr&memmem now exists in some glibc's, so define it only if not provided - cleanup basename declaration - various cleanup in configure.in, now using autoheader - a few bug fixes april 99: - version 1.1.1 - replaced lots of int by INT which 64bits - replaced lseek by llseek (!! portability=linux :( !!) 11 january 99: (:-<>, it's been a long time) - added many shortcuts so that F1..F12 and some others works on more terms (xterm, rxvt, sgi's winterm...) - removed the scanw that's badly handled on sgi (replaced by getstr + sscanf) 24 septembre 98: now displays the reached offset while searching 10 september 98: hexedit 1.0.0 release 08 september 98: Oliver Kiddle's changes: - changed code where a function that returns a void was returning the result of another function. This avoids errors in stricter compilers - used an if where ?: was being used to the left of an assignment - created Makefile.in and configure.in to replace Makefile - added alternative strdup, strerror and memcmp for lacking systems 26 august 98: hexedit 0.9.5 release 26 august 98: removed the total file size in modeline for devices 19 august 98: Evin Robertson's changes: - split hexedit.c into display.c, file.c, hexedit.c, hexedit.h, interact.c, mark.c, misc.c, page.c, search.c - Makefile changes - now defaults to installing in /usr/local/bin - scrolls one line at a time (but not in sector mode) - allow appending to the file - errors during writing are now non-fatal - show total file size in modeline (not really correct for devices) - gives better error messages when functions return -1 - added newlines to the end of fatal error messages - changed sizeof(bufferAttr) to sizeof(*bufferAttr) - grammatical corrections to the man page - removed dashes so the display is 16 bytes wide on an 80 column screen - backspace now moves back an entire byte in hex mode (I thought the previous behavior was inconsistent; it moved the cursor one nybble, but undid an entire byte) - refuse to open directories - disallow using return to go past the end of the file - added truncating ability (M-T) 07 august 98: ability to fill the selection with a string 06 august 98: forgot to mark all the things while doing them. Here is a list of what's been added: - make the display start at the current cursor position - go to a sector when in --sector mode - added a modeline - ability to open another file. Nice for copy&paste between files - you're no more forced to save the file per page. This means the cut&paste can now always be undone. It's much simplier that way (idea from Evin C Robertson, thanks) - the backspace acts as a small undo of the previous character. It's nice when typing (another idea from Evin C Robertson) - the modified-unmodified bytes are not shown in bold (eg: you replace 'a' by 'a') 26 july 98: added a TODO file 26 july 98: added save copied region in a file 26 july 98: added search backward 25 july 98: added copy&paste functions 25 july 98: you can now select a part of the buffer 21 july 98: modified bytes are shown in bold. 21 july 98: corrected a bug, when you call function goto_char and the file is modified, you're now asked if you want to save (before that the changes were lost). You're only asked if the goto_char gets you to a different page of the file. 21 july 98: replace the searchInBuffer function by memmem. Then replaced memmem by mymemmem to counter the libc bug. All this permits a good speedup when searching. 21 july 98: removed the bug in the goto_char function. Now giving an empty string leaves the cursor unmoved. A small bug remains if you give an invalid hexadecimal string starting legally. The scanw(3ncurses) function returns a number corresponding at the legal beginning substring (eg: 1z2 becomes 1). 21 july 98: added an install entry in the Makefile (the one Robert Woodcock made for the debian package, thanks Robert Woodcock). 21 july 98: creation of the Changes file hexedit-1.6/Makefile-build.in000066400000000000000000000022561423046076200161650ustar00rootroot00000000000000# Makefile-build for hexedit PRODUCT = @PRODUCT@ VERSION = @VERSION@ prefix = @prefix@ datarootdir = @datarootdir@ exec_prefix = @exec_prefix@ mandir = @mandir@/man1 bindir = @bindir@ srcdir = @srcdir@ INCL = @INCL@ SRCS = @SRCS@ OTHER = @OTHER@ ALL = $(INCL) $(SRCS) $(OTHER) TARSOURCE = $(PRODUCT)-$(VERSION).src.tgz DYNAMICBIN = $(PRODUCT)-$(VERSION).bin.i386.dynamic.tgz HTMLSITE = $(PRODUCT)-html-site.tar HTMLFILES = $(PRODUCT).html TMPFILES = $(DYNAMICBIN) $(TARSOURCE) $(HTMLFILES) FROMINFILES = hexedit.1 dynamic: $(MAKE) $(PRODUCT) install -d -m 755 usr/bin install -s -m 755 $(PRODUCT) usr/bin install -d -m 755 usr/man/man1 install -m 644 $(PRODUCT).1 usr/man/man1 tar cfz $(DYNAMICBIN) usr rm -rf usr tar: $(ALL) cd .. ; tar cfz $(PRODUCT)/$(TARSOURCE) $(ALL:%=$(PRODUCT)/%) docs: man2html $(PRODUCT).1 hexedit.1: hexedit.1.in m4 -DVERSION=$(VERSION) $< > $@ html-site: tar dynamic docs tar cf $(HTMLSITE) $(TMPFILES) clean: [ ! -e Makefile ] || $(MAKE) clean rm -f $(TMPFILES) $(HTMLSITE) TAGS $(FROMINFILES) distclean: clean [ ! -e Makefile ] || $(MAKE) distclean rm -f Makefile-build configure config.h.in ci: clean ci -l -mdefault * TAGS: etags *.[hc] hexedit-1.6/Makefile.in000066400000000000000000000015771423046076200150750ustar00rootroot00000000000000# Makefile for hexedit PRODUCT = @PRODUCT@ VERSION = @VERSION@ SHELL = /bin/sh CC = @CC@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ DEFS = @DEFS@ INSTALL = @INSTALL@ # Installation directories prefix = @prefix@ datarootdir = @datarootdir@ exec_prefix = @exec_prefix@ mandir = @mandir@ bindir = @bindir@ INCL = @INCL@ SRCS = @SRCS@ OBJS = $(SRCS:.c=.o) .SUFFIXES: .c .o .c.o: $(CC) $(DEFS) $(CFLAGS) $(CPPFLAGS) -c $< all: $(PRODUCT) $(PRODUCT): $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) clean: rm -rf *~ *.o core *.cache config.status config.log $(PRODUCT) $(PRODUCT).1 distclean: clean rm -f Makefile config.h Makefile-build install: $(PRODUCT) $(INSTALL) -d -m 755 $(DESTDIR)$(bindir) $(INSTALL) -m 755 $(PRODUCT) $(DESTDIR)$(bindir) $(INSTALL) -d -m 755 $(DESTDIR)$(mandir)/man1 $(INSTALL) -m 644 $(PRODUCT).1 $(DESTDIR)$(mandir)/man1 hexedit-1.6/README.md000066400000000000000000000001001423046076200142640ustar00rootroot00000000000000To build from git: ``` ./autogen.sh && ./configure && make ``` hexedit-1.6/TODO000066400000000000000000000000001423046076200134740ustar00rootroot00000000000000hexedit-1.6/autogen.sh000077500000000000000000000002101423046076200150100ustar00rootroot00000000000000#!/bin/sh test -f configure.ac || { echo "Please, run this script in the top level project directory." exit } autoconf autoheader hexedit-1.6/configure.ac000066400000000000000000000041721423046076200153100ustar00rootroot00000000000000dnl Autoconfigure input file for hexedit dnl dnl Process this file with autoconf to produce a configure script. dnl AC_PREREQ([2.69]) AC_INIT AC_CONFIG_SRCDIR([hexedit.c]) AC_CONFIG_HEADERS(config.h) define(TheVERSION, 1.6) PRODUCT=hexedit VERSION=TheVERSION INCL=hexedit.h SRCS="hexedit.c display.c mark.c page.c file.c interact.c misc.c search.c" OTHER="COPYING Changes TODO install-sh configure config.h.in hexedit.1 hexedit-TheVERSION.lsm Makefile.in configure.ac Makefile-build.in" AC_SUBST(PRODUCT) AC_SUBST(VERSION) AC_SUBST(INCL) AC_SUBST(SRCS) AC_SUBST(OTHER) dnl Enable GNU extensions on systems that have them. AH_VERBATIM([_GNU_SOURCE], [/* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif]) AC_DEFINE(_GNU_SOURCE) dnl Checks for programs. AC_PROG_CC AC_PROG_INSTALL dnl Checks for libraries. AC_CHECK_LIB(curses, initscr, LIBS="$LIBS -lcurses", [AC_CHECK_LIB(ncurses, initscr, LIBS="$LIBS -lncurses", AC_MSG_ERROR([libcurses/libncurses not found.]))] ) AC_CHECK_LIB(tinfo, keypad, LIBS="$LIBS -ltinfo") AC_CHECK_FUNC(use_default_colors, AC_DEFINE(HAVE_COLORS, , "Define if you want colored (fruit salad) display option") ) dnl This test must come as early as possible after the compiler configuration dnl tests, because the choice of the file model can (in principle) affect dnl whether functions and headers are available, whether they work, etc. AC_SYS_LARGEFILE dnl Checks for header files. AC_PROG_EGREP AC_HEADER_STAT AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(fcntl.h unistd.h libgen.h sys/mount.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T dnl Checks for library functions. AC_CHECK_FUNCS(memcmp memmem memrmem memrchr strdup strerror basename) if test $ac_cv_func_basename = no; then # basename not in the default libraries. See if it's elsewhere AC_CHECK_LIB(gen, basename, [AC_DEFINE(HAVE_BASENAME) LIBS="$LIBS -lgen"]) fi AC_CHECK_DECLS([dirname, basename, memrchr, memmem, memrmem], , , $ac_includes_default #if HAVE_LIBGEN_H #include #endif ) AC_CONFIG_FILES([Makefile Makefile-build hexedit.1]) AC_OUTPUT hexedit-1.6/display.c000066400000000000000000000174211423046076200146340ustar00rootroot00000000000000/* hexedit -- Hexadecimal Editor for Binary Files Copyright (C) 1998 Pixel (Pascal Rigaux) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/ #include "hexedit.h" int move_cursor(INT delta) { return set_cursor(base + cursor + delta); } int set_cursor(INT loc) { if (loc < 0 && base % lineLength) loc = 0; if (!tryloc(loc)) return FALSE; if (loc < base) { if (loc - base % lineLength < 0) set_base(0); else if (!move_base(myfloor(loc - base % lineLength, lineLength) + base % lineLength - base)) return FALSE; cursor = loc - base; } else if (loc >= base + page) { if (!move_base(myfloor(loc - base % lineLength, lineLength) + base % lineLength - page + lineLength - base)) return FALSE; cursor = loc - base; } else if (loc > base + nbBytes) { return FALSE; } else cursor = loc - base; if (mark_set) updateMarked(); return TRUE; } int move_base(INT delta) { if (mode == bySector) { if (delta > 0 && delta < page) delta = page; else if (delta < 0 && delta > -page) delta = -page; } return set_base(base + delta); } int set_base(INT loc) { if (loc < 0) loc = 0; if (!tryloc(loc)) return FALSE; base = loc; readFile(); if (mode != bySector && nbBytes < page - lineLength && base != 0) { base -= myfloor(page - nbBytes - lineLength, lineLength); if (base < 0) base = 0; readFile(); } if (cursor > nbBytes) cursor = nbBytes; return TRUE; } int computeLineSize(void) { return computeCursorXPos(lineLength - 1, 0) + 1; } int computeCursorXCurrentPos(void) { return computeCursorXPos(cursor, hexOrAscii); } int computeCursorXPos(int cursor, int hexOrAscii) { int r = 11; int x = cursor % lineLength; int h = (hexOrAscii ? x : lineLength - 1); r += normalSpaces * (h % blocSize) + (h / blocSize) * (normalSpaces * blocSize + 1) + (hexOrAscii && cursorOffset); if (!hexOrAscii) r += x + normalSpaces + 1; return r; } /*******************************************************************************/ /* Curses functions */ /*******************************************************************************/ void initCurses(void) { struct sigaction sa; initscr(); #ifdef HAVE_COLORS if (colored) { start_color(); use_default_colors(); init_pair(1, COLOR_RED, -1); /* null zeros */ init_pair(2, COLOR_GREEN, -1); /* control chars */ init_pair(3, COLOR_BLUE, -1); /* extended chars */ } init_pair(4, COLOR_BLUE, COLOR_YELLOW); /* current cursor position*/ #endif initDisplay(); } void initDisplay(void) { refresh(); raw(); noecho(); keypad(stdscr, TRUE); if (mode == bySector) { lineLength = modes[bySector].lineLength; page = modes[bySector].page; page = myfloor((LINES - 1) * lineLength, page); blocSize = modes[bySector].blocSize; if (computeLineSize() > COLS) DIE("%s: term is too small for sectored view (width)\n"); if (page == 0) DIE("%s: term is too small for sectored view (height)\n"); } else { /* mode == maximized */ if (LINES <= 4) DIE("%s: term is too small (height)\n"); blocSize = modes[maximized].blocSize; if (lineLength == 0) { /* put as many "blocSize" as can fit on a line */ for (lineLength = blocSize; computeLineSize() <= COLS; lineLength += blocSize); lineLength -= blocSize; if (lineLength == 0) DIE("%s: term is too small (width)\n"); } else { if (computeLineSize() > COLS) DIE("%s: term is too small (width) for selected line length\n"); } page = lineLength * (LINES - 1); } colsUsed = computeLineSize(); buffer = realloc(buffer,page); bufferAttr = realloc(bufferAttr,page * sizeof(*bufferAttr)); } void exitCurses(void) { close(fd); clear(); refresh(); endwin(); } void display(void) { long long fsize; int i; for (i = 0; i < nbBytes; i += lineLength) { move(i / lineLength, 0); displayLine(i, nbBytes); } for (; i < page; i += lineLength) { int j; move(i / lineLength, 0); for (j = 0; j < colsUsed; j++) printw(" "); /* cleanup the line */ move(i / lineLength, 0); PRINTW(("%08lX", (int) (base + i))); } attrset(NORMAL); move(LINES - 1, 0); for (i = 0; i < colsUsed; i++) printw("-"); move(LINES - 1, 0); if (isReadOnly) i = '%'; else if (edited) i = '*'; else i = '-'; printw("-%c%c %s --0x%llX", i, i, baseName, (long long) base + cursor); fsize = getfilesize(); if (MAX(fileSize, lastEditedLoc)) printw("/0x%llX", fsize); printw("--%i%%", fsize == 0 ? 0 : 100 * (base + cursor + fsize/200) / fsize ); if (mode == bySector) printw("--sector %lld", (long long) ((base + cursor) / SECTOR_SIZE)); move(cursor / lineLength, computeCursorXCurrentPos()); } void displayLine(int offset, int max) { int i,mark_color=0; #ifdef HAVE_COLORS mark_color = COLOR_PAIR(4) | A_BOLD; #endif PRINTW(("%08lX ", (int) (base + offset))); for (i = offset; i < offset + lineLength; i++) { if (i > offset) MAXATTRPRINTW(bufferAttr[i] & MARKED, (((i - offset) % blocSize) ? " " : " ")); if (i < max) { ATTRPRINTW( #ifdef HAVE_COLORS (!colored ? 0 : (cursor == i && hexOrAscii == 0 ? mark_color : buffer[i] == 0 ? (int) COLOR_PAIR(1) : buffer[i] < ' ' ? (int) COLOR_PAIR(2) : buffer[i] >= 127 ? (int) COLOR_PAIR(3) : 0) ) | #endif bufferAttr[i], ("%02X", buffer[i])); } else PRINTW((" ")); } PRINTW((" ")); for (i = offset; i < offset + lineLength; i++) { if (i >= max) PRINTW((" ")); else if (buffer[i] >= ' ' && buffer[i] < 127) ATTRPRINTW((cursor == i && hexOrAscii==1 ? mark_color : 0) | bufferAttr[i], ("%c", buffer[i])); else ATTRPRINTW((cursor == i && hexOrAscii == 1 ? mark_color : 0) | bufferAttr[i], (".")); } } void clr_line(int line) { move(line, 0); clrtoeol(); } void displayCentered(const char *msg, int line) { clr_line(line); move(line, (COLS - strlen(msg)) / 2); PRINTW(("%s", msg)); } void displayOneLineMessage(const char *msg) { int center = page / lineLength / 2; clr_line(center - 1); clr_line(center + 1); displayCentered(msg, center); } void displayTwoLineMessage(const char *msg1, const char *msg2) { int center = page / lineLength / 2; clr_line(center - 2); clr_line(center + 1); displayCentered(msg1, center - 1); displayCentered(msg2, center); } void displayMessageAndWaitForKey(const char *msg) { displayTwoLineMessage(msg, pressAnyKey); getch(); } int displayMessageAndGetString(const char *msg, char **last, char *p, int p_size) { int ret = TRUE; displayOneLineMessage(msg); ungetstr(*last); echo(); getnstr(p, p_size - 1); noecho(); if (*p == '\0') { if (*last) strcpy(p, *last); else ret = FALSE; } else { FREE(*last); *last = strdup(p); } return ret; } void ungetstr(char *s) { char *p; if (s) for (p = s + strlen(s) - 1; p >= s; p--) ungetch(*p); } int get_number(INT *i) { unsigned long long n; int err; char tmp[BLOCK_SEARCH_SIZE]; echo(); getnstr(tmp, BLOCK_SEARCH_SIZE - 1); noecho(); if (strbeginswith(tmp, "0x")) err = sscanf(tmp + strlen("0x"), "%llx", &n); else err = sscanf(tmp, "%llu", &n); *i = (off_t)n; if (*i < 0 || n != (unsigned long long) *i) err = 0; return err == 1; } hexedit-1.6/file.c000066400000000000000000000072101423046076200141010ustar00rootroot00000000000000/* hexedit -- Hexadecimal Editor for Binary Files Copyright (C) 1998 Pixel (Pascal Rigaux) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/ #include "hexedit.h" void openFile(void) { struct stat st; if (!is_file(fileName)) { fprintf(stderr, "%s: %s: Not a file.\n", progName, fileName); exit(1); } /* edited should be cleaned here (assert(edited == NULL)) */ if ((fd = open(fileName, O_RDWR)) == -1) { isReadOnly = TRUE; if ((fd = open(fileName, O_RDONLY)) == -1) { if (page) exitCurses(); if (fileName[0] == '-') DIE(usage); fprintf(stderr, "%s: ", progName); perror(fileName); exit(1); } } else isReadOnly = FALSE; baseName = basename(fileName); mark_set = FALSE; lastEditedLoc = base = cursor = cursorOffset = 0; /* check file size- doesn't work on devices. I considered implementing a conquer-and-divide algorithm, but it would unpleasant on tape drives and such. */ if (fstat(fd, &st) != -1 && st.st_size > 0) fileSize = st.st_size; else { #ifdef BLKGETSIZE unsigned long i; if (ioctl(fd, BLKGETSIZE, &i) == 0) fileSize = (INT) i * 512; else #endif fileSize = 0; } biggestLoc = fileSize; } void readFile(void) { typePage *p; INT i; memset(buffer, 0, page * sizeof(*buffer)); LSEEK(fd, base); nbBytes = read(fd, buffer, page); if (nbBytes < 0) nbBytes = 0; else if (nbBytes && base + nbBytes > biggestLoc) biggestLoc = base + nbBytes; memset(bufferAttr, A_NORMAL, page * sizeof(*bufferAttr)); for (p = edited; p; p = p->next) { for (i = MAX(base, p->base); i < MIN(p->base + p->size, base + page); i++) { if (buffer[i - base] != p->vals[i - p->base]) { buffer[i - base] = p->vals[i - p->base]; bufferAttr[i - base] |= MODIFIED; } } if (p->base + p->size > base + nbBytes) { /* Check for modifications past EOF */ for(; p->base + p->size > base + nbBytes && nbBytes < page; nbBytes++) bufferAttr[nbBytes] |= MODIFIED; } } if (mark_set) markSelectedRegion(); } int findFile(void) { char *p, tmp[BLOCK_SEARCH_SIZE]; p = lastFindFile ? strdup(lastFindFile) : NULL; if (!displayMessageAndGetString("File name: ", &p, tmp, sizeof(tmp))) return FALSE; if (!is_file(tmp)) { FREE(p); return FALSE; } FREE(lastFindFile); lastFindFile = fileName; fileName = p; return TRUE; } INT getfilesize(void) { return MAX(lastEditedLoc, biggestLoc); } /* tryloc: * returns TRUE if loc is an apropriate location to place the cursor * assumes the file won't shrink. * returns TRUE if the cursor is one past EOF to allow appending */ int tryloc(INT loc) { char c; if (loc < 0) return FALSE; if (loc <= lastEditedLoc) return TRUE; if (loc <= biggestLoc) return TRUE; if (LSEEK_(fd, loc - 1) != -1 && /* don't have to worry about loc - 1 < 0 */ read(fd, &c, 1) == 1) { biggestLoc = loc; return TRUE; } return FALSE; } int is_file(char *name) { struct stat st; return stat(name, &st) != -1 && !S_ISDIR(st.st_mode); } hexedit-1.6/hexedit.1.in000066400000000000000000000231231423046076200151400ustar00rootroot00000000000000.TH HEXEDIT 1 "12 July 1998" .SH NAME hexedit \- view and edit files in hexadecimal or in ASCII .SH SYNOPSIS .I hexedit [\-s | \-\-sector] [\-m | \-\-maximize] [\-l | \-\-linelength ] [\-h | \-\-help] [filename] .SH DESCRIPTION .LP .I hexedit shows a file both in ASCII and in hexadecimal. The file can be a device as the file is read a piece at a time. You can modify the file and search through it. .SH OPTIONS .TP .I "\-s, \-\-sector" Format the display to have entire sectors. .TP .I "\-m, \-\-maximize" Try to maximize the display. .TP .I "\-\-color" Display colors. This feature is only available if your operating system supports it. .TP .I "\-l, \-\-linelength " Explicitly set the number of bytes to display per line to . .TP .I "\-h, \-\-help" Show the usage. .SH COMMANDS (quickly) .SS Moving .nf <, > : go to start/end of the file Right: next character Left: previous character Down: next line Up: previous line Home: beginning of line End: end of line PUp: page forward PDown: page backward .fi .SS Miscellaneous .nf F2: save F3: load file F1: help Ctrl-L: redraw Ctrl-Z: suspend Ctrl-X: save and exit Ctrl-C: exit without saving Tab: toggle hex/ascii Return: go to Backspace: undo previous character Ctrl-U: undo all Ctrl-S: search forward Ctrl-R: search backward .fi .SS Cut&Paste .nf Ctrl-Space: set mark Esc-W: copy Ctrl-Y: paste Esc-Y: paste into a file Esc-I: fill .fi .SH COMMANDS (full and detailed) o \fIRight-Arrow\fR, \fILeft-Arrow\fR, \fIDown-Arrow\fR, \fIUp-Arrow\fR \- move the cursor. .br o \fICtrl+F\fR, \fICtrl+B\fR, \fICtrl+N\fR, \fICtrl+P\fR \- move the cursor. .br o \fICtrl+Right-Arrow\fR, \fICtrl+Left-Arrow\fR, \fICtrl+Down-Arrow\fR, \fICtrl+Up-Arrow\fR \- move n times the cursor. .br o \fIEsc+Right-Arrow\fR, \fIEsc+Left-Arrow\fR, \fIEsc+Down-Arrow\fR, \fIEsc+Up-Arrow\fR \- move n times the cursor. .br o \fIEsc+F\fR, \fIEsc+B\fR, \fIEsc+N\fR, \fIEsc+P\fR \- move n times the cursor. .br o \fIHome\fR, \fICtrl+A\fR \- go the beginning of the line. .br o \fIEnd\fR, \fICtrl+E\fR \- go to the end of the line. .br o \fIPage up\fR, \fIEsc+V\fR, \fIF5\fR \- go up in the file by one page. .br o \fIPage down\fR, \fICtrl+V\fR, \fIF6\fR \- go down in the file by one page. .br o \fI<\fR, \fIEsc+<\fR, \fIEsc+Home\fR \- go to the beginning of the file. .br o \fI>\fR, \fIEsc+>\fR, \fIEsc+End\fR \- go to the end of the file (for regular files that have a size). .br o \fICtrl+Z\fR \- suspend hexedit. .br o \fICtrl+U\fR, \fICtrl+_\fR, \fICtrl+/\fR \- undo all (forget the modifications). .br o \fICtrl+Q\fR \- read next input character and insert it (this is useful for inserting control characters and bound keys). .br o \fITab\fR, \fICtrl+T\fR \- toggle between ASCII and hexadecimal. .br o \fI/\fR, \fICtrl+S\fR \- search forward (in ASCII or in hexadecimal, use \fITAB\fR to change). .br o \fICtrl+R\fR \- search backward. .br o \fICtrl+G\fR, \fIF4\fR \- go to a position in the file. .br o \fIReturn\fR \- go to a sector in the file if \fI\-\-sector\fR is used, otherwise go to a position in the file. .br o \fIEsc+L\fR \- display the page starting at the current cursor position. .br o \fIF2\fR, \fICtrl+W\fR \- save the modifications. .br o \fIF1\fR, \fIEsc+H\fR \- help (show the man page). .br o \fICtrl+O\fR, \fIF3\fR \- open another file .br o \fICtrl+L\fR \- redisplay (refresh) the display (useful when your terminal screws up). .br o \fIBackspace\fR, \fICtrl+H\fR \- undo the modifications made on the previous byte. .br o \fIEsc+Ctrl+H\fR \- undo the modifications made on the previous bytes. .br o \fICtrl+Space\fR, \fIF9\fR \- set mark where cursor is. .br o \fIEsc+W\fR, \fIDelete\fR, \fIF7\fR \- copy selected region. .br o \fICtrl+Y\fR, \fIInsert\fR, \fIF8\fR \- paste (yank) previously copied region. .br o \fIEsc+Y\fR, \fIF11\fR \- save previously copied region to a file. .br o \fIEsc+I\fR, \fIF12\fR \- fill the selection with a string .br o \fIEsc+T\fR \- truncate the file at the current location .br o \fICtrl+C\fR \- unconditional quit (without saving). .br o \fIF10\fR, \fICtrl+X\fR \- quit. .PP For the \fIEsc\fR commands, it sometimes works to use \fIAlt\fR instead of \fIEsc\fR. Funny things here (especially for froggies :) egrave = Alt+H , ccedilla = Alt+G, Alt+Y = ugrave. .br .SS Modeline At the bottom of the display you have the modeline (copied from emacs). As in emacs, you have the indications --, ** and %% meaning unmodified, modified and read-only. Then you have the name of the file you're currently editing. Next to it is the current position of the cursor in the file followed by the total file size. The total file size isn't quite correct for devices. .br While in --sector mode, it shows the sector the cursor is in. .SS Editing You can edit in ASCII or in hexadecimal. You can switch between the two with \fITab\fR. When the file is read-only, you can't edit it. When trying to edit a read-only file, a message "File is read-only" tells you it is non-writable. .br The modifications are shown in bold until they are saved. The modeline indicates whether you have modified the file or not. .br When editing in hexadecimal, only \fI0\fR,\fI1\fR,...,\fI9\fR, \fIa\fR,\fIb\fR,...,\fIf\fR, \fIA\fR,\fIB\fR,...\fIF\fR are legal. Other keys are unbound. The first time you hit an unbound key, the help pops up. It won't pop again unless you call the help directly (with \fIF1\fR). .br When editing in ascii, you can find it difficult to enter characters like \fI/\fR which are bound to a function. The solution is to use the quoted insert function \fICtrl+Q\fR, the key after the quoted insert function is not processed by \fIhexedit\fR (like emacs' quoted-insert, or like the \\ character in C). .SS Searching You can search for a string in ASCII or in hexadecimal. You can switch between the two with \fITab\fR. If the string is found, the cursor is moved to the beginning of the matching location. If the search failed, a message "not found" tells you so. You can cancel the search by pressing a key. .br The search in hexadecimal is a bit confusing. You must give a hexadecimal string with an even number of characters. The search can then be done byte by byte. If you want to search a long number (eg: a 32 bit number), you must know the internal representation of that number (little/big endian problem) and give it the way it is in memory. For example, on an Intel processor (little endian), you must swap every bytes: 0x12345678 is written 0x78563412 in memory and that's the string you must give to the search engine. .br Before searching you are asked if you want to save the changes, if the file is edited. .PP For more sophisticated search, see Volker Schatz's patch at . .SS Selecting, copying, pasting, filling First, select the part of the buffer you want to copy: start setting the mark where you want. Then go to the end of the area you want to copy (you can use the go to function and the search functions). Then copy it. You can then paste the copied area in the current file or in another file. .PP You can also fill the selected area with a string or a character: start choosing the block you want to fill in (set mark then move to the end of the block), and call the fill function (\fIF12\fR). \fIhexedit\fR ask you the string you want to fill the block with. .br The code is not tuned for huge filling as it keeps the modifications in memory until you save them. That's why \fIhexedit\fR will warn you if you try to fill in a big block. .PP When the mark is set, the selection is shown in reverse mode. .br Be aware that the copied area contains the modifications done at the time of the copy. But if you undo the modifications, it does not change the content of the copy buffer. It seems obvious but it's worth saying. .SS Scrolling The scrolling is different whether you are in \fI\-\-sector\fR mode or not. In normal mode, the scrolling is line by line. In sector mode, the scrolling is sector by sector. In both modes, you can force the display to start at a given position using \fIEsc+L\fR. .SH SEE ALSO od(1), hdump(1), hexdump(1), bpe(1), hexed(1), beav(1). .SH AUTHOR Pixel (Pascal Rigaux) , .br Home page is . .SH UNRESTRICTIONS .I hexedit is Open Source; anyone may redistribute copies of .I hexedit to anyone under the terms stated in the GNU General Public License. .PP You can find .I hexedit at .br .SH TODO Anything you think could be nice... .SH LIMITATIONS There are problems with the curses library given with Redhat 5.0 that make \fIhexedit\fR think the terminal is huge. The result is that hexedit is not usable. .PP The shortcuts work on some machines, and not on others. That's why there are many shortcuts for each function. The Ctrl+Arrows and the Alt+. do not work work as they should most of the time. On SUNs, you must do Ctrl+V-Ctrl+V instead of Ctrl+V (!); and the Alt key is the diamond one. .PP While searching, it could be interesting to know which position the search has reached. It's always nice to see something moving to help waiting. .PP The hexadecimal search could be able to search modulo 4 bits instead of 8 bits. Another feature could be to complete padd odd length hexadecimal searches with zeros. .SH BUGS I have an example where the display is completely screwed up. It seems to be a bug in ncurses (or maybe in xterm and rxvt)?? Don't know if it's me using ncurses badly or not... It seems to happen when \fIhexedit\fR leaves only one space at the end of the lines... If anyone has a (or the) solution, please tell me! .PP If you have any problem with the program (even a small one), please do report it to me. Remarks of any kind are also welcome. .PP hexedit-1.6/hexedit.c000066400000000000000000000074611423046076200146240ustar00rootroot00000000000000/* hexedit -- Hexadecimal Editor for Binary Files Copyright (C) 1998 Pixel (Pascal Rigaux) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/ #include "hexedit.h" /*******************************************************************************/ /* Global variables */ /*******************************************************************************/ INT lastEditedLoc, biggestLoc, fileSize; INT mark_min, mark_max, mark_set; INT base, oldbase; int normalSpaces, cursor, cursorOffset, hexOrAscii; int cursor, blocSize, lineLength, colsUsed, page; int isReadOnly, fd, nbBytes, oldcursor, oldattr, oldcursorOffset; int sizeCopyBuffer, *bufferAttr; char *progName, *fileName, *baseName; unsigned char *buffer, *copyBuffer; typePage *edited; char *lastFindFile = NULL, *lastYankToAFile = NULL, *lastAskHexString = NULL, *lastAskAsciiString = NULL, *lastFillWithStringHexa = NULL, *lastFillWithStringAscii = NULL; const modeParams modes[LAST] = { { 8, 16, 256 }, { 4, 0, 0 }, }; modeType mode = maximized; int colored = FALSE; const char * const usage = "usage: %s [-s | --sector] [-m | --maximize] [-l | --linelength ]" #ifdef HAVE_COLORS " [--color]" #endif " [-h | --help] filename\n"; /*******************************************************************************/ /* main */ /*******************************************************************************/ int main(int argc, char **argv) { progName = basename(argv[0]); argv++; argc--; for (; argc > 0; argv++, argc--) { if (streq(*argv, "-s") || streq(*argv, "--sector")) mode = bySector; else if (streq(*argv, "-m") || streq(*argv, "--maximize")) { mode = maximized; lineLength = 0; } #ifdef HAVE_COLORS else if (streq(*argv, "--color")) colored = TRUE; #endif else if (strbeginswith(*argv, "-l") || strbeginswith(*argv, "--linelength")) { if (strbeginswith(*argv, "-l") && strlen(*argv) > 2) lineLength = atoi(*argv + 2); else { argv++; argc--; lineLength = atoi(*argv); } if (lineLength < 0 || lineLength > 4096) DIE("%s: illegal line length\n") } else if (streq(*argv, "--")) { argv++; argc--; break; } else if (*argv[0] == '-') DIE(usage) else break; } if (argc > 1) DIE(usage); init(); if (argc == 1) { fileName = strdup(*argv); openFile(); } initCurses(); if (fileName == NULL) { if (!findFile()) { exitCurses(); DIE("%s: No such file\n"); } openFile(); } readFile(); do display(); while (key_to_function(getch())); quit(); return 0; /* for no warning */ } /*******************************************************************************/ /* other functions */ /*******************************************************************************/ void init(void) { page = 0; /* page == 0 means initCurses is not done */ normalSpaces = 3; hexOrAscii = TRUE; copyBuffer = NULL; edited = NULL; } void quit(void) { exitCurses(); free(fileName); free(buffer); free(bufferAttr); FREE(copyBuffer); discardEdited(); FREE(lastFindFile); FREE(lastYankToAFile); FREE(lastAskHexString); FREE(lastAskAsciiString); FREE(lastFillWithStringHexa); FREE(lastFillWithStringAscii); exit(0); } hexedit-1.6/hexedit.h000066400000000000000000000163451423046076200146320ustar00rootroot00000000000000#ifndef HEXEDIT_H #define HEXEDIT_H #include "config.h" #include #include #include #include #include #if HAVE_FCNTL_H #include #endif #if HAVE_UNISTD_H #include #endif #include #include #include #if HAVE_SYS_WAIT_H #include #endif #include #if HAVE_LIBGEN_H #include #endif #if HAVE_SYS_MOUNT_H #include /* for BLKGETSIZE */ #endif #define INT off_t /*******************************************************************************/ /* Macros */ /*******************************************************************************/ #define BIGGEST_COPYING (1 * 1024 * 1024) #define BLOCK_SEARCH_SIZE (4 * 1024) #define SECTOR_SIZE ((INT) 512) #ifndef CTRL #define CTRL(c) ((c) & 0x1F) #endif #define ALT(c) ((c) | 0xa0) #define DIE(M) { exitCurses(); fprintf(stderr, M, progName); exit(1); } #define FREE(p) if (p) free(p) #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #define NORMAL A_NORMAL #define MARKED A_REVERSE #define MODIFIED A_BOLD #define ATTRPRINTW(attr, a) do { if (oldattr != (attr)) attrset(attr), oldattr = (attr); printw a; } while (0) #define MAXATTRPRINTW(attr, a) do { if (oldattr & (~(attr))) attrset(attr & oldattr), oldattr &= (attr); printw a; } while (0) #define PRINTW(a) ATTRPRINTW(NORMAL, a) #ifndef getnstr #define getnstr(str, n) wgetnstr(stdscr, str, n) #endif /*******************************************************************************/ /* Configuration parameters */ /*******************************************************************************/ typedef enum { bySector, maximized, LAST } modeType; typedef struct { int blocSize, lineLength, page; } modeParams; extern const modeParams modes[LAST]; extern modeType mode; extern int colored; extern const char * const usage; #define pressAnyKey "(press any key)" /*******************************************************************************/ /* Pages handling */ /*******************************************************************************/ typedef struct _typePage { struct _typePage *next; INT base; int size; unsigned char *vals; } typePage; /*******************************************************************************/ /* Global variables */ /*******************************************************************************/ extern INT lastEditedLoc, biggestLoc, fileSize; extern INT mark_min, mark_max, mark_set; extern INT base, oldbase; extern int normalSpaces, cursor, cursorOffset, hexOrAscii; extern int cursor, blocSize, lineLength, colsUsed, page; extern int isReadOnly, fd, nbBytes, oldcursor, oldattr, oldcursorOffset; extern int sizeCopyBuffer, *bufferAttr; extern char *progName, *fileName, *baseName; extern unsigned char *buffer, *copyBuffer; extern typePage *edited; extern char *lastFindFile, *lastYankToAFile, *lastAskHexString, *lastAskAsciiString, *lastFillWithStringHexa, *lastFillWithStringAscii; /*******************************************************************************/ /* Miscellaneous functions declaration */ /*******************************************************************************/ INT getfilesize(void); int key_to_function(int key); void init(void); void quit(void); int tryloc(INT loc); void openFile(void); void readFile(void); int findFile(void); int computeLineSize(void); int computeCursorXCurrentPos(void); int computeCursorXPos(int cursor, int hexOrAscii); void updateMarked(void); int ask_about_save(void); int ask_about_save_and_redisplay(void); void ask_about_save_and_quit(void); int setTo(int c); void setToChar(int i, unsigned char c); /*******************************************************************************/ /* Pages handling functions declaration */ /*******************************************************************************/ void discardEdited(void); void addToEdited(INT base, int size, unsigned char *vals); void removeFromEdited(INT base, int size); typePage *newPage(INT base, int size); void freePage(typePage *page); /*******************************************************************************/ /* Cursor manipulation function declarations */ /*******************************************************************************/ int move_cursor(INT delta); int set_cursor(INT loc); int move_base(INT delta); int set_base(INT loc); /*******************************************************************************/ /* Curses functions declaration */ /*******************************************************************************/ void initCurses(void); void initDisplay(void); void exitCurses(void); void display(void); void displayLine(int offset, int max); void clr_line(int line); void displayCentered(const char *msg, int line); void displayOneLineMessage(const char *msg); void displayTwoLineMessage(const char *msg1, const char *msg2); void displayMessageAndWaitForKey(const char *msg); int displayMessageAndGetString(const char *msg, char **last, char *p, int p_size); void ungetstr(char *s); int get_number(INT *i); /*******************************************************************************/ /* Search functions declaration */ /*******************************************************************************/ void search_forward(void); void search_backward(void); /*******************************************************************************/ /* Mark functions declaration */ /*******************************************************************************/ void markRegion(INT a, INT b); void unmarkRegion(INT a, INT b); void markSelectedRegion(void); void unmarkAll(void); void markIt(int i); void unmarkIt(int i); void copy_region(void); void yank(void); void yank_to_a_file(void); void fill_with_string(void); /*******************************************************************************/ /* Small common functions declaration */ /*******************************************************************************/ int streq(const char *s1, const char *s2); int strbeginswith(const char *a, const char *prefix); int myceil(int a, int b); INT myfloor(INT a, INT b); int setLowBits(int p, int val); int setHighBits(int p, int val); char *strconcat3(char *a, char *b, char *c); int hexCharToInt(int c); int not(int b); char *mymemmem(char *a, int sizea, char *b, int sizeb); char *mymemrmem(char *a, int sizea, char *b, int sizeb); int is_file(char *name); int hexStringToBinString(char *p, int *l); /*******************************************************************************/ /* Functions provided for OSs that don't have them */ /*******************************************************************************/ void LSEEK(int fd, INT where); int LSEEK_(int fd, INT where); #ifndef HAVE_DECL_MEMRCHR char *memrchr(void *s, char c, int n); #endif #ifndef HAVE_DECL_MEMMEM void *memmem(void *a, size_t sizea, void *b, size_t sizeb); #endif #ifndef HAVE_DECL_MEMRMEM void *memrmem(void *a, size_t sizea, void *b, size_t sizeb); #endif #ifndef HAVE_DECL_BASENAME char *basename(const char *file); #endif #ifndef HAVE_STRERROR char *strerror(int errnum); #endif #ifndef HAVE_STRDUP char *strdup(const char *str) #endif #ifndef HAVE_MEMCMP #define memcmp(s1, s2, n) bcmp(s2, s1, n) #endif #endif /* HEXEDIT_H */ hexedit-1.6/hexedit.lsm.in000066400000000000000000000014551423046076200155770ustar00rootroot00000000000000Begin3 Title: hexedit Version: TheVERSION Entered-date: 10SEP98 Description: view and edit files in hexadecimal or in ASCII. hexedit shows a file both in ASCII and in hexadecimal. The file can be a device as the file is not whole read. You can modify the file and search through it. You have also copy&paste and save to file functions. Truncating or appending to the file. Modifications are shown in bold. Keywords: hex binary file editor Author: pixel@rigaux.org (Pixel) Maintained-by: pixel@rigaux.org (Pixel) Primary-site: sunsite.unc.edu /pub/Linux/utils/file/hex 39kB hexedit-VERSION.src.tgz 14kB hexedit-VERSION.bin.i386.dynamic.tgz Original-site: rigaux.org / Platforms: Linux Unix SunOS Solaris SGI curses Copying-policy: GPL End hexedit-1.6/install-sh000077500000000000000000000127211423046076200150250ustar00rootroot00000000000000#! /bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 hexedit-1.6/interact.c000066400000000000000000000330511423046076200147750ustar00rootroot00000000000000/* hexedit -- Hexadecimal Editor for Binary Files Copyright (C) 1998 Pixel (Pascal Rigaux) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/ #include "hexedit.h" static void goto_char(void); static void goto_sector(void); static void save_buffer(void); static void escaped_command(void); static void help(void); static void short_help(void); /*******************************************************************************/ /* interactive functions */ /*******************************************************************************/ static void forward_char(void) { if (!hexOrAscii || cursorOffset) move_cursor(+1); if (hexOrAscii) cursorOffset = (cursorOffset + 1) % 2; } static void backward_char(void) { if (!hexOrAscii || !cursorOffset) move_cursor(-1); if (hexOrAscii) cursorOffset = (cursorOffset + 1) % 2; } static void next_line(void) { move_cursor(+lineLength); } static void previous_line(void) { move_cursor(-lineLength); } static void forward_chars(void) { move_cursor(+blocSize); } static void backward_chars(void) { move_cursor(-blocSize); } static void next_lines(void) { move_cursor(+lineLength * blocSize); } static void previous_lines(void) { move_cursor(-lineLength * blocSize); } static void beginning_of_line(void) { cursorOffset = 0; move_cursor(-(cursor % lineLength)); } static void end_of_line(void) { cursorOffset = 0; if (!move_cursor(lineLength - 1 - cursor % lineLength)) move_cursor(nbBytes - cursor); } static void scroll_up(void) { move_base(+page); if (mark_set) updateMarked(); } static void scroll_down(void) { move_base(-page); if (mark_set) updateMarked(); } static void beginning_of_buffer(void) { cursorOffset = 0; set_cursor(0); } static void end_of_buffer(void) { INT s = getfilesize(); cursorOffset = 0; if (mode == bySector) set_base(myfloor(s, page)); set_cursor(s); } static void suspend(void) { kill(getpid(), SIGTSTP); } static void undo(void) { discardEdited(); readFile(); } static void quoted_insert(void) { setTo(getch()); } static void toggle(void) { hexOrAscii = (hexOrAscii + 1) % 2; } static void recenter(void) { if (cursor) { base = base + cursor; cursor = 0; readFile(); } } static void find_file(void) { if (!ask_about_save_and_redisplay()) return; if (!findFile()) { displayMessageAndWaitForKey("No such file or directory"); return; } openFile(); readFile(); } static void redisplay(void) { clear(); } static void delete_backward_char(void) { backward_char(); removeFromEdited(base + cursor, 1); readFile(); cursorOffset = 0; if (!tryloc(base + cursor)) end_of_buffer(); } static void delete_backward_chars(void) { backward_chars(); removeFromEdited(base + cursor, blocSize); readFile(); cursorOffset = 0; if (!tryloc(base + cursor)) end_of_buffer(); } static void truncate_file(void) { displayOneLineMessage("Really truncate here? (y/N)"); if (tolower(getch()) == 'y') { if (biggestLoc > base+cursor && ftruncate(fd, base+cursor) == -1) displayMessageAndWaitForKey(strerror(errno)); else { removeFromEdited(base+cursor, lastEditedLoc - (base+cursor)); if (mark_set) { if (mark_min >= base + cursor || mark_max >= base + cursor) unmarkAll(); } if (biggestLoc > base+cursor) biggestLoc = base+cursor; readFile(); } } } static void firstTimeHelp(void) { static int firstTime = TRUE; if (firstTime) { firstTime = FALSE; short_help(); } } static void set_mark_command(void) { unmarkAll(); if ((mark_set = not(mark_set))) { markIt(cursor); mark_min = mark_max = base + cursor; } } int setTo(int c) { int val; if (cursor > nbBytes) return FALSE; if (hexOrAscii) { if (!isxdigit(c)) return FALSE; val = hexCharToInt(c); val = cursorOffset ? setLowBits(buffer[cursor], val) : setHighBits(buffer[cursor], val); } else val = c; if (isReadOnly) { displayMessageAndWaitForKey("File is read-only!"); } else { setToChar(cursor, val); forward_char(); } return TRUE; } /**************************************************** ask_about_* or functions that present a prompt ****************************************************/ int ask_about_save(void) { if (edited) { displayOneLineMessage("Save changes (Yes/No/Cancel) ?"); switch (tolower(getch())) { case 'y': save_buffer(); break; case 'n': discardEdited(); break; default: return FALSE; } return TRUE; } return -TRUE; } int ask_about_save_and_redisplay(void) { int b = ask_about_save(); if (b == TRUE) { readFile(); display(); } return b; } void ask_about_save_and_quit(void) { if (ask_about_save()) quit(); } static void goto_char(void) { INT i; displayOneLineMessage("New position ? "); ungetstr("0x"); if (!get_number(&i) || !set_cursor(i)) displayMessageAndWaitForKey("Invalid position!"); } static void goto_sector(void) { INT i; displayOneLineMessage("New sector ? "); if (get_number(&i) && set_base(i * SECTOR_SIZE)) set_cursor(i * SECTOR_SIZE); else displayMessageAndWaitForKey("Invalid sector!"); } static void save_buffer(void) { int displayedmessage = FALSE; typePage *p, *q; for (p = edited; p; p = q) { if (LSEEK_(fd, p->base) == -1 || write(fd, p->vals, p->size) == -1) if (!displayedmessage) { /* It would be annoying to display lots of error messages when we can't write. */ displayMessageAndWaitForKey(strerror(errno)); displayedmessage = TRUE; } q = p->next; freePage(p); } edited = NULL; if (lastEditedLoc > fileSize) fileSize = lastEditedLoc; lastEditedLoc = 0; memset(bufferAttr, A_NORMAL, page * sizeof(*bufferAttr)); if (displayedmessage) { displayMessageAndWaitForKey("Unwritten changes have been discarded"); readFile(); if (cursor > nbBytes) set_cursor(getfilesize()); } if (mark_set) markSelectedRegion(); } static void help(void) { char *args[3]; int status; args[0] = "man"; args[1] = "hexedit"; args[2] = NULL; endwin(); if (fork() == 0) { execvp(args[0], args); exit(1); } wait(&status); refresh(); raw(); } static void short_help(void) { displayMessageAndWaitForKey("Unknown command, press F1 for help"); } /*******************************************************************************/ /* key_to_function */ /*******************************************************************************/ int key_to_function(int key) { oldcursor = cursor; oldcursorOffset = cursorOffset; oldbase = base; /*printf("*******%d******\n", key);*/ switch (key) { case KEY_RESIZE: /*Close and refresh window to get new size*/ endwin(); refresh(); /*Reset to trigger recalculation*/ lineLength = 0; clear(); initDisplay(); readFile(); display(); break; case ERR: break; case KEY_RIGHT: case CTRL('F'): forward_char(); break; case KEY_LEFT: case CTRL('B'): backward_char(); break; case KEY_DOWN: case CTRL('N'): next_line(); break; case KEY_UP: case CTRL('P'): previous_line(); break; case ALT('F'): forward_chars(); break; case ALT('B'): backward_chars(); break; case ALT('N'): next_lines(); break; case ALT('P'): previous_lines(); break; case CTRL('A'): case KEY_HOME: beginning_of_line(); break; case CTRL('E'): case KEY_END: end_of_line(); break; case KEY_NPAGE: case CTRL('V'): case KEY_F(6): scroll_up(); break; case KEY_PPAGE: case ALT('V'): case KEY_F(5): scroll_down(); break; case '<': case ALT('<'): beginning_of_buffer(); break; case '>': case ALT('>'): end_of_buffer(); break; case KEY_SUSPEND: case CTRL('Z'): suspend(); break; case CTRL('U'): case CTRL('_'): undo(); break; case CTRL('Q'): quoted_insert(); break; case CTRL('T'): case '\t': toggle(); break; case '/': case CTRL('S'): search_forward(); break; case CTRL('R'): search_backward(); break; case CTRL('G'): case KEY_F(4): goto_char(); break; case ALT('L'): recenter(); break; case '\n': case '\r': case KEY_ENTER: if (mode == bySector) goto_sector(); else goto_char(); break; case CTRL('W'): case KEY_F(2): save_buffer(); break; case CTRL('['): /* escape */ escaped_command(); break; case KEY_F(1): case ALT('H'): help(); break; case KEY_F(3): case CTRL('O'): find_file(); break; case CTRL('L'): redisplay(); break; case CTRL('H'): case KEY_BACKSPACE: delete_backward_char(); break; case CTRL('H') | 0x80: /* CTRL-ALT-H */ delete_backward_chars(); break; case CTRL(' '): case KEY_F(9): set_mark_command(); break; case CTRL('D'): case ALT('W'): case KEY_DC: case KEY_F(7): case 0x7F: /* found on a sun */ copy_region(); break; case CTRL('Y'): case KEY_IC: case KEY_F(8): yank(); break; case ALT('Y'): case KEY_F(11): yank_to_a_file(); break; case KEY_F(12): case ALT('I'): fill_with_string(); break; case CTRL('C'): quit(); break; case ALT('T'): truncate_file(); break; case KEY_F(0): case KEY_F(10): case CTRL('X'): ask_about_save_and_quit(); break; default: if ((key >= 256 || !setTo(key))) firstTimeHelp(); } return TRUE; } static void escaped_command(void) { char tmp[BLOCK_SEARCH_SIZE]; int c, i; c = getch(); switch (c) { case KEY_RIGHT: case 'f': forward_chars(); break; case KEY_LEFT: case 'b': backward_chars(); break; case KEY_DOWN: case 'n': next_lines(); break; case KEY_UP: case 'p': previous_lines(); break; case 'v': scroll_down(); break; case KEY_HOME: case '<': beginning_of_buffer(); break; case KEY_END: case '>': end_of_buffer(); break; case 'l': recenter(); break; case 'h': help(); break; case CTRL('H'): delete_backward_chars(); break; case 'w': copy_region(); break; case 'y': yank_to_a_file(); break; case 'i': fill_with_string(); break; case 't': truncate_file(); break; case '': c = getch(); if (c == 'O') { switch (c = getch()) { case 'C': forward_chars(); break; case 'D': backward_chars(); break; case 'B': next_lines(); break; case 'A': previous_lines(); break; case 'H': beginning_of_buffer(); break; case 'F': end_of_buffer(); break; case 'P': /* F1 on a xterm */ help(); break; case 'Q': /* F2 on a xterm */ save_buffer(); break; case 'R': /* F3 on a xterm */ find_file(); break; case 'S': /* F4 on a xterm */ goto_char(); break; default: firstTimeHelp(); } } else firstTimeHelp(); break; case '[': for (i = 0; i < BLOCK_SEARCH_SIZE - 1; i++) { tmp[i] = c = getch(); if (!isdigit(c)) break; } tmp[i < BLOCK_SEARCH_SIZE - 1 ? i + 1 : i] = '\0'; if (0); else if (streq(tmp, "2~")) yank(); else if (streq(tmp, "5~")) scroll_down(); else if (streq(tmp, "6~")) scroll_up(); else if (streq(tmp, "7~")) beginning_of_buffer(); else if (streq(tmp, "8~")) end_of_buffer(); else if (streq(tmp, "010q" /* F10 on a sgi's winterm */)) ask_about_save_and_quit(); else if (streq(tmp, "193z")) fill_with_string(); else if (streq(tmp, "214z")) beginning_of_line(); else if (streq(tmp, "216z")) scroll_down(); else if (streq(tmp, "220z")) end_of_line(); else if (streq(tmp, "222z")) scroll_up(); else if (streq(tmp, "233z")) ask_about_save_and_quit(); else if (streq(tmp, "234z" /* F11 on a sun */)) yank_to_a_file(); else if (streq(tmp, "247z")) yank(); else if (streq(tmp, "11~" /* F1 on a rxvt */)) help(); else if (streq(tmp, "12~" /* F2 on a rxvt */)) save_buffer(); else if (streq(tmp, "13~" /* F3 on a rxvt */)) find_file(); else if (streq(tmp, "14~" /* F4 on a rxvt */)) goto_char(); else if (streq(tmp, "15~" /* F5 on a rxvt */)) scroll_down(); else if (streq(tmp, "17~" /* F6 on a rxvt */)) scroll_up(); else if (streq(tmp, "18~" /* F7 on a rxvt */)) copy_region(); else if (streq(tmp, "19~" /* F8 on a rxvt */)) yank(); else if (streq(tmp, "20~" /* F9 on a rxvt */)) set_mark_command(); else if (streq(tmp, "21~" /* F10 on a rxvt */)) ask_about_save_and_quit(); else if (streq(tmp, "23~" /* F11 on a rxvt */)) yank_to_a_file(); else if (streq(tmp, "24~" /* F12 on a rxvt */)) fill_with_string(); else firstTimeHelp(); break; default: firstTimeHelp(); } } hexedit-1.6/mark.c000066400000000000000000000127351423046076200141240ustar00rootroot00000000000000/* hexedit -- Hexadecimal Editor for Binary Files Copyright (C) 1998 Pixel (Pascal Rigaux) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/ #include "hexedit.h" /*******************************************************************************/ /* Mark functions */ /*******************************************************************************/ void markRegion(INT a, INT b) { int i; for (i = MAX(a - base, 0); i <= MIN(b - base, nbBytes - 1); i++) markIt(i); } void unmarkRegion(INT a, INT b) { int i; for (i = MAX(a - base, 0); i <= MIN(b - base, nbBytes - 1); i++) unmarkIt(i); } void markSelectedRegion(void) { markRegion(mark_min, mark_max); } void unmarkAll(void) { unmarkRegion(base, base + nbBytes - 1); } void markIt(int i) { bufferAttr[i] |= MARKED; } void unmarkIt(int i) { bufferAttr[i] &= ~MARKED; } void copy_region(void) { typePage *p; if (!mark_set) { displayMessageAndWaitForKey("Nothing to copy"); return; } sizeCopyBuffer = mark_max - mark_min + 1; if (sizeCopyBuffer == 0) return; if (sizeCopyBuffer > BIGGEST_COPYING) { displayTwoLineMessage("Hey, don't you think that's too big?!", "Really copy (Yes/No)"); if (tolower(getch()) != 'y') return; } FREE(copyBuffer); if ((copyBuffer = malloc(sizeCopyBuffer)) == NULL) { displayMessageAndWaitForKey("Can't allocate that much memory"); return; } if (LSEEK_(fd, mark_min) == -1 || read(fd, copyBuffer, sizeCopyBuffer) == -1) { displayMessageAndWaitForKey(strerror(errno)); return; } for (p = edited; p; p = p->next) { if (mark_min < p->base + p->size && p->base <= mark_max) { INT min = MIN(p->base, mark_min); memcpy(copyBuffer + p->base - min, p->vals + mark_min - min, MIN(MIN(p->base + p->size, mark_max) - MAX(p->base, mark_min) + 1, p->size)); } } unmarkAll(); mark_set = FALSE; } void yank(void) { if (copyBuffer == NULL) { displayMessageAndWaitForKey("Nothing to paste"); return; } if (isReadOnly) { displayMessageAndWaitForKey("File is read-only!"); return; } addToEdited(base + cursor, sizeCopyBuffer, copyBuffer); readFile(); } void yank_to_a_file(void) { char tmp[BLOCK_SEARCH_SIZE]; int f; if (copyBuffer == NULL) { displayMessageAndWaitForKey("Nothing to paste"); return; } if (!displayMessageAndGetString("File name: ", &lastYankToAFile, tmp, sizeof(tmp))) return; if ((f = open(tmp, O_RDONLY)) != -1) { close(f); displayTwoLineMessage("File exists", "Overwrite it (Yes/No)"); if (tolower(getch()) != 'y') return; } if ((f = creat(tmp, 0666)) == -1 || write(f, copyBuffer, sizeCopyBuffer) == -1) { displayMessageAndWaitForKey(strerror(errno)); } close(f); } void fill_with_string(void) { char *msg = hexOrAscii ? "Hexa string to fill with: " : "Ascii string to fill with: "; char **last = hexOrAscii ? &lastFillWithStringHexa : &lastFillWithStringAscii; char tmp2[BLOCK_SEARCH_SIZE]; unsigned char *tmp1; int i, l1, l2; if (!mark_set) return; if (isReadOnly) { displayMessageAndWaitForKey("File is read-only!"); return; } if (sizeCopyBuffer > BIGGEST_COPYING) { displayTwoLineMessage("Hey, don't you think that's too big?!", "Really fill (Yes/No)"); if (tolower(getch()) != 'y') return; } if (!displayMessageAndGetString(msg, last, tmp2, sizeof(tmp2))) return; l1 = mark_max - mark_min + 1; l2 = strlen(tmp2); if (hexOrAscii) { if (strlen(tmp2) == 1) { if (!isxdigit(*tmp2)) { displayMessageAndWaitForKey("Invalid hexa string"); return; } *tmp2 = hexCharToInt(*tmp2); } else if (!hexStringToBinString(tmp2, &l2)) return; } tmp1 = malloc(l1); if (!tmp1) { displayMessageAndWaitForKey("Can't allocate memory"); return; } for (i = 0; i < l1 - l2 + 1; i += l2) memcpy(tmp1 + i, tmp2, l2); memcpy(tmp1 + i, tmp2, l1 - i); addToEdited(mark_min, l1, tmp1); readFile(); free(tmp1); } void updateMarked(void) { if (base + cursor > oldbase + oldcursor) { if (mark_min == mark_max) { mark_max = base + cursor; } else if (oldbase + oldcursor == mark_min) { if (base + cursor <= mark_max) { mark_min = base + cursor; unmarkRegion(oldbase + oldcursor, mark_min - 1); } else { unmarkRegion(oldbase + oldcursor, mark_max); mark_min = mark_max; mark_max = base + cursor; } } else { mark_max = base + cursor; } } else if (base + cursor < oldbase + oldcursor){ if (mark_min == mark_max) { mark_min = base + cursor; } else if (oldbase + oldcursor == mark_max) { if (base + cursor >= mark_min) { mark_max = base + cursor; unmarkRegion(mark_max + 1, oldbase + oldcursor); } else { unmarkRegion(mark_min, oldbase + oldcursor); markRegion(base + cursor, mark_min - 1); mark_max = mark_min; mark_min = base + cursor; } } else { mark_min = base + cursor; } } if (mark_max >= getfilesize()) mark_max = getfilesize() - 1; markSelectedRegion(); } hexedit-1.6/misc.c000066400000000000000000000104751423046076200141240ustar00rootroot00000000000000/* hexedit -- Hexadecimal Editor for Binary Files Copyright (C) 1998 Pixel (Pascal Rigaux) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/ #include "hexedit.h" int LSEEK_(int fd, INT where) { INT result; result = lseek(fd, where, SEEK_SET); return (result == where) ? 1 : -1; } void LSEEK(int fd, INT where) { INT result; result = lseek(fd, where, SEEK_SET); if (result != where) { exitCurses(); fprintf(stderr, "the long seek failed (%lld instead of %lld), leaving :(\n", (long long) result, (long long) where); exit(1); } } /*******************************************************************************/ /* Functions provided for OSs that don't have them */ /*******************************************************************************/ #ifndef HAVE_BASENAME char *basename(char *file) { char *p = strrchr(file, '/'); return p ? p + 1 : file; } #endif #ifndef HAVE_STRERROR char *strerror(int errnum) { extern char *sys_errlist[]; extern int sys_nerr; if (errnum > 0 && errnum <= sys_nerr) return sys_errlist[errnum]; return _("Unknown system error"); } #endif #ifndef HAVE_STRDUP char *strdup(const char *str) { size_t len = strlen(str) + 1; void *new = malloc(len); if (new == NULL) return NULL; return (char *) bcopy(str, new, len); } #endif /*******************************************************************************/ /* Small common functions */ /*******************************************************************************/ int streq(const char *s1, const char *s2) { return strcmp(s1, s2) == 0; } INT myfloor(INT a, INT b) { return a - a % b; } int setLowBits(int p, int val) { return (p & 0xF0) + val; } int setHighBits(int p, int val) { return (p & 0x0F) + val * 0x10; } int strbeginswith(const char *a, const char *prefix) { return strncmp(a, prefix, strlen(prefix)) == 0; } char *strconcat3(char *a, char *b, char *c) { size_t la = a ? strlen(a) : 0; size_t lb = b ? strlen(b) : 0; size_t lc = c ? strlen(c) : 0; char *p = malloc(la + lb + lc + 1); if (a) memcpy(p, a, la); if (b) memcpy(p + la, b, lb); if (c) memcpy(p + la + lb, c, lc); p[la + lb + lc] = '\0'; return p; } int hexCharToInt(int c) { if (isdigit(c)) return c - '0'; return tolower(c) - 'a' + 10; } int not(int b) { return b ? FALSE: TRUE; } #ifndef HAVE_MEMRCHR void *memrchr(const void *s, int c, size_t n) { int i; const char *cs = s; for (i = n - 1; i >= 0; i--) if (cs[i] == c) return (void *) &cs[i]; return NULL; } #endif char *mymemmem(char *a, int sizea, char *b, int sizeb) { #ifdef HAVE_MEMMEM return memmem(a, sizea, b, sizeb); #else char *p; int i = sizea - sizeb + 1; if (i <= 0) return NULL; for (; (p = memchr(a, b[0], i)); i -= p - a + 1, a = p + 1) { if ((memcmp(p + 1, b + 1, sizeb - 1)) == 0) { return p; } } return NULL; #endif } char *mymemrmem(char *a, int sizea, char *b, int sizeb) { #ifdef HAVE_MEMRMEM return memrmem(a, sizea, b, sizeb); #else char *p; int i = sizea - sizeb + 1; if (i <= 0) return NULL; a += sizea - 1; for (; (p = memrchr(a - i + 1, b[sizeb - 1], i)); i -= a - p + 1, a = p - 1) { if ((memcmp(p - sizeb + 1, b, sizeb - 1)) == 0) return p; } return NULL; #endif } int hexStringToBinString(char *p, int *l) { int i; int j; for (i = 0, j = 0; i < *l; i++, j++) { if( isspace(p[i]) ) { j--; continue; } if (!isxdigit(p[i])) { displayMessageAndWaitForKey("Invalid hexa string"); return FALSE; } p[j / 2] = ((j % 2) ? setLowBits : setHighBits)(p[j / 2], hexCharToInt(p[i])); } if ((j % 2)) { displayMessageAndWaitForKey("Must be an even number of chars"); return FALSE; } *l = j / 2; return TRUE; } hexedit-1.6/page.c000066400000000000000000000107201423046076200140760ustar00rootroot00000000000000/* hexedit -- Hexadecimal Editor for Binary Files Copyright (C) 1998 Pixel (Pascal Rigaux) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/ #include "hexedit.h" void setToChar(int i, unsigned char c) { if (i >= nbBytes) { /* If appending, always mark as modified */ buffer[i] = c; bufferAttr[i] |= MODIFIED; addToEdited(base + i, 1, &c); nbBytes = i+1; } else if (buffer[i] != c) { buffer[i] = c; bufferAttr[i] |= MODIFIED; addToEdited(base + i, 1, &c); } } /*******************************************************************************/ /* Pages handling functions */ /*******************************************************************************/ void updatelastEditedLoc(void) { typePage *p; lastEditedLoc = 0; for (p = edited; p; p = p->next) { if (p->base + p->size > lastEditedLoc) lastEditedLoc = p->base + p->size; } } void discardEdited(void) { typePage *p, *q; for (p = edited; p; p = q) { q = p->next; freePage(p); } edited = NULL; lastEditedLoc = 0; if (base + cursor > biggestLoc) set_cursor(biggestLoc); if (mark_max >= biggestLoc) mark_max = biggestLoc - 1; } void addToEdited(INT base, int size, unsigned char *vals) { typePage *p, *q = NULL; for (p = edited; p; q = p, p = p->next) { if (base + size <= p->base) break; if (base <= p->base && p->base + p->size <= base + size) { if (q) q->next = p->next; else edited = p->next; freePage(p); p = q; if (q == NULL) { p = edited; break; } } } if (q && base <= q->base + q->size && q->base <= base + size) { /* chevauchement (?? how to say it in english ??) */ INT min, max; unsigned char *s; min = MIN(q->base, base); if (p && base + size == p->base) { max = p->base + p->size; s = malloc(max - min); memcpy(s + q->base - min, q->vals, q->size); memcpy(s + base - min, vals, size); memcpy(s + p->base - min, p->vals, p->size); free(q->vals); q->vals = s; q->next = p->next; freePage(p); } else { max = MAX(q->base + q->size, base + size); s = malloc(max - min); memcpy(s + q->base - min, q->vals, q->size); memcpy(s + base - min, vals, size); free(q->vals); q->vals = s; } q->base = min; q->size = max - min; } else if (p && base + size == p->base) { unsigned char *s = malloc(p->base + p->size - base); memcpy(s, vals, size); memcpy(s + p->base - base, p->vals, p->size); free(p->vals); p->vals = s; p->size = p->base + p->size - base; p->base = base; } else { typePage *r = newPage(base, size); memcpy(r->vals, vals, size); if (q) q->next = r; else edited = r; r->next = p; } updatelastEditedLoc(); } void removeFromEdited(INT base, int size) { typePage *p, *q = NULL; for (p = edited; p; p ? (q = p, p = p->next) : (q = NULL, p = edited)) { if (base + size <= p->base) break; if (base <= p->base) { if (p->base + p->size <= base + size) { if (q) q->next = p->next; else edited = p->next; freePage(p); p = q; } else { p->size -= base + size - p->base; memmove(p->vals, p->vals + base + size - p->base, p->size); p->base = base + size; } } else if (p->base + p->size <= base + size) { if (base < p->base + p->size) p->size -= p->base + p->size - base; } else { q = newPage(base + size, p->base + p->size - base - size); memcpy(q->vals, p->vals + base + size - p->base, q->size); q->next = p->next; p->next = q; p->size -= p->base + p->size - base; break; } } updatelastEditedLoc(); } typePage *newPage(INT base, int size) { typePage *p = (typePage *) malloc(sizeof(typePage)); p->base = base; p->size = size; p->vals = malloc(size); return p; } void freePage(typePage *page) { free(page->vals); free(page); } hexedit-1.6/search.c000066400000000000000000000073311423046076200144330ustar00rootroot00000000000000/* hexedit -- Hexadecimal Editor for Binary Files Copyright (C) 1998 Pixel (Pascal Rigaux) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/ #include "hexedit.h" static int searchA(char **string, int *sizea, char *tmp, int tmp_size); static void searchB(INT loc, char *string); /*******************************************************************************/ /* Search functions */ /*******************************************************************************/ static int searchA(char **string, int *sizea, char *tmp, int tmp_size) { char *msg = hexOrAscii ? "Hexa string to search: " : "Ascii string to search: "; char **last = hexOrAscii ? &lastAskHexString : &lastAskAsciiString; if (!ask_about_save_and_redisplay()) return FALSE; if (!displayMessageAndGetString(msg, last, tmp, tmp_size)) return FALSE; *sizea = strlen(tmp); if (hexOrAscii) if (!hexStringToBinString(tmp, sizea)) return FALSE; *string = malloc(*sizea); if (!*string) { displayMessageAndWaitForKey("Can't allocate memory"); return FALSE; } memcpy(*string, tmp, *sizea); nodelay(stdscr, TRUE); displayTwoLineMessage("searching...", "(press any key to cancel)"); return TRUE; } static void searchB(INT loc, char *string) { nodelay(stdscr, FALSE); free(string); if (loc >= 0) set_cursor(loc); else { if (loc == -3) displayMessageAndWaitForKey("not found"); } } void search_forward(void) { char *p, *string, tmp[BLOCK_SEARCH_SIZE], tmpstr[BLOCK_SEARCH_SIZE]; int quit, sizea, sizeb; INT blockstart; if (!searchA(&string, &sizea, tmp, sizeof(tmp))) return; quit = -1; blockstart = base + cursor - BLOCK_SEARCH_SIZE + sizea; do { blockstart += BLOCK_SEARCH_SIZE - sizea + 1; if (LSEEK_(fd, blockstart) == -1) { quit = -3; break; } if ((sizeb = read(fd, tmp, BLOCK_SEARCH_SIZE)) < sizea) quit = -3; else if (getch() != ERR) quit = -2; else if ((p = mymemmem(tmp, sizeb, string, sizea))) quit = p - tmp; sprintf(tmpstr,"searching... 0x%08llX", (long long) blockstart); nodelay(stdscr, TRUE); displayTwoLineMessage(tmpstr, "(press any key to cancel)"); } while (quit == -1); searchB(quit + (quit >= 0 ? blockstart : 0), string); } void search_backward(void) { char *p, *string, tmp[BLOCK_SEARCH_SIZE], tmpstr[BLOCK_SEARCH_SIZE]; int quit, sizea, sizeb; INT blockstart; if (!searchA(&string, &sizea, tmp, sizeof(tmp))) return; quit = -1; blockstart = base + cursor - sizea + 1; do { blockstart -= BLOCK_SEARCH_SIZE - sizea + 1; sizeb = BLOCK_SEARCH_SIZE; if (blockstart < 0) { sizeb -= -blockstart; blockstart = 0; } if (sizeb < sizea) quit = -3; else { if (LSEEK_(fd, blockstart) == -1) { quit = -3; break; } if (sizeb != read(fd, tmp, sizeb)) quit = -3; else if (getch() != ERR) quit = -2; else if ((p = mymemrmem(tmp, sizeb, string, sizea))) quit = p - tmp; } sprintf(tmpstr,"searching... 0x%08llX", (long long) blockstart); nodelay(stdscr, TRUE); displayTwoLineMessage(tmpstr, "(press any key to cancel)"); } while (quit == -1); searchB(quit + (quit >= 0 ? blockstart : 0), string); }