summaryrefslogtreecommitdiffabout
authorMichael Krelin <hacker@klever.net>2009-03-08 20:09:21 (UTC)
committer Michael Krelin <hacker@klever.net>2009-03-08 20:09:21 (UTC)
commitaadaa8b5d7eda23e72dbded9d6437b40358353f3 (patch) (unidiff)
tree0bff6fdde1e2b9be02b48aaf7d03f095604718e1
downloadiii-aadaa8b5d7eda23e72dbded9d6437b40358353f3.zip
iii-aadaa8b5d7eda23e72dbded9d6437b40358353f3.tar.gz
iii-aadaa8b5d7eda23e72dbded9d6437b40358353f3.tar.bz2
Inital commit to public repository0.0
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--.gitignore14
-rw-r--r--AUTHORS12
-rw-r--r--COPYING19
-rw-r--r--ChangeLog0
-rw-r--r--Makefile.am16
-rw-r--r--NEWS2
-rw-r--r--NEWS.xml6
-rw-r--r--NEWS.xsl24
-rw-r--r--README0
-rw-r--r--autogen.sh8
-rw-r--r--configure.ac71
-rw-r--r--debian/changelog5
-rw-r--r--debian/compat1
-rw-r--r--debian/control13
l---------debian/copyright1
-rw-r--r--debian/dirs3
-rw-r--r--debian/docs2
-rw-r--r--debian/examples1
-rwxr-xr-xdebian/iii.init57
-rwxr-xr-xdebian/iii.postinst18
-rwxr-xr-xdebian/iii.postrm3
-rwxr-xr-xdebian/iii.prerm4
-rwxr-xr-xdebian/rules11
-rw-r--r--doc/.gitignore1
-rw-r--r--doc/000000000000.conf17
-rw-r--r--doc/Makefile.am6
-rw-r--r--doc/iiid.8.in106
-rw-r--r--scripts/xml2sh.xsl28
-rw-r--r--src/.gitignore10
-rw-r--r--src/Makefile.am32
-rw-r--r--src/eyefi.h47
-rw-r--r--src/eyefiservice.cc186
-rw-r--r--src/eyefiworker.cc26
-rw-r--r--src/eyefiworker.h15
-rw-r--r--src/eyekinfig.cc67
-rw-r--r--src/eyekinfig.h25
-rw-r--r--src/eyetil.cc103
-rw-r--r--src/eyetil.h48
-rw-r--r--src/iiid.cc86
39 files changed, 1094 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0e9c1c2
--- a/dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
1Makefile
2Makefile.in
3/aclocal.m4
4/autom4te.cache
5/config.h
6/config.h.in
7/config.log
8/config.status
9/configure
10/stamp-h1
11/INSTALL
12/depcomp
13/install-sh
14/missing
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..f054dad
--- a/dev/null
+++ b/AUTHORS
@@ -0,0 +1,12 @@
1Klever dissected:
2 Michael 'hacker' Krelin <hacker@klever.net>
3 Leonid Ivanov <kamel@klever.net>
4
5
6Thanks to:
7
8Brian Muller <bmuller AT butterfat DOT net> of mod_auth_openid project for
9suggestions, bug reports, testing and actually making use of the library.
10
11Joseph Smarr <joseph AT plaxo DOT com> of plaxo.com for robustness enhancements
12and making use of my work.
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..793f9c3
--- a/dev/null
+++ b/COPYING
@@ -0,0 +1,19 @@
1Copyright (c) 2009 Klever Group (http://www.klever.net/)
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of
4this software and associated documentation files (the "Software"), to deal in
5the Software without restriction, including without limitation the rights to
6use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7of the Software, and to permit persons to whom the Software is furnished to do
8so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- a/dev/null
+++ b/ChangeLog
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..fb3b5f3
--- a/dev/null
+++ b/Makefile.am
@@ -0,0 +1,16 @@
1SUBDIRS=doc src
2
3all-local: NEWS
4
5NEWS: NEWS.xsl NEWS.xml
6 ${XSLTPROC} -o $@ $^
7
8EXTRA_DIST = NEWS.xml NEWS.xsl
9
10ISSUEFILES = $$(find ${top_srcdir} -type f '(' \
11 -name '*.cc' -or -name '*.h' \
12 ')' ) \
13 ${top_srcdir}/configure.ac
14issues: todo fixme xxx
15todo fixme xxx:
16 @grep --color=auto -in '$@:' ${ISSUEFILES} || true
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..ba533ad
--- a/dev/null
+++ b/NEWS
@@ -0,0 +1,2 @@
10.0 (March 8th, 2009)
2 - Initial release
diff --git a/NEWS.xml b/NEWS.xml
new file mode 100644
index 0000000..03e1c42
--- a/dev/null
+++ b/NEWS.xml
@@ -0,0 +1,6 @@
1<?xml version="1.0" encoding="us-ascii"?>
2<news>
3 <version version="0.0" date="March 8th, 2009">
4 <ni>Initial release</ni>
5 </version>
6</news>
diff --git a/NEWS.xsl b/NEWS.xsl
new file mode 100644
index 0000000..7c71307
--- a/dev/null
+++ b/NEWS.xsl
@@ -0,0 +1,24 @@
1<?xml version="1.0" encoding="us-ascii"?>
2<xsl:stylesheet version="1.0"
3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4 >
5 <xsl:output
6 method="text"
7 encoding="us-ascii"
8 media-type="text/plain" />
9
10 <xsl:template match="news">
11 <xsl:apply-templates/>
12 </xsl:template>
13 <xsl:template match="version">
14 <xsl:value-of select="concat(@version,' (',@date,')&#xA;')"/>
15 <xsl:apply-templates/>
16 </xsl:template>
17 <xsl:template match="ni">
18 <xsl:text> - </xsl:text>
19 <xsl:apply-templates mode="text"/>
20 <xsl:text>&#xA;</xsl:text>
21 </xsl:template>
22 <xsl:template match="*|text()"/>
23
24</xsl:stylesheet>
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- a/dev/null
+++ b/README
diff --git a/autogen.sh b/autogen.sh
new file mode 100644
index 0000000..86d2d88
--- a/dev/null
+++ b/autogen.sh
@@ -0,0 +1,8 @@
1#!/bin/sh
2WANT_AUTOMAKE=1.8
3export WANT_AUTOMAKE
4 aclocal \
5&& autoheader \
6&& automake -a \
7&& autoconf \
8&& ./configure "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..7b1db54
--- a/dev/null
+++ b/configure.ac
@@ -0,0 +1,71 @@
1AC_INIT([iii], [0.0], [iii-bugs@klever.net])
2AC_CONFIG_SRCDIR([configure.ac])
3AC_CONFIG_HEADERS([config.h])
4AM_INIT_AUTOMAKE([dist-bzip2])
5
6AC_PROG_INSTALL
7AC_PROG_CXX
8AC_PROG_CC
9PKG_PROG_PKG_CONFIG
10
11AC_HEADER_STDC
12
13AC_PATH_PROG([XSLTPROC],[xsltproc],[true])
14
15PKG_CHECK_MODULES([MODULES],[gsoap++ openssl libconfuse],,[
16 AC_MSG_ERROR([one of the build dependencies isn't satisfied])
17])
18
19AC_PATH_PROG([SOAPCPP2],[soapcpp2],[false])
20test "$SOAPCPP2" = "false" && AC_MSG_ERROR([no soapcpp2 tool, part of gsoap package, found.])
21
22notfound=false
23AC_CHECK_HEADERS([archive.h],[
24 AC_CHECK_LIB([archive],[archive_read_new],,[notfound=true])
25],[notfound=true])
26$notfound && AC_MSG_ERROR([no required libarchive library found. get one from http://people.freebsd.org/~kientzle/libarchive/])
27
28notfound=false
29AC_LANG_PUSH([C++])
30AC_CHECK_HEADERS([autosprintf.h],[
31 AC_CHECK_LIB([asprintf],[main],,[notfound=true])
32],[notfound=true])
33$notfound && AC_MSG_ERROR([no autosprintf, part of gettext, found])
34AC_LANG_POP([C++])
35
36nitpick=false
37AC_ARG_ENABLE([nitpicking],
38 AC_HELP_STRING([--enable-nitpicking],[make compiler somewhat overly fastidious about the code it deals with]),
39 [ test "$enableval" = "no" || nitpick=true ]
40)
41if $nitpick ; then
42 CPP_NITPICK="-pedantic -Wall -Wextra -Wundef -Wshadow \
43 -Wunsafe-loop-optimizations -Wconversion -Wmissing-format-attribute \
44 -Wredundant-decls -ansi -Wlogical-op -Wmissing-noreturn"
45 C_NITPICK="$CPP_NITPICK"
46 CXX_NITPICK="$C_NITPICK"
47
48 CPPFLAGS="$CPPFLAGS $CPP_NITPICK"
49 CFLAGS="$CFLAGS $C_NITPICK"
50 CXXFLAGS="$CXXFLAGS $CXX_NITPICK"
51fi
52
53ndebug=true
54AC_ARG_ENABLE([debug],
55 AC_HELP_STRING([--enable-debug],[enable debugginc code]),
56 [ test "$enableval" = "no" || ndebug=false ]
57)
58if $ndebug ; then
59 CPPFLAGS_DEBUG="-DNDEBUG"
60else
61 CPPFLAGS_DEBUG="-DDEBUG"
62fi
63AC_SUBST([CPPFLAGS_DEBUG])
64
65AC_CONFIG_FILES([
66 Makefile
67 src/Makefile
68 doc/Makefile
69 doc/iiid.8
70])
71AC_OUTPUT
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..3603e7e
--- a/dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
1iii (0.0) unstable; urgency=low
2
3 * Initial release
4
5 -- Michael Krelin <hacker@klever.net> Sun, 08 Mar 2009 19:39:38 +0100
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..b8626c4
--- a/dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
4
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..02a6138
--- a/dev/null
+++ b/debian/control
@@ -0,0 +1,13 @@
1Source: iii
2Section: graphics
3Priority: optional
4Maintainer: Michael Krelin <hacker@klever.net>
5Build-Depends: debhelper (>=7), gsoap, libssl-dev, libconfuse-dev, libarchive-dev, gettext
6Standards-Version: 3.8.0
7
8Package: iii
9Architecture: any
10Depends: adduser, ${shlibs:Depends}
11Description: Eye-Fi Manager implementation
12 Implementation of Eye-Fi manager service for Linux
13
diff --git a/debian/copyright b/debian/copyright
new file mode 120000
index 0000000..012065c
--- a/dev/null
+++ b/debian/copyright
@@ -0,0 +1 @@
../COPYING \ No newline at end of file
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..04efab3
--- a/dev/null
+++ b/debian/dirs
@@ -0,0 +1,3 @@
1/etc/iii
2/usr/sbin
3/usr/share/doc/iii
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..3cc350b
--- a/dev/null
+++ b/debian/docs
@@ -0,0 +1,2 @@
1AUTHORS
2NEWS
diff --git a/debian/examples b/debian/examples
new file mode 100644
index 0000000..c1afd06
--- a/dev/null
+++ b/debian/examples
@@ -0,0 +1 @@
doc/000000000000.conf
diff --git a/debian/iii.init b/debian/iii.init
new file mode 100755
index 0000000..c60c25e
--- a/dev/null
+++ b/debian/iii.init
@@ -0,0 +1,57 @@
1#!/bin/sh
2### BEGIN INIT INFO
3# Provides: iii
4# Required-Start: $remote_fs $network
5# Required-Stop: $remote_fs $network
6# Default-Start: 2 3 4 5
7# Default-Stop: 0 1 6
8# Short-Description: Start iii eye-fi card manager daemon.
9### END INIT INFO
10
11set -e
12
13PATH=/sbin:/bin:/usr/sbin:/usr/bin
14NAME=iii
15DAEMON=/usr/sbin/${NAME}d
16DESC="Eye-Fi card manager daemon"
17PIDFILE=/var/run/${NAME}d.pid
18SCRIPTNAME=/etc/init.d/$NAME
19USER=eyefi
20SSD="/sbin/start-stop-daemon"
21
22test -x $DAEMON || exit 0
23
24if [ -f /etc/default/$NAME ] ; then
25 . /etc/default/$NAME
26 fi
27
28test -z "$NO_IIID" || exit 0
29
30. /lib/lsb/init-functions
31
32case "$1" in
33 start)
34 log_daemon_msg "Starting $DESC" $NAME
35 $SSD --start --pidfile $PIDFILE --chuid $USER --background --make-pidfile --exec $DAEMON -- $DAEMON_OPTS
36 log_end_msg $?
37 ;;
38 stop)
39 log_daemon_msg "Stopping $DESC" $NAME
40 if $SSD --stop --oknodo --retry 30 --pidfile $PIDFILE --exec $DAEMON ; then
41 rm -f $PIDFILE
42 log_end_msg 0
43 else
44 log_end_msg 1
45 fi
46 ;;
47 restart|force-reload)
48 $SCRIPTNAME stop
49 $SCRIPTNAME start
50 ;;
51 *)
52 echo "Usage: $SCRIPTNAME {start|stop}" >&2
53 exit 1
54 ;;
55esac
56
57exit 0
diff --git a/debian/iii.postinst b/debian/iii.postinst
new file mode 100755
index 0000000..20463a1
--- a/dev/null
+++ b/debian/iii.postinst
@@ -0,0 +1,18 @@
1#!/bin/sh
2set -e
3UG=eyefi
4P=eyekindo
5H=/var/lib/$P
6
7if [ "$1" = configure ] ; then
8 getent group $UG >/dev/null 2>&1 || addgroup --system $UG
9 getent passwd $UG >/dev/null 2>&1 || adduser --system --home $H \
10 --no-create-home --disabled-password --ingroup $UG $UG
11 if ! test -d $H ; then
12 mkdir -p $H
13 chown $UG:$UG $H
14 chmod 2770 $H
15 fi
16fi
17
18#DEBHELPER#
diff --git a/debian/iii.postrm b/debian/iii.postrm
new file mode 100755
index 0000000..a2c66fa
--- a/dev/null
+++ b/debian/iii.postrm
@@ -0,0 +1,3 @@
1#!/bin/sh
2
3#DEBHELPER#
diff --git a/debian/iii.prerm b/debian/iii.prerm
new file mode 100755
index 0000000..6060c4f
--- a/dev/null
+++ b/debian/iii.prerm
@@ -0,0 +1,4 @@
1#!/bin/sh
2set -e
3
4#DEBHELPER#
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..86549d3
--- a/dev/null
+++ b/debian/rules
@@ -0,0 +1,11 @@
1#!/usr/bin/make -f
2%:
3 dh $@
4
5build: build-stamp
6build-stamp:
7 sh autogen.sh --version
8 dh build --before configure
9 dh_auto_configure -- --enable-debug
10 dh build --after configure
11 touch $@
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 0000000..b6c3d7c
--- a/dev/null
+++ b/doc/.gitignore
@@ -0,0 +1 @@
iiid.8
diff --git a/doc/000000000000.conf b/doc/000000000000.conf
new file mode 100644
index 0000000..d7b365f
--- a/dev/null
+++ b/doc/000000000000.conf
@@ -0,0 +1,17 @@
1# target directory for uploaded files, if the name contains %s, it is replaced
2# with eyefi card mac address.
3targetdir = "/var/lib/eyekindo/%s/"
4# the upload key as seen in Mac and (perhaps) windows Settings.xml file
5uploadkey = "e3e2c4a305cee6bce0ebb38a3259ac08"
6
7# commands to be executed at certain events, the commands also receive certain
8# values of interested passed via environment.
9# for on-start-session: EYEFI_MACADDRESS, EYEFI_TRANSFER_MODE, EYEFI_TRANSFERMODETIMESTAMP
10on-start-session = "bash /usr/local/lib/iii/on-start-session.bash"
11# for on-upload-photo: EYEFI_MACADDRESS, EYEFI_UPLOADED (uploaded file name)
12on-upload-photo = "bash /usr/local/lib/iii/on-upload-photo.bash"
13# for on-mark-last-photo-in-roll: EYEFI_MACADDRESS, EYEFI_MERGEDELTA
14on-mark-last-photo-in-roll = "bash /usr/local/lib/iii/on-mark-last-photo-in-roll.bash"
15
16# file mode creation mask
17umask = 002
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..4a22498
--- a/dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,6 @@
1man_MANS=iiid.8
2
3EXTRA_DIST = 000000000000.conf
4
5clean-local:
6 rm -f iiid.8
diff --git a/doc/iiid.8.in b/doc/iiid.8.in
new file mode 100644
index 0000000..63a941e
--- a/dev/null
+++ b/doc/iiid.8.in
@@ -0,0 +1,106 @@
1.TH iiid 8 "March 8th, 2009" "iiid(8)" "Klever Group (http://www.klever.net/)"
2.hla en
3
4.SH NAME
5
6iiid \- An eye-fi card management daemon
7
8.SH SYNOPSYS
9
10\fBiiid\fR
11[\fB-h\fR] [\fB--help\fR] [\fB--usage\fR]
12[\fB-V\fR] [\fB--version\fR]
13[\fB-L\fR] [\fB--license\fR]
14[\fB-p\fR \fIport\fR] [\fB--port=\fR\fIport\fR]
15
16.SH DESCRIPTION
17
18iiid daemon is a minimalistic open source eye-fi management daemon
19implementation. It is listening for incoming connections and accepts files from
20eye-fi card, optionally invoking scripts to sort out files or send out
21notifications.
22
23.SH OPTIONS
24
25.TP
26\fB-p\fR \fIport\fR, \fB--port=\fR\fIport\fR
27Set the port to listen to. You're not likely to ever need to change this,
28perhaps for debugging purpose or if you want to proxy connections.
29.TP
30\fB-h\fR, \fB--help\fR, \fB--usage\fR
31Display short usage instructions and exit.
32.TP
33\fB-V\fR, \fB--version\fR
34Report version and exit.
35.TP
36\fB-L\fR, \fB--license\fR
37Show licensing terms.
38
39.SH EXIT STATUS
40
41The daemon isn't supposed to exit at this point, but, like most executables, it returns zero in case of success, non-zero otherwise.
42
43.SH FILES
44
45.TP
46@sysconfdir@/iii/\fBXXXXXXXXXXXX.conf/fR
47Upon successfull connection, the daemon reads the configuration from this file,
48where XXXXXXXXXXXX is the macaddress of your eyefi card. You can lookup the mac
49address of your card in your Mac/Windows Settings.xml file. Be sure to remove
50dashes from it.
51
52.SH CONFIGURATION OPTIONS
53
54.TP
55\fBtargetdir\fR = "\fI/var/lib/iii/%s/\fR"
56Sets the target directory for uploaded files. If the \fI%s\fR placeholder is
57present in the string, it is replaced with card mac address.
58.TP
59\fBuploadkey\fR = "\fIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\fR"
60The upload key as seen in Mac/Windows Settings.xml file.
61.TP
62\fBon-start-session\fR = "\fIlogger iii-StartSession ${EYEFI_MACADDRESS} ${EYEFI_TRANSFER_MODE} ${EYEFI_TRANSFERMODETIMESTAMP}\fR"
63The command to execute on \fBStartSession\fR request. The command receives some
64information via environment variables.
65.TP
66\fBon-upload-photo\fR = "\fIlogger iii-UploadPhoto ${EYEFI_MACADDRESS} ${EYEFI_UPLOADED}\fR"
67The command to execute after successfull photo upload. The information about
68the card mac address and uploaded file name is passed via environment
69variables.
70.TP
71\fBon-mark-last-photo-in-roll\fR = "\fIlogger iii-MarkLastPhotoInRoll ${EYEFI_MACADDRESS} ${EYEFI_MERGEDELTA}\fR"
72The command to execute on \fBMarkLastPhotoInRoll\fR request. The information
73about request is passed via environment variables.
74.TP
75\fBumask\fR = \fI002\fR
76The file mode creation mask.
77
78.SH AUTHOR
79
80Written by Michael Krelin <hacker@klever.net>
81
82.SH COPYRIGHT
83
84Copyright (c) 2009 Klever Group (http://www.klever.net/)
85
86Permission is hereby granted, free of charge, to any person obtaining a copy of
87this software and associated documentation files (the "Software"), to deal in
88the Software without restriction, including without limitation the rights to
89use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
90of the Software, and to permit persons to whom the Software is furnished to do
91so, subject to the following conditions:
92
93The above copyright notice and this permission notice shall be included in all
94copies or substantial portions of the Software.
95
96THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
97IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
98FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
99AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
100LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
101OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
102SOFTWARE.
103
104.SH BUGS
105
106You tell me. Send reports to <iii-bugs@klever.net>
diff --git a/scripts/xml2sh.xsl b/scripts/xml2sh.xsl
new file mode 100644
index 0000000..736bc21
--- a/dev/null
+++ b/scripts/xml2sh.xsl
@@ -0,0 +1,28 @@
1<?xml version="1.0" encoding="us-ascii"?>
2<xsl:stylesheet version="1.0"
3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4 >
5 <xsl:output
6 method="text"
7 encoding="us-ascii"
8 media-type="text/plain" />
9
10 <xsl:template match="/">
11 <xsl:apply-templates select="/Config/Cards/Card"/>
12 </xsl:template>
13
14 <xsl:template match="/Config/Cards/Card">
15 <xsl:text>cat &gt;</xsl:text>
16 <xsl:value-of select="translate(@MacAddress,'-','')"/>
17 <xsl:text>.conf &lt;&lt;__EOF__&#xa;</xsl:text>
18 <xsl:text>uploadkey=&quot;</xsl:text>
19 <xsl:value-of select="UploadKey"/>
20 <xsl:text>&quot;&#xa;</xsl:text>
21 <xsl:text>targetdir=&quot;/var/lib/iii/%s&quot;&#xa;</xsl:text>
22 <xsl:text>umask=022&#xa;</xsl:text>
23 <xsl:text>__EOF__&#xa;</xsl:text>
24 </xsl:template>
25
26 <xsl:template match="*|text()"/>
27
28</xsl:stylesheet>
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..425033a
--- a/dev/null
+++ b/src/.gitignore
@@ -0,0 +1,10 @@
1/.deps
2eyefi.nsmap
3soapC.cpp
4soapH.h
5soapStub.h
6soapeyefiService.cpp
7soapeyefiService.h
8*.o
9/iiid
10/COPYING.cc
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..09f698e
--- a/dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,32 @@
1sbin_PROGRAMS=iiid
2noinst_HEADERS = \
3 eyefi.h \
4 eyekinfig.h eyetil.h \
5 eyefiworker.h
6
7AM_CPPFLAGS = ${CPPFLAGS_DEBUG} \
8 -DEYEKIN_CONF_DIR=\"${sysconfdir}/${PACKAGE}\"
9DEFAULT_INCLUDES = -I${top_builddir} -I${builddir} -I${srcdir}
10INCLUDES = ${MODULES_CFLAGS}
11
12iiid_SOURCES = iiid.cc \
13 eyekinfig.cc eyetil.cc \
14 eyefiservice.cc eyefiworker.cc
15nodist_iiid_SOURCES = \
16 ${builddir}/soapC.cpp ${builddir}/soapeyefiService.cpp \
17 COPYING.cc
18iiid_LDADD = ${MODULES_LIBS}
19
20COPYING.cc: ${top_srcdir}/COPYING
21 echo "const char * COPYING = " >$@ || (rm $@;exit 1)
22 sed -e 's/"/\\"/g' -e 's/^/\"/' -e 's/$$/\\n\"/' $< >>$@ || (rm $@;exit 1)
23 echo ';' >>$@ || (rm $@;exit 1)
24
25${srcdir}/eyefiservice.cc: ${builddir}/soapeyefiService.h
26${srcdir}/iiid.cc: ${builddir}/eyefi.nsmap
27
28${builddir}soapC.cpp ${builddir}/soapeyefiService.cpp ${builddir}/eyefi.nsmap ${builddir}/soapeyefiService.h: ${srcdir}/eyefi.h
29 ${SOAPCPP2} -d${builddir} -S -L -a -i -w -x $<
30
31clean-local:
32 rm -f soap{{H,Stub,eyefiService}.h,{C,eyefiService}.cpp} eyefi.nsmap COPYING.cc
diff --git a/src/eyefi.h b/src/eyefi.h
new file mode 100644
index 0000000..70e918d
--- a/dev/null
+++ b/src/eyefi.h
@@ -0,0 +1,47 @@
1 //gsoap efs service name: eyefi
2 //gsoap efs service location: http://api.eye.fi/api/soap/eyefilm/v1
3 //gsoap efs service namespace: EyeFi/SOAP/EyeFilm
4 //gsoap efs service method-action:StartSession "urn:StartSession"
5 //gsoap efs service method-action:GetPhotoStatus "urn:GetPhotoStatus"
6 //gsoap efs service method-action:MarkLastPhotoInRoll "urn:MarkLastPhotoInRoll"
7 //gsoap rns service namespace: http://localhost/api/soap/eyefilm
8
9struct rns__StartSessionResponse {
10 std::string credential;
11 std::string snonce;
12 int transfermode;
13 unsigned int transfermodetimestamp;
14 bool upsyncallowed;
15};
16
17int efs__StartSession(
18 std::string macaddress,std::string cnonce,
19 int transfermode,long transfermodetimestamp,
20 struct rns__StartSessionResponse &r );
21
22struct rns__GetPhotoStatusResponse {
23 int fileid;
24 long offset;
25};
26
27int efs__GetPhotoStatus(
28 std::string credential, std::string macaddress,
29 std::string filename, long filesize, std::string filesignature,
30 struct rns__GetPhotoStatusResponse &r );
31
32struct rns__MarkLastPhotoInRollResponse {
33};
34
35int efs__MarkLastPhotoInRoll(
36 std::string macaddress, int mergedelta,
37 struct rns__MarkLastPhotoInRollResponse &r );
38
39struct rns__UploadPhotoResponse {
40 bool success;
41};
42
43int efs__UploadPhoto(
44 int fileid, std::string macaddress,
45 std::string filename, long filesize, std::string filesignature,
46 std::string encryption, int flags,
47 struct rns__UploadPhotoResponse& r );
diff --git a/src/eyefiservice.cc b/src/eyefiservice.cc
new file mode 100644
index 0000000..30c06fa
--- a/dev/null
+++ b/src/eyefiservice.cc
@@ -0,0 +1,186 @@
1#include <cassert>
2#include <iostream>
3#include <fstream>
4#include <stdexcept>
5#include <iterator>
6#include <syslog.h>
7#include <sys/wait.h>
8#include <autosprintf.h>
9#include "eyekinfig.h"
10#include "eyetil.h"
11#include "soapeyefiService.h"
12
13static bool detached_child() {
14 pid_t p = fork();
15 if(p<0) throw std::runtime_error("failed to fork()");
16 if(!p) {
17 p = fork();
18 if(p<0) {
19 syslog(LOG_ERR,"Failed to re-fork child process");
20 _exit(-1);
21 }
22 if(!p) {
23 setsid();
24 for(int i=getdtablesize();i>=0;--i) close(i);
25 int i=open("/dev/null",O_RDWR); assert(i==0);
26 i = dup(i); assert(i==1);
27 i = dup(i); assert(i==2);
28 return true;
29 }
30 _exit(0);
31 }
32 int rc;
33 if(waitpid(p,&rc,0)<0) throw std::runtime_error("failed to waitpid()");
34 if(!WIFEXITED(rc)) throw std::runtime_error("error in forked process");
35 if(WEXITSTATUS(rc)) throw std::runtime_error("forked process signalled error");
36 return false;
37}
38
39int eyefiService::StartSession(
40 std::string macaddress,std::string cnonce,
41 int transfermode,long transfermodetimestamp,
42 struct rns__StartSessionResponse &r ) {
43#ifndef NDEBUG
44 syslog(LOG_DEBUG,
45 "StartSession request from %s with cnonce=%s, transfermode=%d, transfermodetimestamp=%ld",
46 macaddress.c_str(), cnonce.c_str(), transfermode, transfermodetimestamp );
47#endif
48 r.credential = binary_t(macaddress+cnonce+eyekinfig_t(macaddress).get_upload_key()).md5().hex();
49 /* TODO: better nonce generator */
50 time_t t = time(0);
51 r.snonce = binary_t(&t,sizeof(t)).md5().hex();
52 r.transfermode=2;
53 r.transfermodetimestamp=t;
54 r.upsyncallowed=false;
55
56 std::string cmd = eyekinfig_t(macaddress).get_on_start_session();
57 if(!cmd.empty()) {
58 if(detached_child()) {
59 putenv( gnu::autosprintf("EYEFI_MACADDRESS=%s",macaddress.c_str()) );
60 putenv( gnu::autosprintf("EYEFI_TRANSFERMODE=%d",transfermode) );
61 putenv( gnu::autosprintf("EYEFI_TRANSFERMODETIMESTAMP=%ld",transfermodetimestamp) );
62 char *argv[] = { (char*)"/bin/sh", (char*)"-c", (char*)cmd.c_str(), 0 };
63 execv("/bin/sh",argv);
64 syslog(LOG_ERR,"Failed to execute '%s'",cmd.c_str());
65 _exit(-1);
66 }
67 }
68 return SOAP_OK;
69}
70
71int eyefiService::GetPhotoStatus(
72 std::string credential, std::string macaddress,
73 std::string filename, long filesize, std::string filesignature,
74 struct rns__GetPhotoStatusResponse &r ) {
75#ifndef NDEBUG
76 syslog(LOG_DEBUG,
77 "GetPhotoStatus request from %s with credential=%s, filename=%s, filesize=%ld, filesignature=%s",
78 macaddress.c_str(), credential.c_str(), filename.c_str(), filesize, filesignature.c_str() );
79#endif
80 r.fileid = 1; r.offset = 0;
81 return SOAP_OK;
82}
83
84int eyefiService::MarkLastPhotoInRoll(
85 std::string macaddress, int mergedelta,
86 struct rns__MarkLastPhotoInRollResponse &r ) {
87#ifndef NDEBUG
88 syslog(LOG_DEBUG,
89 "MarkLastPhotoInRoll request from %s with mergedelta=%d",
90 macaddress.c_str(), mergedelta );
91#endif
92 std::string cmd = eyekinfig_t(macaddress).get_on_mark_last_photo_in_roll();
93 if(!cmd.empty()) {
94 if(detached_child()) {
95 putenv( gnu::autosprintf("EYEFI_MACADDRESS=%s",macaddress.c_str()) );
96 putenv( gnu::autosprintf("EYEFI_MERGEDELTA=%d",mergedelta) );
97 char *argv[] = { (char*)"/bin/sh", (char*)"-c", (char*)cmd.c_str(), 0 };
98 execv("/bin/sh",argv);
99 syslog(LOG_ERR,"Failed to execute '%s'",cmd.c_str());
100 _exit(-1);
101 }
102 }
103 return SOAP_OK;
104}
105
106int eyefiService::UploadPhoto(
107 int fileid, std::string macaddress,
108 std::string filename, long filesize, std::string filesignature,
109 std::string encryption, int flags,
110 struct rns__UploadPhotoResponse& r ) {
111#ifndef NDEBUG
112 syslog(LOG_DEBUG,
113 "UploadPhoto request from %s with fileid=%d, filename=%s, filesize=%ld,"
114 " filesignature=%s, encryption=%s, flags=%04X",
115 macaddress.c_str(), fileid, filename.c_str(), filesize,
116 filesignature.c_str(), encryption.c_str(), flags );
117#endif
118 eyekinfig_t eyekinfig(macaddress);
119
120 umask(eyekinfig.get_umask());
121
122 std::string td = eyekinfig.get_targetdir();
123 /* TODO: try to create, if needed */
124 tmpdir_t indir(td+"/.incoming.XXXXXX");
125
126 for(soap_multipart::iterator i=mime.begin(),ie=mime.end();i!=ie;++i) {
127#ifndef NDEBUG
128 syslog(LOG_DEBUG,
129 " MIME attachment with id=%s, type=%s, size=%ld",
130 (*i).id, (*i).type, (long)(*i).size );
131#endif
132
133#ifndef NDEBUG
134 if((*i).id && !strcmp((*i).id,"INTEGRITYDIGEST")) {
135 std::string idigest((*i).ptr,(*i).size);
136 syslog(LOG_DEBUG, " INTEGRITYDIGEST=%s", idigest.c_str());
137 }
138#endif
139 if( (*i).id && !strcmp((*i).id,"FILENAME") ) {
140 assert( (*i).type && !strcmp((*i).type,"application/x-tar") );
141#ifdef III_SAVE_TARS
142 std::string tarfile = indir.get_file(filename);
143 {
144 std::ofstream(tarfile.c_str(),std::ios::out|std::ios::binary).write((*i).ptr,(*i).size);
145 }
146#endif
147 tarchive_t a((*i).ptr,(*i).size);
148 if(!a.read_next_header())
149 throw std::runtime_error("failed to tarchive_t::read_next_header())");
150 std::string jf = indir.get_file(a.entry_pathname());
151 std::string::size_type ls = jf.rfind('/');
152 std::string jbn = (ls==std::string::npos)?jf:jf.substr(ls+1);
153 int fd=open(jf.c_str(),O_CREAT|O_WRONLY,0666);
154 assert(fd>0);
155 a.read_data_into_fd(fd);
156 close(fd);
157 std::string tf = td+'/'+jbn;
158 bool success = false;
159 if(!link(jf.c_str(), tf.c_str())) {
160 unlink(jf.c_str()); success = true;
161 }else{
162 for(int i=1;i<32767;++i) {
163 tf = (const char*)gnu::autosprintf( "%s/(%05d)%s",
164 td.c_str(), i, jbn.c_str() );
165 if(!link(jf.c_str(), tf.c_str())) {
166 unlink(jf.c_str()); success = true;
167 break;
168 }
169 }
170 }
171 std::string cmd = eyekinfig.get_on_upload_photo();
172 if(success && !cmd.empty()) {
173 if(detached_child()) {
174 putenv( gnu::autosprintf("EYEFI_MACADDRESS=%s",macaddress.c_str()) );
175 putenv( gnu::autosprintf("EYEFI_UPLOADED=%s",tf.c_str()) );
176 char *argv[] = { (char*)"/bin/sh", (char*)"-c", (char*)cmd.c_str(), 0 };
177 execv("/bin/sh",argv);
178 syslog(LOG_ERR,"Failed to execute '%s'",cmd.c_str());
179 _exit(-1);
180 }
181 }
182 }
183 }
184 r.success = true;
185 return SOAP_OK;
186}
diff --git a/src/eyefiworker.cc b/src/eyefiworker.cc
new file mode 100644
index 0000000..d87c36e
--- a/dev/null
+++ b/src/eyefiworker.cc
@@ -0,0 +1,26 @@
1#include <sys/wait.h>
2#include <stdexcept>
3#include "eyefiworker.h"
4
5eyefiworker::eyefiworker()
6 : eyefiService(SOAP_IO_STORE|SOAP_IO_KEEPALIVE) {
7 bind_flags = SO_REUSEADDR; max_keep_alive = 0;
8 }
9
10int eyefiworker::run(int port) {
11 if(!soap_valid_socket(bind(0,port,5)))
12 throw std::runtime_error("failed to bind()");
13 while(true) {
14 while(waitpid(-1,0,WNOHANG)>0);
15 if(!soap_valid_socket(accept()))
16 throw std::runtime_error("failed to accept()");
17 pid_t p = fork();
18 if(p<0) throw std::runtime_error("failed to fork()");
19 if(!p) {
20 (void)serve();
21 soap_destroy(this); soap_end(this); soap_done(this);
22 _exit(0);
23 }
24 close(socket); socket = SOAP_INVALID_SOCKET;
25 }
26}
diff --git a/src/eyefiworker.h b/src/eyefiworker.h
new file mode 100644
index 0000000..c08ec8b
--- a/dev/null
+++ b/src/eyefiworker.h
@@ -0,0 +1,15 @@
1#ifndef __EYEFIWORKER_H
2#define __EYEFIWORKER_H
3
4#include "soapeyefiService.h"
5
6class eyefiworker : public eyefiService {
7 public:
8
9 eyefiworker();
10
11 int run(int port);
12
13};
14
15#endif /* __EYEFIWORKER_H */
diff --git a/src/eyekinfig.cc b/src/eyekinfig.cc
new file mode 100644
index 0000000..27a5a56
--- a/dev/null
+++ b/src/eyekinfig.cc
@@ -0,0 +1,67 @@
1#include <cassert>
2#include <stdexcept>
3#include <autosprintf.h>
4#include "eyekinfig.h"
5
6#include "config.h"
7
8eyekinfig_t::eyekinfig_t(const std::string& ma)
9 : macaddress(ma) {
10 static cfg_opt_t opts[] = {
11 CFG_STR((char*)"targetdir",(char*)"/var/lib/" PACKAGE "/%s",CFGF_NONE),
12 CFG_STR((char*)"uploadkey",(char*)"",CFGF_NONE),
13 CFG_STR((char*)"on-start-session",(char*)"",CFGF_NONE),
14 CFG_STR((char*)"on-upload-photo",(char*)"",CFGF_NONE),
15 CFG_STR((char*)"on-mark-last-photo-in-roll",(char*)"",CFGF_NONE),
16 CFG_INT((char*)"umask",022,CFGF_NONE),
17 CFG_END()
18 };
19 cfg = cfg_init(opts,CFGF_NONE);
20 if(!cfg)
21 throw std::runtime_error("failed to cfg_init()");
22 std::string::size_type ls = macaddress.rfind('/');
23 if(cfg_parse(cfg,gnu::autosprintf(
24 EYEKIN_CONF_DIR "/%s.conf",
25 (ls==std::string::npos)
26 ? macaddress.c_str()
27 : macaddress.substr(ls+1).c_str()
28 )) ==CFG_PARSE_ERROR) {
29 if(cfg) cfg_free(cfg);
30 cfg=0;
31 throw std::runtime_error("failed to cfg_parse()");
32 }
33 }
34
35eyekinfig_t::~eyekinfig_t() {
36 if(cfg) cfg_free(cfg);
37}
38
39std::string eyekinfig_t::get_targetdir() {
40 assert(cfg);
41 return gnu::autosprintf(cfg_getstr(cfg,"targetdir"),macaddress.c_str());
42}
43
44std::string eyekinfig_t::get_upload_key() {
45 assert(cfg);
46 return cfg_getstr(cfg,"uploadkey");
47}
48
49std::string eyekinfig_t::get_on_start_session() {
50 assert(cfg);
51 return cfg_getstr(cfg,"on-start-session");
52}
53std::string eyekinfig_t::get_on_upload_photo() {
54 assert(cfg);
55 return cfg_getstr(cfg,"on-upload-photo");
56}
57
58std::string eyekinfig_t::get_on_mark_last_photo_in_roll() {
59 assert(cfg);
60 return cfg_getstr(cfg,"on-mark-last-photo-in-roll");
61}
62
63
64int eyekinfig_t::get_umask() {
65 assert(cfg);
66 return cfg_getint(cfg,"umask");
67}
diff --git a/src/eyekinfig.h b/src/eyekinfig.h
new file mode 100644
index 0000000..34f8d49
--- a/dev/null
+++ b/src/eyekinfig.h
@@ -0,0 +1,25 @@
1#ifndef __EYEKINFIG_H
2#define __EYEKINFIG_H
3
4#include <confuse.h>
5#include <string>
6
7class eyekinfig_t {
8 public:
9 std::string macaddress;
10 cfg_t *cfg;
11
12 eyekinfig_t(const std::string& ma);
13 ~eyekinfig_t();
14
15 std::string get_targetdir();
16 std::string get_upload_key();
17
18 std::string get_on_start_session();
19 std::string get_on_upload_photo();
20 std::string get_on_mark_last_photo_in_roll();
21
22 int get_umask();
23};
24
25#endif /* __EYEKINFIG_H */
diff --git a/src/eyetil.cc b/src/eyetil.cc
new file mode 100644
index 0000000..d00c2ee
--- a/dev/null
+++ b/src/eyetil.cc
@@ -0,0 +1,103 @@
1#include <stdlib.h>
2#include <syslog.h>
3#include <iostream>
4#include <cassert>
5#include <stdexcept>
6#include <openssl/md5.h>
7#include "eyetil.h"
8
9binary_t& binary_t::from_hex(const std::string& h) {
10 /* TODO: algorithmize */
11 std::string::size_type hs = h.length();
12 if(hs&1)
13 throw std::runtime_error("odd number of characters in hexadecimal number");
14 int rvs = hs>>1;
15 resize(rvs);
16 const unsigned char *hp = (const unsigned char*)h.data();
17 iterator oi=begin();
18 char t[3] = { 0,0,0 };
19 for(int i=0;i<rvs;++i) {
20 t[0]=*(hp++); t[1]=*(hp++);
21 *(oi++) = strtol(t,0,16);
22 }
23 return *this;
24}
25
26binary_t& binary_t::from_data(const void *d,size_t s) {
27 resize(s);
28 std::copy((const unsigned char*)d,(const unsigned char *)d+s,
29 begin() );
30 return *this;
31}
32
33std::string binary_t::hex() const {
34 std::string rv;
35 rv.reserve((size()<<1)+1);
36 char t[3] = {0,0,0};
37 for(const_iterator i=begin(),ie=end();i!=ie;++i) {
38 int rc = snprintf(t,sizeof(t),"%02x",*i);
39 assert(rc<sizeof(t));
40 rv += t;
41 }
42 return rv;
43}
44
45binary_t binary_t::md5() const {
46 binary_t rv(MD5_DIGEST_LENGTH);
47 if(!MD5(
48 (const unsigned char*)&(front()),size(),
49 (unsigned char*)&(rv.front()) ))
50 throw std::runtime_error("failed to md5()");
51 return rv;
52}
53
54tmpdir_t::tmpdir_t(const std::string& dt) : dir(dt) {
55 if(!mkdtemp((char*)dir.data()))
56 throw std::runtime_error("failed to mkdtmp()");
57}
58tmpdir_t::~tmpdir_t() {
59 assert(!dir.empty());
60 if(rmdir(dir.c_str())) {
61 syslog(LOG_WARNING,"Failed to remove '%s' directory",dir.c_str());
62 }
63}
64
65std::string tmpdir_t::get_file(const std::string& f) {
66 std::string::size_type ls = f.rfind('/');
67 return dir+'/'+(
68 (ls==std::string::npos)
69 ? f
70 : f.substr(ls+1)
71 );
72}
73
74tarchive_t::tarchive_t(void *p,size_t s) : a(archive_read_new()), e(0) {
75 if(!a) throw std::runtime_error("failed to archive_read_new()");
76 if(archive_read_support_format_tar(a)) {
77 archive_read_finish(a);
78 throw std::runtime_error("failed to archive_read_support_format_tar()");
79 }
80 if(archive_read_open_memory(a,p,s)) {
81 archive_read_finish(a);
82 throw std::runtime_error("failed to archive_read_open_memory()");
83 }
84}
85tarchive_t::~tarchive_t() {
86 assert(a);
87 archive_read_finish(a);
88}
89
90bool tarchive_t::read_next_header() {
91 assert(a);
92 return archive_read_next_header(a,&e)==ARCHIVE_OK;
93}
94
95std::string tarchive_t::entry_pathname() {
96 assert(a); assert(e);
97 return archive_entry_pathname(e);
98}
99
100bool tarchive_t::read_data_into_fd(int fd) {
101 assert(a);
102 return archive_read_data_into_fd(a,fd)==ARCHIVE_OK;
103}
diff --git a/src/eyetil.h b/src/eyetil.h
new file mode 100644
index 0000000..195d24f
--- a/dev/null
+++ b/src/eyetil.h
@@ -0,0 +1,48 @@
1#ifndef __EYETIL_H
2#define __EYETIL_H
3
4#include <vector>
5#include <string>
6#include <archive.h>
7#include <archive_entry.h>
8
9class binary_t : public std::vector<unsigned char> {
10 public:
11 binary_t() { }
12 binary_t(size_type n) : std::vector<unsigned char>(n) { }
13 binary_t(const std::string& h) { from_hex(h); }
14 binary_t(const void *d,size_t s) { from_data(d,s); }
15
16 binary_t& from_hex(const std::string& h);
17 binary_t& from_data(const void *d,size_t s);
18
19 std::string hex() const;
20 binary_t md5() const;
21};
22
23class tmpdir_t {
24 public:
25 std::string dir;
26
27 tmpdir_t(const std::string& dt);
28 ~tmpdir_t();
29
30 std::string get_file(const std::string& f);
31};
32
33class tarchive_t {
34 public:
35 struct archive *a;
36 struct archive_entry *e;
37
38 tarchive_t(void *p,size_t s);
39 ~tarchive_t();
40
41 bool read_next_header();
42
43 std::string entry_pathname();
44
45 bool read_data_into_fd(int fd);
46};
47
48#endif /* __EYETIL_H */
diff --git a/src/iiid.cc b/src/iiid.cc
new file mode 100644
index 0000000..6c23790
--- a/dev/null
+++ b/src/iiid.cc
@@ -0,0 +1,86 @@
1#include <syslog.h>
2#include <getopt.h>
3#include <iostream>
4#include <cassert>
5#include <stdexcept>
6#include "eyetil.h"
7#include "eyefiworker.h"
8
9#include "config.h"
10
11#include "eyefi.nsmap"
12
13#define PHEADER \
14 PACKAGE " Version " VERSION "\n" \
15 "Copyright (c) 2009 Klever Group"
16
17int main(int argc,char **argv) try {
18
19 int port = 59278;
20
21 while(true) {
22 static struct option opts[] = {
23 { "help", no_argument, 0, 'h' },
24 { "usage", no_argument, 0, 'h' },
25 { "version", no_argument, 0, 'V' },
26 { "license", no_argument, 0, 'L' },
27 { "port", required_argument, 0, 'p' },
28 { NULL, 0, 0, 0 }
29 };
30 int c = getopt_long(argc,argv,"hVLp:",opts,NULL);
31 if(c==-1) break;
32 switch(c) {
33 case 'h':
34 std::cerr << PHEADER << std::endl << std::endl
35 << " " << argv[0] << " [options]" << std::endl
36 << std::endl <<
37 " -h, --help,\n"
38 " --usage display this text\n"
39 " -V, --version display version information\n"
40 " -L, --license show license\n"
41 " -p <port>, --port=<port> port to listen to\n"
42 " (you're not likely to ever need it)\n"
43 << std::endl << std::endl;
44 exit(0);
45 break;
46 case 'V':
47 std::cerr << VERSION << std::endl;
48 exit(0);
49 break;
50 case 'L':
51 extern const char *COPYING;
52 std::cerr << COPYING << std::endl;
53 exit(0);
54 break;
55 case 'p':
56 port = strtol(optarg,0,0);
57 if(errno) {
58 std::cerr << "Failed to parse port number" << std::endl;
59 exit(1);
60 }
61 break;
62 default:
63 std::cerr << "Huh?" << std::endl;
64 exit(1);
65 break;
66 }
67 }
68
69 const char *ident = rindex(*argv,'/');
70 if(ident)
71 ++ident;
72 else
73 ident = *argv;
74 openlog(ident,LOG_PERROR|LOG_PID,LOG_DAEMON);
75 syslog(LOG_INFO,"Starting iii eye-fi manager");
76
77 eyefiworker().run(port);
78
79 closelog();
80 return 0;
81} catch(std::exception& e) {
82 syslog(LOG_CRIT,"Exiting iii daemon, because of error condition");
83 syslog(LOG_CRIT,"Exception: %s",e.what());
84 return 1;
85}
86