Compare commits

...

5 Commits
1.07 ... master

Author SHA1 Message Date
Carsten Sonne Larsen c048b79a21 Release 1.12 2021-01-31 20:10:59 +01:00
Carsten Sonne Larsen 7f7b1173c0 Release 1.11 2021-01-12 23:16:18 +01:00
Carsten Sonne Larsen 4431f67f75 Release 1.10 2021-01-12 23:02:29 +01:00
Carsten Sonne Larsen 324aeec752 Release 1.09 2021-01-12 23:00:49 +01:00
Carsten Sonne Larsen 82fd462f87 Release 1.08 2021-01-12 22:55:34 +01:00
104 changed files with 11444 additions and 3374 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.uaem
/bin
/dist
/dist-src
/log
/obj
/test

18
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "amiga",
"includePath": [
"/opt/amiga/m68k-amigaos/ndk-include/",
"/opt/amiga/m68k-amigaos/clib2/include/"
],
"defines": ["__CLIB2__"],
"compilerPath": "/opt/amiga/bin/m68k-amigaos-gcc",
"cStandard": "c99",
"cppStandard": "c++98",
"intelliSenseMode": "${default}",
"compilerArgs": []
}
],
"version": 4
}

23
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,23 @@
// Debug with remote gdbserver for AmigaOS:
// http://aminet.net/package/dev/debug/bgdbserver
// Start in FSUAE with:
// >bgdbserver TimeKeeper
// AmigaOS GCC & GDB:
// https://github.com/bebbo/amiga-gcc
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to gdbserver",
"type": "gdb",
"request": "attach",
"executable": "obj/TimeKeeper",
"target": "localhost:2345",
"remote": true,
"cwd": "${workspaceRoot}",
"gdbpath": "/opt/amiga/bin/m68k-amigaos-gdb",
}
]
}

19
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,19 @@
{
"cSpell.words": [
"Sonne",
"TZ",
"TZONE"
],
"files.associations": {
"alib_protos.h": "c",
"timer.h": "c",
"timer_protos.h": "c",
"shutdown.h": "c",
"gfxbase.h": "c",
"type_traits": "cpp",
"typeinfo": "c",
"dos.h": "c",
"commodities.h": "c",
"battclock.h": "c"
}
}

16
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "All",
"type": "shell",
"command": "make -f Makefile.m68k",
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@ -1,25 +0,0 @@
Short: Keep your time right
Uploader: Carsten Larsen
Author: Carsten Larsen (carsten.larsen@mail.com)
Type: util/cdity
Version: 1.05
Architecture: i386-aros
AmiTimeKeeper is a small program which keeps the time right on your
machine. No installation is required. Only an internet connection is
needed.
AmiTimeKeeper can be controlled through a number of settings. This
can be done either directly from the command line or by using the
tooltypes of an icon. Preferences can also be saved between reboots.
The default server address is currently pool.ntp.org. To find another
server try visiting support.ntp.org or one of the other sites listing
time servers.
Major changes in 1.05 06.08.2018
- Preferences can now be saved from settings window
- Running multiple instances no longer creates zombie processes
- Low water option renamed to threshold and high water option removed
- New option for sending log messages to file instead of to screen
- Read-only options is now applied consistently

View File

@ -1,4 +0,0 @@
[Project]
CreatedFrom=Makefile.m68k
Manager=KDevCustomMakeManager
Name=AmiTimeKeeper

View File

@ -1,25 +0,0 @@
Short: Keep your time right
Uploader: Carsten Larsen
Author: Carsten Larsen (carsten.larsen@mail.com)
Type: util/cdity
Version: 1.05
Architecture: m68k-amigaos
AmiTimeKeeper is a small program which keeps the time right on your
machine. No installation is required. Only an internet connection is
needed.
AmiTimeKeeper can be controlled through a number of settings. This
can be done either directly from the command line or by using the
tooltypes of an icon. Preferences can also be saved between reboots.
The default server address is currently pool.ntp.org. To find another
server try visiting support.ntp.org or one of the other sites listing
time servers.
Major changes in 1.05 06.08.2018
- Preferences can now be saved from settings window
- Running multiple instances no longer creates zombie processes
- Low water option renamed to threshold and high water option removed
- New option for sending log messages to file instead of to screen
- Read-only options is now applied consistently

View File

@ -1,8 +1,52 @@
AmiTimeKeeper Change Log
v1.12 31.01.2021
- New options to specify the local time zone
- New ARexx commands, parameters and error variables
- New option to start without active time synchronization
- New deactivate logging option for performance saving
- More bugs in calculation of time zone transition fixed
- Sanity check on value for interval between requests
- Updated ARexx documentation and script
- Honour ARexx result flag (RXFF_RESULT)
- Various minor bug fixes and improvements
v1.11 11.01.2021
- New dedicated external control utility
- New ARexx port with a diverse set of commands
- Rewritten logger facility with more verbose output
- Bug preventing commodity to shutdown fixed
- Bug in CLI SWITCH parameters reporting wrong values fixed
- Support AmigaOS 1.3 (v34) but without settings window
- Time zone information displayed using GMT instead of UTC
- Only watch current env variable for time zone changes
- Improved validation of application settings
- Several dead and duplicated code blocks removed
- Various minor bug fixes and improvements
- Documentation in HTML format
v1.10 15.03.2020
- RTC is no longer required during startup
- When time zone changes it is now recognized
- Several bugs affecting time zone logic fixed
- Documentation updated with POSIX TZ examples
- Compiled with upgraded GCC, version 6.2
- Various minor bug fixes and improvements
v1.09 14.07.2019
- Initial DST support using POSIX TZ and Amiga TZONE variable
- Restart synchronizer processes on DNS lookup failures
v1.08 18.05.2019
- When using pool server cycle with prefix 0 to 3
- Display of wrong signes in time zone fixed
- Faulty log messages about settings fixed
- Timer bug causing infinitive loop fixed
- Memory leak in settings window fixed
v1.07 15.02.2019
- Support commodity hotkey and popup options
- Hide advanced setting with new expert option
- Hide advanced settings with new expert option
v1.06 08.02.2019
- Adjust layout in settings window
@ -29,7 +73,7 @@ v1.03 09.12.2017
v1.02 29.11.2017
- AROS code compliance
v1.01 28.11.2017
- Handle network disconnection
- Fix infinity timeout problem

View File

@ -1,7 +1,7 @@
Copyright (c) 2001, 02 Motoyuki Kasahara
Copyright (c) 2007 TANDBERG Telecom AS
Copyright (c) 2008-2009 Dag-Erling Smørgrav <des@des.no>
Copyright (c) 2017-2019 Carsten Sonne Larsen <cs@innolan.net>
Copyright (c) 2017-2021 Carsten Sonne Larsen <cs@innolan.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@ -1,49 +1,49 @@
all: timekeeper
all: timekeeper timelogger timectrl
mkdir -p obj/
mv *.o obj/
CC = gcc
CFLAGS += -O2 -fno-stack-protector -DAROS -Wall
LDLIBS +=
CC = gcc
CFLAGS = -Wall
LFLAGS1 = -s -Wl,--cref,-M,-Map=TimeKeeper.map
LFLAGS2 = -s -Wl,--cref,-M,-Map=TimeLogger.map
LFLAGS3 = -s -Wl,--cref,-M,-Map=TimeCtrl.map
broker.o: compiler.h config.h message.h win.h
OBJECTS = arexx.o broker.o conv.o ctrlmsg.o global.o library.o log.o locale.o main.o mem.o \
message.o net_getaddrinfo.o net_poll.o net.o notify.o ptz.o setting.o shutdown.o \
sntp.o string.o sync.o text.o timer.o tz.o val.o win_main.o win_gad.o
com.o: compiler.h config.h message.h state.h time.h sntp.h mem.h
OBJLOG = logger.o string.o
library.o: compiler.h config.h time.h mem.h
OBJCTRL = ctrl.o string.o
log.o: compiler.h config.h log.h mem.h
timekeeper: ${OBJECTS}
${CC} ${CFLAGS} ${LFLAGS1} -o TimeKeeper ${OBJECTS} ${LDLIBS}
mkdir -p obj/
mv TimeKeeper obj/
mv TimeKeeper.map obj/
main.o: compiler.h config.h state.h time.h mem.h
timelogger: ${OBJLOG}
${CC} ${CFLAGS} ${LFLAGS2} -o TimeLogger ${OBJLOG} ${LDLIBS}
mkdir -p obj/
mv TimeLogger obj/
mv TimeLogger.map obj/
mem.o: compiler.h config.h mem.h
message.o: compiler.h config.h message.h mem.h
net_getaddrinfo.o: compiler.h mem.h config.h net_getaddrinfo.h
net_poll.o: compiler.h config.h mem.h
net.o: compiler.h config.h net_getaddrinfo.h message.h mem.h
sntp.o: compiler.h config.h sntp.h time.h net_getaddrinfo.h message.h mem.h
state.o: compiler.h config.h state.h mem.h
string.o: compiler.h config.h string.h mem.h
time.o: compiler.h config.h time.h mem.h
win_main.o: compiler.h config.h message.h state.h time.h mem.h win.h
win_gad.o: compiler.h config.h message.h state.h time.h mem.h win.h
timekeeper: broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o sntp.o state.o time.o string.o win_main.o win_gad.o
${CC} ${CFLAGS} ${LFLAGS} -s -o TimeKeeper \
broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o sntp.o state.o time.o string.o win_main.o win_gad.o \
${LDLIBS}
timectrl: ${OBJCTRL}
${CC} ${CFLAGS} ${LFLAGS3} -o TimeCtrl ${OBJCTRL} ${LDLIBS}
mkdir -p obj/
mv TimeCtrl obj/
mv TimeCtrl.map obj/
clean:
rm -f TimeKeeper broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o settings.o sntp.o state.o time.o string.o win_main.o win_gad.o TimeKeeper.map
rm -Rf *.o
rm -Rf TimeLogger
rm -Rf TimeLogger.map
rm -Rf TimeKeeper
rm -Rf TimeKeeper.map
rm -Rf TimeCtrl
rm -Rf TimeCtrl.map
rm -Rf obj
depend:
@echo Dependencies already done

View File

@ -1,58 +1,52 @@
all: timekeeper
all: timekeeper timelogger timectrl
mkdir -p obj/
mv *.o obj/
CC = /opt/m68k-amigaos/bin/m68k-amigaos-gcc
# GCC 6.x
# https://github.com/bebbo/amiga-gcc
#
CC = /opt/amiga/bin/m68k-amigaos-gcc
CFLAGS = -O0 -DAOS3 -DLIB_HOST -Iinclude -mcrt=clib2 -Wall
LFLAGS1 = -s -Wl,--cref,-M,-Map=TimeKeeper.map
LFLAGS2 = -s -Wl,--cref,-M,-Map=TimeLogger.map
LFLAGS3 = -s -Wl,--cref,-M,-Map=TimeCtrl.map
# clib2
#CFLAGS = -O2 -DAOS3 -Iinclude -mcrt=clib2 -m68020 -fbaserel32 -Wall
#LFALGS = -Wl,--cref,-M,-Map=TimeKeeper.map
#LDLIBS = -lnet
OBJECTS = arexx.o broker.o conv.o ctrlmsg.o global.o library.o log.o locale.o main.o mem.o \
message.o net_getaddrinfo.o net_poll.o net.o notify.o ptz.o setting.o shutdown.o \
sntp.o string.o sync.o text.o timer.o tz.o val.o win_main.o win_gad.o
# libnix
#CFLAGS = -O2 -DAOS3 -fomit-frame-pointer -fno-stack-check -Iinclude -noixemul -Wall
CFLAGS = -O2 -DAOS3 -fno-stack-check -Iinclude -noixemul -Wall
LFLAGS = -Wl,--cref,-M,-Map=TimeKeeper.map
LDLIBS =
OBJLOG = logger.o string.o
broker.o: compiler.h config.h message.h win.h
OBJCTRL = ctrl.o string.o
com.o: compiler.h config.h message.h state.h time.h sntp.h mem.h
timekeeper: ${OBJECTS}
${CC} ${CFLAGS} ${LFLAGS1} -o TimeKeeper ${OBJECTS} ${LDLIBS}
mkdir -p obj/
mv TimeKeeper obj/
mv TimeKeeper.map obj/
library.o: compiler.h config.h time.h mem.h
timelogger: ${OBJLOG}
${CC} ${CFLAGS} ${LFLAGS2} -o TimeLogger ${OBJLOG} ${LDLIBS}
mkdir -p obj/
mv TimeLogger obj/
mv TimeLogger.map obj/
log.o: compiler.h config.h log.h mem.h
main.o: compiler.h config.h state.h time.h mem.h
mem.o: compiler.h config.h mem.h
message.o: compiler.h config.h message.h mem.h
net_getaddrinfo.o: compiler.h mem.h config.h net_getaddrinfo.h
net_poll.o: compiler.h config.h mem.h
net.o: compiler.h config.h net_getaddrinfo.h message.h mem.h
sntp.o: compiler.h config.h sntp.h time.h net_getaddrinfo.h message.h mem.h
state.o: compiler.h config.h state.h mem.h
string.o: compiler.h config.h string.h mem.h
time.o: compiler.h config.h time.h mem.h
win_main.o: compiler.h config.h message.h state.h time.h mem.h win.h
win_gad.o: compiler.h config.h message.h state.h time.h mem.h win.h
timekeeper: broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o sntp.o state.o time.o string.o win_main.o win_gad.o
${CC} ${CFLAGS} ${LFLAGS} -s -o TimeKeeper \
broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o sntp.o state.o time.o string.o win_main.o win_gad.o \
${LDLIBS}
timectrl: ${OBJCTRL}
${CC} ${CFLAGS} ${LFLAGS3} -o TimeCtrl ${OBJCTRL} ${LDLIBS}
mkdir -p obj/
mv TimeCtrl obj/
mv TimeCtrl.map obj/
clean:
rm -f TimeKeeper broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o settings.o sntp.o state.o time.o string.o win_main.o win_gad.o TimeKeeper.map
rm -Rf *.o
rm -Rf TimeLogger
rm -Rf TimeLogger.map
rm -Rf TimeKeeper
rm -Rf TimeKeeper.map
rm -Rf TimeCtrl
rm -Rf TimeCtrl.map
rm -Rf obj
depend:
@echo Dependencies already done

289
Manual
View File

@ -1,289 +0,0 @@
@database TimeKeeper.guide
@$VER: TimeKeeper.guide 1.06 (2019-02-08)
@(c) 2017-2019 Carsten Sonne Larsen <cs@innolan.net>
@author Carsten Sonne Larsen
@rem Copyright (c) 2017-2019 Carsten Sonne Larsen <cs@innolan.net>
@rem All rights reserved.
@rem
@rem Redistribution and use in source and binary forms, with or without
@rem modification, are permitted provided that the following conditions
@rem are met:
@rem 1. Redistributions of source code must retain the above copyright
@rem notice, this list of conditions and the following disclaimer.
@rem 2. Redistributions in binary form must reproduce the above copyright
@rem notice, this list of conditions and the following disclaimer in the
@rem documentation and/or other materials provided with the distribution.
@rem
@rem THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
@rem IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@rem OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
@rem IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@rem INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
@rem NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
@rem THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@Width 74
@Node Main "TimeKeeper.guide"
@Next "Configuring the client"
AmiTimeKeeper is a small program which keeps the time right on your
machine. No installation is required.
AmiTimeKeeper is operated as a commodity and is controlled by AmigaOS.
An AmiTCP compatible TCP/IP stack is required for AmiTimeKeeper to work.
AmiTimeKeeper can be configured through several settings. This can be
done either directly from the command line or by using the tooltypes
of an icon. Preferences can also be saved between reboots.
@{"Configuring the client" Link "Configuring the client"}
@{"Using tooltypes of an icon" Link "Using tooltypes of an icon"}
@{"Saving preferences" Link "Saving preferences"}
@{"Change Log / Change History" Link "Change Log"}
@{"Software License" Link "Software License"}
@{"Contacting the author" Link "Contacting the author"}
@EndNode
@Node "Configuring the client" "TimeKeeper.guide/Configuring the client"
@Toc "Main"
@Prev "Main"
@Next "Using tooltypes of an icon"
@{b}Server Address@{ub}
NTP servers are managed by several organizations. The pool.ntp.org
project and Network Time Foundation are probably the two most famous.
The pool.ntp.org project organize servers into pools whereas Network
Time Foundation maintains a list of valid NTP servers. The servers are
divided into two categories: Stratum 1 and Stratum 2.
The NTP pool servers are divided into zones. If you want to use a server
in Europe you can use set the server address to europe.pool.ntp.org.
For North America the server address is north-america.pool.ntp.org.
Zones also exists for countries. To use a server in for example Germany
the server address should be set to de.pool.ntp.org. For Switzerland
the address should be ch.pool.ntp.org.
Network Time Foundation has a website on http://support.ntp.org/
The pool.ntp.org project website is located at https://www.ntppool.org/
@{b}Server Port@{ub}
NTP servers use port 123 as default. Only under special circumstances
are the NTP server port different from 123.
@{b}Interval between requests@{ub}
The Amiga hardware clock will slowly drift away from true time. The
drift is determined by several factors and is small, but the drift is not
insignificant. Request are repeatedly sent to the NTP server in order to
keep the Amiga hardware clock as close to true time as possible.
The requests are sent in certain intervals defined by the interval
parameter. The interval should be specified using milliseconds. One
thousand (1.000) milliseconds are equal to one second.
@{b}Threshold@{ub}
Due to the accuracy of NTP servers and the nature of Amiga CPUs it does
not make sense to adjust the Amiga clock on every response from the NTP
server. Processing the response could take longer time than anticipated.
The amount of accepted inaccuracy is set using the threshold parameter.
The threshold should be specified using microsecond. One million
microseconds (1.000.000) are equal to one second.
@{b}Read Only@{ub}
It is possible to send request to the NTP server without setting the
Amiga hardware clock. This option can be handy when debugging time zone
setup and other time related parameters.
@{b}Connection Timeout@{ub}
In some cases, a connection to the NTP server cannot be established or
the NTP server simply does respond. To avoid an infinitive wait for a
response the connection will instead make a time out. The timeout
interval should be specified using milliseconds. One thousand (1.000)
milliseconds are equal to one second.
@{b}Verbosity@{ub}
The level of logging can be adjusted from none to all. Expressed as a
numeric value verbose can be 0, 1, 2 or 3, where 0 is equal to none and
3 is equal to maximum verbosity.
@{b}Log file@{ub}
It is possible to send log messages to a file instead of sending them to
a console window.
@EndNode
@Node "Using tooltypes of an icon" "TimeKeeper.guide/Using tooltypes of an icon"
@Toc "Main"
@Prev "Configuring the client"
@Next "Saving preferences"
Settings can be changes by setting tooltypes in the TimeKeeper icon.
Add the following line to the icon tooltypes in order to set the server
to an European pool server:
SERVER=europe.pool.ntp.org
The available tooltypes are the same as the available command line
parameters.
@{b}Parameter@{ub} | @{b}Short description@{ub}
-----------------------------------------
SERVER | Server Address
PORT | Server Port
THRESHOLD | Adjustment threshold
INTERVAL | Interval between requests
CX_PRIORITY | Commodity priority
READONLY | Read only option
TIMEOUT | Connection Timeout
VERBOSE | Log verbosity
LOGFILE | Log file location
@{b}Caveats@{ub}
Settings can be overridden and are set in the following order:
1. Preference file
2. Icon tooltypes
3. CLI parameters
CLI parameters has highest precedence and will always override settings
from icon tooltypes and from the preference file.
@EndNode
@Node "Saving preferences" "TimeKeeper.guide/Saving preferences"
@Toc "Main"
@Prev "Using tooltypes of an icon"
@Next "Change Log"
Preferences from the setting window are saved in the file
ENV:timekeeper.prefs
Preferences are also persisted between reboots in the file
ENVARC:timekeeper.prefs
Depending on the setup the content of timekeeper.prefs could be:
CX_PRIORITY=25
THRESHOLD=1000000
SERVER=de.pool.ntp.org
PORT=123
TIMEOUT=5000
INTERVAL=17500
VERBOSE=3
READONLY=0
LOGFILE=RAM:log
The preference file should not be edited under normal circumstances.
@{b}Caveats@{ub}
If LOGFILE is set in the preference file, no messages will be emitted
to screen (unless overridden by CLI or Icon tooltype with LOGFILE=NO).
@EndNode
@Node "Change Log" "TimeKeeper.guide/Change Log"
@Toc "Main"
@Prev "Saving preferences"
@Next "Software License"
@{b}v1.06 08.02.2019@{ub}
- Adjust layout in settings window
@{b}v1.05 06.08.2018@{ub}
- Preferences can now be saved from settings window
- Time zone is shown as UTC offset in settings window
- Running multiple instances no longer create zombie processes
- Low water option renamed to threshold and high water option removed
- New option for sending log messages to file instead of to screen
- Some incorrect NTP log messages no longer appears
- Read-only option is now applied consistently
- Potential race condition in memory allocation fixed
- Other minor enhancements
@{b}v1.04 15.12.2017@{ub}
- Default settings adjusted to comply better with AmigaOS
- Bugs in threshold settings (high/low water) fixed
- Bugs in opening and closing of libraries fixed
- New and more accurate error and log messages
@{b}v1.03 09.12.2017@{ub}
- Settings window
@{b}v1.02 29.11.2017@{ub}
- AROS code compliance
@{b}v1.01 28.11.2017@{ub}
- Handle network disconnection
- Fix infinity timeout problem
- Support hardware clock
- Improved error messages
@{b}v1.00 26.11.2017@{ub}
- First public release
@EndNode
@Node "Software License" "TimeKeeper.guide/Software License"
@Prev "Change Log"
@Next "Contacting the author"
@Toc "Main"
@{b}Simplified BSD License / 2-clause BSD license@{ub}
Copyright (c) 2001, 02 Motoyuki Kasahara
Copyright (c) 2007 TANDBERG Telecom AS
Copyright (c) 2008-2009 Dag-Erling Smørgrav <des@des.no>
Copyright (c) 2017-2019 Carsten Sonne Larsen <cs@innolan.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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 AUTHOR ``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 AUTHOR 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.
@EndNode
@Node "Contacting the author" "TimeKeeper.guide/Contacting the author"
@Toc "Main"
@Prev "Software License"
The author of AmiTimeKeeper can be contacted using the following
email addresses: <carsten.larsen@mail.com> or <cs@innolan.net>.
Please notice <cs@innolan.net> is a member of several high volume
mailing lists and should not be used under normal circumstances.
Feel free to send suggestions, feature request and bug reports.
General comment and questions are also welcome.
Carsten Sonne Larsen
February 2019
@EndNode

1220
TimeKeeper.guide Normal file

File diff suppressed because it is too large Load Diff

1204
TimeKeeper.html Normal file

File diff suppressed because it is too large Load Diff

45
TimeKeeper.readme Normal file
View File

@ -0,0 +1,45 @@
Short: Keep your time right
Author: Carsten Larsen (carsten.larsen@mail.com)
Uploader: Carsten Larsen (carsten.larsen@mail.com)
Type: util/cdity
Version: 1.12
Architecture: m68k-amigaos
AmiTimeKeeper is a small program which keeps the time right on your
machine. No installation is required. It is operated as a commodity
and is controlled by AmigaOS. An AmiTCP compatible TCP/IP stack is
required for AmiTimeKeeper to work.
Several settings determine the behaviour. The settings are passed
either directly from the command line or by using the tool types of
an icon. Preferences can also be saved between reboots. A utility
for small tasks like starting and stopping is also included.
Comprehensive control is possible using ARexx.
The default server address is pool.ntp.org. To find another server
try visiting support.ntp.org or one of the other sites listing time
servers. Use a fixed pool server by prefixing the domain, for example,
1.pool.ntp.org.
The time zone needs to be configured using Workbench preferences or
a similar tool. In Amiga OS this is available through the Locale
Preferences Editor. The local time zone and daylight saving time are
optionally specified manually or using a POSIX TZ variable style.
The Icaros Desktop system is distributed with a custom build version of
AmiTimeKeeper. The author encourages everyone with an interest to build
their own version.
Please report bugs and other issues by sending a mail or using:
https://ranger.innolan.net/rainlance/AmiTimeKeeper
v1.12 31.01.2021
- New options to specify the local time zone
- New ARexx commands, parameters and error variables
- New option to start without active time synchronization
- New deactivate logging option for performance saving
- More bugs in calculation of time zone transition fixed
- Sanity check on value for interval between requests
- Updated ARexx documentation and script
- Honour ARexx result flag (RXFF_RESULT)
- Various minor bug fixes and improvements

832
arexx.c Normal file
View File

@ -0,0 +1,832 @@
/*-
* Copyright (c) 2020-2021 Carsten Sonne Larsen <cs@innolan.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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 AUTHOR ``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 AUTHOR 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.
*
*/
#include "config.h"
#include "global.h"
#include "string.h"
#include "message.h"
#include "setting.h"
#include "text.h"
#include "sync.h"
#include "conv.h"
#include "mem.h"
#include "win.h"
#include "val.h"
#include "tz.h"
#include <proto/rexxsyslib.h>
#include <proto/alib.h>
#include <rexx/errors.h>
#include <rexx/storage.h>
#include <rexx/rxslib.h>
#include "logmod.h"
#define MODULENAME "ARexx"
static char *arexxHelpText = NULL;
typedef void (*ARexxCommand)(struct RexxMsg *, char **);
struct ARexxCommandDef
{
/* Unique numeric command identifier */
const int Identifier;
/* Command name as exposed in ARexx interface */
const char *Name;
/* Short description of command purpose */
const char *Description;
/* Function pointer to action code */
ARexxCommand Command;
/* True if command only return a result. False is command is an action */
bool ResultCommand;
/* Number of parameters / arguments */
int Parameters;
};
struct ARexxParameterDef
{
const int Identifier;
const char *Keyword;
};
static void ARexxIdentifierCommand(struct RexxMsg *, char **);
static void ARexxVersionCommand(struct RexxMsg *, char **);
static void ARexxHelpCommand(struct RexxMsg *, char **);
static void ARexxStatusCommand(struct RexxMsg *, char **);
static void ARexxTimezoneCommand(struct RexxMsg *msg, char **);
static void ARexxLastSyncCommand(struct RexxMsg *msg, char **);
static void ARexxLastAdjustCommand(struct RexxMsg *msg, char **);
static void ARexxGetValueCommand(struct RexxMsg *, char **);
static void ARexxSetValueCommand(struct RexxMsg *, char **);
static void ARexxNowCommand(struct RexxMsg *, char **);
static void ARexxShowCommand(struct RexxMsg *, char **);
static void ARexxHideCommand(struct RexxMsg *, char **);
static void ARexxStartCommand(struct RexxMsg *, char **);
static void ARexxStopCommand(struct RexxMsg *, char **);
static void ARexxShutdownCommand(struct RexxMsg *, char **);
static void ARexxLogTransitionsCommand(struct RexxMsg *, char **);
#define AREXX_COMMAND_COUNT 16
static struct ARexxCommandDef arexxCommands[] = {
{1, "ID", "Get application identifier", ARexxIdentifierCommand, true, 0},
{2, "VERSION", "Get application version number", ARexxVersionCommand, true, 0},
{3, "HELP", "Get a list of ARexx commands and a short description", ARexxHelpCommand, true, 0},
{4, "STATUS", "Get current synchronization status", ARexxStatusCommand, true, 1},
{5, "TIMEZONE", "Get current time zone", ARexxTimezoneCommand, true, 1},
{6, "LASTSYNC", "Get time of last synchronization operation", ARexxLastSyncCommand, true, 2},
{7, "LASTADJ", "Get time of last clock adjustment", ARexxLastAdjustCommand, true, 2},
{8, "GET", "Get a runtime configuration value", ARexxGetValueCommand, true, 1},
{9, "SET", "Set a runtime configuration value", ARexxSetValueCommand, false, 2},
{10, "NOW", "Get current time and date", ARexxNowCommand, false, 2},
{11, "SHOW", "Show settings window", ARexxShowCommand, false, 0},
{12, "HIDE", "Hide settings window", ARexxHideCommand, false, 0},
{13, "START", "Start the time synchronization process", ARexxStartCommand, false, 0},
{14, "STOP", "Stop the time synchronization process", ARexxStopCommand, false, 0},
{15, "SHUTDOWN", "Shutdown " APP_SHORT_NAME, ARexxShutdownCommand, false, 0},
{16, "LOGTRANS", "Emit time zone transition map to log", ARexxLogTransitionsCommand, false, 0}};
#define AREXX_PARAMETER_SERVER 1
#define AREXX_PARAMETER_PORT 2
#define AREXX_PARAMETER_THRESHOLD 3
#define AREXX_PARAMETER_INTERVAL 4
#define AREXX_PARAMETER_PRIORITY 5
#define AREXX_PARAMETER_POPKEY 6
#define AREXX_PARAMETER_POPUP 7
#define AREXX_PARAMETER_READONLY 8
#define AREXX_PARAMETER_EXPERT 9
#define AREXX_PARAMETER_TIMEOUT 10
#define AREXX_PARAMETER_ACTIVE 11
#define AREXX_PARAMETER_NOLOG 12
#define AREXX_PARAMETER_TZ 13
#define AREXX_PARAMETER_TZD 14
#define AREXX_PARAMETER_TZNAME 15
#define AREXX_PARAMETER_TZVALUE 16
#define AREXX_PARAMETER_TZDST 17
#define AREXX_PARAMETER_LAST 17
#define AREXX_PARAMETER_UNKNOWN 90
#define AREXX_PARAMETER_MISSING 91
#define AREXX_PARAMETER_SHUTDOWN 92
#define AREXX_PARAMETER_COUNT AREXX_PARAMETER_LAST
static struct ARexxParameterDef arexxParameters[] = {
{AREXX_PARAMETER_SERVER, KEYWORD_SERVER},
{AREXX_PARAMETER_PORT, KEYWORD_PORT},
{AREXX_PARAMETER_THRESHOLD, KEYWORD_THRESHOLD},
{AREXX_PARAMETER_INTERVAL, KEYWORD_INTERVAL},
{AREXX_PARAMETER_PRIORITY, KEYWORD_PRIORITY},
{AREXX_PARAMETER_POPKEY, KEYWORD_POPKEY},
{AREXX_PARAMETER_POPUP, KEYWORD_POPUP},
{AREXX_PARAMETER_READONLY, KEYWORD_READONLY},
{AREXX_PARAMETER_EXPERT, KEYWORD_EXPERT},
{AREXX_PARAMETER_TIMEOUT, KEYWORD_TIMEOUT},
{AREXX_PARAMETER_ACTIVE, KEYWORD_ACTIVE},
{AREXX_PARAMETER_NOLOG, KEYWORD_NOLOG},
{AREXX_PARAMETER_TZ, KEYWORD_TZ},
{AREXX_PARAMETER_TZD, KEYWORD_TZD},
{AREXX_PARAMETER_TZNAME, KEYWORD_TZNAME},
{AREXX_PARAMETER_TZVALUE, KEYWORD_TZVALUE},
{AREXX_PARAMETER_TZDST, KEYWORD_TZDST}};
#define AREXX_MAX_ARGS_COUNT 8
struct ARexxErrorDef
{
const long Code;
const char **Text;
};
#define AREXX_ERROR_UNKNOWN_CMD 10 /* Unknown ARexx command */
#define AREXX_ERROR_UNKNOWN_PARM 11 /* Unknown parameter */
#define AREXX_ERROR_PARM_MISS 12 /* Parameter is missing */
#define AREXX_ERROR_PARM_INV 13 /* Invalid parameter value */
#define AREXX_ERROR_CLOCK_INV 18 /* Clock has not been adjusted */
#define AREXX_ERROR_SYNC_INV 19 /* No responses from NTP server */
#define AREXX_ERROR_SYNC_ON 20 /* Synchronization is already active */
#define AREXX_ERROR_SYNC_OFF 21 /*Synchronization is already deactivated */
#define AREXX_ERROR_COUNT 8
static struct ARexxErrorDef arexxErrors[] = {
{AREXX_ERROR_UNKNOWN_CMD, &TextARexxCmdUnknown},
{AREXX_ERROR_UNKNOWN_PARM, &TextARexxParmUnknown},
{AREXX_ERROR_PARM_MISS, &TextARexxParmMiss},
{AREXX_ERROR_PARM_INV, &TextARexxParmInvalid},
{AREXX_ERROR_CLOCK_INV, &TextNoClockAdjust},
{AREXX_ERROR_SYNC_INV, &TextNoResponses},
{AREXX_ERROR_SYNC_ON, &TextSyncAlreadyOn},
{AREXX_ERROR_SYNC_OFF, &TextSyncAlreadyOff}};
static void SplitAndTerminate(char *string, char **res)
{
char *p = string;
char **q = res;
int count = 1;
while (*p != '\0')
{
if (*p == ' ')
{
// Terminate
*p = '\0';
p++;
// Skip trailing spaces
while (*p == ' ')
p++;
*q = p;
q++;
count++;
// Bail out
if (count >= AREXX_MAX_ARGS_COUNT)
return;
}
else
{
p++;
}
}
}
static void BuildARexxHelpText(void)
{
char *p;
int i, line, len = 0;
if (arexxHelpText != NULL)
return;
len += 26; // Header
len += 71 * 2; // Spacer
len += StrLen(AREXX_ERROR_VAR_CODE) + StrLen(AREXX_ERROR_VAR_TEXT) + 32; // Footer
for (i = 0; i < AREXX_COMMAND_COUNT; i++)
{
len += StrLen(arexxCommands[i].Description) + 14;
}
arexxHelpText = (char *)AllocStringSafe(len);
if (arexxHelpText == NULL)
return;
p = AppendText(arexxHelpText, " Command | Description\n");
p = AppendChar(p, '-', 70);
p = AppendChar(p, '\n', 1);
for (i = 0; i < AREXX_COMMAND_COUNT; i++)
{
line = 10 - StrLen(arexxCommands[i].Name);
p = AppendChar(p, ' ', 1);
p = AppendText(p, arexxCommands[i].Name);
p = AppendChar(p, ' ', line);
p = AppendChar(p, '|', 1);
p = AppendChar(p, ' ', 1);
p = AppendText(p, arexxCommands[i].Description);
p = AppendChar(p, '\n', 1);
}
p = AppendChar(p, '-', 70);
p = AppendChar(p, '\n', 1);
p = AppendText(p, "Error status is set in ");
p = AppendText(p, AREXX_ERROR_VAR_CODE);
p = AppendText(p, " and ");
p = AppendText(p, AREXX_ERROR_VAR_TEXT);
}
void CleanupARexx(void)
{
if (arexxHelpText != NULL)
{
FreeMemSafe(arexxHelpText);
arexxHelpText = NULL;
}
}
static void SetARexxVar(struct RexxMsg *msg, const char *var, const char *text)
{
LONG error = SetRexxVar(msg, (CONST_STRPTR)var, (CONST_STRPTR)text, (LONG)StrLen(text));
if (error != 0)
{
LogWarn(TextARexxVarError, (long)error);
LogWarn(TextARexxVarValue, var, text);
}
else
{
LogTrace(TextARexxVarValue, var, text);
}
}
static void ARexxErrorClear(struct RexxMsg *msg)
{
SetARexxVar(msg, AREXX_ERROR_VAR_CODE, "0");
SetARexxVar(msg, AREXX_ERROR_VAR_TEXT, "");
}
static void ARexxError(struct RexxMsg *msg, long code)
{
char errorCode[MAXLONGCHARSIZE];
LongToStr(code, errorCode);
SetARexxVar(msg, AREXX_ERROR_VAR_CODE, errorCode);
int i;
for (i = 0; i < AREXX_ERROR_COUNT; i++)
{
if (arexxErrors[i].Code == code)
{
const char *text = *(arexxErrors[i].Text);
SetARexxVar(msg, AREXX_ERROR_VAR_TEXT, text);
break;
}
}
}
static void ARexxResult(struct RexxMsg *msg, const char *text)
{
if (msg->rm_Action & RXFF_RESULT)
{
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)text, (LONG)StrLen(text));
}
LogTrace(TextARexxResult, text);
ARexxErrorClear(msg);
}
static void ARexxResultLong(struct RexxMsg *msg, long value)
{
char text[MAXLONGCHARSIZE];
SNPrintf(text, MAXLONGCHARSIZE, "%ld", value);
ARexxResult(msg, text);
}
static void ARexxResultBool(struct RexxMsg *msg, char *parm, long value)
{
char text[MAXBOOLCHARSIZE];
if (Stricmp((STRPTR)parm, (STRPTR)KEYWORD_NUMBER) == 0)
BoolToStrNum(value, text);
else
BoolToStr(value, text);
ARexxResult(msg, text);
}
static void ARexxTimeResult(struct RexxMsg *msg, char **parms, struct timeval *utv, long error)
{
if (utv->tv_secs == 0 && utv->tv_micro == 0)
{
ARexxError(msg, error);
return;
}
bool utc;
STRPTR format = (STRPTR)*parms++;
if (Stricmp((STRPTR)*parms, (STRPTR)KEYWORD_UTC) == 0)
{
utc = true;
}
else if (*parms == NULL || Stricmp((STRPTR)*parms, (STRPTR)KEYWORD_LOCAL) == 0)
{
utc = false;
}
else
{
ARexxError(msg, AREXX_ERROR_PARM_INV);
return;
}
char result[DATETIME_TEXT_LEN + 1];
if (format == NULL || Stricmp(format, (STRPTR)KEYWORD_DOS) == 0)
Utc2DOS(utv, result, utc);
else if (Stricmp(format, (STRPTR)KEYWORD_ASCII) == 0)
Utc2ASCII(utv, result, utc);
else if (Stricmp(format, (STRPTR)KEYWORD_DATE) == 0)
Utc2ARexxDate(utv, result, utc);
else if (Stricmp(format, (STRPTR)KEYWORD_TIME) == 0)
Utc2ARexxTime(utv, result, utc);
else if (Stricmp(format, (STRPTR)KEYWORD_RFC850) == 0)
Utc2RFC850(utv, result);
else if (Stricmp(format, (STRPTR)KEYWORD_RFC1123) == 0)
Utc2RFC1123(utv, result);
else if (Stricmp(format, (STRPTR)KEYWORD_RFC2822) == 0)
Utc2RFC2822(utv, result, utc);
else if (Stricmp(format, (STRPTR)KEYWORD_RFC3339) == 0)
Utc2RFC3339(utv, result, utc);
else if (Stricmp(format, (STRPTR)KEYWORD_ISO8601) == 0)
Utc2ISO8601(utv, result, utc);
else
{
ARexxError(msg, AREXX_ERROR_PARM_INV);
return;
}
ARexxResult(msg, result);
}
static void ARexxIdentifierCommand(struct RexxMsg *msg, char **parms)
{
ARexxResult(msg, APP_TITLE);
}
static void ARexxVersionCommand(struct RexxMsg *msg, char **parms)
{
ARexxResult(msg, APP_VERSION);
}
static void ARexxHelpCommand(struct RexxMsg *msg, char **parms)
{
BuildARexxHelpText();
ARexxResult(msg, arexxHelpText);
}
static void ARexxStatusCommand(struct RexxMsg *msg, char **parms)
{
if (Stricmp((STRPTR)*parms, (STRPTR)KEYWORD_NUMBER) == 0)
{
char buf[4];
BoolToStrNum(SynchronizerRunning, buf);
ARexxResult(msg, buf);
}
else if (*parms == NULL)
{
const char *result = SynchronizerRunning ? TextSyncOn : TextSyncOff;
ARexxResult(msg, result);
}
else
{
ARexxError(msg, AREXX_ERROR_PARM_INV);
}
}
static void ARexxTimezoneCommand(struct RexxMsg *msg, char **parms)
{
long val;
if (parms == NULL)
{
ARexxError(msg, AREXX_ERROR_PARM_MISS);
}
else if (!TryParseLong(*parms, &val))
{
ARexxError(msg, AREXX_ERROR_PARM_INV);
}
else if (val < 1 || val > 12)
{
ARexxError(msg, AREXX_ERROR_PARM_INV);
}
else
{
char buf[TIMEZONE_TEXT_LEN];
GetTimezoneText(buf, val);
ARexxResult(msg, buf);
}
}
static void ARexxNowCommand(struct RexxMsg *msg, char **parms)
{
struct timeval tv;
GetTimeOfDay(&tv);
ARexxTimeResult(msg, parms, &tv, AREXX_ERROR_SYNC_INV);
}
static void ARexxLastSyncCommand(struct RexxMsg *msg, char **parms)
{
struct timeval tv = LastSync;
ARexxTimeResult(msg, parms, &tv, AREXX_ERROR_SYNC_INV);
}
static void ARexxLastAdjustCommand(struct RexxMsg *msg, char **parms)
{
struct timeval tv = LastAdjust;
ARexxTimeResult(msg, parms, &tv, AREXX_ERROR_CLOCK_INV);
}
static int ARexxFindParameter(char **parms)
{
int i;
char *parm = parms[0];
if (parm == NULL || *parm == '\0')
{
return AREXX_PARAMETER_MISSING;
}
for (i = 0; i < AREXX_PARAMETER_COUNT; i++)
{
if (Stricmp((STRPTR)parm, (STRPTR)arexxParameters[i].Keyword) == 0)
{
return arexxParameters[i].Identifier;
}
}
return AREXX_PARAMETER_UNKNOWN;
}
static void ARexxGetValueCommand(struct RexxMsg *msg, char **parms)
{
int param = ARexxFindParameter(parms++);
switch (param)
{
case AREXX_PARAMETER_UNKNOWN:
ARexxError(msg, AREXX_ERROR_UNKNOWN_PARM);
break;
case AREXX_PARAMETER_MISSING:
ARexxError(msg, AREXX_ERROR_PARM_MISS);
break;
case AREXX_PARAMETER_SERVER:
ARexxResult(msg, Settings->DestinationAddress);
break;
case AREXX_PARAMETER_PORT:
ARexxResult(msg, Settings->DestinationPort);
break;
case AREXX_PARAMETER_INTERVAL:
ARexxResultLong(msg, Settings->Interval);
break;
case AREXX_PARAMETER_PRIORITY:
ARexxResultLong(msg, Settings->Priority);
break;
case AREXX_PARAMETER_POPKEY:
ARexxResult(msg, Settings->PopKey);
break;
case AREXX_PARAMETER_POPUP:
ARexxResultBool(msg, *parms, Settings->Popup);
break;
case AREXX_PARAMETER_READONLY:
ARexxResultBool(msg, *parms, Settings->Readonly);
break;
case AREXX_PARAMETER_EXPERT:
ARexxResultBool(msg, *parms, Settings->Expert);
break;
case AREXX_PARAMETER_TIMEOUT:
ARexxResultLong(msg, Settings->Timeout);
break;
case AREXX_PARAMETER_ACTIVE:
ARexxResultBool(msg, *parms, SynchronizerRunning);
break;
case AREXX_PARAMETER_NOLOG:
ARexxResultBool(msg, *parms, Settings->NoLog);
break;
case AREXX_PARAMETER_TZ:
ARexxResult(msg, Settings->TZ);
break;
case AREXX_PARAMETER_TZD:
ARexxResultLong(msg, Settings->TimeZoneDisplay);
break;
case AREXX_PARAMETER_TZNAME:
ARexxResult(msg, Settings->TimeZoneName);
break;
case AREXX_PARAMETER_TZVALUE:
if (Settings->TimeZoneValue != TZVALUE_DEF)
ARexxResultLong(msg, Settings->TimeZoneValue);
else
ARexxResult(msg, "");
break;
case AREXX_PARAMETER_TZDST:
ARexxResultLong(msg, Settings->TimeZoneDst);
break;
case AREXX_PARAMETER_THRESHOLD:
{
char buf[MAXLONGLONGCHARSIZE];
LongLongToStr(Settings->Threshold, buf);
ARexxResult(msg, buf);
}
break;
default:
ARexxError(msg, AREXX_ERROR_UNKNOWN_PARM);
break;
}
}
static void ARexxSetValueCommand(struct RexxMsg *msg, char **parms)
{
int param = ARexxFindParameter(parms++);
char *valueString = *parms;
long long longlongValue;
long longValue;
bool boolValue;
switch (param)
{
case AREXX_PARAMETER_UNKNOWN:
ARexxError(msg, AREXX_ERROR_UNKNOWN_PARM);
break;
case AREXX_PARAMETER_MISSING:
ARexxError(msg, AREXX_ERROR_PARM_MISS);
break;
case AREXX_PARAMETER_SERVER:
SetServer(valueString, APPLY_VALUE);
ARexxErrorClear(msg);
break;
case AREXX_PARAMETER_PORT:
SetPort(valueString, APPLY_VALUE);
ARexxErrorClear(msg);
break;
case AREXX_PARAMETER_THRESHOLD:
if (TryParseLongLong(valueString, &longlongValue))
{
SetThreshold(valueString, APPLY_VALUE);
ARexxErrorClear(msg);
}
else
ARexxError(msg, AREXX_ERROR_PARM_INV);
break;
case AREXX_PARAMETER_INTERVAL:
if (TryParseLong(valueString, &longValue))
{
SetInterval(longValue, APPLY_VALUE);
ARexxErrorClear(msg);
}
else
ARexxError(msg, AREXX_ERROR_PARM_INV);
break;
case AREXX_PARAMETER_PRIORITY:
if (TryParseLong(valueString, &longValue))
{
SetPriority(valueString, APPLY_VALUE);
ARexxErrorClear(msg);
}
else
ARexxError(msg, AREXX_ERROR_PARM_INV);
break;
case AREXX_PARAMETER_POPKEY:
// TODO: Remove CX filter object and add new filter (Settings->PopKey)
// http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node0587.html
ARexxError(msg, AREXX_ERROR_UNKNOWN_PARM);
break;
case AREXX_PARAMETER_POPUP:
if (TryParseBoolean(valueString, &boolValue))
{
Settings->Popup = boolValue;
ARexxErrorClear(msg);
}
else
ARexxError(msg, AREXX_ERROR_PARM_INV);
break;
case AREXX_PARAMETER_READONLY:
if (TryParseBoolean(valueString, &boolValue))
{
Settings->Readonly = boolValue;
ARexxErrorClear(msg);
}
else
ARexxError(msg, AREXX_ERROR_PARM_INV);
break;
case AREXX_PARAMETER_EXPERT:
if (TryParseBoolean(valueString, &boolValue))
{
Settings->Expert = boolValue;
SendWindowMessage(ATK_SHUTDOWN);
ShowSettingWindow();
ARexxErrorClear(msg);
}
else
ARexxError(msg, AREXX_ERROR_PARM_INV);
break;
case AREXX_PARAMETER_TIMEOUT:
if (TryParseLong(valueString, &longValue))
{
SetTimeout(longValue, APPLY_VALUE);
ARexxErrorClear(msg);
}
else
ARexxError(msg, AREXX_ERROR_PARM_INV);
break;
case AREXX_PARAMETER_ACTIVE:
if (TryParseBoolean(valueString, &boolValue))
{
if (boolValue)
ARexxStartCommand(msg, NULL);
else
ARexxStopCommand(msg, NULL);
}
else
ARexxError(msg, AREXX_ERROR_PARM_INV);
break;
case AREXX_PARAMETER_NOLOG:
if (TryParseBoolean(valueString, &boolValue))
{
Settings->NoLog = boolValue;
ARexxErrorClear(msg);
}
else
ARexxError(msg, AREXX_ERROR_PARM_INV);
case AREXX_PARAMETER_TZ:
SetTimeZoneSetting(SettingKeys->TZ, &Settings->TZ, valueString, APPLY_VALUE);
break;
case AREXX_PARAMETER_TZD:
SetTimeZoneSettingLong(SettingKeys->TimeZoneDisplay, &Settings->TimeZoneDisplay, valueString, APPLY_VALUE);
break;
case AREXX_PARAMETER_TZNAME:
SetTimeZoneSetting(SettingKeys->TimeZoneName, &Settings->TimeZoneName, valueString, APPLY_VALUE);
break;
case AREXX_PARAMETER_TZVALUE:
SetTimeZoneSettingLong(SettingKeys->TimeZoneValue, &Settings->TimeZoneValue, valueString, APPLY_VALUE);
break;
case AREXX_PARAMETER_TZDST:
SetTimeZoneSettingLong(SettingKeys->TimeZoneDst, &Settings->TimeZoneDst, valueString, APPLY_VALUE);
break;
default:
ARexxError(msg, AREXX_ERROR_UNKNOWN_PARM);
break;
}
}
static void ARexxShowCommand(struct RexxMsg *msg, char **parms)
{
ShowSettingWindow();
ARexxErrorClear(msg);
}
static void ARexxHideCommand(struct RexxMsg *msg, char **parms)
{
SendWindowMessage(ATK_SHUTDOWN);
ARexxErrorClear(msg);
}
static void ARexxStartCommand(struct RexxMsg *msg, char **parms)
{
if (!SynchronizerRunning)
{
Activate();
ARexxErrorClear(msg);
}
else
{
ARexxError(msg, AREXX_ERROR_SYNC_ON);
}
}
static void ARexxStopCommand(struct RexxMsg *msg, char **parms)
{
if (SynchronizerRunning)
{
Deactivate();
ARexxErrorClear(msg);
}
else
{
ARexxError(msg, AREXX_ERROR_SYNC_OFF);
}
}
static void ARexxShutdownCommand(struct RexxMsg *msg, char **parms)
{
LogWarn(TextARexxShutdown);
msg->rm_Result1 = AREXX_PARAMETER_SHUTDOWN;
ARexxErrorClear(msg);
}
static void ARexxLogTransitionsCommand(struct RexxMsg *msg, char **parms)
{
LogTransitionMap();
ARexxErrorClear(msg);
}
static void ExecuteARexxCommand(struct RexxMsg *msg, struct ARexxCommandDef *cmd, char **parms)
{
LogNotice(TextARexxReceived, cmd->Name);
bool execute = !cmd->ResultCommand || (cmd->ResultCommand && (msg->rm_Action & RXFF_RESULT));
if (execute)
{
if (parms == NULL)
LogTrace(TextARexxExecute1, cmd->Name);
else
LogTrace(TextARexxExecute2, cmd->Name, *parms);
cmd->Command(msg, parms);
}
}
static bool HandleARexxMessage(struct RexxMsg *msg)
{
int i;
bool found = false;
bool cont = true;
for (i = 0; i < AREXX_COMMAND_COUNT; i++)