Initial commit.
This commit is contained in:
commit
a9a0ade08c
|
@ -0,0 +1,5 @@
|
|||
/Makefile.cfg
|
||||
/obj
|
||||
/man
|
||||
/p7
|
||||
/p7screen
|
|
@ -0,0 +1,2 @@
|
|||
# p7utils authors
|
||||
Thomas "Cakeisalie5" is the man behind these utilities.
|
|
@ -0,0 +1,336 @@
|
|||
GNU General Public License
|
||||
==========================
|
||||
|
||||
_Version 2, June 1991_
|
||||
_Copyright © 1989, 1991 Free Software Foundation, Inc.,_
|
||||
_51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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.
|
||||
|
||||
### 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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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.
|
||||
|
||||
<signature of Ty Coon>, 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 Lesser General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,179 @@
|
|||
#!/usr/bin/make -f
|
||||
#******************************************************************************#
|
||||
# Include variables and message subsystem #
|
||||
#******************************************************************************#
|
||||
include Makefile.vars Makefile.msg
|
||||
|
||||
#******************************************************************************#
|
||||
# General targets #
|
||||
#******************************************************************************#
|
||||
# Make it all
|
||||
all: all-bins all-doc
|
||||
|
||||
# Mostly clean
|
||||
mostlyclean: mostlyclean-bins
|
||||
mclean: mostlyclean
|
||||
|
||||
# Clean it all
|
||||
clean: clean-bins clean-doc
|
||||
fclean: clean
|
||||
|
||||
# Clean it entirely
|
||||
mrproper: clean
|
||||
$(call rmsg,Removing configuration.)
|
||||
$(call rcmd,Makefile.cfg,$(RM) Makefile.cfg)
|
||||
|
||||
# Remake it all
|
||||
re: clean all
|
||||
|
||||
# Install it all
|
||||
install: install-bins install-doc
|
||||
|
||||
# Uninstall it all
|
||||
uninstall: uninstall-bins uninstall-doc
|
||||
|
||||
# Reinstall it all
|
||||
reinstall: uninstall install
|
||||
|
||||
.PHONY: all mostlyclean mclean clean fclean mrproper re
|
||||
.PHONY: install uninstall reinstall
|
||||
#******************************************************************************#
|
||||
# Configuration (version) checking dependencies #
|
||||
#******************************************************************************#
|
||||
# Define the dependencies.
|
||||
CHECKCFG := $(if $(shell test -f Makefile.cfg || echo y),check-config, \
|
||||
$(if $(shell [ "$(VERSION)" = "$(CONFIG_VERSION)" ] || echo y), \
|
||||
check-config-version))
|
||||
|
||||
# Define the rules.
|
||||
check-config:
|
||||
@printf "\033[1;31mNo configuration file found!\n"
|
||||
@printf "You should configure before re-running this target.\033[0m\n"
|
||||
@false
|
||||
check-config-version:
|
||||
@printf "\033[1;31mConfiguration version is incorrect!\n"
|
||||
@printf "You should re-configure before re-running this target.\033[0m\n"
|
||||
@false
|
||||
|
||||
.PHONY: check-config check-config-version
|
||||
#******************************************************************************#
|
||||
# Information getting from the Makefile variables #
|
||||
#******************************************************************************#
|
||||
# Get the project name.
|
||||
getname:
|
||||
@echo "$(NAME)"
|
||||
|
||||
# Get the project version.
|
||||
getversion:
|
||||
@echo "$(VERSION)"
|
||||
|
||||
# Get the project author.
|
||||
getauthor:
|
||||
@echo "$(AUTHOR_NAME) <$(AUTHOR_MAIL)>"
|
||||
getauthor_name:
|
||||
@echo "$(AUTHOR_NAME)"
|
||||
|
||||
.PHONY: getname getauthor getauthor_name getversion
|
||||
#******************************************************************************#
|
||||
# Binaries-specific targets #
|
||||
#******************************************************************************#
|
||||
# Make the binaries.
|
||||
all-bins: $(CHECKCFG) $(BINARIES:%=%$(if $(FOR_WINDOWS),.exe))
|
||||
|
||||
# Make a binary object directory.
|
||||
$(BINARIES:%=$(OBJDIR)/%):
|
||||
$(call bcmd,mkdir,$@,$(MD) $@)
|
||||
|
||||
# Make an object out of a C source file.
|
||||
define make-binaryobj-rule
|
||||
$(OBJDIR)/$1/%.o: $(SRCDIR)/$1/%.c | $(OBJDIR)/$1
|
||||
$(call bcmd,cc,$$@,$(CC) -c -o $$@ $$< $(CFLAGS))
|
||||
endef
|
||||
$(foreach bin,$(BINARIES),\
|
||||
$(eval $(call make-binaryobj-rule,$(bin))))
|
||||
|
||||
# Make a binary
|
||||
define make-binary-rule
|
||||
$1$(if $(FOR_WINDOWS),.exe): $(SRC_$1:%=$(OBJDIR)/$1/%.o) | $(OBJDIR)/$1
|
||||
$(call bcmd,ld,$$@,$(LD) -o $$@ $$^ $(LDFLAGS))
|
||||
endef
|
||||
$(foreach bin,$(BINARIES),\
|
||||
$(eval $(call make-binary-rule,$(bin))))
|
||||
|
||||
# Remove object files.
|
||||
mostlyclean-bins:
|
||||
$(call rmsg,Removing objects directory.)
|
||||
$(call qcmd,$(RM) -r $(OBJDIR))
|
||||
mclean-bins: mostlyclean-bins
|
||||
|
||||
# Clean and remove binaries.
|
||||
clean-bins: mostlyclean-bins
|
||||
$(call rmsg,Removing binaries.)
|
||||
$(call qcmd,$(RM) $(BINARIES:%=%*))
|
||||
|
||||
# Install binaries
|
||||
install-bins: all-bins
|
||||
$(call imsg,Installing binaries.)
|
||||
$(call qcmd,$(INSTALL) -m 755 -d "$(IBINDIR)")
|
||||
$(call qcmd,$(INSTALL) -m 755 -t "$(IBINDIR)" \
|
||||
$(BINARIES:%=%$(if $(FOR_WINDOWS),.exe)))
|
||||
|
||||
# Uninstall binaries
|
||||
uninstall-bins: $(CHECKCFG)
|
||||
$(call rmsg,Uninstalling binaries.)
|
||||
$(call qcmd,$(RM) $(BINARIES) $(BINARIES:%=%.exe))
|
||||
|
||||
.PHONY: all-bins mostlyclean-bins mclean-bins clean-bins re-bins
|
||||
.PHONY: install-bins uninstall-bins
|
||||
#******************************************************************************#
|
||||
# Documentation-related #
|
||||
#******************************************************************************#
|
||||
# Make all manpages
|
||||
all-doc: $(foreach s,$(MAN_SECTIONS), $(MAN_$(s):%=$(MANDIR)/man$(s)/%.$(s)))
|
||||
|
||||
# Make manpages directories
|
||||
$(MAN_SECTIONS:%=$(MANDIR)/man%):
|
||||
$(call bcmd,mkdir,$@,$(MD) $@)
|
||||
|
||||
# Make-A-Manpage
|
||||
define make-manpage-rule
|
||||
$(MANDIR)/man$1/%.$1: $(DOCDIR)/%.$1.txt | $(MANDIR)/man$1
|
||||
$(call bcmd,a2x,$$<,$(A2X) -f manpage -D $$| $$< 2>/dev/null)
|
||||
endef
|
||||
$(foreach section, $(MAN_SECTIONS), \
|
||||
$(eval $(call make-manpage-rule,$(section))))
|
||||
|
||||
# Remove all manpages
|
||||
clean-doc:
|
||||
$(call rmsg,Removing manpages directory.)
|
||||
$(call rcmd,$(MANDIR),$(RM) -r $(MANDIR))
|
||||
|
||||
# Remake all manpages
|
||||
re-doc: clean-doc all-doc
|
||||
|
||||
# Install a manpage section.
|
||||
define make-installmansection-rule
|
||||
install-doc-$1: $(MAN_$1:%=$(MANDIR)/man$1/%.$1)
|
||||
$(call imsg,Installing manpages section $1.)
|
||||
$(call qcmd,$(INST) -m 755 -d "$(IMANDIR)/man$1")
|
||||
$(foreach i,$(MAN_$1),$(call icmd,man$1/$(i).$1))
|
||||
$(call qcmd,$(INST) -m 644 -t "$(IMANDIR)/man$1" \
|
||||
$(MAN_$1:%=$(MANDIR)/man$1/%.$1))
|
||||
$(call qcmd,$(GZIP) $(MAN_$1:%="$(IMANDIR)/man$1/%.$1"))
|
||||
endef
|
||||
$(foreach section, $(MAN_SECTIONS), \
|
||||
$(eval $(call make-installmansection-rule,$(section))))
|
||||
|
||||
# Install manpages
|
||||
install-doc: $(CHECKCFG) $(if $(INSTALL_MANPAGES),\
|
||||
$(MAN_SECTIONS:%=install-doc-%))
|
||||
|
||||
# Uninstall manpages
|
||||
uninstall-doc: $(CHECKCFG)
|
||||
$(call rmsg,Removing manpages.)
|
||||
$(call qcmd,$(RM) $(foreach s,$(MAN_SECTIONS),\
|
||||
$(patsubst %,"$(IMANDIR)"/man$(s)/%.$(s)*,$(MAN_$(s)))))
|
||||
|
||||
.PHONY: all-doc clean-doc re-doc install-doc uninstall-doc
|
||||
.PHONY: $(MAN_SECTIONS:%=install-doc-%)
|
||||
# End of file.
|
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/make -f
|
||||
# The Makefile message subsystem.
|
||||
# For nice logs. 5 dollars per log only.
|
||||
#******************************************************************************#
|
||||
# Colors and misc #
|
||||
#******************************************************************************#
|
||||
# Used colors ANSI modifiers escape codes
|
||||
color_green := 32
|
||||
color_red := 31
|
||||
color_yellow := 33
|
||||
|
||||
# Newline - comes handy in some situations
|
||||
define \n
|
||||
|
||||
|
||||
endef
|
||||
|
||||
#******************************************************************************#
|
||||
# General messages #
|
||||
#******************************************************************************#
|
||||
# Command message - display basic info about the command, and run it.
|
||||
define cmd
|
||||
@$(if $(MAKE_FULL_LOG),,printf "\033[1;""$4""m>\033[0m \033[1m%s\033[0m %s\n" "$1" "$2";)
|
||||
$(if $(MAKE_FULL_LOG),,@)$3
|
||||
endef
|
||||
|
||||
# Quiet command - make it non-quiet if full log is enabled.
|
||||
define qcmd
|
||||
$(if $(MAKE_FULL_LOG),,@)$1
|
||||
endef
|
||||
|
||||
# Normal message - display it.
|
||||
define msg
|
||||
$(if $(MAKE_FULL_LOG),,@printf "\033[1;""$2""m>\033[0m \033[1m%s\033[0m\n" "$1")
|
||||
endef
|
||||
|
||||
#******************************************************************************#
|
||||
# Commands #
|
||||
#******************************************************************************#
|
||||
# Build command
|
||||
define bcmd
|
||||
$(call cmd,$1,$2,$3,$(color_green))
|
||||
endef
|
||||
|
||||
#******************************************************************************#
|
||||
# Messages #
|
||||
#******************************************************************************#
|
||||
# Remove message
|
||||
define rmsg
|
||||
$(call msg,$1,$(color_red))
|
||||
endef
|
||||
|
||||
# Install message
|
||||
define imsg
|
||||
$(call msg,$1,$(color_yellow))
|
||||
endef
|
||||
|
||||
# End of file
|
|
@ -0,0 +1,126 @@
|
|||
#!/usr/bin/make -f
|
||||
#******************************************************************************#
|
||||
# Include configuration #
|
||||
#******************************************************************************#
|
||||
-include Makefile.cfg
|
||||
|
||||
# Correct target and adapt
|
||||
TARGET := $(if $(TARGET),$(TARGET)-)
|
||||
FOR_WINDOWS := $(if $(findstring mingw,$(TARGET)),y)
|
||||
|
||||
#******************************************************************************#
|
||||
# Project main information #
|
||||
#******************************************************************************#
|
||||
# Project name.
|
||||
NAME := p7utils
|
||||
|
||||
# Required packages
|
||||
LIBS := libp7 sdl
|
||||
|
||||
# Author information.
|
||||
AUTHOR_NAME := Thomas \"Cakeisalie5\" Touhey
|
||||
AUTHOR_MAIL := thomas@touhey.fr
|
||||
|
||||
# Project license.
|
||||
LICENSE := GPLv2
|
||||
|
||||
# Project version.
|
||||
MAJOR := 2
|
||||
MINOR := 0
|
||||
INDEV := yes
|
||||
|
||||
# Project version string.
|
||||
VERSION := $(MAJOR).$(MINOR)$(if $(INDEV),-indev)
|
||||
|
||||
#******************************************************************************#
|
||||
# Project directories #
|
||||
#******************************************************************************#
|
||||
# Sources directory
|
||||
SRCDIR := ./src
|
||||
|
||||
# Objects directory
|
||||
OBJDIR := ./obj
|
||||
|
||||
# Manpages sources directory
|
||||
DOCDIR := ./doc
|
||||
|
||||
# Manpages directory
|
||||
MANDIR := ./man
|
||||
|
||||
#******************************************************************************#
|
||||
# Binary utilities #
|
||||
#******************************************************************************#
|
||||
# Package configuration
|
||||
PKGCONFIG := $(TARGET)pkg-config
|
||||
|
||||
# C Compiler
|
||||
CC := $(TARGET)gcc
|
||||
# - Check flags (enable warnings)
|
||||
CWARN := -Wall -Wextra
|
||||
# - More flags (profiling, ...)
|
||||
#CMOREFLAGS :=
|
||||
# - All C Compiler flags
|
||||
CFLAGS := $(CWARN) -std=gnu11 -fPIC -O2 \
|
||||
-D LICENSE="$(LICENSE)" -D VERSION="$(VERSION)" \
|
||||
-D AUTHOR="$(AUTHOR_NAME) <$(AUTHOR_MAIL)>" \
|
||||
-D DEFAULT_STORAGE="$(DEFAULT_STORAGE)" \
|
||||
-D DEFAULT_ZOOM="$(DEFAULT_ZOOM)" \
|
||||
$(shell $(PKGCONFIG) --cflags $(LIBS) 2>/dev/null) \
|
||||
$(CMOREFLAGS)
|
||||
|
||||
# Linker
|
||||
LD := $(TARGET)gcc
|
||||
# - Specific linker flags
|
||||
LDFLAGS_Linux := -Wl,-z,relro
|
||||
# - Linker flags
|
||||
LDFLAGS := $(shell $(PKGCONFIG) --libs $(LIBS) 2>/dev/null) \
|
||||
$(if $(FOR_WINDOWS),,$(LDFLAGS_Linux))
|
||||
|
||||
# Directory maker
|
||||
MD := mkdir -p
|
||||
# File remover
|
||||
RM := rm -f
|
||||
# Installer
|
||||
INSTALL := install
|
||||
# Asciidoc
|
||||
A2X := a2x
|
||||
|
||||
#******************************************************************************#
|
||||
# Binaries and sources #
|
||||
#******************************************************************************#
|
||||
# Look for binaries
|
||||
BINARIES := $(notdir $(shell find $(SRCDIR) -mindepth 1 -maxdepth 1 \
|
||||
-type d | sort))
|
||||
|
||||
# Look for their sources
|
||||
define get-binary-sources
|
||||
SRC_$1 := $(basename $(shell find $(SRCDIR)/$1 \
|
||||
-maxdepth 1 -mindepth 1 -type f -name "*.c" -printf "%P\n" | sort))
|
||||
endef
|
||||
$(foreach bin,$(BINARIES), \
|
||||
$(eval $(call get-binary-sources,$(bin))))
|
||||
|
||||
#******************************************************************************#
|
||||
# Look for manpages #
|
||||
#******************************************************************************#
|
||||
# Get the manpages sections and contents
|
||||
MAN_SECTIONS :=
|
||||
define check-man
|
||||
MAN_SECTIONS += $1
|
||||
MAN_$1 += $2
|
||||
endef
|
||||
$(foreach doc, $(basename $(shell find $(DOCDIR) \
|
||||
-maxdepth 1 -mindepth 1 -printf "%P\n" -type f -or -type l -name "*.*.txt")), \
|
||||
$(eval $(call check-man,$(patsubst .%,%,$(suffix $(doc))),$(basename $(doc)))))
|
||||
|
||||
# Remove duplicate sections.
|
||||
MAN_SECTIONS := $(sort $(MAN_SECTIONS))
|
||||
|
||||
#******************************************************************************#
|
||||
# Check for DESTDIR (add as prefix to installation root) #
|
||||
#******************************************************************************#
|
||||
define add-dest-dir
|
||||
$1 = $(DESTDIR)$($1)
|
||||
endef
|
||||
$(if $(DESTDIR), $(foreach idir,IBINDIR IMANDIR, \
|
||||
$(eval $(call add-dest-dir,$(idir)))))
|
|
@ -0,0 +1,29 @@
|
|||
# p7utils - Shell utilities for libp7
|
||||
## Introduction
|
||||
**p7utils** is a set of command-line utilities that allow you to interact with
|
||||
your calculator. `p7` will interact with the storage memories, `p7screen` will
|
||||
display the result of the screen streaming and `p7os` will play with the
|
||||
calculator's OS (backup, flash).
|
||||
|
||||
## Prerequisites
|
||||
### Making-only dependencies
|
||||
| Name | Version |
|
||||
| -------------------------------------------------- | -------- |
|
||||
| [gcc](https://gcc.gnu.org/) | >= 4.9 |
|
||||
| [binutils](https://www.gnu.org/software/binutils/) | >= 2.25 |
|
||||
| [asciidoc](http://asciidoc.org/) | >= 8.6.9 |
|
||||
| [gzip](https://www.gnu.org/software/gzip/) | >= 1.6 |
|
||||
|
||||
### Making and runtime dependencies
|
||||
| Name | Version |
|
||||
| -------------------------------------------------- | --------- |
|
||||
| [libp7](https://forge.touhey.fr/lib/p7/) | >= 1.5 |
|
||||
| [libsdl](https://libsdl.org/) | == 1.2.15 |
|
||||
|
||||
## Building
|
||||
Just `./configure` then `make`. To install, use `make install`.
|
||||
Make the manpages with `make all-doc` and install them with `make install-doc`.
|
||||
|
||||
Other useful targets :
|
||||
- `clean`, `fclean`, `clean-doc`: remove built files ;
|
||||
- `re`, `re-doc`: regenerate binary and/or manpages.
|
|
@ -0,0 +1,170 @@
|
|||
#!/bin/sh
|
||||
cd "$(dirname "$0")"
|
||||
#******************************************************************************#
|
||||
# Defaults #
|
||||
#******************************************************************************#
|
||||
# Project variables
|
||||
name="$(make -s getname)"
|
||||
version="$(make -s getversion)"
|
||||
|
||||
# Author
|
||||
author="$(make -s getauthor)"
|
||||
author_name="$(make -s getauthor_name)"
|
||||
|
||||
# Target
|
||||
target=""
|
||||
|
||||
# Make options
|
||||
make_full_log=
|
||||
|
||||
# Build options
|
||||
default_zoom=8
|
||||
default_storage=fls0
|
||||
|
||||
# Installation directories
|
||||
root=''
|
||||
prefix='${root}/usr'
|
||||
bindir='${prefix}/bin'
|
||||
mandir='${prefix}/share/man'
|
||||
|
||||
# Installation options
|
||||
install_manpages=yes
|
||||
|
||||
#******************************************************************************#
|
||||
# Help message #
|
||||
#******************************************************************************#
|
||||
usage() {
|
||||
cat <<EOF
|
||||
\`configure\` configures ${name} to adapt to systems that aren't mine.
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
Defaults for the options are specified in brackets.
|
||||
|
||||
General options:
|
||||
--help display this help and exit
|
||||
--version display version information and quit
|
||||
--make-full-log display full commands while making
|
||||
|
||||
Build options:
|
||||
--target=TARGET the build target [$target]
|
||||
--default-zoom=ZOOM the default zoom for \`p7screen\` [$default_zoom]
|
||||
--default-storage=STOR the default storage device [$default_storage]
|
||||
|
||||
Installation options:
|
||||
--noinstall-manpages do not install manpages
|
||||
|
||||
Installation directories:
|
||||
--root=ROOT installation root [$root]
|
||||
--prefix=PREFIX main installation prefix [$prefix]
|
||||
|
||||
Fine tuning of the installation directories:
|
||||
--bindir=DIR user executables, not "dustbin" [$bindir]
|
||||
--mandir=DIR man root [$mandir]
|
||||
|
||||
Report bugs to ${author}.
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
#******************************************************************************#
|
||||
# Version message #
|
||||
#******************************************************************************#
|
||||
version() {
|
||||
cat <<EOF
|
||||
${name} configure script v${version}
|
||||
Hand-written by ${author_name}.
|
||||
|
||||
This configure script is free software.
|
||||
There is NO warranty; not even for MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE.
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
#******************************************************************************#
|
||||
# Check for help and version #
|
||||
#******************************************************************************#
|
||||
put_version=
|
||||
put_help=
|
||||
for arg ; do case "$arg" in
|
||||
--help|-h) put_help=y ;;
|
||||
--version|-v) put_version=y ;;
|
||||
esac; done
|
||||
[ $put_version ] && version
|
||||
[ $put_help ] && usage
|
||||
|
||||
#******************************************************************************#
|
||||
# Parse arguments #
|
||||
#******************************************************************************#
|
||||
for arg ; do case "$arg" in
|
||||
--make-full-log) make_full_log=yes ;;
|
||||
--target=*) target="${arg#*=}" ;;
|
||||
--default-zoom=*)
|
||||
zoom="${arg#*=}"
|
||||
if ! [ $zoom -eq $zoom 2>/dev/null ]; then
|
||||
echo "--default-zoom: a number is expected (got \"$zoom\")" >&2
|
||||
elif [ $zoom -lt 1 ]; then
|
||||
echo "--default-zoom: should be 1 or more (got $zoom)" >&2
|
||||
elif [ $zoom -gt 16 ]; then
|
||||
echo "--default-zoom: should be 16 or less (got $zoom)" >&2
|
||||
else default_zoom=$zoom; fi ;;
|
||||
--default-storage=*)
|
||||
storage="${arg#*=}"
|
||||
# check if 4 chars long
|
||||
if [ ! $(echo "$storage" | wc -c ) -eq 5 ]; then
|
||||
echo "$0: --default-storage: must be 4 characters long"
|
||||
continue
|
||||
fi
|
||||
# then set
|
||||
default_storage="$storage" ;;
|
||||
--noinstall-manpages) install_manpages= ;;
|
||||
--root=*) root="${arg#*=}" ;;
|
||||
--prefix=*) prefix="${arg#*=}" ;;
|
||||
--bindir=*) bindir="${arg#*=}" ;;
|
||||
--mandir=*) mandir="${arg#*=}" ;;
|
||||
*) echo "$arg: didn't read" ;;
|
||||
esac; done
|
||||
|
||||
#******************************************************************************#
|
||||
# Evaluate variables #
|
||||
#******************************************************************************#
|
||||
for var in prefix bindir mandir; do
|
||||
eval $var'='$(eval 'echo $'$var)
|
||||
done
|
||||
|
||||
#******************************************************************************#
|
||||
# Create Makefile configuration #
|
||||
#******************************************************************************#
|
||||
exec 3>&1 1>Makefile.cfg
|
||||
cat <<EOF
|
||||
#!/usr/bin/make -f
|
||||
#******************************************************************************#
|
||||
# Makefile configuration generated by ./configure #
|
||||
#******************************************************************************#
|
||||
# Configuration version and messages configuration
|
||||
CONFIG_VERSION := $version
|
||||
MAKE_FULL_LOG := $make_full_log
|
||||
|
||||
# Build options
|
||||
TARGET := $target
|
||||
DEFAULT_ZOOM := $default_zoom
|
||||
DEFAULT_STORAGE := $default_storage
|
||||
|
||||
# Installation directories
|
||||
IBINDIR := $bindir
|
||||
IMANDIR := $mandir
|
||||
|
||||
# Installation options
|
||||
INSTALL_MANPAGES := $install_manpages
|
||||
|
||||
# End of file.
|
||||
EOF
|
||||
exec 1>&3 3>&-
|
||||
chmod +x Makefile.cfg
|
||||
|
||||
#******************************************************************************#
|
||||
# Finish #
|
||||
#******************************************************************************#
|
||||
echo "Configuration loaded, you can make now."
|
||||
|
||||
# End of file.
|
|
@ -0,0 +1,81 @@
|
|||
P7(1)
|
||||
=====
|
||||
Thomas "Cakeisalie5" Touhey
|
||||
:Email: thomas@touhey.fr
|
||||
:man source: p7
|
||||
:man manual: p7 manual
|
||||
|
||||
NAME
|
||||
----
|
||||
p7 - command-line utility to communicate with casio calculators
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[source,bash]
|
||||
----
|
||||
p7 [-h|--help] [-v|--version] [<command> [<args>]]
|
||||
----
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
p7 is a command-line utility to communicate with machines using casio's
|
||||
communication protocol 7.00, like (almost only, not gonna lie) CASIO
|
||||
fx calculators. For now, it only implements file sending/getting functions
|
||||
on flash memories.
|
||||
|
||||
Available submenus are:
|
||||
|
||||
*send [-f] [-o oncalc.ext] [-d oncalcdir] local.ext*::
|
||||
Send a file to the calculator.
|
||||
*get [-o local.ext] [-d oncalcdir] oncalc.ext*::
|
||||
Get a file from calculator.
|
||||
*copy [-d sourcedir] [-t destdir] source.ext dest.ext*::
|
||||
Copies a file into another on the calculator.
|
||||
*del [-d oncalcdir] oncalc.ext*::
|
||||
Delete a file on the calculator.
|
||||
*ls*::
|
||||
List files on the calculator.
|
||||
*optimize*::
|
||||
Optimize the distant filesystem (defragment).
|
||||
*info*::
|
||||
Dumps information about the calculator.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
Options start with one or two dashes. Some of the options require an additional
|
||||
value next to them.
|
||||
|
||||
*-h, --help*::
|
||||
Display command/subcommand help page and quit.
|
||||
*-v, --version*::
|
||||
Display version and quit.
|
||||
*--device /dev/mydevice0*::
|
||||
The device with which to interact, usually */dev/ttyUSBx*.
|
||||
Will use the first device it finds by default.
|
||||
*--storage abc0*::
|
||||
The storage device with which to interact.
|
||||
*--no-term, --no-exit*::
|
||||
Do not terminate connection when action is completed.
|
||||
*--no-start, --no-init*::
|
||||
Do not initialize connection -- should only be used when
|
||||
*--no-term*/*--no-exit* was used last time p7 was called.
|
||||
*-d DIR, --directory=DIR*::
|
||||
The on-calc directory to work in.
|
||||
Default for this option is device root.
|
||||
*-t DDIR, --to=DIR*::
|
||||
The destination directory (for file copying/moving).
|
||||
Default for this option is device root.
|
||||
*-o OUT, --output=OUT*::
|
||||
For the *get* subcommand, the local file path to store in the output (or
|
||||
'-' for stdout). For the *send* subcommand, the distant filename. For the
|
||||
two subcommands, default is adapted from the input parameter.
|
||||
*-f, --force*::
|
||||
For the *send* subcommand, force overwrite (default is interactive
|
||||
confirmation from user).
|
||||
*-#*::
|
||||
Displays a nice little loading bar for *send* and *get* subcommands. If
|
||||
command is *get* and output is stdout, loading bar won't be displayed.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*libp7*(3)
|
|
@ -0,0 +1,38 @@
|
|||
P7SCREEN(1)
|
||||
===========
|
||||
Thomas "Cakeisalie5" Touhey
|
||||
:Email: thomas@touhey.fr
|
||||
:man source: p7screen
|
||||
:man manual: p7screen manual
|
||||
|
||||
NAME
|
||||
----
|
||||
p7screen - display streamed screen from casio fx calculator
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[source,bash]
|
||||
----
|
||||
p7screen [-h|--help] [-v|--version]
|
||||
----
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
p7screen is a command-line utility to display streamed screen from casio fx
|
||||
calculator, using its communication protocol 7.00 and screenstreaming mode.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
Options start with one or two dashes. Some of the options require an additional
|
||||
value next to them.
|
||||
|
||||
*-h, --help*::
|
||||
Display help page and quit.
|
||||
*-v, --version*::
|
||||
Display version and quit.
|
||||
*-z ZOOM, --zoom=ZOOM*::
|
||||
Change the zoom (will change the window size too).
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*libp7*(3)
|
|
@ -0,0 +1,334 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* args.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : p7 | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/08/21 19:10:17 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include "main.h"
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Help and version messages */
|
||||
/* ************************************************************************** */
|
||||
/* Version message */
|
||||
static const char version_message[] =
|
||||
"P7 v" QUOTE(VERSION) " (licensed under " QUOTE(LICENSE) ")\n"
|
||||
"Made by " QUOTE(AUTHOR) " <" QUOTE(AUTHOR_MAIL) ">.\n"
|
||||
"\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or\n"
|
||||
"FITNESS FOR A PARTICULAR PURPOSE.";
|
||||
|
||||
/* Main help message */
|
||||
static const char help_main[] =
|
||||
"Usage: p7 [--version|-v] [--help|-h] [--no-init] [--no-exit]\n"
|
||||
" [--storage abc0] [--device /dev/omg0]\n"
|
||||
" <subcommand> [options...]\n"
|
||||
"\n"
|
||||
"Subcommands you can use are:\n"
|
||||
" send Send a file to the calculator.\n"
|
||||
" get Get a file from the calculator.\n"
|
||||
" copy Copy a file into another on the calculator.\n"
|
||||
" del Delete a file on the calculator.\n"
|
||||
" reset Reset the flash memory.\n"
|
||||
" optimize Optimize the distant filesystem.\n"
|
||||
" ls List files on the distant filesystem.\n"
|
||||
" info Dump info about the calculator.\n"
|
||||
"\n"
|
||||
"General options:\n"
|
||||
" -h, --help Display the help page of the (sub)command and quit.\n"
|
||||
" -v, --version Display the version message and quit.\n"
|
||||
" --device dev The calculator device (ttyUSBx).\n"
|
||||
" By default, will use the first appropriate device found.\n"
|
||||
" --storage abc0 The storage device with which to interact (fls0, crd0).\n"
|
||||
" Default storage device is '" QUOTE(DEFAULT_STORAGE) "'.\n"
|
||||
" --no-exit Does not terminate connection when action is completed.\n"
|
||||
" --no-init Does not initialize connection (should only be used\n"
|
||||
" when --no-exit was used last time p7 was called).\n"
|
||||
"\n"
|
||||
"Type \"p7 <subcommand> --help\" for some help about the subcommand.\n"
|
||||
"Report bugs to " QUOTE(AUTHOR) " <" QUOTE(AUTHOR_MAIL) ">.";
|
||||
|
||||
/* Sending help message */
|
||||
static const char help_send[] =
|
||||
"Usage: p7 send [-f] [-o <on-calc filename>]\n"
|
||||
" [-d <on-calc directory>] [-#] <local file>\n"
|
||||
"Send a file to the calculator.\n"
|
||||
"\n"
|
||||
"Options are:\n"
|
||||
" -f, --force Overwrite without asking\n"
|
||||
" -o <name> The output filename on the calculator (by default, the same\n"
|
||||
" as the local file)\n"
|
||||
" -d <dir> The directory on-calc in which the file will be stored (by\n"
|
||||
" default, the root directory)\n"
|
||||
" -# Display a nice little loading bar\n"
|
||||
"\n"
|
||||
"Type \"p7 --help\" for other subcommands and general options.";
|
||||
|
||||
/* Getting help message */
|
||||
static const char help_get[] =
|
||||
"Usage: p7 get [-o <local file>]\n"
|
||||
" [-d <on-calc directory>] <on-calc filename>\n"
|
||||
"Request a file from the calculator.\n"
|
||||
"\n"
|
||||
"Options are:\n"
|
||||
" -o <name> The output filename (by default, the same as the on-calc file)\n"
|
||||
" -d <dir> The directory on-calc in which to get the file (by default,\n"
|
||||
" the root directory)\n"
|
||||
" -# Display a nice little loading bar (if output isn't stdout)\n"
|
||||
"\n"
|
||||
"Type \"p7 --help\" for other subcommands and general options.";
|
||||
|
||||
/* Copying help message */
|
||||
static const char help_copy[] =
|
||||
"Usage: p7 copy [-f] [-d <source directory]\n"
|
||||
" [-t <destination directory>] <source file> <dest file>\n"
|
||||
"Copies a file into the other on the calculator.\n"
|
||||
"\n"
|
||||
"Options are:\n"
|
||||
" -d <srcdir> The source directory (by default, the root directory)\n"
|
||||
" -t <dstdir> The dest. directory (by default, the root directory)\n"
|
||||
"\n"
|
||||
"Type \"p7 --help\" for other subcommands and general options.";
|
||||
|
||||
/* Deleting help message */
|
||||
static const char help_del[] =
|
||||
"Usage: p7 del [-d <on-calc directory] <on-calc filename>\n"
|
||||
"Delete a file on the calculator.\n"
|
||||
"\n"
|
||||
"Options are:\n"
|
||||
" -d <dir> The directory on-calc in which to remove the file (by default,\n"
|
||||
" the root directory)\n"
|
||||
"\n"
|
||||
"Type \"p7 --help\" for other subcommands and general options.";
|
||||
|
||||
/* Listing help message */
|
||||
static const char help_ls[] =
|
||||
"Usage: p7 ls\n"
|
||||
"List files on the distant filesystem.\n"
|
||||
"\n"
|
||||
"Type \"p7 --help\" for other subcommands and general options.";
|
||||
|
||||
/* Resetting help message */
|
||||
static const char help_reset[] =
|
||||
"Usage: p7 reset\n"
|
||||
"Reset the distant filesystem.\n"
|
||||
"\n"
|
||||
"Type \"p7 --help\" for other subcommands and general options.";
|
||||
|
||||
/* Optimizing help message */
|
||||
static const char help_optimize[] =
|
||||
"Usage: p7 optimize\n"
|
||||
"Optimize the distant filesystem.\n"
|
||||
"\n"
|
||||
"Type \"p7 --help\" for other subcommands and general options.";
|
||||
|
||||
/* Dumping help message */
|
||||
static const char help_info[] =
|
||||
"Usage: p7 info\n"
|
||||
"Dump information about the calculator.\n"
|
||||
"\n"
|
||||
"Type \"p7 --help\" for other subcommands and general options.";
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Main function */
|
||||
/* ************************************************************************** */
|
||||
/* useful macros */
|
||||
#define sub_init(CMD, NARGS) \
|
||||
args->menu = mn_##CMD; \
|
||||
if (help || aac != 1 + (NARGS)) { \
|
||||
puts(help_##CMD); \
|
||||
return (0); \
|
||||
}
|
||||
|
||||
/**
|
||||
* parse_args:
|
||||
* Args parsing main function.
|
||||
*
|
||||
* Was my very first experiment with getopt.
|
||||
* Then I took an arrow in the knee.
|
||||
*
|
||||
* @arg ac the arguments count
|
||||
* @arg av the arguments values
|
||||
* @arg args the parsed args pointer
|
||||
* @return if it was successfully parsed
|
||||
*/
|
||||
|
||||
int parse_args(int ac, char **av, args_t *args)
|
||||
{
|
||||
/* initialize args */
|
||||
*args = (args_t){
|
||||
.menu = 0,
|
||||
.nicedisp = 0,
|
||||
.dirname = NULL, .filename = NULL,
|
||||
.newdir = NULL, .newname = NULL,
|
||||
.local = NULL, .force = 0,
|
||||
.device = NULL,
|
||||
.storage = QUOTE(DEFAULT_STORAGE),
|
||||
.noinit = 0, .noexit = 0};
|
||||
|
||||
/* define options */
|
||||
char short_options[] = "hvfo:d:t:#";
|
||||
struct option long_options[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"device", required_argument, NULL, 'p'},
|
||||
{"storage", required_argument, NULL, 's'},
|
||||
{"force", no_argument, NULL, 'f'},
|
||||
{"output", required_argument, NULL, 'o'},
|
||||
{"directory", required_argument, NULL, 'd'},
|
||||
{"to", required_argument, NULL, 't'},
|
||||
{"no-init", no_argument, NULL, 'i'},
|
||||
{"no-start", no_argument, NULL, 'i'},
|
||||
{"no-exit", no_argument, NULL, 'e'},
|
||||
{"no-term", no_argument, NULL, 'e'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* get all options */
|
||||
int c; opterr = 0;
|
||||
int help = 0;
|
||||
const char *s_out = NULL, *s_dir = NULL, *s_todir = NULL;
|
||||
while ((c = getopt_long(ac, av, short_options, long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
/* help */
|
||||
case 'h': help = 1; break;
|
||||
/* version */
|
||||
case 'v': puts(version_message); return (0); break;
|
||||
/* force */
|
||||
case 'f': args->force = 1; break;
|
||||
/* nice display */
|
||||
case '#': args->nicedisp = 1; break;
|
||||
|
||||
/* output file (on calc or local) */
|
||||
case 'o': s_out = optarg; break;
|
||||
/* directory name */
|
||||
case 'd': s_dir = optarg; break;
|
||||
/* destination directory name */
|
||||
case 't': s_todir = optarg; break;
|
||||
|
||||
/* device */
|
||||
case 'p': args->device = optarg; break;
|
||||
/* storage */
|
||||
case 's': args->storage = optarg; break;
|
||||
/* force no initialization */
|
||||
case 'i': args->noinit = 1; break;
|
||||
/* force no exit */
|
||||
case 'e': args->noexit = 1; break;
|
||||
|
||||
/* in case of error */
|
||||
case '?':
|
||||
if (optopt == 'o')
|
||||
log("-o, --output: expected an argument\n");
|
||||
else if (optopt == 'd')
|
||||
log("-d, --directory: expected an argument\n");
|
||||
else if (optopt == 't')
|
||||
log("-t, --to: expected an argument\n");
|
||||
else if (optopt == 'p')
|
||||
log("--device: expected an argument\n");
|
||||
else if (optopt == 's')
|
||||
log("--storage: expected an argument\n");
|
||||
else
|
||||
break;
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get non-option arguments (subcommand and parameters) */
|
||||
int aac = ac - optind;
|
||||
char **aav = &av[optind];
|
||||
|
||||
/* get subcommand and things to check */
|
||||
char fpmode[2] = " ";
|
||||
args->localpath = NULL;
|
||||
/* - all subcommands - */
|
||||
if (!aac || !strcmp(aav[0], "help")) {
|
||||
puts(help_main);
|
||||
return (0);
|
||||
} else if (!strcmp(aav[0], "info")) {
|
||||
sub_init(info, 0)
|
||||
} else if (!strcmp(aav[0], "ls")) {
|
||||
sub_init(ls, 0)
|
||||
} else if (!strcmp(aav[0], "reset")) {
|
||||
sub_init(reset, 0)
|
||||
} else if (!strcmp(aav[0], "optimize")) {
|
||||
sub_init(optimize, 0)
|
||||
} else if (!strcmp(aav[0], "send")) {
|
||||
sub_init(send, 1)
|
||||
|
||||
/* put arguments to check */
|
||||
fpmode[0] = 'r';
|
||||
args->localpath = aav[1];
|
||||
args->dirname = s_dir ? s_dir : NULL;
|
||||
if (s_out) args->filename = s_out;
|
||||
else {
|
||||
char *rs = strrchr(args->localpath, '/');
|
||||
args->filename = rs ? rs + 1 : args->localpath;
|
||||
}
|
||||
} else if (!strcmp(aav[0], "get")) {
|
||||
sub_init(get, 1)
|
||||
|
||||
/* put arguments to check */
|
||||
fpmode[0] = 'w';
|
||||
args->filename = aav[1];
|
||||
args->dirname = s_dir ? s_dir : NULL;
|
||||
args->localpath = s_out ? s_out : args->filename;
|
||||
} else if (!strcmp(aav[0], "copy")) {
|
||||
sub_init(copy, 2)
|
||||
|
||||
/* get filename */
|
||||
args->filename = aav[1];
|
||||
args->dirname = s_dir ? s_dir : NULL;
|
||||
args->newname = aav[2];
|
||||
args->newdir = s_todir ? s_todir : NULL;
|
||||
} else if (!strcmp(aav[0], "del")) {
|
||||
sub_init(del, 1)
|
||||
|
||||
/* get filename */
|
||||
args->filename = aav[1];
|
||||
args->dirname = s_dir ? s_dir : NULL;
|
||||
} else {
|
||||
/* unknown subcommand ! */
|
||||
log("Unknown subcommand '%s'.\n", aav[0]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* check string lengths */
|
||||
int noerror = 0;
|
||||
if (args->filename && strnlen(args->filename, 13) == 13)
|
||||
log("On-calc filename must have 12 chars or less!\n");
|
||||
else if (args->newname && strnlen(args->newname, 13) == 13)
|
||||
log("Destination filename must have 12 chars or less!\n");
|
||||
else if (args->dirname && strnlen(args->dirname, 9) == 9)
|
||||
log("On-calc directory name must have 8 chars or less!\n");
|
||||
else if (args->newdir && strnlen(args->newdir, 9) == 9)
|
||||
log("Destination directory name must have 8 chars or less!\n");
|
||||
else if (strnlen(args->storage, 5) != 4)
|
||||
log("Storage device (%s) should be 4 chars long!\n", args->storage);
|
||||
else
|
||||
noerror = 1;
|
||||
if (!noerror) return (0);
|
||||
|
||||
/* check local path */
|
||||
if (args->localpath) {
|
||||
if (fpmode[0] == 'w' && !strcmp(args->localpath, "-"))
|
||||
args->local = stdout;
|
||||
else if (!(args->local = fopen(args->localpath, fpmode))) {
|
||||
log("Could not open local file : %s\n", strerror(errno));
|
||||
if (fpmode[0] == 'w')
|
||||
unlink(args->localpath);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* everything went well */
|
||||
return (1);
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* dump.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : p7 | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/08/26 20:14:25 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include "main.h"
|
||||
#include <libp7/packetio.h>
|
||||
#define info (response->ack)
|
||||
|
||||
/**
|
||||
* dump:
|
||||
* Dump calculator information.
|
||||
*
|
||||
* @arg handle the libp7 handle
|
||||
* @return the error code (0 if ok).
|
||||
*/
|
||||
|
||||
int dump(p7_handle_t *handle)
|
||||
{
|
||||
/* get response buffer */
|
||||
const p7_packet_t *response = p7_get_response(handle);
|
||||
|
||||
/* send get info command and check response */
|
||||
int err;
|
||||
if ((err = p7_send_cmdsys_getinfo(handle)))
|
||||
return (err);
|
||||
if (response->type != p7_pt_ack || !response->ack.extended)
|
||||
return (p7_error_unknown);
|
||||
|
||||
/* dump information */
|
||||
/* - wiped out things - */
|
||||
if (info.preprog_rom_wiped)
|
||||
log("Warning: Preprogrammed ROM information looks wiped out !\n");
|
||||
if (info.bootcode_wiped)
|
||||
log("Warning: Bootcode information looks wiped out !\n");
|
||||
|
||||
/* - preprogrammed ROM - */
|
||||
if (!info.preprog_rom_wiped) {
|
||||
printf("Preprogrammed ROM capacity : %luo\n", info.preprog_rom_capacity);
|
||||
printf("Preprogrammed ROM version : %02u.%02u.%02u\n",
|
||||
info.preprog_rom_version.major, info.preprog_rom_version.minor,
|
||||
info.preprog_rom_version.rev);
|
||||
printf("Preprogrammed ROM type : \"%s\"\n", info.preprog_rom_version.type);
|
||||
}
|
||||
/* - ROM - */
|
||||
printf("ROM capacity : %luo\n", info.flash_rom_capacity);
|
||||
/* - RAM - */
|
||||
printf("RAM capacity : %luo\n", info.ram_capacity);
|
||||
/* - Bootcode - */
|
||||
if (!info.bootcode_wiped) {
|
||||
printf("Bootcode version : %02u.%02u.%02u\n",
|
||||
info.bootcode_version.major, info.bootcode_version.minor,
|
||||
info.bootcode_version.rev);
|
||||
printf("Bootcode type : \"%s\"\n", info.bootcode_version.type);
|
||||
printf("Bootcode offset : %#08lx\n", info.bootcode_offset);
|
||||
printf("Bootcode size : %luo\n", info.bootcode_size);
|
||||
}
|
||||
/* - OS - */
|
||||
printf("OS version : %02u.%02u.%02u\n",
|
||||
info.os_version.major, info.os_version.minor, info.os_version.rev);
|
||||
printf("OS type : \"%s\"\n", info.os_version.type);
|
||||
printf("OS offset : %#08lx\n", info.os_offset);
|
||||
printf("OS size : %luo\n", info.os_size);
|
||||
/* - Miscallenous info - */
|
||||
printf("Protocol version : %01u.%02u\n",
|
||||
info.protocol_version.major, info.protocol_version.minor);
|
||||
printf("Product ID : \"%s\"\n", info.product_id);
|
||||
printf("Username : \"%s\"\n", info.username);
|
||||
printf("Hardware ID : \"%s\"\n", info.hwid);
|
||||
printf("CPU ID : \"%s\"\n", info.cpuid);
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* main.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : p7 | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/08/21 16:50:46 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include "main.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Error messages */
|
||||
/* ************************************************************************** */
|
||||
/* Couldn't initialize connexion with the calculator. */
|
||||
static const char error_noconnexion[] =
|
||||
"Could not connect to the calculator.\n"
|
||||
"- Is it plugged in and in receive mode?\n"
|
||||
"- Have you tried changing the cable?\n";
|
||||
|
||||
/* Calculator was disconnected. */
|
||||
static const char error_disconnected[] =
|
||||
"Lost connexion to the calculator!\n"
|
||||
"Please reconnect the calculator, rerun receive mode and try again.\n";
|
||||
|
||||
/* Calculator was found but program wasn't allowed to communicate with it. */
|
||||
static const char error_noaccess[] =
|
||||
"Could not get access to the calculator.\n"
|
||||
"Install the appropriate udev rule, or run as root.\n";
|
||||
|
||||
/* Command was unsupported. */
|
||||
static const char error_unsupported[] =
|
||||
"The command is unsupported by the calculator.\n"
|
||||
"- Does the calculator have mass storage?\n"
|
||||
"- Does its OS allow the use of it?\n"
|
||||
"- Is it in Receive Mode (and not in OS Update)?\n";
|
||||
|
||||
/* The device didn't exist. */
|
||||
static const char error_unsupported_device[] =
|
||||
"Device '%s' is not supported by the device.\n";
|
||||
|
||||
/* The calculator acted in an unplanned way. */
|
||||
static const char error_unplanned[] =
|
||||
"The calculator didn't act as planned.\n"
|
||||
"Stop receive mode on calculator and start it again before re-running p7.\n"
|
||||
"Error was: %s\n";
|
||||
|
||||
/* Requested file didn't exist. */
|
||||
static const char error_noexists[] =
|
||||
"Requested file didn't exist.\n";
|
||||
|
||||
/* Sent file cannot be empty. */
|
||||
static const char error_empty[] =
|
||||
"Can't send an empty file!\n";
|
||||
|
||||
/* Not enough space left on the calculator. */
|
||||
static const char error_nospace[] =
|
||||
"Not enough space on the calculator for the file you're trying to send.\n"
|
||||
"If you believe there should be, try optimizing (OPT) on the calculator\n"
|
||||
"(in MEMORY menu) and try again.\n";
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Auxiliary functions */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* sendfile_confirm:
|
||||
* Confirm file sending.
|
||||
*
|
||||
* @return if the file overwriting is confirmed
|
||||
*/
|
||||
|
||||
static int sendfile_display_initialized = 0;
|
||||
static int sendfile_confirm(void)
|
||||
{
|
||||
/* Print stuff */
|
||||
printf("It looks like the file already exists on the calculator.\n");
|
||||
printf("Overwrite ? ([n]/y) ");
|
||||
|
||||
/* Get the line */
|
||||
char *line = NULL; size_t n;
|
||||
ssize_t err = getline(&line, &n, stdin);
|
||||
if (err < 0) return (0);
|
||||
|
||||
/* Check if should overwrite */
|
||||
int overwrite = err >= 1 && !strncmp(line, "y", 1);
|
||||
free(line);
|
||||
return (overwrite);
|
||||
}
|
||||
|
||||
/**
|
||||
* sendfile_display:
|
||||
* File sending nice display.
|
||||
*
|
||||
* "Initialization" is when id > total (called in main).
|
||||
*
|
||||
* @arg id data packet ID
|
||||
* @arg total total number of data packets
|
||||
*/
|
||||
|
||||
static void sendfile_display(p7ushort_t id, p7ushort_t total)
|
||||
{
|
||||
/* here's the buffer */
|
||||
static char buf[50] =
|
||||
"\r|---------------------------------------| 00.00%";
|
||||
static char *bar = &buf[2];
|
||||
|
||||
/* initialize */
|
||||
static int pos;
|
||||
|
||||
/* if is initialize, fill */
|
||||
if (id > total) {
|
||||
pos = 0;
|
||||
/* indicate that is has been initialized */
|
||||
sendfile_display_initialized = 1;
|
||||
/* put initial buffer */
|
||||
fputs(buf, stdout);
|
||||
/* save cursor position */
|
||||
fputs("\x1B[s", stdout);
|
||||
/* we're done */
|
||||
return ;
|
||||
}
|
||||
|
||||
/* id and total start from 1, let them start from zero */
|
||||
id--; total--;
|
||||
|
||||
/* modify buffer */
|
||||
/* - # - */
|
||||
int current = 38 * id / total;
|
||||
while (pos <= current) bar[pos++] = '#';
|
||||
/* - % - */
|
||||
unsigned int percent = 10000 * id / total;
|
||||
sprintf(&buf[43], "%02u.%02u", percent / 100, percent % 100);
|
||||
|
||||
/* put it */
|
||||
fputs(buf, stdout);
|
||||
/* force cursor position */
|
||||
fputs("\x1B""8", stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
* print_file_info:
|
||||
* File listing callback.
|
||||
*
|
||||
* @arg dir the directory in which the file is stored (NULL if root)
|
||||
* @arg name the filename
|
||||
* @arg size the filesize
|
||||
*/
|
||||
|
||||
static void print_file_info(const char *dir, const char *name, p7uint_t size)
|
||||
{
|
||||
/* initialize buffer */
|
||||
static char buf[45];
|
||||
|
||||
/* clean buffer */
|
||||
memset(buf, ' ', 28);
|
||||
/* put path in buffer */
|
||||
char *b = buf;
|
||||
if (dir) b = stpcpy(b, dir), *b++ = '/';
|
||||
b = stpcpy(b, name), *b = ' ';
|
||||
/* put size */
|
||||
sprintf(&buf[28], "% 10luo", size);
|
||||
|
||||
/* put the string */
|
||||
puts(buf);
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Main function */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* main:
|
||||
* User entry point of the program.
|
||||
*
|
||||
* @arg ac arguments count
|
||||
* @arg av arguments values
|
||||
* @return return code (0 if ok)
|
||||
*/
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
/* Parse args */
|
||||
args_t args;
|
||||
if (!parse_args(ac, av, &args))
|
||||
return (0);
|
||||
|
||||
/* Initialize libp7 and communication */
|
||||
p7_handle_t *handle; int err;
|
||||
if (args.device) err = p7_cinit(&handle, 1, !args.noinit, args.device, 0);
|
||||
else err = p7_init(&handle, 1, !args.noinit);
|
||||
if (err) {
|
||||
/* display error */
|
||||
switch (err) {
|
||||
case p7_error_nocalc: log(error_noconnexion); break;
|
||||
case p7_error_noaccess: log(error_noaccess); break;
|
||||
default: log(error_unplanned, p7_strerror(err)); break;
|
||||
}
|
||||
|
||||
/* closing, removing if necessary */
|
||||
if (args.menu == mn_send)
|
||||
fclose(args.local);
|
||||
if (args.menu == mn_get && args.local != stdout) {
|
||||
fclose(args.local);
|
||||
unlink(args.localpath);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Check according to menu */
|
||||
switch (args.menu) {
|
||||
case mn_send:
|
||||
err = p7_sendfile(handle, args.local, args.dirname, args.filename,
|
||||
args.storage, 1, args.force ? NULL : &sendfile_confirm,
|
||||
args.nicedisp ? &sendfile_display : NULL);
|
||||
break;
|
||||
case mn_get:
|
||||
err = p7_reqfile(handle, args.local, args.dirname, args.filename,
|
||||
args.storage, args.nicedisp && args.local != stdout
|
||||
? &sendfile_display : NULL);
|
||||
if (err) unlink(args.localpath);
|
||||
break;
|
||||
case mn_copy:
|
||||
err = p7_copyfile(handle, args.dirname, args.filename,
|
||||
args.newdir, args.newname, args.storage);
|
||||
break;
|
||||
case mn_del:
|
||||
err = p7_delfile(handle, args.dirname, args.filename,
|
||||
args.storage);
|
||||
break;
|
||||
case mn_ls:
|
||||
err = p7_lsfiles(handle, args.storage, &print_file_info);
|
||||
break;
|
||||
case mn_reset:
|
||||
err = p7_resetflash(handle, args.storage);
|
||||
break;
|
||||
case mn_optimize:
|
||||
err = p7_optimize(handle, args.storage);
|
||||
break;
|
||||
case mn_info:
|
||||
err = dump(handle);
|
||||
break;
|
||||
}
|
||||
|
||||
/* put error */
|
||||
if (err && err != p7_error_denied_overwrite) {
|
||||
if (sendfile_display_initialized)
|
||||
puts("\b\b\b\b\b\bError !");
|
||||
|
||||
/* close the file */
|
||||
if (args.local) fclose(args.local);
|
||||
if (args.menu == mn_get && args.local != stdout)
|
||||
unlink(args.localpath);
|
||||
|
||||
/* put the error string */
|
||||
switch (err) {
|
||||
case p7_error_fullmem: log(error_nospace); break;
|
||||
case p7_error_empty: log(error_empty); break;
|
||||
case p7_error_notfound: log(error_noexists); break;
|
||||
case p7_error_nocalc: log(error_disconnected); break;
|
||||
case p7_error_unsupported: log(error_unsupported); break;
|
||||
case p7_error_unsupported_device:
|
||||
log(error_unsupported_device, args.device); break;
|
||||
default: log(error_unplanned, p7_strerror(err));
|
||||
}
|
||||
|
||||
/* return that an error has occured */
|
||||
return (1);
|
||||
}
|
||||
|
||||
puts("\b\b\b\b\b\bTransfer complete.");
|
||||
if (args.local) fclose(args.local);
|
||||
|
||||
/* terminate communication and de-initialize libp7 */
|
||||
p7_exit(handle, !args.noexit);
|
||||
|
||||
/* Then we're good */
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* main.h |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : p7 | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/08/21 16:50:57 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#ifndef MAIN_H
|
||||
# define MAIN_H
|
||||
# define Q(x) #x
|
||||
# define QUOTE(x) Q(x)
|
||||
# include <stdio.h>
|
||||
# include <libp7.h>
|
||||
# define log(S, ...) fprintf(stderr, S, ##__VA_ARGS__)
|
||||
|
||||
/* Menus */
|
||||
typedef enum {
|
||||
mn_send, mn_get, mn_copy, mn_del, mn_ls, mn_reset, mn_optimize,
|
||||
mn_info
|
||||
} menu_t;
|
||||
|
||||
/* Arguments */
|
||||
typedef struct {
|
||||
/* basic things */
|
||||
menu_t menu;
|
||||
int nicedisp;
|
||||
|
||||
/* for file transferring menus */
|
||||
const char *dirname, *filename;
|
||||
const char *newdir, *newname;
|
||||
FILE *local; const char *localpath;
|
||||
int force;
|
||||
|
||||
/* other options */
|
||||
const char *device;
|
||||
const char *storage;
|
||||
int noinit;
|
||||
int noexit;
|
||||
} args_t;
|
||||
|
||||
/* Parsing function */
|
||||
int parse_args(int ac, char **av, args_t *args);
|
||||
|
||||
/* Dumping function */
|
||||
int dump(p7_handle_t *handle);
|
||||
|
||||
#endif /* MAIN_H */
|
|
@ -0,0 +1,118 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* args.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : p7screen | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/06 15:35:29 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include "main.h"
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Help and version messages */
|
||||
/* ************************************************************************** */
|
||||
/* Version message */
|
||||
static const char version_message[] =
|
||||
"P7SCREEN v" QUOTE(VERSION) " (licensed under " QUOTE(LICENSE) ")\n"
|
||||
"Made by " QUOTE(AUTHOR) " <" QUOTE(AUTHOR_MAIL) ">.\n"
|
||||
"\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or\n"
|
||||
"FITNESS FOR A PARTICULAR PURPOSE.";
|
||||
|
||||
/* Help message */
|
||||
static const char help_main[] =
|
||||
"Usage: p7screen [--help|-h] [--version|-v]\n"
|
||||
" [--device /dev/omg0]\n"
|
||||
"\n"
|
||||
"Displays the streamed screen from a CASIO fx calculator.\n"
|
||||
"\n"
|
||||
"Options are:\n"
|
||||
" -h, --help Display this help page\n"
|
||||
" -v, --version Displays the version\n"
|
||||
" --device dev The calculator device (/dev/ttyUSBx).\n"
|
||||
" By default, will use the first appropriate device found.\n"
|
||||
" -z ZOOM Change the zoom (1 to 16)\n"
|
||||
" By default, the zoom will be " QUOTE(DEFAULT_ZOOM) ".\n"
|
||||
"\n"
|
||||
"Report bugs to " QUOTE(AUTHOR) " <" QUOTE(AUTHOR_MAIL) ">.";
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Main function */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* parse_args:
|
||||
* Args parsing main function.
|
||||
*
|
||||
* Inspired of the edits of my first experiment with getopt.
|
||||
* Interesting, huh?
|
||||
*
|
||||
* @arg ac the arguments count
|
||||
* @arg av the arguments values
|
||||
* @arg device pointer to the device
|
||||
* @arg zoom pointer the zoom
|
||||
* @arg args the parsed args pointer
|
||||
* @return 0 if ok, other if not.
|
||||
*/
|
||||
|
||||
int parse_args(int ac, char **av, const char **device, int *zoom)
|
||||
{
|
||||
/* initialize args */
|
||||
*device = NULL;
|
||||
*zoom = DEFAULT_ZOOM;
|
||||
|
||||
/* define options */
|
||||
const char short_options[] = "hvz:";
|
||||
const struct option long_options[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"device", required_argument, NULL, 'd'},
|
||||
{"zoom", required_argument, NULL, 'z'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* get all options */
|
||||
int c; opterr = 0;
|
||||
int help = 0, version = 0;
|
||||
while ((c = getopt_long(ac, av, short_options, long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
/* help */
|
||||
case 'h': help = 1; break;
|
||||
/* version */
|
||||
case 'v': version = 1; break;
|
||||
/* device */
|
||||
case 'd': *device = optarg; break;
|
||||
/* zoom */
|
||||
case 'z':
|
||||
*zoom = atoi(optarg);
|
||||
if (*zoom <= 0 || *zoom > 16) {
|
||||
log("-z, --zoom: should be between 1 and 16");
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
|
||||
/* error (ignore) */
|
||||
case '?':
|
||||
if (optopt == 'z')
|
||||
log("-z, --zoom: expected an argument\n");
|
||||
else if (optopt == 'd')
|
||||
log("--device: expected an argument\n");
|
||||
else
|
||||
break;
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* check if there is any parameter */
|
||||
if (ac - optind)
|
||||
help = 1;
|
||||
|
||||
/* print help or version if required, and return */
|
||||
if (version) puts(version_message);
|
||||
else if (help) puts(help_main);
|
||||
else return (0);
|
||||
return (1);
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* main.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : p7screen | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/06 15:35:22 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include "main.h"
|
||||
#include <string.h>
|
||||
#include <libp7.h>
|
||||
#include <SDL.h>
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Error messages */
|
||||
/* ************************************************************************** */
|
||||
/* Couldn't initialize connexion to calculator. */
|
||||
static const char error_noconnexion[] =
|
||||
"Could not connect to the calculator.\n"
|
||||
"- Is it plugged in and in PROJ mode?\n"
|
||||
"- Have you tried unplugging, plugging and selecting Projector on pop-up?\n"
|
||||
"- Have you tried changing the cable?\n";
|
||||
|
||||
/* Calculator was found but program wasn't allowed to communicate with it. */
|
||||
static const char error_noaccess[] =
|
||||
"Could not get access to the calculator.\n"
|
||||
"Install the appropriate udev rule, or run as root.\n";
|
||||
|
||||
/* The calculator acted in a weird way. */
|
||||
static const char error_unplanned[] =
|
||||
"The calculator didn't act as planned.\n"
|
||||
"Stop receive mode on calculator and start it again before re-running p7screen.\n"
|
||||
"Error was: %s\n";
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Globals */
|
||||
/* ************************************************************************** */
|
||||
/* The z00m (omG) */
|
||||
static int zoom;
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Auxiliary functions */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* display_callback:
|
||||
* The main callback for screen streaming.
|
||||
*
|
||||
* @arg w the width of the received image
|
||||
* @arg h the height of the received image
|
||||
* @arg pixels the image data
|
||||
* @return if reception should continue
|
||||
*/
|
||||
|
||||
static int display_callback(int w, int h, uint32_t **pixels)
|
||||
{
|
||||
/* create screen if there isn't one */
|
||||
static SDL_Surface *screen = NULL;
|
||||
static int saved_w = 0, saved_h = 0;
|
||||
if (!screen || saved_w != w || saved_h != h) {
|
||||
/* create the window */
|
||||
if (!(screen = SDL_SetVideoMode(w * zoom, h * zoom, 32,
|
||||
SDL_SWSURFACE | SDL_DOUBLEBUF))) {
|
||||
log("Couldn't set video mode: %s\n", SDL_GetError());
|
||||
return (0);
|
||||
}
|
||||
SDL_WM_SetCaption("P7screen", NULL);
|
||||
|
||||
/* save data and display message */
|
||||
saved_w = w; saved_h = h;
|
||||
puts("Turn off your calculator (SHIFT+AC) when you have finished.");
|
||||
}
|
||||
|
||||
/* edit screen */
|
||||
/* - lock it - */
|
||||
SDL_LockSurface(screen);
|
||||
/* - copy - */
|
||||
uint32_t *px = (uint32_t*)screen->pixels;
|
||||
int linesize = w * zoom;
|
||||
for (int y = 0; y < h; y++) {
|
||||
uint32_t *refline = px;
|
||||
for (int x = 0; x < w; x++) {
|
||||
uint32_t pixel = pixels[y][x];
|
||||
for (int zx = 0; zx < zoom; zx++)
|
||||
*px++ = pixel;
|
||||
}
|
||||
for (int zy = 1; zy < zoom; zy++) {
|
||||
memcpy(px, refline, linesize * sizeof(uint32_t));
|
||||
px += linesize;
|
||||
}
|
||||
}
|
||||
/* - unlock it - */
|
||||
SDL_UnlockSurface(screen);
|
||||
|
||||
/* update screen */
|
||||
SDL_Flip(screen);
|
||||
|
||||
/* check if user has pressed escape or cross */
|
||||
SDL_Event event;
|
||||
SDL_PollEvent(&event);
|
||||
if ((event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)
|
||||
|| event.type == SDL_QUIT)
|
||||
return (0);
|
||||
|
||||
/* continue! */
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Main function */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* main:
|
||||
* Entry point of the program.
|
||||
*
|
||||
* @arg ac arguments count
|
||||
* @arg av arguments values
|
||||
* @return if it worked (0 if OK)
|
||||
*/
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
/* parse args */
|
||||
const char *device;
|
||||
if (parse_args(ac, av, &device, &zoom))
|
||||
return (0);
|
||||
|
||||
/* Initialize SDL */
|
||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||
log("Failed to initialize SDL: %s\n", SDL_GetError());
|
||||
return (3);
|
||||
}
|
||||
atexit(SDL_Quit);
|
||||
|
||||
/* Initialize libp7 */
|
||||
p7_handle_t *handle; int err;
|
||||
if (device) err = p7_cinit(&handle, 0, 0, device, 0);
|
||||
else err = p7_init(&handle, 0, 0);
|
||||
if (err) {
|
||||
/* display error */
|
||||
switch (err) {
|
||||
case p7_error_nocalc: log(error_noconnexion); break;
|
||||
case p7_error_noaccess: log(error_noaccess); break;
|
||||
default: log(error_unplanned, p7_strerror(err)); break;
|
||||
}
|
||||
|
||||
/* return */
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* receive screen */
|
||||
if ((err = p7_getscreen(handle, &display_callback))
|
||||
&& err != p7_error_nocalc) {
|
||||
switch (err) {
|
||||
case p7_error_timeout: log(error_noconnexion); break;
|
||||
default: log(error_unplanned, p7_strerror(err)); break;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* close */
|
||||
p7_exit(handle, 0);
|
||||
|
||||
/* everything went well */
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* main.h |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : p7screen | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/06 15:35:37 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#ifndef MAIN_H
|
||||
# define MAIN_H
|
||||
# include <stdio.h>
|
||||
# define Q(x) #x
|
||||
# define QUOTE(x) Q(x)
|
||||
# define log(S, ...) fprintf(stderr, S, ##__VA_ARGS__)
|
||||
|
||||
/* all functions */
|
||||
int parse_args(int ac, char **av, const char **device, int *zoom);
|
||||
|
||||
#endif /* MAIN_H */
|
Reference in New Issue