Compare commits

...

80 Commits

Author SHA1 Message Date
9ee3344c46 tests: simplify the pkgconfig test script 2025-03-14 11:36:50 +01:00
c489093b0e Register new targets 2025-03-14 11:27:32 +01:00
fdf6d51887 tests: move the pkg-config test to a separate script 2025-03-14 11:25:29 +01:00
5465283ff4 tests: code cleanup 2025-03-14 11:11:57 +01:00
3856cc9748 Update the copyright notice 2025-03-14 11:11:45 +01:00
031887ebf2 tests: improve the output on macOS 2025-03-14 11:11:45 +01:00
7195117804 tools: register more dependencies 2025-03-13 12:28:15 +01:00
10513104f0 libApp: partially fix the build with OBJDIR 2025-03-13 12:25:01 +01:00
092937a5d0 Update the copyright notice 2025-03-13 12:20:28 +01:00
d0e1dbd2e3 AppBroker: let the program name be changed 2025-03-13 12:19:55 +01:00
8d2424ed40 AppClient: code cleanup 2025-03-13 12:11:45 +01:00
e455db85fd tools: register the new target 2025-03-13 12:11:31 +01:00
314ea122b8 tools: introduce AppTransport
This tool currently allows listing the transport protocols available.
2025-03-13 12:10:55 +01:00
91a6f38dc8 AppClient: re-indent 2025-03-13 11:34:32 +01:00
f63438e736 AppClient: avoid a couple compilation warnings 2025-03-13 11:33:08 +01:00
fa419377f5 AppClient: use unsigned for unsigned return values 2025-03-13 11:29:06 +01:00
386fc440fd Update the copyright notice 2025-03-13 11:28:51 +01:00
1fd59a5f41 AppClient: use PROGNAME_APPCLIENT 2025-03-13 11:28:35 +01:00
41e364ecef transport: sort targets before sources 2025-03-13 10:46:05 +01:00
45d6dc6774 Update the copyright notice 2025-03-13 10:44:00 +01:00
e8e65fe2c0 transport: set the plug-in descriptions 2025-03-13 10:43:42 +01:00
deaae04315 Update the copyright notice 2025-03-12 17:11:01 +01:00
04e8f21cd2 App: provide the path to the plug-ins 2025-03-12 17:09:57 +01:00
a984ce1452 deforaos-c-ci_ubuntu-latest: use checkout v4 2024-05-26 00:07:50 +02:00
8120944d5a Code cleanup 2024-04-30 02:25:04 +02:00
c19142336c Update the copyright notice 2024-04-30 02:24:50 +02:00
87c629e9c9 libApp: fix the build
This reflects the new Config API.
2024-04-30 02:23:44 +02:00
462136fbd8 Update the scripts from DeforaOS configure 2024-04-30 02:19:35 +02:00
5ade15bd7b deforaos-c-ci_ubuntu: fix bootstrapping libMarshall 2022-05-20 03:51:13 +02:00
eb05528c7f deforaos-c-ci_ubuntu: bootstrap configure with its configuration 2022-05-20 03:43:30 +02:00
f062054e9f Create deforaos-c-ci_ubuntu-latest.yml 2022-05-20 03:39:21 +02:00
8a7456eed0 Update the copyright notice 2022-05-17 23:40:45 +02:00
6643a3e217 Fix the build with the latest libSystem 2022-05-17 23:40:34 +02:00
83a1bf0b71 Update the scripts from DeforaOS configure 2021-09-17 10:20:03 +02:00
dca219b7b6 Import the newer scripts from DeforaOS configure 2020-11-19 02:48:39 +01:00
95d45851b5 Update the copyright notice 2020-11-05 21:10:31 +01:00
6968cfd261 Provide the AppServerClient in AppInterface calls 2020-11-05 21:09:45 +01:00
b922ec51fb Avoid a compilation warning 2020-11-05 21:08:14 +01:00
aa76254a1c Fix an undefined free() 2020-11-05 18:51:33 +01:00
57ae51b11b Update the copyright notice 2020-04-14 14:24:25 +02:00
892b8100da Match the latest libSystem API 2020-04-14 14:23:41 +02:00
147f025360 Update the copyright notice 2020-04-14 13:04:30 +02:00
06e16fbad6 Use more logical values for AMCD_{IN,IN_OUT,OUT} 2020-04-14 13:03:38 +02:00
cbc93775d5 Actually report connection errors 2020-04-13 09:53:39 +02:00
d0ec7a589f Report more errors 2020-04-13 08:39:58 +02:00
3d6a6705c3 Reflect the API change in libMarshall 2020-04-13 08:04:45 +02:00
874d7a8fee Only quit Event loops for clients 2020-03-29 21:19:52 +02:00
c4e1784816 Look for calls and callbacks according to the mode 2020-03-29 11:04:47 +02:00
eb3fe28e7c Keep the network address for the lifetime of the plug-in 2020-03-25 21:45:42 +01:00
36e95e95d4 Fix the labels for the Variable types 2020-03-25 21:33:47 +01:00
5dced389d5 Code cleanup 2020-03-25 21:17:36 +01:00
8795cceaf0 Update the copyright notice 2020-03-25 21:17:18 +01:00
1132c45143 Check and handle more errors
While there avoid some potential memory leaks.
2020-03-25 20:29:20 +01:00
06e33a406f Update the copyright notice 2020-03-25 20:14:41 +01:00
54d57b441f Check for errors in appmessage_new_call() 2020-03-25 20:14:28 +01:00
7f4451b9a0 Update the copyright notice 2020-03-25 09:35:31 +01:00
688d40c1ad Attempt to really re-implement the AppClient
This is still very messy... :(
2020-03-25 09:35:04 +01:00
607c9b00f3 Update the copyright notice 2020-03-12 02:28:38 +01:00
04b3177051 Replace "FIXME" with "TODO" in the template transport 2020-03-12 02:28:23 +01:00
cae0ac9453 Do not run any test by default 2020-03-12 02:27:13 +01:00
3473d9c713 Register the Gtk-Doc targets 2020-02-13 11:02:56 +01:00
6fbfc9b274 Import the latest gtkdoc.sh from DeforaOS configure 2020-02-13 11:01:53 +01:00
37d3714060 Register config.ent 2020-02-13 09:34:17 +01:00
91c2a0aadf Use config.ent for the Gtk-Doc documentation 2020-02-13 09:33:43 +01:00
b4cd799664 Import the latest gtkdoc.sh from DeforaOS configure 2020-02-13 08:59:50 +01:00
6ea20eb1c5 Register three targets 2020-01-17 20:52:46 +01:00
985268a76a Stick to the default stack protector 2020-01-17 20:51:30 +01:00
2f45a85464 Register a missing dependency 2020-01-17 20:49:19 +01:00
47f6049119 Correct a dependency 2020-01-17 20:48:34 +01:00
56fb20d8fd Code cleanup 2020-01-17 20:47:19 +01:00
8b815c58bf Give a chance to cross-compilation to work 2020-01-17 20:47:09 +01:00
07e00a809a Update the copyright notice 2020-01-17 20:40:44 +01:00
cd01e8468e Fix building the tests with OBJDIR 2020-01-17 20:40:35 +01:00
c1d0cf8e3f Register a few more files 2020-01-17 20:35:40 +01:00
ad55e78919 Update the copyright notice 2020-01-17 20:28:03 +01:00
74e061a9a7 Let the tests work without installing libApp first 2020-01-17 20:27:12 +01:00
b20c1301fc Sort the targets and source files separately 2020-01-17 20:14:02 +01:00
f3dcfaf146 Link to HTTPS websites 2019-09-28 03:43:13 +02:00
87c85bd38c About to release libApp 0.3.2 2019-09-28 03:40:36 +02:00
ae5235b7a7 Install the README file by default 2019-09-28 03:39:55 +02:00
51 changed files with 1902 additions and 743 deletions

View File

@ -0,0 +1,29 @@
name: DeforaOS C CI (ubuntu-latest)
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: bootstrap libSystem
run: git clone https://github.com/DeforaOS/libSystem.git libSystem && for dir in include data src tools; do (cd libSystem/$dir && make PREFIX="$HOME/opt/DeforaOS" install); done
- name: bootstrap configure
run: git clone https://github.com/DeforaOS/configure.git configure && for dir in data src; do (cd configure/$dir && PKG_CONFIG_PATH="$HOME/opt/DeforaOS/lib/pkgconfig" make PREFIX="$HOME/opt/DeforaOS" install); done
- name: bootstrap libMarshall
run: git clone https://github.com/DeforaOS/libMarshall.git libMarshall && $HOME/opt/DeforaOS/bin/configure -p "$HOME/opt/DeforaOS" libMarshall && for dir in include data src tools; do (cd libMarshall/$dir && PKG_CONFIG_PATH="$HOME/opt/DeforaOS/lib/pkgconfig" make install); done
- name: configure
run: $HOME/opt/DeforaOS/bin/configure -p "$HOME/opt/DeforaOS"
- name: make
run: PKG_CONFIG_PATH="$HOME/opt/DeforaOS/lib/pkgconfig" make CCSHARED="cc -shared"
- name: make tests
run: PKG_CONFIG_PATH="$HOME/opt/DeforaOS/lib/pkgconfig" make CCSHARED="cc -shared" tests
- name: make distcheck
run: PKG_CONFIG_PATH="$HOME/opt/DeforaOS/lib/pkgconfig" make CCSHARED="cc -shared" distcheck

1
.gitignore vendored
View File

@ -6,5 +6,6 @@ Makefile
*.o
*.so
*.so.*
/config.ent
/config.h
/config.sh

View File

@ -17,15 +17,14 @@ Dependencies for libApp
libApp depends on the following software components to build:
- pkg-config from the freedesktop software collection, as found in most
software distributions already; otherwise at
<http://www.freedesktop.org/wiki/Software/pkg-config/>
<https://www.freedesktop.org/wiki/Software/pkg-config/> (or a compatible
replacement)
- libSystem from the DeforaOS Project, as found at
<http://www.defora.org/os/project/27/libSystem> if not packaged for your
system.
<https://www.defora.org/os/project/27/libSystem>
- libMarshall from the DeforaOS Project, as found at
<http://www.defora.org/os/project/4400/libMarshall> if not packaged for your
system.
<https://www.defora.org/os/project/4400/libMarshall>
- configure from the DeforaOS Project, likewise found at
<http://www.defora.org/os/project/16/configure>
<https://www.defora.org/os/project/16/configure>
Configuring libApp

View File

@ -1,6 +1,6 @@
#!/bin/sh
#$Id$
#Copyright (c) 2011-2019 Pierre Pronchery <khorben@defora.org>
#Copyright (c) 2011-2022 Pierre Pronchery <khorben@defora.org>
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
@ -27,18 +27,114 @@
#variables
CONFIGSH="${0%/pkgconfig.sh}/../config.sh"
PREFIX="/usr/local"
DEBUG="_debug"
DEVNULL="/dev/null"
PROGNAME="pkgconfig.sh"
#executables
INSTALL="install -m 0644"
DEBUG="_debug"
INSTALL="install"
MKDIR="mkdir -m 0755 -p"
RM="rm -f"
SED="sed"
[ -f "$CONFIGSH" ] && . "$CONFIGSH"
#functions
#pkgconfig
_pkgconfig()
{
#check the variables
if [ -z "$PACKAGE" ]; then
_error "The PACKAGE variable needs to be set"
return $?
fi
if [ -z "$VERSION" ]; then
_error "The VERSION variable needs to be set"
return $?
fi
[ -z "$BINDIR" ] && BINDIR="$PREFIX/bin"
[ -z "$DATADIR" ] && DATADIR="$PREFIX/share"
[ -z "$INCLUDEDIR" ] && INCLUDEDIR="$PREFIX/include"
[ -z "$LIBDIR" ] && LIBDIR="$PREFIX/lib"
[ -z "$LIBEXECDIR" ] && LIBEXECDIR="$PREFIX/libexec"
[ -z "$MANDIR" ] && MANDIR="$DATADIR/man"
[ -z "$SBINDIR" ] && SBINDIR="$PREFIX/sbin"
if [ -z "$SYSCONFDIR" ]; then
SYSCONFDIR="$PREFIX/etc"
[ "$PREFIX" = "/usr" ] && SYSCONFDIR="/etc"
fi
PKGCONFIG="$PREFIX/lib/pkgconfig"
while [ $# -gt 0 ]; do
target="$1"
shift
#clean
[ "$clean" -ne 0 ] && continue
#uninstall
if [ "$uninstall" -eq 1 ]; then
$DEBUG $RM -- "$PKGCONFIG/$target" || return 2
continue
fi
#install
if [ "$install" -eq 1 ]; then
source="${target#$OBJDIR}"
$DEBUG $MKDIR -- "$PKGCONFIG" || return 2
mode="-m 0644"
basename="$source"
if [ "${source##*/}" != "$source" ]; then
basename="${source##*/}"
fi
$DEBUG $INSTALL $mode "$target" "$PKGCONFIG/$basename" \
|| return 2
continue
fi
#portability
RPATH=
if [ "$PREFIX" != "/usr" ]; then
RPATH="-Wl,-rpath-link,\${libdir} -Wl,-rpath,\${libdir}"
case $(uname -s) in
"Darwin")
RPATH="-Wl,-rpath,\${libdir}"
;;
"SunOS")
RPATH="-Wl,-R\${libdir}"
;;
esac
fi
#create
source="${target#$OBJDIR}"
source="${source}.in"
([ -z "$OBJDIR" ] || $DEBUG $MKDIR -- "${target%/*}") \
|| return 2
$DEBUG $SED -e "s;@VENDOR@;$VENDOR;g" \
-e "s;@PACKAGE@;$PACKAGE;g" \
-e "s;@VERSION@;$VERSION;g" \
-e "s;@PREFIX@;$PREFIX;g" \
-e "s;@BINDIR@;$BINDIR;g" \
-e "s;@DATADIR@;$DATADIR;g" \
-e "s;@INCLUDEDIR@;$INCLUDEDIR;g" \
-e "s;@LIBDIR@;$LIBDIR;g" \
-e "s;@LIBEXECDIR@;$LIBEXECDIR;g" \
-e "s;@MANDIR@;$MANDIR;g" \
-e "s;@PWD@;$PWD;g" \
-e "s;@RPATH@;$RPATH;g" \
-e "s;@SBINDIR@;$SBINDIR;g" \
-e "s;@SYSCONFDIR@;$SYSCONFDIR;g" \
-- "$source" > "$target"
if [ $? -ne 0 ]; then
$RM -- "$target" 2> "$DEVNULL"
return 2
fi
done
return 0
}
#debug
_debug()
{
@ -93,91 +189,10 @@ while getopts "ciuO:P:" name; do
esac
done
shift $(($OPTIND - 1))
if [ $# -lt 0 ]; then
if [ $# -lt 1 ]; then
_usage
exit $?
fi
#check the variables
if [ -z "$PACKAGE" ]; then
_error "The PACKAGE variable needs to be set"
exit $?
fi
if [ -z "$VERSION" ]; then
_error "The VERSION variable needs to be set"
exit $?
fi
[ -z "$BINDIR" ] && BINDIR="$PREFIX/bin"
[ -z "$DATADIR" ] && DATADIR="$PREFIX/share"
[ -z "$INCLUDEDIR" ] && INCLUDEDIR="$PREFIX/include"
[ -z "$LIBDIR" ] && LIBDIR="$PREFIX/lib"
[ -z "$LIBEXECDIR" ] && LIBEXECDIR="$PREFIX/libexec"
[ -z "$MANDIR" ] && MANDIR="$DATADIR/man"
if [ -z "$SYSCONFDIR" ]; then
SYSCONFDIR="$PREFIX/etc"
[ "$PREFIX" = "/usr" ] && SYSCONFDIR="/etc"
fi
PKGCONFIG="$PREFIX/lib/pkgconfig"
exec 3>&1
while [ $# -gt 0 ]; do
target="$1"
shift
#clean
[ "$clean" -ne 0 ] && continue
#uninstall
if [ "$uninstall" -eq 1 ]; then
$DEBUG $RM -- "$PKGCONFIG/$target" || exit 2
continue
fi
#install
if [ "$install" -eq 1 ]; then
source="${target#$OBJDIR}"
$DEBUG $MKDIR -- "$PKGCONFIG" || exit 2
basename="$source"
if [ "${source##*/}" != "$source" ]; then
basename="${source##*/}"
fi
$DEBUG $INSTALL "$target" "$PKGCONFIG/$basename"|| exit 2
continue
fi
#portability
RPATH=
if [ "$PREFIX" != "/usr" ]; then
RPATH="-Wl,-rpath-link,\${libdir} -Wl,-rpath,\${libdir}"
case $(uname -s) in
"Darwin")
RPATH="-Wl,-rpath,\${libdir}"
;;
"SunOS")
RPATH="-Wl,-R\${libdir}"
;;
esac
fi
#create
source="${target#$OBJDIR}"
source="${source}.in"
([ -z "$OBJDIR" ] || $DEBUG $MKDIR -- "${target%/*}") || exit 2
$DEBUG $SED -e "s;@PACKAGE@;$PACKAGE;g" \
-e "s;@VERSION@;$VERSION;g" \
-e "s;@PREFIX@;$PREFIX;g" \
-e "s;@BINDIR@;$BINDIR;g" \
-e "s;@DATADIR@;$DATADIR;g" \
-e "s;@INCLUDEDIR@;$INCLUDEDIR;g" \
-e "s;@LIBDIR@;$LIBDIR;g" \
-e "s;@LIBEXECDIR@;$LIBEXECDIR;g" \
-e "s;@MANDIR@;$MANDIR;g" \
-e "s;@PWD@;$PWD;g" \
-e "s;@RPATH@;$RPATH;g" \
-e "s;@SYSCONFDIR@;$SYSCONFDIR;g" \
-- "$source" > "$target"
if [ $? -ne 0 ]; then
$DEBUG $RM -- "$target"
exit 2
fi
done
_pkgconfig "$@"

5
doc/.gitignore vendored
View File

@ -2,3 +2,8 @@
/AppBroker.html
/AppClient.1
/AppClient.html
/gtkdoc/html
/gtkdoc/html.stamp
/gtkdoc/libApp.types
/gtkdoc/tmpl.stamp
/gtkdoc/xml.stamp

View File

@ -1,6 +1,6 @@
#!/bin/sh
#$Id$
#Copyright (c) 2012-2017 Pierre Pronchery <khorben@defora.org>
#Copyright (c) 2012-2024 Pierre Pronchery <khorben@defora.org>
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
@ -25,17 +25,22 @@
#variables
CONFIGSH="${0%/docbook.sh}/../config.sh"
PREFIX="/usr/local"
[ -f "../config.sh" ] && . "../config.sh"
PROGNAME="docbook.sh"
XSL_HTML="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"
XSL_MAN="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"
XSL_PDF="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"
#executables
DEBUG="_debug"
FOP="fop"
INSTALL="install -m 0644"
MKDIR="mkdir -m 0755 -p"
RM="rm -f"
XMLLINT="xmllint"
XSLTPROC="xsltproc --nonet --xinclude"
XMLLINT="xmllint --noent --nonet --xinclude --path ${PWD}"
XSLTPROC="xsltproc --nonet --xinclude --path ${PWD}"
[ -f "$CONFIGSH" ] && . "$CONFIGSH"
#functions
@ -58,18 +63,20 @@ _docbook()
ext="${ext##.}"
case "$ext" in
html)
XSL="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"
XSL="$XSL_HTML"
[ -f "${source%.*}.xsl" ] && XSL="${source%.*}.xsl"
[ -f "${target%.*}.xsl" ] && XSL="${target%.*}.xsl"
if [ -f "${target%.*}.css.xml" ]; then
XSLTPROC="$XSLTPROC --param custom.css.source \"${target%.*}.css.xml\" --param generate.css.header 1"
XSLTPROC_PARAMS="--param custom.css.source \"${target%.*}.css.xml\" --param generate.css.header 1"
elif [ -f "${source%.*}.css.xml" ]; then
XSLTPROC="$XSLTPROC --param custom.css.source \"${source%.*}.css.xml\" --param generate.css.header 1"
XSLTPROC_PARAMS="--param custom.css.source \"${source%.*}.css.xml\" --param generate.css.header 1"
else
XSLTPROC_PARAMS=
fi
$DEBUG $XSLTPROC -o "$target" "$XSL" "$source"
$DEBUG $XSLTPROC $XSLTPROC_PARAMS -o "$target" "$XSL" "$source"
;;
pdf)
XSL="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"
XSL="$XSL_PDF"
[ -f "${source%.*}.xsl" ] && XSL="${source%.*}.xsl"
[ -f "${target%.*}.xsl" ] && XSL="${target%.*}.xsl"
$DEBUG $XSLTPROC -o "${target%.*}.fo" "$XSL" "$source" &&
@ -77,7 +84,7 @@ _docbook()
$RM -- "${target%.*}.fo"
;;
1|2|3|4|5|6|7|8|9)
XSL="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"
XSL="$XSL_MAN"
$DEBUG $XSLTPROC -o "$target" "$XSL" "$source"
;;
*)
@ -168,7 +175,7 @@ while [ $# -gt 0 ]; do
source="${target#$OBJDIR}"
source="${source%.*}.xml"
xpath="string(/refentry/refmeta/manvolnum)"
section=$($XMLLINT --xpath "$xpath" "$source")
section=$($DEBUG $XMLLINT --xpath "$xpath" "$source")
if [ $? -eq 0 -a -n "$section" ]; then
instdir="$MANDIR/html$section"
fi

View File

@ -1,6 +1,6 @@
#!/bin/sh
#$Id$
#Copyright (c) 2012-2017 Pierre Pronchery <khorben@defora.org>
#Copyright (c) 2012-2020 Pierre Pronchery <khorben@defora.org>
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
@ -25,6 +25,7 @@
#variables
CONFIGSH="${0%/gtkdoc.sh}/../config.sh"
PREFIX="/usr/local"
PROGNAME="gtkdoc.sh"
#executables
@ -38,9 +39,10 @@ GTKDOC_SCAN="gtkdoc-scan"
INSTALL="install -m 0644"
MKDIR="mkdir -m 0755 -p"
RM="rm -f"
RMDIR="rmdir"
TOUCH="touch"
[ -f "../config.sh" ] && . "../config.sh"
[ -f "$CONFIGSH" ] && . "$CONFIGSH"
#functions
@ -60,6 +62,77 @@ _error()
}
#gtkdoc_fixxref
_gtkdoc_fixxref()
{
module="$1"
moduledir="$2"
htmldir="$3"
outputdir="$4"
(cd "$outputdir" &&
$DEBUG $GTKDOC_FIXXREF \
--module="$module" \
--module-dir="$moduledir" \
--html-dir="$htmldir") || exit 2
}
#gtkdoc_mkdb
_gtkdoc_mkdb()
{
module="$1"
sourcedir="$2"
outputdir="$3"
(cd "$sourcedir" &&
$DEBUG $GTKDOC_MKDB --module="$module" \
--output-dir="$outputdir" \
--output-format="xml" --tmpl-dir="tmpl")
}
#gtkdoc_mkhtml
_gtkdoc_mkhtml()
{
module="$1"
path="$2"
driver="$3"
outputdir="$4"
(cd "$outputdir" &&
$DEBUG $GTKDOC_MKHTML --path "$path" "$module" "$driver")
}
#gtkdoc_mktmpl
_gtkdoc_mktmpl()
{
module="$1"
sourcedir="$2"
outputdir="$3"
(cd "$sourcedir" &&
$DEBUG $GTKDOC_MKTMPL --module="$module" \
--output-dir="$outputdir")
}
#gtkdoc_scan
_gtkdoc_scan()
{
module="$1"
sourcedir="$2"
outputdir="$3"
(cd ".." &&
$DEBUG $GTKDOC_SCAN --module="$module" \
--source-dir="$sourcedir" \
--output-dir="$outputdir")
# --rebuild-types
}
#usage
_usage()
{
@ -129,23 +202,28 @@ while [ $# -gt 0 ]; do
file="${i##*/}"
$DEBUG $RM -- "$instdir/$MODULE/$file" || exit 2
done
if [ -d "$instdir/$MODULE" ]; then
$DEBUG $RMDIR -- "$instdir/$MODULE" || exit 2
fi
continue
fi
#create
case "$target" in
gtkdoc/html.stamp)
driver="../$MODULE-docs.xml"
if [ -n "$OBJDIR" ]; then
driver="gtkdoc/$MODULE-docs.xml"
$DEBUG $CP -- "$driver" "${OBJDIR}gtkdoc" \
|| exit 2
fi
output="${OBJDIR}gtkdoc/html"
$DEBUG $MKDIR -- "$output" || exit 2
(cd "$output" &&
$DEBUG $GTKDOC_MKHTML "$MODULE" \
"${OBJDIR}$driver")
driver="$MODULE-docs.xml"
oldpath="$PWD"
[ -n "$OBJDIR" ] && for file in \
"gtkdoc/$driver" \
"gtkdoc/xml/gtkdocentities.ent"; do
[ -f "$file" ] || continue
$DEBUG $CP -- "$file" \
"${OBJDIR}$file" || exit 2
done
_gtkdoc_mkhtml "$MODULE" "${oldpath%/*}" "../$driver" \
"$output"
#detect when gtk-doc is not available
res=$?
if [ $res -eq 127 ]; then
@ -156,24 +234,7 @@ while [ $# -gt 0 ]; do
exit 2
fi
output="${OBJDIR}gtkdoc"
(cd "$output" &&
$DEBUG $GTKDOC_FIXXREF \
--module="$MODULE" \
--module-dir="html" \
--html-dir="$instdir") || exit 2
;;
gtkdoc/sgml.stamp)
output="xml"
if [ -n "$OBJDIR" ]; then
output="${OBJDIR}gtkdoc/xml"
$DEBUG $MKDIR -- "$output" || exit 2
fi
(cd "${OBJDIR}gtkdoc" &&
$DEBUG $GTKDOC_MKDB \
--module="$MODULE" \
--output-dir="$output" \
--output-format="xml" \
--tmpl-dir="tmpl")
_gtkdoc_fixxref "$MODULE" "html" "$instdir" "$output"
;;
gtkdoc/tmpl.stamp)
output="tmpl"
@ -181,22 +242,28 @@ while [ $# -gt 0 ]; do
output="${OBJDIR}gtkdoc/tmpl"
$DEBUG $MKDIR -- "$output" || exit 2
fi
(cd "${OBJDIR}gtkdoc" &&
$DEBUG $GTKDOC_MKTMPL \
--module="$MODULE" \
--output-dir="$output")
_gtkdoc_mktmpl "$MODULE" "${OBJDIR}gtkdoc" "$output"
;;
gtkdoc/xml.stamp)
output="xml"
if [ -n "$OBJDIR" ]; then
output="${OBJDIR}gtkdoc"
sections="gtkdoc/$MODULE-sections.txt"
$DEBUG $MKDIR -- "$output/xml" || exit 2
$DEBUG $CP -- "$sections" "$output" \
|| exit 2
_gtkdoc_scan "$MODULE" "include" "$output"
output="${OBJDIR}gtkdoc/xml"
fi
_gtkdoc_mkdb "$MODULE" "${OBJDIR}gtkdoc" "$output"
;;
gtkdoc/*.types)
output="doc/gtkdoc" || exit 2
output="$PWD/gtkdoc" || exit 2
if [ -n "$OBJDIR" ]; then
output="${OBJDIR}gtkdoc"
$DEBUG $MKDIR -- "$output" || exit 2
fi
(cd ".." &&
$DEBUG $GTKDOC_SCAN \
--module="$MODULE" \
--source-dir="include" \
--output-dir="$output")
_gtkdoc_scan "$MODULE" "include" "$output"
;;
*)
_error "$target: Unknown type"
@ -208,7 +275,7 @@ while [ $# -gt 0 ]; do
_error "$target: Could not create documentation"
install=0
fi
$TOUCH "$target"
$TOUCH "${OBJDIR}$target"
#install
if [ "$install" -eq 1 ]; then

View File

@ -3,28 +3,35 @@
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
<!ENTITY server "www.defora.org/doc/gtk-doc/html">
<!ENTITY title "DeforaOS libApp">
<!ENTITY version "0.1.5">
<!ENTITY % gtkdocentities SYSTEM "xml/gtkdocentities.ent">
%gtkdocentities;
<!ENTITY % configentities SYSTEM "config.ent">
%configentities;
]>
<book id="index">
<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
<bookinfo>
<title>libApp Reference Manual</title>
<title>&vendor; &package; &title;</title>
<releaseinfo>
for libApp &version;.
for &vendor; &package; &version;.
The latest version of this documentation can be found on-line at
<ulink role="online-location" url="http://&server;/libApp/index.html">http://&server;/libApp/</ulink>.
<ulink role="online-location" url="https://&server;/&package;/">https://&server;/&package;/</ulink>.
</releaseinfo>
</bookinfo>
<chapter>
<title>&title;</title>
<title>&vendor; &package;</title>
<xi:include href="xml/app.xml"/>
<xi:include href="xml/appclient.xml"/>
<xi:include href="xml/appmessage.xml"/>
<xi:include href="xml/appserver.xml"/>
<xi:include href="xml/apptransport.xml"/>
</chapter>
<!-- enable this when you use gobject types
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
-->
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
@ -33,6 +40,7 @@
<title>Index of deprecated API</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index>
<!-- enable this when you use gobject introspection annotations
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
-->
</book>

View File

@ -0,0 +1,56 @@
<SECTION>
<FILE>App</FILE>
</SECTION>
<SECTION>
<FILE>app</FILE>
AppMessage
</SECTION>
<SECTION>
<FILE>appclient</FILE>
AppClient
appclient_call
appclient_delete
appclient_new
appclient_new_event
</SECTION>
<SECTION>
<FILE>appmessage</FILE>
AppMessageType
appmessage_delete
appmessage_get_method
appmessage_get_type
appmessage_new_call
appmessage_new_deserialize
appmessage_serialize
</SECTION>
<SECTION>
<FILE>appserver</FILE>
APPSERVER_MAX_ARGUMENTS
AppServer
AppServerOptions
appserver_delete
appserver_get_client_id
appserver_loop
appserver_new
appserver_new_event
</SECTION>
<SECTION>
<FILE>apptransport</FILE>
AppTransport
AppTransportClient
AppTransportMode
AppTransportPlugin
AppTransportPluginDefinition
AppTransportStatus
client_delete
client_new
client_receive
status
</SECTION>

View File

@ -1 +1 @@
dist=Makefile,libApp-docs.xml
dist=Makefile,libApp-docs.xml,libApp-sections.txt,xml/gtkdocentities.ent

View File

@ -0,0 +1,2 @@
<!ENTITY server "www.defora.org/doc/gtk-doc/html">
<!ENTITY title "Reference Manual">

View File

@ -1,7 +1,8 @@
subdirs=gtkdoc
targets=AppBroker.1,AppBroker.html,AppClient.1,AppClient.html,gtkdoc/libApp.types,gtkdoc/tmpl.stamp,gtkdoc/sgml.stamp,gtkdoc/html.stamp
targets=AppBroker.1,AppBroker.html,AppClient.1,AppClient.html,gtkdoc/html.stamp,gtkdoc/libApp.types,gtkdoc/tmpl.stamp,gtkdoc/xml.stamp
dist=Makefile,AppBroker.css.xml,AppBroker.xml,AppClient.css.xml,AppClient.xml,docbook.sh,gtkdoc.sh,manual.css.xml
#targets
[AppBroker.1]
type=script
script=./docbook.sh
@ -26,22 +27,23 @@ script=./docbook.sh
depends=AppClient.css.xml,AppClient.xml,manual.css.xml
#install=
[gtkdoc/html.stamp]
type=script
script=./gtkdoc.sh
depends=gtkdoc.sh,gtkdoc/libApp-docs.xml,$(OBJDIR)gtkdoc/xml.stamp,gtkdoc/xml/gtkdocentities.ent,../config.ent
install=
[gtkdoc/libApp.types]
type=script
script=./gtkdoc.sh
depends=gtkdoc.sh
[gtkdoc/tmpl.stamp]
type=script
script=./gtkdoc.sh
depends=$(OBJDIR)gtkdoc/libApp.types
depends=gtkdoc.sh,$(OBJDIR)gtkdoc/libApp.types
[gtkdoc/sgml.stamp]
[gtkdoc/xml.stamp]
type=script
script=./gtkdoc.sh
depends=$(OBJDIR)gtkdoc/tmpl.stamp
[gtkdoc/html.stamp]
type=script
script=./gtkdoc.sh
depends=gtkdoc/libApp-docs.xml,$(OBJDIR)gtkdoc/sgml.stamp,$(OBJDIR)gtkdoc/tmpl.stamp
install=
depends=gtkdoc.sh,$(OBJDIR)gtkdoc/tmpl.stamp

1
include/App/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/app.h

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2025 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -25,4 +25,8 @@ typedef struct _App App;
typedef struct _AppMessage AppMessage;
/* constants */
# define APP_PATH "@LIBDIR@/App"
#endif /* !LIBAPP_APP_APP_H */

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2011-2015 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2011-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -18,6 +18,7 @@
#ifndef LIBAPP_APP_APPCLIENT_H
# define LIBAPP_APP_APPCLIENT_H
# include <stdarg.h>
# include <stdint.h>
# include <System/event.h>
# include <System/variable.h>
@ -42,7 +43,13 @@ AppStatus * appclient_get_status(AppClient * appclient);
/* useful */
int appclient_call(AppClient * appclient,
void ** result, char const * method, ...);
int appclient_callv(AppClient * appclient,
void ** result, char const * method, va_list args);
int appclient_call_variable(AppClient * appclient,
Variable * result, char const * method, ...);
int appclient_call_variables(AppClient * appclient,
Variable * result, char const * method, Variable ** args);
int appclient_call_variablev(AppClient * appclient,
Variable * result, char const * method, va_list args);
#endif /* !LIBAPP_APP_APPCLIENT_H */

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012-2015 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -41,7 +41,7 @@ typedef uint32_t AppMessageID;
/* calls */
typedef enum _AppMessageCallDirection
{
AMCD_IN = 0,
AMCD_IN = 1,
AMCD_OUT,
AMCD_IN_OUT
} AppMessageCallDirection;

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012-2014 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2025 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -84,4 +84,8 @@ struct _AppTransportPluginDefinition
AppTransportClient * client, AppMessage * message);
};
/* constants */
# define APP_TRANSPORT_PATH APP_PATH "/transport"
#endif /* !LIBAPP_APP_APPTRANSPORT_H */

View File

@ -1,9 +1,8 @@
includes=app.h,appclient.h,appmessage.h,appserver.h,appstatus.h,apptransport.h
dist=Makefile
[app.h]
install=$(INCLUDEDIR)/System/App
includes=appclient.h,appmessage.h,appserver.h,appstatus.h,apptransport.h
targets=app.h
dist=Makefile,app.h.in
#includes
[appclient.h]
install=$(INCLUDEDIR)/System/App
@ -18,3 +17,10 @@ install=$(INCLUDEDIR)/System/App
[apptransport.h]
install=$(INCLUDEDIR)/System/App
#targets
[app.h]
type=script
script=../../tools/subst.sh
install=$(INCLUDEDIR)/System/App
depends=app.h.in,../../config.sh

View File

@ -1,7 +1,7 @@
package=libApp
version=0.3.1
config=h,sh
dist=Makefile,COPYING,README.md,config.h,config.sh
version=0.3.2
config=ent,h,sh
dist=Makefile,COPYING,README.md,config.ent,config.h,config.sh
subdirs=data,doc,include,src,src/transport,tools,tests
targets=tests
@ -9,7 +9,11 @@ targets=tests
#targets
[tests]
type=command
command=cd tests && (if [ -n "$(OBJDIR)" ]; then $(MAKE) OBJDIR="$(OBJDIR)tests/" "$(OBJDIR)tests/fixme.log"; else $(MAKE) fixme.log; fi)
command=cd tests && (if [ -n "$(OBJDIR)" ]; then $(MAKE) OBJDIR="$(OBJDIR)tests/" "$(OBJDIR)tests/fixme.log" "$(OBJDIR)tests/pkgconfig.log" "$(OBJDIR)tests/shlint.log" "$(OBJDIR)tests/tests.log"; else $(MAKE) fixme.log pkgconfig.log shlint.log tests.log; fi)
depends=all
enabled=0
phony=1
#dist
[README.md]
install=$(PREFIX)/share/doc/$(PACKAGE)

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2011-2014 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2011-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -79,10 +79,14 @@ AppClient * appclient_new_event(App * self, char const * app,
appclient->transport = apptransport_new_app(ATM_CLIENT,
&appclient->helper, app, name, appclient->event);
/* check for errors */
if(appclient->interface == NULL || appclient->transport == NULL
if(appclient->interface == NULL
|| appclient->transport == NULL
|| appclient->event == NULL)
{
appclient_delete(appclient);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() => NULL\n", __func__);
#endif
return NULL;
}
#ifdef DEBUG
@ -131,34 +135,73 @@ int appclient_call(AppClient * appclient,
va_list ap;
va_start(ap, method);
ret = appinterface_callv(appclient->interface, appclient->app, result,
method, ap);
ret = appclient_callv(appclient, result, method, ap);
va_end(ap);
return ret;
}
/* appclient_callv */
int appclient_callv(AppClient * appclient,
void ** result, char const * method, va_list ap)
{
int ret;
AppMessage * message;
if((message = appinterface_messagev(appclient->interface, method, ap))
== NULL)
return -1;
/* FIXME obtain the answer (AICD_{,IN}OUT) */
ret = apptransport_client_send(appclient->transport, message, 1);
appmessage_delete(message);
return ret;
}
/* appclient_call_variable */
int appclient_call_variable(AppClient * appclient,
Variable * result, char const * method, ...)
{
int ret;
size_t cnt;
size_t i;
va_list ap;
Variable ** argv;
if(appinterface_get_args_count(appclient->interface, &cnt, method) != 0)
return -1;
if((argv = malloc(sizeof(*argv) * cnt)) == NULL)
return error_set_code(-errno, "%s", strerror(errno));
va_start(ap, method);
for(i = 0; i < cnt; i++)
argv[i] = va_arg(ap, Variable *);
ret = appclient_call_variablev(appclient, result, method, ap);
va_end(ap);
ret = appinterface_call_variablev(appclient->interface, appclient->app,
result, method, cnt, argv);
free(argv);
return ret;
}
/* appclient_call_variables */
int appclient_call_variables(AppClient * appclient,
Variable * result, char const * method, Variable ** args)
{
int ret;
AppMessage * message;
if((message = appinterface_message_variables(appclient->interface,
method, args)) == NULL)
return -1;
/* FIXME obtain the answer (AICD_{,IN}OUT) */
ret = apptransport_client_send(appclient->transport, message, 1);
appmessage_delete(message);
return ret;
}
/* appclient_call_variablev */
int appclient_call_variablev(AppClient * appclient,
Variable * result, char const * method, va_list args)
{
int ret;
AppMessage * message;
if((message = appinterface_message_variablev(appclient->interface,
method, args)) == NULL)
return -1;
/* FIXME obtain the answer (AICD_{,IN}OUT) */
ret = apptransport_client_send(appclient->transport, message, 1);
appmessage_delete(message);
return ret;
}
@ -201,7 +244,7 @@ static int _helper_message_call(AppClient * appclient, AppTransport * transport,
/* XXX report errors */
return -1;
ret = appinterface_call_variablev(appclient->interface, appclient->app,
result, method, 0, NULL);
NULL, result, method, 0, NULL);
if(result != NULL)
variable_delete(result);
return ret;

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2011-2016 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2011-2022 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -26,6 +26,7 @@
#include <errno.h>
#include <System.h>
#include <System/Marshall.h>
#include "App/appmessage.h"
#include "App/appserver.h"
#include "appstatus.h"
#include "appinterface.h"
@ -43,7 +44,6 @@
/* private */
/* types */
/* XXX get rid of this */
#define VT_LAST VT_STRING
#define VT_COUNT (VT_LAST + 1)
#define AICT_MASK 077
@ -51,7 +51,8 @@
static const String * AICTString[VT_COUNT] =
{
"void", "bool", "int8", "uint8", "int16", "uint16", "int32", "uint32",
"int64", "uint64", "String", "Buffer", "float", "double"
"int64", "uint64", "float", "double", "Buffer", "String", "Array",
"Compound"
};
#endif
@ -76,7 +77,7 @@ typedef struct _AppInterfaceCall
AppInterfaceCallArg type;
AppInterfaceCallArg * args;
size_t args_cnt;
MarshallCallback func;
MarshallCall call;
} AppInterfaceCall;
struct _AppInterface
@ -88,6 +89,9 @@ struct _AppInterface
AppStatus * status;
AppInterfaceCall * calls;
size_t calls_cnt;
AppInterfaceCall * callbacks;
size_t callbacks_cnt;
/* XXX for hash_foreach() in _new_interface_do() */
int error;
};
@ -161,8 +165,14 @@ static AppInterfaceCall * _appinterface_get_call(AppInterface * appinterface,
char const * method);
/* useful */
static int _appinterface_call(App * app, Variable * result,
AppInterfaceCall * call, size_t argc, Variable ** argv);
static Variable ** _appinterface_argv_new(AppInterfaceCall * call,
va_list ap);
static void _appinterface_argv_free(Variable ** argv, size_t argc);
static int _appinterface_call(App * app, AppServerClient * asc,
Variable * result, AppInterfaceCall * call,
size_t argc, Variable ** argv);
static AppMessage * _appinterface_message(AppInterfaceCall * call,
size_t argc, Variable ** argv);
/* functions */
@ -220,51 +230,38 @@ static String * _new_interface(String const * app)
/* appinterface_new_interface */
static int _new_interface_append(AppInterface * ai, VariableType type,
char const * method);
static int _new_interface_append_arg(AppInterface * ai, char const * arg);
static AppInterfaceCall * _new_interface_append_call(AppInterface * ai,
VariableType type, char const * method);
static AppInterfaceCall * _new_interface_append_callback(AppInterface * ai,
VariableType type, char const * method);
static int _new_interface_append_arg(AppInterfaceCall * call, char const * arg);
AppInterface * _new_interface_do(AppTransportMode mode, String const * app,
String const * pathname);
static int _new_interface_do_appstatus(AppInterface * appinterface);
static int _new_interface_foreach(char const * key, Hash * value,
static int _new_interface_foreach_calls(char const * key, Hash * value,
AppInterface * appinterface);
static int _new_interface_foreach_callbacks(char const * key, Hash * value,
AppInterface * appinterface);
static AppInterface * _new_interface_mode_client(AppTransportMode mode,
String const * app, String const * pathname);
static AppInterface * _new_interface_mode_server(AppTransportMode mode,
String const * app, String const * pathname);
AppInterface * appinterface_new_interface(AppTransportMode mode,
String const * app, String const * pathname)
{
AppInterface * ai;
Plugin * handle;
size_t i;
String * name;
if((handle = plugin_new_self()) == NULL)
return NULL;
if((ai = _new_interface_do(mode, app, pathname)) == NULL)
return NULL;
for(i = 0; i < ai->calls_cnt; i++)
switch(mode)
{
if((name = string_new_append(ai->name, "_", ai->calls[i].name,
NULL)) == NULL)
{
appinterface_delete(ai);
ai = NULL;
break;
}
ai->calls[i].func = plugin_lookup(handle, name);
string_delete(name);
if(ai->calls[i].func == NULL)
{
appinterface_delete(ai);
ai = NULL;
break;
}
case ATM_CLIENT:
return _new_interface_mode_client(mode, app, pathname);
case ATM_SERVER:
return _new_interface_mode_server(mode, app, pathname);
}
plugin_delete(handle);
return ai;
return NULL;
}
static int _new_interface_append(AppInterface * ai, VariableType type,
char const * method)
static AppInterfaceCall * _new_interface_append_call(AppInterface * ai,
VariableType type, char const * method)
{
AppInterfaceCall * p;
@ -272,25 +269,47 @@ static int _new_interface_append(AppInterface * ai, VariableType type,
fprintf(stderr, "DEBUG: %s(%d, \"%s\")\n", __func__, type, method);
#endif
if((p = realloc(ai->calls, sizeof(*p) * (ai->calls_cnt + 1))) == NULL)
return -1;
return NULL;
ai->calls = p;
p = &ai->calls[ai->calls_cnt];
if((p->name = string_new(method)) == NULL)
return -1;
return NULL;
p->type.type = type & AICT_MASK;
p->type.direction = type & AICD_MASK;
p->args = NULL;
p->args_cnt = 0;
ai->calls_cnt++;
return 0;
return p;
}
static int _new_interface_append_arg(AppInterface * ai, char const * arg)
static AppInterfaceCall * _new_interface_append_callback(AppInterface * ai,
VariableType type, char const * method)
{
AppInterfaceCall * p;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%d, \"%s\")\n", __func__, type, method);
#endif
if((p = realloc(ai->callbacks, sizeof(*p) * (ai->callbacks_cnt + 1)))
== NULL)
return NULL;
ai->callbacks = p;
p = &ai->callbacks[ai->callbacks_cnt];
if((p->name = string_new(method)) == NULL)
return NULL;
p->type.type = type & AICT_MASK;
p->type.direction = type & AICD_MASK;
p->args = NULL;
p->args_cnt = 0;
ai->callbacks_cnt++;
return p;
}
static int _new_interface_append_arg(AppInterfaceCall * call, char const * arg)
{
char buf[16];
char * p;
int type;
AppInterfaceCall * q;
AppInterfaceCallArg * r;
#ifdef DEBUG
@ -301,11 +320,10 @@ static int _new_interface_append_arg(AppInterface * ai, char const * arg)
*p = '\0';
if((type = _string_enum(buf, _string_type)) < 0)
return -1;
q = &ai->calls[ai->calls_cnt - 1];
if((r = realloc(q->args, sizeof(*r) * (q->args_cnt + 1))) == NULL)
if((r = realloc(call->args, sizeof(*r) * (call->args_cnt + 1))) == NULL)
return error_set_code(-errno, "%s", strerror(errno));
q->args = r;
r = &q->args[q->args_cnt++];
call->args = r;
r = &call->args[call->args_cnt++];
r->type = type & AICT_MASK;
r->direction = type & AICD_MASK;
#ifdef DEBUG
@ -330,6 +348,8 @@ AppInterface * _new_interface_do(AppTransportMode mode, String const * app,
appinterface->status = NULL;
appinterface->calls = NULL;
appinterface->calls_cnt = 0;
appinterface->callbacks = NULL;
appinterface->callbacks_cnt = 0;
appinterface->error = 0;
if(appinterface->name == NULL
|| appinterface->config == NULL
@ -340,7 +360,11 @@ AppInterface * _new_interface_do(AppTransportMode mode, String const * app,
return NULL;
}
appinterface->error = 0;
hash_foreach(appinterface->config, (HashForeach)_new_interface_foreach,
hash_foreach(appinterface->config,
(HashForeach)_new_interface_foreach_calls,
appinterface);
hash_foreach(appinterface->config,
(HashForeach)_new_interface_foreach_callbacks,
appinterface);
if(appinterface->error != 0)
{
@ -359,29 +383,28 @@ static int _new_interface_do_appstatus(AppInterface * appinterface)
return 0;
}
static int _new_interface_foreach(char const * key, Hash * value,
static int _new_interface_foreach_callbacks(char const * key, Hash * value,
AppInterface * appinterface)
{
String const * prefix = (appinterface->mode == ATM_SERVER)
? APPINTERFACE_CALL_PREFIX : APPINTERFACE_CALLBACK_PREFIX;
String const * prefix = APPINTERFACE_CALLBACK_PREFIX;
unsigned int i;
char buf[8];
int type = VT_NULL;
char const * p;
AppInterfaceCall * callback;
if(key == NULL || strncmp(prefix, key, string_length(prefix)) != 0)
if(key == NULL || strncmp(prefix, key, string_get_length(prefix)) != 0)
return 0;
key += string_length(prefix);
key += string_get_length(prefix);
if((p = hash_get(value, "ret")) != NULL
&& (type = _string_enum(p, _string_type)) < 0)
{
appinterface->error = error_set_code(1, "%s: %s%s", p,
"Invalid return type for ",
(appinterface->mode == ATM_SERVER)
? "call" : "callback");
appinterface->error = error_set_code(1, "%s: %s", p,
"Invalid return type for callback");
return -appinterface->error;
}
if(_new_interface_append(appinterface, type, key) != 0)
if((callback = _new_interface_append_callback(appinterface, type, key))
== NULL)
{
appinterface->error = 1;
return -appinterface->error;
@ -391,7 +414,7 @@ static int _new_interface_foreach(char const * key, Hash * value,
snprintf(buf, sizeof(buf), "arg%u", i + 1);
if((p = hash_get(value, buf)) == NULL)
break;
if(_new_interface_append_arg(appinterface, p) != 0)
if(_new_interface_append_arg(callback, p) != 0)
{
/* FIXME may crash here? */
appinterface->error = 1;
@ -401,6 +424,123 @@ static int _new_interface_foreach(char const * key, Hash * value,
return 0;
}
static int _new_interface_foreach_calls(char const * key, Hash * value,
AppInterface * appinterface)
{
String const * prefix = APPINTERFACE_CALL_PREFIX;
unsigned int i;
char buf[8];
int type = VT_NULL;
char const * p;
AppInterfaceCall * call;
if(key == NULL || strncmp(prefix, key, string_get_length(prefix)) != 0)
return 0;
key += string_get_length(prefix);
if((p = hash_get(value, "ret")) != NULL
&& (type = _string_enum(p, _string_type)) < 0)
{
appinterface->error = error_set_code(1, "%s: %s", p,
"Invalid return type for call");
return -appinterface->error;
}
if((call = _new_interface_append_call(appinterface, type, key)) == NULL)
{
appinterface->error = 1;
return -appinterface->error;
}
for(i = 0; i < APPSERVER_MAX_ARGUMENTS; i++)
{
snprintf(buf, sizeof(buf), "arg%u", i + 1);
if((p = hash_get(value, buf)) == NULL)
break;
if(_new_interface_append_arg(call, p) != 0)
{
/* FIXME may crash here? */
appinterface->error = 1;
return -1;
}
}
return 0;
}
AppInterface * _new_interface_mode_client(AppTransportMode mode,
String const * app, String const * pathname)
{
AppInterface * ai;
Plugin * plugin;
size_t i;
String * name;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u, \"%s\", \"%s\")\n", __func__, mode, app,
pathname);
#endif
if((plugin = plugin_new_self()) == NULL)
return NULL;
if((ai = _new_interface_do(mode, app, pathname)) == NULL)
{
plugin_delete(plugin);
return NULL;
}
for(i = 0; i < ai->callbacks_cnt; i++)
{
if((name = string_new_append(ai->name, "_",
ai->callbacks[i].name, NULL))
== NULL)
break;
ai->callbacks[i].call = plugin_lookup(plugin, name);
string_delete(name);
if(ai->callbacks[i].call == NULL)
break;
}
plugin_delete(plugin);
if(i != ai->callbacks_cnt)
{
appinterface_delete(ai);
return NULL;
}
return ai;
}
AppInterface * _new_interface_mode_server(AppTransportMode mode,
String const * app, String const * pathname)
{
AppInterface * ai;
Plugin * plugin;
size_t i;
String * name;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u, \"%s\", \"%s\")\n", __func__, mode, app,
pathname);
#endif
if((plugin = plugin_new_self()) == NULL)
return NULL;
if((ai = _new_interface_do(mode, app, pathname)) == NULL)
{
plugin_delete(plugin);
return NULL;
}
for(i = 0; i < ai->calls_cnt; i++)
{
if((name = string_new_append(ai->name, "_", ai->calls[i].name,
NULL)) == NULL)
break;
ai->calls[i].call = plugin_lookup(plugin, name);
string_delete(name);
if(ai->calls[i].call == NULL)
break;
}
plugin_delete(plugin);
if(i != ai->calls_cnt)
{
appinterface_delete(ai);
return NULL;
}
return ai;
}
/* appinterface_delete */
void appinterface_delete(AppInterface * appinterface)
@ -507,31 +647,14 @@ AppStatus * appinterface_get_status(AppInterface * appinterface)
/* useful */
/* appinterface_callv */
int appinterface_callv(AppInterface * appinterface, App * app, void ** result,
int appinterface_callv(AppInterface * appinterface, App * app,
AppServerClient * asc, void ** result,
String const * method, va_list args)
{
int ret = 0;
AppInterfaceCall * call;
Variable * r;
size_t argc;
Variable ** argv;
union
{
bool b;
int8_t i8;
uint8_t u8;
int16_t i16;
uint16_t u16;
int32_t i32;
uint32_t u32;
int64_t i64;
uint64_t u64;
char * str;
Buffer * buf;
float f;
double d;
} u;
void * p;
if((call = _appinterface_get_call(appinterface, method)) == NULL)
return -1;
@ -539,100 +662,93 @@ int appinterface_callv(AppInterface * appinterface, App * app, void ** result,
r = NULL;
else if((r = variable_new(call->type.type, NULL)) == NULL)
return -1;
if((argv = malloc(sizeof(*argv) * (call->args_cnt))) == NULL)
if((argv = _appinterface_argv_new(call, args)) == NULL)
{
if(r != NULL)
variable_delete(r);
return -1;
}
for(argc = 0; argc < call->args_cnt; argc++)
{
/* FIXME also implement AICD_{,IN}OUT */
switch(call->args[argc].type)
{
case VT_BOOL:
u.b = va_arg(args, unsigned int);
p = &u.b;
break;
case VT_INT8:
u.i8 = va_arg(args, int);
p = &u.i8;
break;
case VT_UINT8:
u.u8 = va_arg(args, unsigned int);
p = &u.u8;
break;
case VT_INT16:
u.i16 = va_arg(args, int);
p = &u.i16;
break;
case VT_UINT16:
u.u16 = va_arg(args, unsigned int);
p = &u.u16;
break;
case VT_INT32:
u.i32 = va_arg(args, int32_t);
p = &u.i32;
break;
case VT_UINT32:
u.u32 = va_arg(args, uint32_t);
p = &u.u32;
break;
case VT_INT64:
u.i64 = va_arg(args, int64_t);
p = &u.i64;
break;
case VT_UINT64:
u.u64 = va_arg(args, uint64_t);
p = &u.u64;
break;
case VT_STRING:
u.str = va_arg(args, char *);
p = u.str;
break;
case VT_BUFFER:
u.buf = va_arg(args, Buffer *);
p = u.buf;
break;
case VT_FLOAT:
u.f = va_arg(args, double);
p = &u.f;
break;
case VT_DOUBLE:
u.d = va_arg(args, double);
p = &u.d;
break;
case VT_NULL:
default:
p = NULL;
break;
}
argv[argc] = (p != NULL)
? variable_new(call->args[argc].type, p) : NULL;
if(p == NULL || argv[argc] == NULL)
ret = -1;
}
if(ret == 0)
ret = _appinterface_call(app, r, call, argc, argv);
if(ret == 0 && result != NULL)
/* XXX return 0 anyway? */
ret = variable_get_as(r, call->type.type, *result);
ret = _appinterface_call(app, asc, r, call,
call->args_cnt, argv);
if(r != NULL)
{
if(ret == 0 && result != NULL)
/* XXX return 0 anyway? */
ret = variable_get_as(r, call->type.type, *result,
NULL);
variable_delete(r);
}
/* FIXME also implement AICD_{,IN}OUT */
_appinterface_argv_free(argv, call->args_cnt);
return ret;
}
/* appinterface_call_variablev */
int appinterface_call_variablev(AppInterface * appinterface, App * app,
Variable * result, char const * method,
AppServerClient * asc, Variable * result, char const * method,
size_t argc, Variable ** argv)
{
AppInterfaceCall * call;
if((call = _appinterface_get_call(appinterface, method)) == NULL)
return -1;
return _appinterface_call(app, result, call, argc, argv);
return _appinterface_call(app, asc, result, call, argc, argv);
}
/* appinterface_messagev */
AppMessage * appinterface_messagev(AppInterface * appinterface,
char const * method, va_list ap)
{
AppInterfaceCall * call;
Variable ** argv;
AppMessage * message;
if((call = _appinterface_get_call(appinterface, method)) == NULL)
return NULL;
if((argv = _appinterface_argv_new(call, ap)) == NULL)
return NULL;
message = _appinterface_message(call, call->args_cnt, argv);
_appinterface_argv_free(argv, call->args_cnt);
return message;
}
/* appinterface_message_variables */
AppMessage * appinterface_message_variables(AppInterface * appinterface,
char const * method, Variable ** args)
{
AppInterfaceCall * call;
if((call = _appinterface_get_call(appinterface, method)) == NULL)
return NULL;
return _appinterface_message(call, call->args_cnt, args);
}
/* appinterface_message_variablev */
AppMessage * appinterface_message_variablev(AppInterface * appinterface,
char const * method, va_list ap)
{
AppInterfaceCall * call;
Variable ** argv;
size_t i;
AppMessage * message;
if((call = _appinterface_get_call(appinterface, method)) == NULL)
return NULL;
if(call->args_cnt == 0)
argv = NULL;
else if((argv = malloc(sizeof(*argv) * call->args_cnt)) == NULL)
/* XXX report error */
return NULL;
for(i = 0; i < call->args_cnt; i++)
argv[i] = va_arg(ap, Variable *);
message = _appinterface_message(call, call->args_cnt, argv);
free(argv);
return message;
}
@ -654,28 +770,281 @@ static AppInterfaceCall * _appinterface_get_call(AppInterface * appinterface,
/* useful */
/* appinterface_argv */
static Variable * _argv_new_in(VariableType type, va_list ap);
static Variable * _argv_new_in_out(VariableType type, va_list ap);
static Variable * _argv_new_out(VariableType type, va_list ap);
static Variable ** _appinterface_argv_new(AppInterfaceCall * call, va_list ap)
{
Variable ** argv;
size_t i;
if((argv = object_new(sizeof(*argv) * (call->args_cnt))) == NULL)
return NULL;
for(i = 0; i < call->args_cnt; i++)
{
switch(call->args[i].direction)
{
case AICD_IN:
argv[i] = _argv_new_in(call->args[i].type, ap);
break;
case AICD_IN_OUT:
argv[i] = _argv_new_in_out(call->args[i].type,
ap);
break;
case AICD_OUT:
argv[i] = _argv_new_out(call->args[i].type,
ap);
break;
default:
/* XXX report the error */
argv[i] = NULL;
break;
}
if(argv[i] == NULL)
{
_appinterface_argv_free(argv, i);
return NULL;
}
}
return argv;
}
static Variable * _argv_new_in(VariableType type, va_list ap)
{
return variable_newv(type, ap);
}
static Variable * _argv_new_in_out(VariableType type, va_list ap)
{
union
{
bool * bp;
int8_t * i8p;
uint8_t * u8p;
int16_t * i16p;
uint16_t * u16p;
int32_t * i32p;
uint32_t * u32p;
int64_t * i64p;
uint64_t * u64p;
char ** strp;
Buffer * buf;
float * fp;
double * dp;
} u;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, type);
#endif
switch(type)
{
case VT_NULL:
return variable_new(type);
case VT_BOOL:
u.bp = va_arg(ap, bool *);
return variable_new(type, *u.bp);
case VT_INT8:
u.i8p = va_arg(ap, int8_t *);
return variable_new(type, *u.i8p);
case VT_UINT8:
u.u8p = va_arg(ap, uint8_t *);
return variable_new(type, *u.u8p);
case VT_INT16:
u.i16p = va_arg(ap, int16_t *);
return variable_new(type, *u.i16p);
case VT_UINT16:
u.u16p = va_arg(ap, uint16_t *);
return variable_new(type, *u.u16p);
case VT_INT32:
u.i32p = va_arg(ap, int32_t *);
return variable_new(type, *u.i32p);
case VT_UINT32:
u.u32p = va_arg(ap, uint32_t *);
return variable_new(type, *u.u32p);
case VT_INT64:
u.i64p = va_arg(ap, int64_t *);
return variable_new(type, *u.i64p);
case VT_UINT64:
u.u64p = va_arg(ap, uint64_t *);
return variable_new(type, *u.u64p);
case VT_FLOAT:
u.fp = va_arg(ap, float *);
return variable_new(type, *u.fp);
case VT_DOUBLE:
u.dp = va_arg(ap, double *);
return variable_new(type, *u.dp);
case VT_STRING:
u.strp = va_arg(ap, char **);
return variable_new(type, *u.strp);
case VT_BUFFER:
u.buf = va_arg(ap, Buffer *);
return variable_new(type, u.buf);
}
return NULL;
}
static Variable * _argv_new_out(VariableType type, va_list ap)
{
union
{
bool * bp;
int8_t * i8p;
uint8_t * u8p;
int16_t * i16p;
uint16_t * u16p;
int32_t * i32p;
uint32_t * u32p;
int64_t * i64p;
uint64_t * u64p;
char ** strp;
Buffer * buf;
float * fp;
double * dp;
} u;
void * p;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, type);
#endif
switch(type)
{
case VT_BOOL:
u.bp = va_arg(ap, bool *);
p = u.bp;
break;
case VT_INT8:
u.i8p = va_arg(ap, int8_t *);
p = u.i8p;
break;
case VT_UINT8:
u.u8p = va_arg(ap, uint8_t *);
p = u.u8p;
break;
case VT_INT16:
u.i16p = va_arg(ap, int16_t *);
p = u.i16p;
break;
case VT_UINT16:
u.u16p = va_arg(ap, uint16_t *);
p = u.u16p;
break;
case VT_INT32:
u.i32p = va_arg(ap, int32_t *);
p = u.i32p;
break;
case VT_UINT32:
u.u32p = va_arg(ap, uint32_t *);
p = u.u32p;
break;
case VT_INT64:
u.i64p = va_arg(ap, int64_t *);
p = u.i64p;
break;
case VT_UINT64:
u.u64p = va_arg(ap, uint64_t *);
p = u.u64p;
break;
case VT_STRING:
u.strp = va_arg(ap, char **);
p = u.strp;
break;
case VT_BUFFER:
u.buf = va_arg(ap, Buffer *);
p = u.buf;
break;
case VT_FLOAT:
u.fp = va_arg(ap, float *);
p = u.fp;
break;
case VT_DOUBLE:
u.dp = va_arg(ap, double *);
p = u.dp;
break;
case VT_NULL:
default:
p = NULL;
break;
}
if(p == NULL)
return NULL;
return variable_new(type, NULL);
}
/* appinterface_argv_free */
static void _appinterface_argv_free(Variable ** argv, size_t argc)
{
size_t i;
for(i = 0; i < argc; i++)
variable_delete(argv[i]);
object_delete(argv);
}
/* appinterface_call */
static int _appinterface_call(App * app, Variable * result,
AppInterfaceCall * call, size_t argc, Variable ** argv)
static int _appinterface_call(App * app, AppServerClient * asc,
Variable * result, AppInterfaceCall * call,
size_t argc, Variable ** argv)
{
int ret;
Variable ** p;
size_t i;
if(argc != call->args_cnt)
/* XXX set the error */
return -1;
if((p = malloc(sizeof(*p) * (argc + 1))) == NULL)
if((p = object_new(sizeof(*p) * (argc + 2))) == NULL)
return -1;
/* XXX really is a VT_POINTER (void *) */
if((p[0] = variable_new(VT_BUFFER, app)) == NULL)
p[0] = variable_new(VT_POINTER, app);
p[1] = variable_new(VT_POINTER, asc);
if(p[0] == NULL || p[1] == NULL)
{
free(p);
if(p[0] != NULL)
variable_delete(p[0]);
if(p[1] != NULL)
variable_delete(p[1]);
object_delete(p);
return -1;
}
for(i = 0; i < argc; i++)
p[i + 1] = argv[i];
ret = marshall_call(result, call->func, argc, argv);
p[i + 2] = argv[i];
ret = marshall_callp(result, call->call, argc + 2, p);
variable_delete(p[1]);
variable_delete(p[0]);
free(p);
object_delete(p);
return ret;
}
/* appinterface_message */
static AppMessage * _appinterface_message(AppInterfaceCall * call,
size_t argc, Variable ** argv)
{
AppMessage * message;
AppMessageCallArgument * args;
size_t i;
if(argc != call->args_cnt)
{
error_set_code(1, "%s: %s%zu%s%zu%s", call->name,
"Invalid number of arguments (", argc,
", expected: ", call->args_cnt, ")");
return NULL;
}
if(argc == 0)
args = NULL;
else if((args = object_new(sizeof(*args) * argc)) == NULL)
return NULL;
else
for(i = 0; i < argc; i++)
{
args[i].direction = call->args[i].direction;
args[i].arg = argv[i];
}
message = appmessage_new_call(call->name, args, argc);
object_delete(args);
return message;
}

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2011-2015 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2011-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -20,6 +20,7 @@
# include <stdarg.h>
# include <System/variable.h>
# include "App/appserver.h"
# include "App/appstatus.h"
# include "App/apptransport.h"
@ -45,10 +46,18 @@ int appinterface_get_args_count(AppInterface * appinterface, size_t * count,
AppStatus * appinterface_get_status(AppInterface * appinterface);
/* useful */
int appinterface_callv(AppInterface * appinterface, App * app, void ** result,
int appinterface_callv(AppInterface * appinterface, App * app,
AppServerClient * asc, void ** result,
char const * method, va_list args);
int appinterface_call_variablev(AppInterface * appinterface, App * app,
Variable * result, char const * method,
AppServerClient * asc, Variable * result, char const * method,
size_t argc, Variable ** argv);
AppMessage * appinterface_messagev(AppInterface * appinterface,
char const * method, va_list args);
AppMessage * appinterface_message_variables(AppInterface * appinterface,
char const * method, Variable ** args);
AppMessage * appinterface_message_variablev(AppInterface * appinterface,
char const * method, va_list args);
#endif /* !LIBAPP_APPINTERFACE_H */

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012-2016 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2022 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -21,6 +21,8 @@
#ifdef DEBUG
# include <stdio.h>
#endif
#include <string.h>
#include <errno.h>
#include <System.h>
#include "appmessage.h"
@ -78,18 +80,26 @@ AppMessage * appmessage_new_call(char const * method,
message->type = AMT_CALL;
message->id = 0;
message->t.call.method = string_new(method);
message->t.call.args = malloc(sizeof(*args) * args_cnt);
message->t.call.args_cnt = args_cnt;
if(message->t.call.args == NULL)
if((message->t.call.args = object_new(sizeof(*args) * args_cnt))
== NULL)
{
message->t.call.args_cnt = 0;
appmessage_delete(message);
return NULL;
}
for(i = 0; i < args_cnt; i++)
{
/* FIXME check for errors */
message->t.call.args[i].direction = args[i].direction;
message->t.call.args[i].arg = variable_new_copy(args[i].arg);
if((message->t.call.args[i].arg = variable_new_copy(
args[i].arg)) == NULL)
break;
}
message->t.call.args_cnt = i;
/* check for errors */
if(i != args_cnt)
{
appmessage_delete(message);
return NULL;
}
return message;
}
@ -125,6 +135,7 @@ AppMessage * appmessage_new_callv(char const * method, ...)
if((p = realloc(message->t.call.args, sizeof(*p) * (i + 1)))
== NULL)
{
error_set_code(-errno, "%s", strerror(errno));
appmessage_delete(message);
message = NULL;
break;
@ -173,7 +184,12 @@ AppMessage * appmessage_new_callv_variables(char const * method, ...)
{
if((p = realloc(message->t.call.args, sizeof(*p) * (i + 1)))
== NULL)
{
error_set_code(-errno, "%s", strerror(errno));
appmessage_delete(message);
message = NULL;
break;
}
message->t.call.args = p;
if((v = variable_new_copy(v)) == NULL)
{
@ -181,7 +197,7 @@ AppMessage * appmessage_new_callv_variables(char const * method, ...)
message = NULL;
break;
}
message->t.call.args[i].direction = AMCD_IN; /* XXX */
message->t.call.args[i].direction = AMCD_IN; /* FIXME */
message->t.call.args[i].arg = v;
message->t.call.args_cnt = i + 1;
}
@ -223,7 +239,7 @@ AppMessage * appmessage_new_deserialize(Buffer * buffer)
pos += s;
size -= s;
/* XXX may fail */
variable_get_as(v, VT_UINT8, &u8);
variable_get_as(v, VT_UINT8, &u8, NULL);
variable_delete(v);
switch((message->type = u8))
{
@ -276,7 +292,7 @@ static AppMessage * _new_deserialize_call(AppMessage * message,
}
pos += s;
/* XXX may fail */
variable_get_as(v, VT_STRING, &message->t.call.method);
variable_get_as(v, VT_STRING, &message->t.call.method, NULL);
variable_delete(v);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__,
@ -291,6 +307,7 @@ static AppMessage * _new_deserialize_call(AppMessage * message,
if((p = realloc(message->t.call.args, sizeof(*p) * (i + 1)))
== NULL)
{
error_set_code(-errno, "%s", strerror(errno));
appmessage_delete(message);
return NULL;
}
@ -330,7 +347,7 @@ static AppMessage * _new_deserialize_id(AppMessage * message, char const * data,
appmessage_delete(message);
return NULL;
}
ret = variable_get_as(v, VT_UINT32, &message->id);
ret = variable_get_as(v, VT_UINT32, &message->id, NULL);
variable_delete(v);
if(ret != 0)
{
@ -360,6 +377,11 @@ void appmessage_delete(AppMessage * message)
static void _delete_call(AppMessage * message)
{
size_t i;
for(i = 0; i < message->t.call.args_cnt; i++)
variable_delete(message->t.call.args[i].arg);
free(message->t.call.args);
string_delete(message->t.call.method);
}

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2011-2015 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2011-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -183,8 +183,9 @@ static int _helper_message_call(AppServer * appserver, AppTransport * transport,
if(!appinterface_can_call(appserver->interface, method, name))
/* XXX report errors */
return -1;
/* FIXME provide the actual AppServerClient */
ret = appinterface_call_variablev(appserver->interface, appserver->app,
result, method, 0, NULL);
NULL, result, method, 0, NULL);
if(result != NULL)
variable_delete(result);
return ret;

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2015 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2015-2024 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -32,7 +32,8 @@ struct _AppStatus
/* public */
/* methods */
/* appstatus_new */
static void _new_config_foreach_section(String const * variable,
static void _new_config_foreach_section(Config const * config,
String const * section, String const * variable,
String const * value, void * data);
AppStatus * appstatus_new_config(Config * config, String const * section)
@ -41,8 +42,8 @@ AppStatus * appstatus_new_config(Config * config, String const * section)
struct
{
size_t members;
VariableType * types;
void ** values;
String const ** names;
Variable ** variables;
} data;
if((appstatus = object_new(sizeof(*appstatus))) == NULL)
@ -52,9 +53,9 @@ AppStatus * appstatus_new_config(Config * config, String const * section)
NULL);
if(data.members == 0)
appstatus->variable = NULL;
else if((appstatus->variable = variable_new_compoundv(NULL,
data.members, data.types, data.values))
== NULL)
else if((appstatus->variable = variable_new_compound_variables(NULL,
data.members, data.names,
data.variables)) == NULL)
{
appstatus_delete(appstatus);
return NULL;
@ -62,14 +63,15 @@ AppStatus * appstatus_new_config(Config * config, String const * section)
return appstatus;
}
static void _new_config_foreach_section(String const * variable,
static void _new_config_foreach_section(Config const * config,
String const * section, String const * variable,
String const * value, void * data)
{
struct
{
size_t members;
VariableType * types;
void ** values;
String const ** names;
Variable ** variables;
} * d = data;
/* FIXME implement */

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012-2015 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -408,7 +408,16 @@ static AppTransportClient * _apptransport_helper_client_new(
if((client = object_new(sizeof(*client))) == NULL)
return NULL;
client->transport = transport;
client->name = (name != NULL) ? string_new(name) : NULL;
if(name != NULL)
{
if((client->name = string_new(name)) == NULL)
{
object_delete(client);
return NULL;
}
}
else
client->name = NULL;
return client;
}

View File

@ -1,17 +1,19 @@
targets=libApp
cppflags_force=-I ../include
cppflags_force=-I ../include -I ${OBJDIR}../include/App
cflags_force=-fPIC `pkg-config --cflags libSystem libMarshall`
cflags=-W -Wall -g -O2 -D_FORTIFY_SOURCE=2 -fstack-protector-all
cflags=-W -Wall -g -O2 -D_FORTIFY_SOURCE=2 -fstack-protector
ldflags_force=`pkg-config --libs libSystem libMarshall`
ldflags=-Wl,-z,relro -Wl,-z,now
dist=Makefile,appinterface.h,appmessage.h,appstatus.h,apptransport.h
#targets
[libApp]
type=library
sources=appclient.c,appinterface.c,appmessage.c,appserver.c,appstatus.c,apptransport.c
ldflags=-lsocket -lws2_32
install=$(LIBDIR)
#sources
[appclient.c]
depends=appinterface.h,../include/App/appclient.h

View File

@ -1,12 +1,13 @@
targets=self,tcp,tcp4,tcp6,template,udp,udp4,udp6
cppflags_force=-I ../../include
cppflags_force=-I ../../include -I ${OBJDIR}../../include/App
cppflags=
cflags_force=-fPIC `pkg-config --cflags libSystem`
cflags=-W -Wall -g -O2 -D_FORTIFY_SOURCE=2 -fstack-protector-all
cflags=-W -Wall -g -O2 -D_FORTIFY_SOURCE=2 -fstack-protector
ldflags_force=`pkg-config --libs libSystem` -L$(OBJDIR).. -lApp
ldflags=-Wl,-z,relro -Wl,-z,now
dist=Makefile,common.h,common.c
#targets
[self]
type=plugin
sources=self.c
@ -19,27 +20,18 @@ sources=tcp.c
ldflags=-lsocket
install=$(LIBDIR)/App/transport
[tcp.c]
depends=common.h,common.c
[tcp4]
type=plugin
sources=tcp4.c
ldflags=-lsocket
install=$(LIBDIR)/App/transport
[tcp4.c]
depends=tcp.c,common.h,common.c
[tcp6]
type=plugin
sources=tcp6.c
ldflags=-lsocket
install=$(LIBDIR)/App/transport
[tcp6.c]
depends=tcp.c,common.h,common.c
[template]
type=plugin
sources=template.c
@ -50,23 +42,33 @@ sources=udp.c
ldflags=-lsocket
install=$(LIBDIR)/App/transport
[udp.c]
depends=common.h,common.c
[udp4]
type=plugin
sources=udp4.c
ldflags=-lsocket
install=$(LIBDIR)/App/transport
[udp4.c]
depends=udp.c,common.h,common.c
[udp6]
type=plugin
sources=udp6.c
ldflags=-lsocket
install=$(LIBDIR)/App/transport
#sources
[tcp.c]
depends=common.h,common.c
[tcp4.c]
depends=tcp.c,common.h,common.c
[tcp6.c]
depends=tcp.c,common.h,common.c
[udp.c]
depends=common.h,common.c
[udp4.c]
depends=udp.c,common.h,common.c
[udp6.c]
depends=udp.c,common.h,common.c

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012-2016 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2022 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -77,7 +77,7 @@ struct _AppTransportPlugin
AppTransportMode mode;
struct addrinfo * ai;
socklen_t ai_addrlen;
struct addrinfo * aip;
union
{
@ -109,9 +109,9 @@ static TCP * _tcp_init(AppTransportPluginHelper * helper, AppTransportMode mode,
char const * name);
static void _tcp_destroy(TCP * tcp);
static int _tcp_client_send(TCP * tcp, AppTransportClient * client,
static int _tcp_client_send(TCP * tcp, AppMessage * message);
static int _tcp_server_send(TCP * tcp, AppTransportClient * client,
AppMessage * message);
static int _tcp_send(TCP * tcp, AppMessage * message);
/* useful */
static int _tcp_error(char const * message);
@ -120,7 +120,8 @@ static int _tcp_error(char const * message);
static int _tcp_server_add_client(TCP * tcp, TCPSocket * client);
/* sockets */
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, TCP * tcp);
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, int flags,
TCP * tcp);
static void _tcp_socket_init_fd(TCPSocket * tcpsocket, TCP * tcp, int fd,
struct sockaddr * sa, socklen_t sa_len);
static TCPSocket * _tcp_socket_new_fd(TCP * tcp, int fd, struct sockaddr * sa,
@ -143,11 +144,14 @@ static int _tcp_socket_callback_write(int fd, TCPSocket * tcpsocket);
AppTransportPluginDefinition transport =
{
"TCP",
NULL,
#ifndef TRANSPORT_DESCRIPTION
# define TRANSPORT_DESCRIPTION "Plain TCP/IP"
#endif
TRANSPORT_DESCRIPTION,
_tcp_init,
_tcp_destroy,
_tcp_send,
_tcp_client_send
_tcp_client_send,
_tcp_server_send
};
@ -199,7 +203,6 @@ static TCP * _tcp_init(AppTransportPluginHelper * helper, AppTransportMode mode,
static int _init_client(TCP * tcp, char const * name, int domain)
{
struct addrinfo * aip;
#ifdef DEBUG
struct sockaddr_in * sa;
#endif
@ -210,26 +213,27 @@ static int _init_client(TCP * tcp, char const * name, int domain)
if((tcp->ai = _init_address(name, domain, 0)) == NULL)
return -1;
/* connect to the remote host */
for(aip = tcp->ai; aip != NULL; aip = aip->ai_next)
for(tcp->aip = tcp->ai; tcp->aip != NULL; tcp->aip = tcp->aip->ai_next)
{
tcp->u.client.fd = -1;
/* initialize the client socket */
if(_tcp_socket_init(&tcp->u.client, aip->ai_family, tcp) != 0)
if(_tcp_socket_init(&tcp->u.client, tcp->aip->ai_family,
O_NONBLOCK, tcp) != 0)
continue;
#ifdef DEBUG
if(aip->ai_family == AF_INET)
if(tcp->aip->ai_family == AF_INET)
{
sa = (struct sockaddr_in *)aip->ai_addr;
fprintf(stderr, "DEBUG: %s() %s (%s:%u)\n", __func__,
"connect()", inet_ntoa(sa->sin_addr),
sa = (struct sockaddr_in *)tcp->aip->ai_addr;
fprintf(stderr, "DEBUG: %s() connect(%s:%u)\n", __func__,
inet_ntoa(sa->sin_addr),
ntohs(sa->sin_port));
}
else
fprintf(stderr, "DEBUG: %s() %s %d\n", __func__,
"connect()", aip->ai_family);
fprintf(stderr, "DEBUG: %s() connect(%d)\n", __func__,
tcp->aip->ai_family);
#endif
if(connect(tcp->u.client.fd, aip->ai_addr, aip->ai_addrlen)
!= 0)
if(connect(tcp->u.client.fd, tcp->aip->ai_addr,
tcp->aip->ai_addrlen) != 0)
{
if(errno != EINPROGRESS)
{
@ -242,24 +246,33 @@ static int _init_client(TCP * tcp, char const * name, int domain)
tcp->u.client.fd,
(EventIOFunc)_tcp_callback_connect,
tcp);
event_loop(tcp->helper->event);
}
else
/* listen for any incoming message */
event_register_io_read(tcp->helper->event,
tcp->u.client.fd,
(EventIOFunc)_tcp_socket_callback_read,
&tcp->u.client);
tcp->ai_addrlen = aip->ai_addrlen;
break;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() connect() => %d\n", __func__,
tcp->u.client.fd);
#endif
if(tcp->u.client.fd >= 0)
break;
}
freeaddrinfo(tcp->ai);
tcp->ai = NULL;
return (aip != NULL) ? 0 : -1;
if(tcp->aip == NULL)
return -1;
/* listen for any incoming message */
event_register_io_read(tcp->helper->event, tcp->u.client.fd,
(EventIOFunc)_tcp_socket_callback_read, &tcp->u.client);
/* write pending messages if any */
if(tcp->u.client.bufout_cnt > 0)
{
event_register_io_write(tcp->helper->event, tcp->u.client.fd,
(EventIOFunc)_tcp_socket_callback_write,
&tcp->u.client);
event_loop(tcp->helper->event);
}
return 0;
}
static int _init_server(TCP * tcp, char const * name, int domain)
{
struct addrinfo * aip;
TCPSocket tcpsocket;
#ifdef DEBUG
struct sockaddr_in * sa;
@ -269,27 +282,29 @@ static int _init_server(TCP * tcp, char const * name, int domain)
/* obtain the local address */
if((tcp->ai = _init_address(name, domain, AI_PASSIVE)) == NULL)
return -1;
for(aip = tcp->ai; aip != NULL; aip = aip->ai_next)
for(tcp->aip = tcp->ai; tcp->aip != NULL; tcp->aip = tcp->aip->ai_next)
{
/* create the socket */
if(_tcp_socket_init(&tcpsocket, aip->ai_family, tcp) != 0)
if(_tcp_socket_init(&tcpsocket, tcp->aip->ai_family, O_NONBLOCK,
tcp) != 0)
continue;
/* XXX ugly */
tcp->u.server.fd = tcpsocket.fd;
/* accept incoming connections */
#ifdef DEBUG
if(aip->ai_family == AF_INET)
if(tcp->aip->ai_family == AF_INET)
{
sa = (struct sockaddr_in *)aip->ai_addr;
sa = (struct sockaddr_in *)tcp->aip->ai_addr;
fprintf(stderr, "DEBUG: %s() %s (%s:%u)\n", __func__,
"bind()", inet_ntoa(sa->sin_addr),
ntohs(sa->sin_port));
}
else
fprintf(stderr, "DEBUG: %s() %s %d\n", __func__,
"bind()", aip->ai_family);
"bind()", tcp->aip->ai_family);
#endif
if(bind(tcp->u.server.fd, aip->ai_addr, aip->ai_addrlen) != 0)
if(bind(tcp->u.server.fd, tcp->aip->ai_addr,
tcp->aip->ai_addrlen) != 0)
{
_tcp_error("bind");
close(tcp->u.server.fd);
@ -306,14 +321,11 @@ static int _init_server(TCP * tcp, char const * name, int domain)
tcp->u.server.fd = -1;
continue;
}
tcp->ai_addrlen = aip->ai_addrlen;
event_register_io_read(tcp->helper->event, tcp->u.server.fd,
(EventIOFunc)_tcp_callback_accept, tcp);
break;
}
freeaddrinfo(tcp->ai);
tcp->ai = NULL;
return (aip != NULL) ? 0 : -1;
return (tcp->aip != NULL) ? 0 : -1;
}
@ -358,7 +370,26 @@ static void _destroy_server(TCP * tcp)
/* tcp_client_send */
static int _tcp_client_send(TCP * tcp, AppTransportClient * client,
static int _tcp_client_send(TCP * tcp, AppMessage * message)
{
int ret;
Buffer * buffer;
if(tcp->mode != ATM_CLIENT)
return -error_set_code(1, "%s", "Not a client");
/* send the message */
if((buffer = buffer_new(0, NULL)) == NULL)
return -1;
if((ret = appmessage_serialize(message, buffer)) == 0
&& (ret = _tcp_socket_queue(&tcp->u.client, buffer)) == 0)
event_loop(tcp->helper->event);
buffer_delete(buffer);
return ret;
}
/* tcp_server_send */
static int _tcp_server_send(TCP * tcp, AppTransportClient * client,
AppMessage * message)
{
size_t i;
@ -389,27 +420,6 @@ static int _tcp_client_send(TCP * tcp, AppTransportClient * client,
}
/* tcp_send */
static int _tcp_send(TCP * tcp, AppMessage * message)
{
Buffer * buffer;
if(tcp->mode != ATM_CLIENT)
return -error_set_code(1, "%s", "Not a client");
/* send the message */
if((buffer = buffer_new(0, NULL)) == NULL)
return -1;
if(appmessage_serialize(message, buffer) != 0
|| _tcp_socket_queue(&tcp->u.client, buffer) != 0)
{
buffer_delete(buffer);
return -1;
}
buffer_delete(buffer);
return 0;
}
/* useful */
/* tcp_error */
static int _tcp_error(char const * message)
@ -457,23 +467,27 @@ static int _tcp_server_add_client(TCP * tcp, TCPSocket * client)
/* sockets */
/* tcp_socket_init */
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, TCP * tcp)
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, int flags,
TCP * tcp)
{
int flags;
int f;
if((tcpsocket->fd = socket(domain, SOCK_STREAM, 0)) < 0)
return -_tcp_error("socket");
_tcp_socket_init_fd(tcpsocket, tcp, tcpsocket->fd, NULL, 0);
/* set the socket as non-blocking */
if((flags = fcntl(tcpsocket->fd, F_GETFL)) == -1)
return -_tcp_error("fcntl");
if((flags & O_NONBLOCK) == 0)
if(fcntl(tcpsocket->fd, F_SETFL, flags | O_NONBLOCK) == -1)
/* set the socket flags */
if(flags != 0)
{
if((f = fcntl(tcpsocket->fd, F_GETFL)) == -1)
return -_tcp_error("fcntl");
if((f & flags) != flags)
if(fcntl(tcpsocket->fd, F_SETFL, f | flags) == -1)
return -_tcp_error("fcntl");
}
#ifdef TCP_NODELAY
/* do not wait before sending any traffic */
flags = 1;
setsockopt(fd, SOL_SOCKET, TCP_NODELAY, &flags, sizeof(flags));
f = 1;
setsockopt(fd, SOL_SOCKET, TCP_NODELAY, &f, sizeof(f));
#endif
return 0;
}
@ -593,7 +607,7 @@ static int _accept_client(TCP * tcp, int fd, struct sockaddr * sa,
static int _tcp_callback_accept(int fd, TCP * tcp)
{
struct sockaddr * sa;
socklen_t sa_len = tcp->ai_addrlen;
socklen_t sa_len = tcp->aip->ai_addrlen;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, fd);
@ -652,8 +666,8 @@ static int _accept_client(TCP * tcp, int fd, struct sockaddr * sa,
/* tcp_callback_connect */
static int _tcp_callback_connect(int fd, TCP * tcp)
{
int res;
socklen_t s = sizeof(res);
int ret;
socklen_t s = sizeof(ret);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, fd);
@ -662,7 +676,7 @@ static int _tcp_callback_connect(int fd, TCP * tcp)
if(tcp->u.client.fd != fd)
return -1;
/* obtain the connection status */
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &res, &s) != 0)
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &s) != 0)
{
error_set_code(-errno, "%s: %s", "getsockopt", strerror(errno));
close(fd);
@ -671,33 +685,29 @@ static int _tcp_callback_connect(int fd, TCP * tcp)
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %s\n", __func__, strerror(errno));
#endif
return -1;
ret = -1;
}
if(res != 0)
else if(ret != 0)
{
/* the connection failed */
error_set_code(-res, "%s: %s", "connect", strerror(res));
error_set_code(-ret, "%s: %s", "connect", strerror(ret));
close(fd);
tcp->u.client.fd = -1;
/* FIXME report error */
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %s\n", __func__, strerror(res));
fprintf(stderr, "DEBUG: %s() %s\n", __func__, strerror(ret));
#endif
return -1;
ret = -1;
}
/* listen for any incoming message */
event_register_io_read(tcp->helper->event, fd,
(EventIOFunc)_tcp_socket_callback_read,
&tcp->u.client);
/* write pending messages if any */
if(tcp->u.client.bufout_cnt > 0)
{
event_register_io_write(tcp->helper->event, fd,
(EventIOFunc)_tcp_socket_callback_write,
&tcp->u.client);
return 0;
}
return 1;
else
/* deregister this callback */
ret = 1;
if(tcp->mode == ATM_CLIENT)
event_loop_quit(tcp->helper->event);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() => %d\n", __func__, ret);
#endif
return ret;
}
@ -755,7 +765,7 @@ static AppMessage * _socket_callback_message(TCPSocket * tcpsocket)
tcpsocket->bufin_cnt -= size;
memmove(tcpsocket->bufin, &tcpsocket->bufin[size],
tcpsocket->bufin_cnt);
if((variable_get_as(variable, VT_BUFFER, &buffer)) == 0)
if((variable_get_as(variable, VT_BUFFER, &buffer, NULL)) == 0)
{
message = appmessage_new_deserialize(buffer);
buffer_delete(buffer);
@ -850,6 +860,10 @@ static int _tcp_socket_callback_write(int fd, TCPSocket * tcpsocket)
tcpsocket->bufout_cnt -= ssize;
/* unregister the callback if there is nothing left to write */
if(tcpsocket->bufout_cnt == 0)
{
if(tcpsocket->tcp->mode == ATM_CLIENT)
event_loop_quit(tcpsocket->tcp->helper->event);
return 1;
}
return 0;
}

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012-2013 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2025 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -15,5 +15,6 @@
#define TCP_DOMAIN AF_INET
#define TCP_DOMAIN AF_INET
#define TRANSPORT_DESCRIPTION "Plain TCP/IP (IPv4 only)"
#include "tcp.c"

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012-2013 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2025 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -16,4 +16,5 @@
#define TCP_DOMAIN AF_INET6
#define TRANSPORT_DESCRIPTION "Plain TCP/IP (IPv6 only)"
#include "tcp.c"

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -89,13 +89,13 @@ static Template * _template_init(AppTransportPluginHelper * helper,
static int _init_client(Template * template, char const * name)
{
/* FIXME really implement */
/* TODO implement */
return -1;
}
static int _init_server(Template * template, char const * name)
{
/* FIXME really implement */
/* TODO implement */
return -1;
}
@ -103,6 +103,6 @@ static int _init_server(Template * template, char const * name)
/* template_destroy */
static void _template_destroy(Template * template)
{
/* FIXME really implement */
/* TODO implement */
object_delete(template);
}

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012-2016 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2025 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -126,7 +126,10 @@ static int _udp_callback_read(int fd, UDP * udp);
AppTransportPluginDefinition transport =
{
"UDP",
NULL,
#ifndef TRANSPORT_DESCRIPTION
# define TRANSPORT_DESCRIPTION "Plain UDP"
#endif
TRANSPORT_DESCRIPTION,
_udp_init,
_udp_destroy,
_udp_send,

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2025 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -16,4 +16,5 @@
#define UDP_DOMAIN AF_INET
#define TRANSPORT_DESCRIPTION "Plain UDP (IPv4 only)"
#include "udp.c"

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2012 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2012-2025 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -16,4 +16,5 @@
#define UDP_DOMAIN AF_INET6
#define TRANSPORT_DESCRIPTION "Plain UDP (IPv6 only)"
#include "udp.c"

4
tests/.gitignore vendored
View File

@ -1,4 +1,6 @@
/AppBroker
/Dummy.h
/Test.h
/appclient
/appinterface
/appmessage
@ -6,5 +8,7 @@
/fixme.log
/includes
/lookup
/pkgconfig.log
/shlint.log
/tests.log
/transport

18
tests/appbroker.c Normal file
View File

@ -0,0 +1,18 @@
/* $Id$ */
/* Copyright (c) 2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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, version 3 of the License.
*
* 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, see <http://www.gnu.org/licenses/>. */
#include "../tools/appbroker.c"

View File

@ -1,6 +1,6 @@
#!/bin/sh
#$Id$
#Copyright (c) 2011-2019 Pierre Pronchery <khorben@defora.org>
#Copyright (c) 2011-2020 Pierre Pronchery <khorben@defora.org>
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
@ -27,7 +27,7 @@
#variables
PROGNAME="appbroker.sh"
#executables
APPBROKER="AppBroker"
APPBROKER=
DEBUG="_debug"
@ -85,6 +85,17 @@ fi
[ "$clean" -ne 0 ] && exit 0
if [ -z "$APPBROKER" ]; then
if [ -n "$PKG_CONFIG_SYSROOT_DIR" ]; then
#XXX cross-compiling (requires AppBroker(1) installed)
APPBROKER="AppBroker$EXEEXT"
elif [ -n "$OBJDIR" ]; then
APPBROKER="${OBJDIR}AppBroker$EXEEXT"
else
APPBROKER="./AppBroker$EXEEXT"
fi
fi
exec 3>&1
while [ $# -gt 0 ]; do
target="$1"
@ -92,6 +103,8 @@ while [ $# -gt 0 ]; do
source="${target#$OBJDIR}"
appinterface="${source##*/}"
appinterface="${appinterface%%.h}.interface"
appinterface="${appinterface%.h}.interface"
#XXX also look in ../data
[ ! -f "$appinterface" ] && appinterface="../data/$appinterface"
_appbroker "$target" "$appinterface" || exit 2
done

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2014 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2014-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -19,7 +19,6 @@
#include <stdio.h>
#include <System/error.h>
#include "App/appserver.h"
/* FIXME does not survive OBJDIR */
#include "Dummy.h"

View File

@ -1,6 +1,6 @@
#!/bin/sh
#$Id$
#Copyright (c) 2017-2019 Pierre Pronchery <khorben@defora.org>
#Copyright (c) 2017-2022 Pierre Pronchery <khorben@defora.org>
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
@ -25,23 +25,30 @@
#variables
CONFIGSH="${0%/fixme.sh}/../config.sh"
PROGNAME="fixme.sh"
PROJECTCONF="../project.conf"
REGEXP_ERROR="FIXME"
REGEXP_WARNING="\\(TODO\|XXX\\)"
#executables
DATE="date"
DEBUG="_debug"
FIND="find"
GREP="grep"
HEAD="head"
MKDIR="mkdir -p"
SORT="sort -n"
TR="tr"
[ -f "$CONFIGSH" ] && . "$CONFIGSH"
#functions
#fixme
_fixme()
{
res=0
subdirs=
$DATE
echo
@ -56,27 +63,14 @@ _fixme()
;;
esac
done < "$PROJECTCONF"
if [ ! -n "$subdirs" ]; then
_error "Could not locate directories to analyze"
return $?
fi
for subdir in $subdirs; do
[ -d "../$subdir" ] || continue
for filename in $($FIND "../$subdir" -type f | $SORT); do
callback=
ext=${filename##*/}
ext=${ext%.in}
ext=${ext##*.}
case "$ext" in
asm|S)
callback="_fixme_asm"
;;
c|cc|cpp|cxx|h|js)
callback="_fixme_c"
;;
conf|sh)
callback="_fixme_sh"
;;
htm|html|xml)
callback="_fixme_xml"
;;
esac
callback=$(_fixme_callback "$filename")
[ -n "$callback" ] || continue
($callback "$filename") 2>&1
if [ $? -ne 0 ]; then
@ -88,54 +82,114 @@ _fixme()
return $res
}
_fixme_asm()
_fixme_callback()
{
filename="$1"
ext=${filename##*/}
ext=${ext%.in}
ext=${ext##*.}
callback=
case "$ext" in
asm|S)
echo "_fixme_callback_asm"
return 0
;;
c|cc|cpp|cxx|go|h|js|v)
echo "_fixme_callback_c"
return 0
;;
conf|sh)
echo "_fixme_callback_sh"
return 0
;;
py)
echo "_fixme_callback_python"
return 0
;;
htm|html|xml|xsl)
echo "_fixme_callback_xml"
return 0
;;
esac
case $($HEAD -n 1 "$filename") in
"#!/bin/sh"*|"#! /bin/sh"*|\
"#!/usr/bin/env bash"*|"#! /usr/bin/env bash"*)
echo "_fixme_callback_sh"
return 0
;;
"#!/usr/bin/env python"*|"#! /usr/bin/env python"*)
echo "_fixme_callback_python"
return 0
;;
"<!DOCTYPE"*|"<!doctype"*|"<HTML"*|"<html"*|"<?xml"*)
echo "_fixme_callback_xml"
return 0
;;
esac
return 2
}
_fixme_callback_asm()
{
res=0
filename="$1"
#warnings
$GREP -nH '/\*.*\(TODO\|XXX\)' "$filename"
$GREP -nH "/\\*.*$REGEXP_WARNING" "$filename"
#failures
$GREP -nH '/\*.*FIXME' "$filename" && res=2
$GREP -nH "/\\*.*$REGEXP_ERROR" "$filename" && res=2
return $res
}
_fixme_c()
_fixme_callback_c()
{
res=0
filename="$1"
#warnings
$GREP -nH '/\(/\|\*\).*\(TODO\|XXX\)' "$filename"
$GREP -nH "/\\(/\\|\\*\\).*$REGEXP_WARNING" "$filename"
#failures
$GREP -nH '/\(/\|\*\).*FIXME' "$filename" && res=2
$GREP -nH "/\\(/\\|\\*\\).*$REGEXP_ERROR" "$filename" && res=2
return $res
}
_fixme_sh()
_fixme_callback_python()
{
res=0
filename="$1"
#XXX avoid matching the regexp
comment="#"
#warnings
$GREP -nH "$comment.*\\(TODO\\|XXX\\)" "$filename"
$GREP -nH "$comment.*$REGEXP_WARNING" "$filename"
#failures
$GREP -nH "$comment.*FIXME" "$filename" && res=2
$GREP -nH "$comment.*$REGEXP_ERROR" "$filename" && res=2
return $res
}
_fixme_xml()
_fixme_callback_sh()
{
res=0
filename="$1"
comment="#"
#warnings
$GREP -nH "$comment.*$REGEXP_WARNING" "$filename"
#failures
$GREP -nH "$comment.*$REGEXP_ERROR" "$filename" && res=2
return $res
}
_fixme_callback_xml()
{
res=0
filename="$1"
#XXX limited to a single line
#warnings
$GREP -nH '<!--.*\(TODO\|XXX\)' "$filename"
$GREP -nH "<!--.*$REGEXP_WARNING" "$filename"
#failures
$GREP -nH '<!--.*FIXME' "$filename" && res=2
$GREP -nH "<!--.*$REGEXP_ERROR" "$filename" && res=2
return $res
}
@ -145,10 +199,14 @@ _debug()
{
echo "$@" 1>&3
"$@"
res=$?
#ignore errors when the command is not available
[ $res -eq 127 ] && return 0
return $res
}
#error
_error()
{
echo "$PROGNAME: $@" 1>&2
return 2
}

View File

@ -1,6 +1,6 @@
#!/bin/sh
#$Id$
#Copyright (c) 2016 Pierre Pronchery <khorben@defora.org>
#Copyright (c) 2016-2025 Pierre Pronchery <khorben@defora.org>
#This file is part of DeforaOS Desktop libDesktop
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
@ -23,35 +23,94 @@
#OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#variables
PACKAGE="libApp"
CONFIGSH="${0%/pkgconfig.sh}/../config.sh"
PKG_CONFIG_PATH="$OBJDIR../data:$PKG_CONFIG_PATH"
PKG_CONFIG_PATH="${PKG_CONFIG_PATH%:}"
PROGNAME="pkgconfig.sh"
#executables
ECHO="echo"
PKGCONFIG="pkg-config"
UNAME="uname"
[ "$($UNAME -s)" != "Darwin" ] || ECHO="/bin/echo"
[ -f "$CONFIGSH" ] && . "$CONFIGSH"
#functions
#pkgconfig
_pkgconfig()
{
{(
ret=0
_pkgconfig_do "EXISTS:" --exists "$PACKAGE" || return 2
_pkgconfig_do "VERSION:" --modversion "$PACKAGE" || ret=3
_pkgconfig_do "CFLAGS: " --cflags "$PACKAGE" || ret=4
_pkgconfig_do "LIBS: " --libs "$PACKAGE" || ret=5
_pkgconfig_do "PROVIDES:" --print-provides "$PACKAGE" || ret=6
_pkgconfig_do "REQUIRES:" --print-requires "$PACKAGE" || ret=7
return $ret
)}
_pkgconfig_do()
{
caption="$1"
options="$2"
packages="$3"
echo -n "$caption"
output=$($PKGCONFIG $options "$packages")
ret=$?
echo "$output"
return $ret
$ECHO -n "$caption"
PKG_CONFIG_PATH="$PKG_CONFIG_PATH" $PKGCONFIG $options "$packages"
}
_pkgconfig "EXISTS:" --exists "$PACKAGE" || exit 2
#usage
_usage()
{
echo "Usage: $PROGNAME [-c] target..." 1>&2
return 1
}
#main
clean=0
while getopts "cO:P:" name; do
case "$name" in
c)
clean=1
;;
O)
export "${OPTARG%%=*}"="${OPTARG#*=}"
;;
P)
#XXX ignored for compatibility
;;
?)
_usage
exit $?
;;
esac
done
shift $((OPTIND - 1))
if [ $# -lt 1 ]; then
_usage
exit $?
fi
#clean
[ $clean -ne 0 ] && exit 0
exec 3>&1
ret=0
while [ $# -gt 0 ]; do
target="$1"
dirname="${target%/*}"
shift
_pkgconfig "VERSION:" --modversion "$PACKAGE" || ret=3
_pkgconfig "CFLAGS: " --cflags "$PACKAGE" || ret=4
_pkgconfig "LIBS: " --libs "$PACKAGE" || ret=5
_pkgconfig "PROVIDES:" --print-provides "$PACKAGE" || ret=6
_pkgconfig "REQUIRES:" --print-requires "$PACKAGE" || ret=7
if [ -n "$dirname" -a "$dirname" != "$target" ]; then
$MKDIR -- "$dirname" || ret=$?
fi
_pkgconfig > "$target" || ret=$?
done
exit $ret

View File

@ -1,49 +1,43 @@
targets=Dummy.h,appclient,appinterface,appmessage,appserver,fixme.log,includes,lookup,shlint.log,tests.log,transport
cppflags_force=-I../include -I$(OBJDIR).
targets=AppBroker,Dummy.h,appclient,appinterface,appmessage,appserver,fixme.log,includes,lookup,pkgconfig.log,shlint.log,tests.log,transport
cppflags_force=-I../include -I. -I$(OBJDIR).
cflags_force=`pkg-config --cflags libSystem`
cflags=-W -Wall -g -O2 -fPIE -D_FORTIFY_SOURCE=2 -fstack-protector-all
cflags=-W -Wall -g -O2 -fPIE -D_FORTIFY_SOURCE=2 -fstack-protector
ldflags_force=`pkg-config --libs libSystem` -L$(OBJDIR)../src -Wl,-rpath,$(OBJDIR)../src -lApp
ldflags=-pie -Wl,-z,relro -Wl,-z,now -rdynamic
dist=System/App.h,appbroker.sh,fixme.sh,Makefile,Test.expected,Test.interface,pkgconfig.sh,shlint.sh,tests.sh
#targets
[AppBroker]
type=binary
sources=appbroker.c
depends=$(OBJDIR)../src/libApp.a
ldflags=$(OBJDIR)../src/libApp.a
[Dummy.h]
type=script
script=../tools/appbroker.sh
flags=-O APPBROKER=$(OBJDIR)../tools/AppBroker$(EXEEXT)
depends=../data/Dummy.interface,../tools/appbroker.sh
script=./appbroker.sh
depends=../data/Dummy.interface,appbroker.sh
[appclient]
type=binary
sources=appclient.c
ldflags=$(OBJDIR)../src/libApp.a
[appclient.c]
depends=$(OBJDIR)../src/libApp.a
[appinterface]
type=binary
sources=appinterface.c
ldflags=$(OBJDIR)../src/libApp.a
[appinterface.c]
depends=$(OBJDIR)../src/libApp.a
[appmessage]
type=binary
sources=appmessage.c
ldflags=$(OBJDIR)../src/libApp.a
[appmessage.c]
depends=$(OBJDIR)../src/libApp.a
[appserver]
type=binary
sources=appserver.c
ldflags=$(OBJDIR)../src/libApp.a
[appserver.c]
depends=$(OBJDIR)../src/libApp.a,$(OBJDIR)Dummy.h
[fixme.log]
type=script
script=./fixme.sh
@ -58,22 +52,46 @@ sources=includes.c
type=binary
sources=lookup.c
[lookup.c]
depends=../src/apptransport.h
[pkgconfig.log]
type=script
script=./pkgconfig.sh
depends=$(OBJDIR)../data/libApp.pc,pkgconfig.sh
enabled=0
[shlint.log]
type=script
script=./shlint.sh
depends=$(OBJDIR)../src/libApp.a,shlint.sh
enabled=0
[tests.log]
type=script
script=./tests.sh
depends=Test.expected,Test.interface,$(OBJDIR)../tools/AppBroker$(EXEEXT),appbroker.sh,$(OBJDIR)appclient$(EXEEXT),$(OBJDIR)appmessage$(EXEEXT),$(OBJDIR)appserver$(EXEEXT),$(OBJDIR)includes$(EXEEXT),$(OBJDIR)lookup$(EXEEXT),pkgconfig.sh,tests.sh,$(OBJDIR)transport$(EXEEXT),../src/transport/tcp.c,../src/transport/udp.c
depends=Test.expected,Test.interface,$(OBJDIR)AppBroker$(EXEEXT),appbroker.sh,$(OBJDIR)appclient$(EXEEXT),$(OBJDIR)appmessage$(EXEEXT),$(OBJDIR)appserver$(EXEEXT),$(OBJDIR)includes$(EXEEXT),$(OBJDIR)lookup$(EXEEXT),tests.sh,$(OBJDIR)transport$(EXEEXT),../src/transport/tcp.c,../src/transport/udp.c
enabled=0
[transport]
type=binary
sources=transport.c
#sources
[appbroker.c]
depends=../tools/appbroker.c
[appclient.c]
depends=$(OBJDIR)../src/libApp.a
[appinterface.c]
depends=$(OBJDIR)../src/libApp.a
[appmessage.c]
depends=$(OBJDIR)../src/libApp.a
[appserver.c]
depends=$(OBJDIR)../src/libApp.a,$(OBJDIR)Dummy.h
[lookup.c]
depends=../src/apptransport.h
[transport.c]
depends=$(OBJDIR)../src/libApp.a

View File

@ -1,6 +1,6 @@
#!/bin/sh
#$Id$
#Copyright (c) 2014-2017 Pierre Pronchery <khorben@defora.org>
#Copyright (c) 2014-2021 Pierre Pronchery <khorben@defora.org>
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
@ -25,26 +25,30 @@
#variables
CONFIGSH="${0%/shlint.sh}/../config.sh"
PROGNAME="shlint.sh"
PROJECTCONF="../project.conf"
#executables
DATE="date"
DEBUG="_debug"
ECHO="/bin/echo"
FIND="find"
MKDIR="mkdir -p"
SHLINT="sh -n"
SORT="sort -n"
TR="tr"
[ -f "$CONFIGSH" ] && . "$CONFIGSH"
#functions
#shlint
_shlint()
{
ret=0
subdirs="data doc src tests tools"
res=0
subdirs=
$DATE
echo
while read line; do
case "$line" in
"["*)
@ -56,19 +60,30 @@ _shlint()
;;
esac
done < "$PROJECTCONF"
if [ ! -n "$subdirs" ]; then
_error "Could not locate directories to analyze"
return $?
fi
for subdir in $subdirs; do
[ -d "../$subdir" ] || continue
for filename in $($FIND "../$subdir" -type f -a -name '*.sh' | $SORT); do
while read filename; do
[ -n "$filename" ] || continue
echo
$ECHO -n "$filename:"
_shlint_file "$filename"
if [ $? -eq 0 ]; then
echo "$filename:"
echo " OK"
echo "$PROGNAME: $filename: OK" 1>&2
else
echo "FAIL"
echo "$PROGNAME: $filename: FAIL" 1>&2
ret=2
res=2
fi
done
done << EOF
$($FIND "../$subdir" -type f -a -iname '*.sh' | $SORT)
EOF
done
return $ret
return $res
}
_shlint_file()
@ -88,7 +103,7 @@ _shlint_file()
esac
done < "$filename"
if [ $warn -ne 0 ]; then
_warning "$filename: return instead of exit in the global scope"
_error "$filename: return instead of exit in the global scope"
fi
return 0
}
@ -99,10 +114,14 @@ _debug()
{
echo "$@" 1>&3
"$@"
res=$?
#ignore errors when the command is not available
[ $res -eq 127 ] && return 0
return $res
}
#error
_error()
{
echo "$PROGNAME: $@" 1>&2
return 2
}
@ -114,14 +133,6 @@ _usage()
}
#warning
_warning()
{
echo "$PROGNAME: $@" 1>&2
return 2
}
#main
clean=0
while getopts "cO:P:" name; do
@ -151,9 +162,15 @@ fi
[ $clean -ne 0 ] && exit 0
exec 3>&1
ret=0
while [ $# -gt 0 ]; do
target="$1"
dirname="${target%/*}"
shift
_shlint > "$target" || exit 2
if [ -n "$dirname" -a "$dirname" != "$target" ]; then
$MKDIR -- "$dirname" || ret=$?
fi
_shlint > "$target" || ret=$?
done
exit $ret

View File

@ -1,6 +1,6 @@
#!/bin/sh
#$Id$
#Copyright (c) 2012-2019 Pierre Pronchery <khorben@defora.org>
#Copyright (c) 2012-2025 Pierre Pronchery <khorben@defora.org>
#This file is part of DeforaOS System libApp
#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
@ -20,6 +20,9 @@ PROGNAME="tests.sh"
#executables
DATE="date"
DEBUG="_debug"
ECHO="echo"
UNAME="uname"
[ "$($UNAME -s)" != "Darwin" ] || ECHO="/bin/echo"
#functions
@ -67,7 +70,7 @@ _run()
shift
shift
echo -n "$test:" 1>&2
$ECHO -n "$test:" 1>&2
(echo
echo "Testing: $test $name ($OBJDIR)"
[ -n "$OBJDIR" ] || OBJDIR="./"
@ -159,7 +162,6 @@ while [ $# -ne 0 ]; do
-n "tcp4:localhost:4242"
APPSERVER_Session="tcp:localhost:4242" _test "lookup" \
"lookup Session" -a "Session"
_test "pkgconfig.sh" "pkg-config"
_test "transport" "tcp4 127.0.0.1:4242" -p tcp4 127.0.0.1:4242
_test "transport" "tcp4 localhost:4242" -p tcp4 localhost:4242
_test "transport" "tcp6 ::1.4242" -p tcp6 ::1.4242

1
tools/.gitignore vendored
View File

@ -1,2 +1,3 @@
/AppBroker
/AppClient
/AppTransport

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2011-2016 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2011-2025 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -20,9 +20,12 @@
#include <string.h>
#include <errno.h>
#include <System.h>
#include "App.h"
#include "App/appserver.h"
#include "App/apptransport.h"
#define PROGNAME_APPBROKER "AppBroker"
#ifndef PROGNAME_APPBROKER
# define PROGNAME_APPBROKER "AppBroker"
#endif
/* AppBroker */
@ -325,7 +328,7 @@ static int _appbroker_foreach_call_arg(AppBroker * appbroker, char const * sep,
}
if(appbroker->fp != NULL)
fprintf(appbroker->fp, "%s%s%s%s", sep, ctype,
(p != NULL && string_length(p + 1)) ? " " : "",
(p != NULL && string_get_length(p + 1)) ? " " : "",
(p != NULL) ? p + 1 : "");
return 0;
}

View File

@ -1,106 +0,0 @@
#!/bin/sh
#$Id$
#Copyright (c) 2011-2016 Pierre Pronchery <khorben@defora.org>
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
#FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
#CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#variables
PROGNAME="appbroker.sh"
#executables
APPBROKER=
DEBUG="_debug"
#functions
#appbroker
_appbroker()
{
target="$1"
appinterface="$2"
$DEBUG $APPBROKER -o "$target" "$appinterface"
}
#debug
_debug()
{
echo "$@" 1>&3
"$@"
}
#usage
_usage()
{
echo "Usage: $PROGNAME [-c] target..." 1>&2
return 1
}
#main
clean=0
while getopts "cO:P:" name; do
case "$name" in
c)
clean=1
;;
O)
export "${OPTARG%%=*}"="${OPTARG#*=}"
;;
P)
#XXX ignored for compatibility
;;
?)
_usage
exit $?
;;
esac
done
shift $((OPTIND - 1))
if [ $# -eq 0 ]; then
_usage
exit $?
fi
[ "$clean" -ne 0 ] && exit 0
if [ -n "$PKG_CONFIG_SYSROOT_DIR" ]; then
#XXX cross-compiling (requires AppBroker(1) installed)
APPBROKER="AppBroker$EXEEXT"
elif [ -z "$APPBROKER" ]; then
APPBROKER="$OBJDIR../tools/AppBroker$EXEEXT"
#XXX ugly workaround
export LD_LIBRARY_PATH="$OBJDIR../src"
fi
exec 3>&1
while [ $# -gt 0 ]; do
target="$1"
shift
source="${target#$OBJDIR}"
appinterface="${source##*/}"
appinterface="../data/${appinterface%%.h}.interface"
_appbroker "$target" "$appinterface" || exit 2
done

View File

@ -1,5 +1,5 @@
/* $Id$ */
/* Copyright (c) 2011-2016 Pierre Pronchery <khorben@defora.org> */
/* Copyright (c) 2011-2025 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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
@ -15,16 +15,17 @@
#include <inttypes.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <System.h>
#include "App.h"
#include "App/appclient.h"
#ifndef PROGNAME
# define PROGNAME "AppClient"
#ifndef PROGNAME_APPCLIENT
# define PROGNAME_APPCLIENT "AppClient"
#endif
@ -75,13 +76,13 @@ static int _appclient(int verbose, char const * app, char const * name,
app, name, (void *)calls, calls_cnt);
#endif
if((ac = appclient_new(NULL, app, name)) == NULL)
return _error(PROGNAME, 1);
return _error(PROGNAME_APPCLIENT, 1);
if(verbose != 0)
puts("Connected.");
for(i = 0; i < calls_cnt; i++)
if(_appclient_call(verbose, ac, &calls[i]) != 0)
{
ret |= _error(PROGNAME, 1);
ret |= _error(PROGNAME_APPCLIENT, 1);
break;
}
if(verbose != 0)
@ -95,9 +96,10 @@ static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
int ret = 0;
Variable * v;
VariableType type;
int64_t res;
double dres;
int64_t ires;
String * sres;
uint64_t ures;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
@ -206,23 +208,35 @@ static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
{
case VT_BOOL:
case VT_INT8:
case VT_UINT8:
case VT_INT16:
case VT_UINT16:
case VT_INT32:
case VT_UINT32:
case VT_INT64:
if(variable_get_as(v, VT_INT64, &ires, NULL)
== 0)
printf("\"%s\"%s%" PRId64 "\n",
call->name,
" returned ", ires);
else
printf("\"%s\"%s\n", call->name,
" returned");
break;
case VT_UINT8:
case VT_UINT16:
case VT_UINT32:
case VT_UINT64:
if(variable_get_as(v, VT_INT64, &res) == 0)
printf("\"%s\"%s%ld\n", call->name,
" returned ", res);
if(variable_get_as(v, VT_UINT64, &ures, NULL)
== 0)
printf("\"%s\"%s%" PRIu64 "\n",
call->name,
" returned ", ures);
else
printf("\"%s\"%s\n", call->name,
" returned");
break;
case VT_FLOAT:
case VT_DOUBLE:
if(variable_get_as(v, VT_DOUBLE, &dres) == 0)
if(variable_get_as(v, VT_DOUBLE, &dres, NULL)
== 0)
printf("\"%s\"%s%f\n", call->name,
" returned ", dres);
else
@ -231,7 +245,8 @@ static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
break;
case VT_STRING:
sres = NULL;
if(variable_get_as(v, VT_STRING, &sres) == 0)
if(variable_get_as(v, VT_STRING, &sres, NULL)
== 0)
printf("\"%s\"%s\"%s\"\n", call->name,
" returned ", sres);
else
@ -261,7 +276,7 @@ static int _error(char const * message, int ret)
/* usage */
static int _usage(void)
{
fputs("Usage: " PROGNAME " [-v][-H hostname] -S service"
fputs("Usage: " PROGNAME_APPCLIENT " [-v][-H hostname] -S service"
" [-C call [-d double|-f float|-i integer|-s string]...]...\n"
" -v Be more verbose\n"
" -H Hostname to connect to\n"
@ -328,7 +343,7 @@ int main(int argc, char * argv[])
return _usage();
}
if(res != 0)
return _error(PROGNAME, 2);
return _error(PROGNAME_APPCLIENT, 2);
}
if(app == NULL)
return _usage();

132
tools/apptransport.c Normal file
View File

@ -0,0 +1,132 @@
/* $Id$ */
/* Copyright (c) 2025 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* 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, version 3 of the License.
*
* 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, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <System/error.h>
#include <System/plugin.h>
#include "App/apptransport.h"
#include "../config.h"
#ifndef PROGNAME_APPTRANSPORT
# define PROGNAME_APPTRANSPORT "AppTransport"
#endif
/* AppTransport */
/* private */
/* prototypes */
static int _apptransport_list(void);
static int _error(char const * message, int ret);
static int _usage(void);
/* functions */
/* apptransport_list */
static int _apptransport_list(void)
{
#if defined(__APPLE__)
char const soext[] = ".dylib";
#elif defined(__WIN32__)
char const soext[] = ".dll";
#else
char const soext[] = ".so";
#endif
DIR * dir;
struct dirent * de;
size_t len;
String * path;
Plugin * plugin;
AppTransportPluginDefinition * transport;
if((dir = opendir(APP_TRANSPORT_PATH)) == NULL)
return _error(APP_TRANSPORT_PATH, -1);
while((de = readdir(dir)) != NULL)
{
if((len = strlen(de->d_name)) < sizeof(soext))
continue;
if(strcmp(&de->d_name[len - sizeof(soext) + 1], soext) != 0)
continue;
if((path = string_new_append(APP_TRANSPORT_PATH "/", de->d_name,
NULL)) == NULL)
{
_error(PROGNAME_APPTRANSPORT, -1);
continue;
}
plugin = plugin_new_path(path);
string_delete(path);
if(plugin == NULL)
{
_error(PROGNAME_APPTRANSPORT, -1);
continue;
}
if((transport = plugin_lookup(plugin, "transport")) == NULL)
{
_error(PROGNAME_APPTRANSPORT, -1);
plugin_delete(plugin);
continue;
}
de->d_name[len - sizeof(soext) + 1] = '\0';
printf("%s (%s): %s\n", de->d_name, transport->name,
transport->description);
plugin_delete(plugin);
}
closedir(dir);
return 0;
}
/* error */
static int _error(char const * message, int ret)
{
error_print(message);
return ret;
}
/* usage */
static int _usage(void)
{
fputs("Usage: " PROGNAME_APPTRANSPORT " -l\n", stderr);
return 1;
}
/* public */
/* functions */
/* main */
int main(int argc, char * argv[])
{
int o;
int list = 0;
while((o = getopt(argc, argv, "l")) != -1)
switch(o)
{
case 'l':
list = 1;
break;
default:
return _usage();
}
if(optind != argc || list == 0)
return _usage();
return (_apptransport_list() == 0) ? 0 : 2;
}

View File

@ -1,12 +1,13 @@
targets=AppBroker,AppClient
cppflags_force=-I ../include
targets=AppBroker,AppClient,AppTransport
cppflags_force=-I ../include -I $(OBJDIR)../include/App
cppflags=
cflags_force=`pkg-config --cflags libSystem libMarshall`
cflags=-W -Wall -g -O2 -fPIE -D_FORTIFY_SOURCE=2 -fstack-protector-all
cflags=-W -Wall -g -O2 -fPIE -D_FORTIFY_SOURCE=2 -fstack-protector
ldflags_force=-L$(OBJDIR)../src `pkg-config --libs libSystem libMarshall` -lApp
ldflags=-pie -Wl,-z,relro -Wl,-z,now
dist=Makefile,appbroker.sh
dist=Makefile,tools.sh
#targets
[AppBroker]
type=binary
sources=appbroker.c
@ -16,3 +17,18 @@ install=$(BINDIR)
type=binary
sources=appclient.c
#install=$(BINDIR)
[AppTransport]
type=binary
sources=apptransport.c
install=$(BINDIR)
#sources
[appbroker.c]
depends=../include/App/appserver.h,../include/App/apptransport.h
[appclient.c]
depends=../include/App/appclient.h
[apptransport.c]
depends=$(OBJDIR)../include/App/app.h,../include/App/apptransport.h

213
tools/subst.sh Executable file
View File

@ -0,0 +1,213 @@
#!/bin/sh
#$Id$
#Copyright (c) 2012-2022 Pierre Pronchery <khorben@defora.org>
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
#FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
#CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#variables
CONFIGSH="${0%/subst.sh}/../config.sh"
PREFIX="/usr/local"
BINDIR=
DATADIR=
DEVNULL="/dev/null"
INCLUDEDIR=
LDSO=
LIBDIR=
LIBEXECDIR=
MANDIR=
PROGNAME="subst.sh"
SBINDIR=
SYSCONFDIR=
#executables
CHMOD="chmod"
DATE="date"
DEBUG="_debug"
INSTALL="install"
MKDIR="mkdir -m 0755 -p"
RM="rm -f"
SED="sed"
[ -f "$CONFIGSH" ] && . "$CONFIGSH"
#functions
#subst
_subst()
{
#check the variables
if [ -z "$PACKAGE" ]; then
_error "The PACKAGE variable needs to be set"
return $?
fi
if [ -z "$VERSION" ]; then
_error "The VERSION variable needs to be set"
return $?
fi
[ -z "$BINDIR" ] && BINDIR="$PREFIX/bin"
[ -z "$DATADIR" ] && DATADIR="$PREFIX/share"
[ -z "$INCLUDEDIR" ] && INCLUDEDIR="$PREFIX/include"
if [ -z "$LDSO" ]; then
case "$(uname -s)" in
FreeBSD)
LDSO="/libexec/ld-elf.so.1"
;;
Linux)
LDSO="/lib/ld-linux-$(uname -m | tr _ -).so.2"
;;
*)
LDSO="/libexec/ld.elf_so"
;;
esac
fi
[ -z "$LIBDIR" ] && LIBDIR="$PREFIX/lib"
[ -z "$LIBEXECDIR" ] && LIBEXECDIR="$PREFIX/libexec"
[ -z "$MANDIR" ] && MANDIR="$DATADIR/man"
if [ -z "$SYSCONFDIR" ]; then
SYSCONFDIR="$PREFIX/etc"
[ "$PREFIX" = "/usr" ] && SYSCONFDIR="/etc"
fi
[ -z "$SBINDIR" ] && SBINDIR="$PREFIX/sbin"
while [ $# -gt 0 ]; do
target="$1"
shift
#clean
[ "$clean" -ne 0 ] && continue
#uninstall
if [ "$uninstall" -eq 1 ]; then
$DEBUG $RM -- "$PREFIX/$target" || return 2
continue
fi
#install
if [ "$install" -eq 1 ]; then
source="${target#$OBJDIR}"
$DEBUG $MKDIR -- "$PREFIX" || return 2
mode="-m 0644"
[ -x "${source}.in" ] && mode="-m 0755"
$DEBUG $INSTALL $mode "$target" "$PREFIX/$source" \
|| return 2
continue
fi
#create
source="${target#$OBJDIR}"
source="${source}.in"
([ -z "$OBJDIR" ] || $DEBUG $MKDIR -- "${target%/*}") \
|| return 2
$DEBUG $SED -e "s;@VENDOR@;$VENDOR;g" \
-e "s;@PACKAGE@;$PACKAGE;g" \
-e "s;@VERSION@;$VERSION;g" \
-e "s;@PREFIX@;$PREFIX;g" \
-e "s;@BINDIR@;$BINDIR;g" \
-e "s;@DATADIR@;$DATADIR;g" \
-e "s;@DATE@;$DATE;g" \
-e "s;@INCLUDEDIR@;$INCLUDEDIR;g" \
-e "s;@LDSO@;$LDSO;g" \
-e "s;@LIBDIR@;$LIBDIR;g" \
-e "s;@LIBEXECDIR@;$LIBEXECDIR;g" \
-e "s;@MANDIR@;$MANDIR;g" \
-e "s;@PWD@;$PWD;g" \
-e "s;@SBINDIR@;$SBINDIR;g" \
-e "s;@SYSCONFDIR@;$SYSCONFDIR;g" \
-- "$source" > "$target"
if [ $? -ne 0 ]; then
$RM -- "$target" 2> "$DEVNULL"
return 2
elif [ -x "$source" ]; then
$DEBUG $CHMOD -- 0755 "$target"
fi
done
return 0
}
#debug
_debug()
{
echo "$@" 1>&3
"$@"
}
#error
_error()
{
echo "$PROGNAME: $@" 1>&2
return 2
}
#usage
_usage()
{
echo "Usage: $PROGNAME [-c|-i|-u][-P prefix] target..." 1>&2
return 1
}
#main
clean=0
install=0
uninstall=0
while getopts "ciuO:P:" name; do
case $name in
c)
clean=1
;;
i)
uninstall=0
install=1
;;
u)
install=0
uninstall=1
;;
O)
export "${OPTARG%%=*}"="${OPTARG#*=}"
;;
P)
PREFIX="$OPTARG"
;;
?)
_usage
exit $?
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -lt 1 ]; then
_usage
exit $?
fi
if [ -n "$SOURCE_DATE_EPOCH" ]; then
DATE="$($DATE -d "@$SOURCE_DATE_EPOCH" '+%B %d, %Y')"
else
DATE="$($DATE '+%B %d, %Y')"
fi
exec 3>&1
_subst "$@"