Version 1.05
This commit is contained in:
25
AmiTimeKeeper.i386-aros.readme
Normal file
25
AmiTimeKeeper.i386-aros.readme
Normal file
@ -0,0 +1,25 @@
|
||||
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
|
4
AmiTimeKeeper.kdev4
Normal file
4
AmiTimeKeeper.kdev4
Normal file
@ -0,0 +1,4 @@
|
||||
[Project]
|
||||
CreatedFrom=Makefile.m68k
|
||||
Manager=KDevCustomMakeManager
|
||||
Name=AmiTimeKeeper
|
25
AmiTimeKeeper.readme
Normal file
25
AmiTimeKeeper.readme
Normal file
@ -0,0 +1,25 @@
|
||||
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
|
33
ChangeLog
Normal file
33
ChangeLog
Normal file
@ -0,0 +1,33 @@
|
||||
AmiTimeKeeper Change Log
|
||||
|
||||
v1.05 06.08.2018
|
||||
- Preferences can now be saved from settings window
|
||||
- Time zone is shown as UTC offset in 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
|
||||
- Some incorrect NTP log messages no longer appears
|
||||
- Read-only options is now applied consistently
|
||||
- Potential race condition in memory allocation fixed
|
||||
- Other minor enhancements
|
||||
|
||||
v1.04 15.12.2017
|
||||
- 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
|
||||
|
||||
v1.03 09.12.2017
|
||||
- Settings window
|
||||
|
||||
v1.02 29.11.2017
|
||||
- AROS code compliance
|
||||
|
||||
v1.01 28.11.2017
|
||||
- Handle network disconnection
|
||||
- Fix infinity timeout problem
|
||||
- Support hardware clock
|
||||
- Improved error messages
|
||||
|
||||
v1.00 26.11.2017
|
||||
- First public release
|
25
LICENSE
Normal file
25
LICENSE
Normal file
@ -0,0 +1,25 @@
|
||||
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-2018 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.
|
49
Makefile.aros
Normal file
49
Makefile.aros
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
all: timekeeper
|
||||
|
||||
CC = gcc
|
||||
CFLAGS += -O2 -fno-stack-protector -DAROS -Wall
|
||||
LDLIBS +=
|
||||
|
||||
broker.o: compiler.h config.h message.h win.h
|
||||
|
||||
com.o: compiler.h config.h message.h state.h time.h sntp.h mem.h
|
||||
|
||||
library.o: compiler.h config.h time.h mem.h
|
||||
|
||||
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}
|
||||
|
||||
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
|
||||
|
||||
depend:
|
||||
@echo Dependencies already done
|
58
Makefile.m68k
Normal file
58
Makefile.m68k
Normal file
@ -0,0 +1,58 @@
|
||||
|
||||
all: timekeeper
|
||||
|
||||
CC = /opt/m68k-amigaos/bin/m68k-amigaos-gcc
|
||||
|
||||
# clib2
|
||||
#CFLAGS = -O2 -DAOS3 -Iinclude -mcrt=clib2 -m68020 -fbaserel32 -Wall
|
||||
#LFALGS = -Wl,--cref,-M,-Map=TimeKeeper.map
|
||||
#LDLIBS = -lnet
|
||||
|
||||
# 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 =
|
||||
|
||||
broker.o: compiler.h config.h message.h win.h
|
||||
|
||||
com.o: compiler.h config.h message.h state.h time.h sntp.h mem.h
|
||||
|
||||
library.o: compiler.h config.h time.h mem.h
|
||||
|
||||
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}
|
||||
|
||||
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
|
||||
|
||||
depend:
|
||||
@echo Dependencies already done
|
331
broker.c
Normal file
331
broker.c
Normal file
@ -0,0 +1,331 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "message.h"
|
||||
#include "mem.h"
|
||||
#include "win.h"
|
||||
|
||||
static void ProcessMsg(void);
|
||||
|
||||
static struct NewBroker newBroker = {
|
||||
NB_VERSION,
|
||||
(STRPTR)APP_SHORT_NAME,
|
||||
(STRPTR)APP_TITLE_VERSION,
|
||||
(STRPTR) "Synchronize Clock With Internet Servers",
|
||||
NBU_UNIQUE | NBU_NOTIFY,
|
||||
COF_SHOW_HIDE,
|
||||
0, 0, 0};
|
||||
|
||||
void StartBroker(void)
|
||||
{
|
||||
LONG error;
|
||||
struct Message *msg;
|
||||
|
||||
Globals->Broker->BrokerPort = CreateMsgPort();
|
||||
if (Globals->Broker->BrokerPort == NULL)
|
||||
{
|
||||
LogError("Could not allocate broker port");
|
||||
return;
|
||||
}
|
||||
|
||||
Globals->Broker->UserPort = CreateMsgPort();
|
||||
if (Globals->Broker->UserPort == NULL)
|
||||
{
|
||||
LogError("Could not allocate broker user port");
|
||||
DeleteMsgPort(Globals->Broker->BrokerPort);
|
||||
Globals->Broker->BrokerPort = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
Globals->Broker->ReplyPort = CreateMsgPort();
|
||||
if (Globals->Broker->ReplyPort == NULL)
|
||||
{
|
||||
LogError("Could not allocate broker reply port");
|
||||
DeleteMsgPort(Globals->Broker->BrokerPort);
|
||||
DeleteMsgPort(Globals->Broker->UserPort);
|
||||
Globals->Broker->BrokerPort = NULL;
|
||||
Globals->Broker->UserPort = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
Globals->Broker->ShutdownSigBit = AllocSignal(-1);
|
||||
if (Globals->Broker->ShutdownSigBit == -1)
|
||||
{
|
||||
SendErrorMessage("Could not allocate signal for broker");
|
||||
DeleteMsgPort(Globals->Broker->BrokerPort);
|
||||
DeleteMsgPort(Globals->Broker->UserPort);
|
||||
DeleteMsgPort(Globals->Broker->ReplyPort);
|
||||
Globals->Broker->BrokerPort = NULL;
|
||||
Globals->Broker->UserPort = NULL;
|
||||
Globals->Broker->ReplyPort = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
newBroker.nb_Port = Globals->Broker->BrokerPort;
|
||||
newBroker.nb_Pri = Globals->Settings->Priority;
|
||||
|
||||
Globals->Broker->Object = CxBroker(&newBroker, &error);
|
||||
if (!Globals->Broker->Object)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case CBERR_SYSERR:
|
||||
LogError("System problems (CBERR_SYSERR). Could not allocate broker object");
|
||||
break;
|
||||
case CBERR_DUP:
|
||||
LogWarning(APP_SHORT_NAME " already running");
|
||||
break;
|
||||
default:
|
||||
LogError("Could not allocate broker object (error code: %ld)", error);
|
||||
break;
|
||||
}
|
||||
|
||||
DeleteMsgPort(Globals->Broker->BrokerPort);
|
||||
DeleteMsgPort(Globals->Broker->UserPort);
|
||||
DeleteMsgPort(Globals->Broker->ReplyPort);
|
||||
Globals->Broker->BrokerPort = NULL;
|
||||
Globals->Broker->UserPort = NULL;
|
||||
Globals->Broker->ReplyPort = NULL;
|
||||
Globals->Broker->Object = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
Globals->Broker->Task = FindTask(NULL);
|
||||
|
||||
StartCom();
|
||||
ProcessMsg();
|
||||
|
||||
while ((msg = GetMsg(Globals->Broker->BrokerPort)))
|
||||
ReplyMsg(msg);
|
||||
|
||||
while ((msg = GetMsg(Globals->Broker->UserPort)))
|
||||
ReplyMsg(msg);
|
||||
|
||||
while ((msg = GetMsg(Globals->Broker->ReplyPort)))
|
||||
ReplyMsg(msg);
|
||||
|
||||
DeleteCxObj(Globals->Broker->Object);
|
||||
FreeSignal(Globals->Broker->ShutdownSigBit);
|
||||
DeleteMsgPort(Globals->Broker->BrokerPort);
|
||||
DeleteMsgPort(Globals->Broker->UserPort);
|
||||
DeleteMsgPort(Globals->Broker->ReplyPort);
|
||||
Globals->Broker->BrokerPort = NULL;
|
||||
Globals->Broker->UserPort = NULL;
|
||||
Globals->Broker->ReplyPort = NULL;
|
||||
Globals->Broker->Object = NULL;
|
||||
}
|
||||
|
||||
void ShutdownBroker(void)
|
||||
{
|
||||
Signal((struct Task *)Globals->Broker->Task,
|
||||
(1 << Globals->Broker->ShutdownSigBit));
|
||||
}
|
||||
|
||||
void SetBrokerPriority(int priority)
|
||||
{
|
||||
SetCxObjPri(Globals->Broker->Object, priority);
|
||||
}
|
||||
|
||||
static void Activate(void)
|
||||
{
|
||||
LogWarning("ACTIVE changed: 1 -> 0");
|
||||
ActivateCxObj(Globals->Broker->Object, 0);
|
||||
Globals->Active = false;
|
||||
StopComAsync();
|
||||
while (!CheckComClosed())
|
||||
Delay(1);
|
||||
}
|
||||
|
||||
static void Deactivate(void)
|
||||
{
|
||||
LogWarning("ACTIVE changed: 0 -> 1");
|
||||
ActivateCxObj(Globals->Broker->Object, 1);
|
||||
Globals->Active = true;
|
||||
StartCom();
|
||||
}
|
||||
|
||||
static void StopSubProcesses(void)
|
||||
{
|
||||
Forbid();
|
||||
Globals->ShuttingDown = true;
|
||||
Permit();
|
||||
|
||||
HideSettingWindow();
|
||||
while (!CheckSettingWindowClosed())
|
||||
Delay(10);
|
||||
|
||||
StopComAsync();
|
||||
while (!CheckComClosed())
|
||||
Delay(10);
|
||||
}
|
||||
|
||||
static void ProcessMsg(void)
|
||||
{
|
||||
bool run = true;
|
||||
ULONG sigmask = SIGBREAKF_CTRL_C |
|
||||
(1 << Globals->Broker->ShutdownSigBit) |
|
||||
(1 << Globals->Broker->BrokerPort->mp_SigBit) |
|
||||
(1 << Globals->Broker->UserPort->mp_SigBit) |
|
||||
(1 << Globals->Broker->ReplyPort->mp_SigBit);
|
||||
|
||||
ActivateCxObj(Globals->Broker->Object, 1);
|
||||
Globals->Active = true;
|
||||
|
||||
do
|
||||
{
|
||||
ULONG sigrcvd = Wait(sigmask);
|
||||
|
||||
if (sigrcvd & (1 << Globals->Broker->BrokerPort->mp_SigBit))
|
||||
{
|
||||
CxMsg *msg;
|
||||
while ((msg = (CxMsg *)GetMsg(Globals->Broker->BrokerPort)))
|
||||
{
|
||||
LONG msgid = CxMsgID(msg);
|
||||
ULONG msgtype = CxMsgType(msg);
|
||||
ReplyMsg((struct Message *)msg);
|
||||
|
||||
switch (msgtype)
|
||||
{
|
||||
case CXM_IEVENT:
|
||||
break;
|
||||
case CXM_COMMAND:
|
||||
switch (msgid)
|
||||
{
|
||||
case CXCMD_DISABLE:
|
||||
Activate();
|
||||
break;
|
||||
case CXCMD_ENABLE:
|
||||
Deactivate();
|
||||
break;
|
||||
case CXCMD_KILL:
|
||||
LogInfo("Received shut down from commodity");
|
||||
LogWarning("Shutting down");
|
||||
StopSubProcesses();
|
||||
run = false;
|
||||
break;
|
||||
case CXCMD_UNIQUE:
|
||||
LogWarning("Commodity duplicate detected");
|
||||
LogTrace("Show window");
|
||||
ShowSettingWindow();
|
||||
break;
|
||||
case CXCMD_APPEAR:
|
||||
LogTrace("Show window");
|
||||
ShowSettingWindow();
|
||||
break;
|
||||
case CXCMD_DISAPPEAR:
|
||||
LogTrace("Hide window");
|
||||
HideSettingWindow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sigrcvd & (1 << Globals->Broker->UserPort->mp_SigBit))
|
||||
{
|
||||
struct AppWindowMessage *msg;
|
||||
while ((msg = (struct AppWindowMessage *)GetMsg(Globals->Broker->UserPort)))
|
||||
{
|
||||
switch (msg->Type)
|
||||
{
|
||||
case ATK_LOGERROR:
|
||||
LogError(msg->Text);
|
||||
break;
|
||||
case ATK_LOGWARN:
|
||||
LogWarning(msg->Text);
|
||||
break;
|
||||
case ATK_LOGINFO:
|
||||
LogInfo(msg->Text);
|
||||
break;
|
||||
case ATK_LOGTRACE:
|
||||
LogTrace(msg->Text);
|
||||
break;
|
||||
case ATK_STORE:
|
||||
SaveSettings(true);
|
||||
SaveSettings(false);
|
||||
break;
|
||||
case ATK_APPLY:
|
||||
SaveSettings(false);
|
||||
break;
|
||||
case ATK_UNDO:
|
||||
ApplyAppSettings(Globals->Window->Settings, true);
|
||||
break;
|
||||
case ATK_RESTART:
|
||||
RestartSntpAsync();
|
||||
break;
|
||||
case ATK_REFRESH:
|
||||
// Broker cannot refresh
|
||||
break;
|
||||
case ATK_DISABLE:
|
||||
Activate();
|
||||
break;
|
||||
case ATK_ENABLE:
|
||||
Deactivate();
|
||||
break;
|
||||
case ATK_READONLY:
|
||||
LogWarning("READONLY changed: 1 -> 0");
|
||||
break;
|
||||
case ATK_READWRITE:
|
||||
LogWarning("READONLY changed: 0 -> 1");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ReplyMsg((struct Message *)msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (sigrcvd & (1 << Globals->Broker->ReplyPort->mp_SigBit))
|
||||
{
|
||||
struct AppWindowMessage *msg;
|
||||
while ((msg = (struct AppWindowMessage *)GetMsg(Globals->Broker->ReplyPort)))
|
||||
{
|
||||
if (msg->Text != NULL)
|
||||
{
|
||||
FreeMemSafe(msg->Text);
|
||||
}
|
||||
FreeMemSafe(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (sigrcvd & (1 << Globals->Broker->ShutdownSigBit))
|
||||
{
|
||||
LogInfo("Received shut down from setting window");
|
||||
LogWarning("Shutting down");
|
||||
StopSubProcesses();
|
||||
run = false;
|
||||
}
|
||||
|
||||
if (sigrcvd & SIGBREAKF_CTRL_C)
|
||||
{
|
||||
LogInfo("Received CTRL + C");
|
||||
LogWarning("Shutting down");
|
||||
StopSubProcesses();
|
||||
run = false;
|
||||
}
|
||||
} while (run);
|
||||
}
|
461
com.c
Normal file
461
com.c
Normal file
@ -0,0 +1,461 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "message.h"
|
||||
#include "state.h"
|
||||
#include "time.h"
|
||||
#include "sntp.h"
|
||||
#include "mem.h"
|
||||
|
||||
struct AppCom
|
||||
{
|
||||
bool Run;
|
||||
bool Restart;
|
||||
bool Exited;
|
||||
struct Process *Task;
|
||||
struct TimerInfo *TimerInfo;
|
||||
struct sntp *Client;
|
||||
short RestartSigBit;
|
||||
bool FirstRun;
|
||||
int RunCount;
|
||||
int FailCount;
|
||||
};
|
||||
|
||||
static void SyncProc(void);
|
||||
static void ComOpen(void);
|
||||
static void ComInit(void);
|
||||
static int SyncClock(void);
|
||||
static void ShowStats(void);
|
||||
static ULONG GetSntpRestartSigMask(void);
|
||||
static const char *SntpErrorText(enum sntp_err error);
|
||||
|
||||
void RestartSntpAsync(void)
|
||||
{
|
||||
if (Globals->Syncer->Task != NULL)
|
||||
{
|
||||
Signal((struct Task *)Globals->Syncer->Task, GetSntpRestartSigMask());
|
||||
}
|
||||
}
|
||||
|
||||
void StopComAsync(void)
|
||||
{
|
||||
if (Globals->Syncer->Task != NULL)
|
||||
{
|
||||
Signal((struct Task *)Globals->Syncer->Task, SIGBREAKF_CTRL_C);
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckComClosed(void)
|
||||
{
|
||||
return Globals->Syncer->Exited;
|
||||
}
|
||||
|
||||
void StartCom(void)
|
||||
{
|
||||
if (Globals->Syncer != NULL && Globals->Syncer->Task != NULL)
|
||||
{
|
||||
LogTrace("Synchronizer process already running");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Globals->Syncer == NULL)
|
||||
{
|
||||
Globals->Syncer = (struct AppCom *)AllocMemSafe(sizeof(struct AppCom));
|
||||
}
|
||||
|
||||
Globals->Syncer->Run = true;
|
||||
Globals->Syncer->Restart = false;
|
||||
Globals->Syncer->Exited = false;
|
||||
Globals->Syncer->FirstRun = true;
|
||||
Globals->Syncer->RunCount = 0;
|
||||
Globals->Syncer->FailCount = 0;
|
||||
|
||||
Forbid();
|
||||
Globals->Syncer->Task = CreateNewProcTags(
|
||||
NP_Entry, (IPTR)SyncProc,
|
||||
NP_Name, (IPTR)APP_SHORT_NAME " Synchronizer",
|
||||
NP_StackSize, 64 * 1024,
|
||||
TAG_DONE);
|
||||
Permit();
|
||||
|
||||
if (Globals->Syncer->Task != NULL)
|
||||
{
|
||||
LogTrace("Created synchronizer process");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("Failed to create synchronizer process");
|
||||
}
|
||||
}
|
||||
|
||||
static ULONG GetSntpRestartSigMask(void)
|
||||
{
|
||||
return (1 << Globals->Syncer->RestartSigBit);
|
||||
}
|
||||
|
||||
static void ComDestroy(void)
|
||||
{
|
||||
if (Globals->Syncer->Client != NULL)
|
||||
{
|
||||
sntp_destroy(Globals->Syncer->Client);
|
||||
Globals->Syncer->Client = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
ComOpen();
|
||||
SetTimer(Globals->Syncer->TimerInfo);
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Sending next NTP request in %ld milliseconds",
|
||||
Globals->Settings->Interval);
|
||||
SendTraceMessage(message);
|
||||
ShowStats();
|
||||
Globals->Syncer->RunCount++;
|
||||
}
|
||||
|
||||
static void SyncProc(void)
|
||||
{
|
||||
Globals->Syncer->TimerInfo = CreateTimer(false);
|
||||
if (Globals->Syncer->TimerInfo == NULL)
|
||||
{
|
||||
SendErrorMessage("Could not create timer for synchronizer");
|
||||
Globals->Syncer->Exited = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Globals->Syncer->RestartSigBit = AllocSignal(-1);
|
||||
if (Globals->Syncer->RestartSigBit == -1)
|
||||
{
|
||||
SendErrorMessage("Could not allocate signal for synchronizer");
|
||||
DeleteTimer(Globals->Syncer->TimerInfo);
|
||||
Globals->Syncer->Exited = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Sync();
|
||||
|
||||
do
|
||||
{
|
||||
ULONG sigtime = GetTimerSigMask(Globals->Syncer->TimerInfo);
|
||||
ULONG sigrest = GetSntpRestartSigMask();
|
||||
ULONG sigmask = SIGBREAKF_CTRL_C | sigtime | sigrest;
|
||||
ULONG sigrcvd = Wait(sigmask);
|
||||
|
||||
if (sigrcvd & sigtime)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
if (sigrcvd & sigrest)
|
||||
{
|
||||
ComDestroy();
|
||||
Globals->Syncer->Restart = true;
|
||||
ComOpen();
|
||||
}
|
||||
|
||||
if (sigrcvd & SIGBREAKF_CTRL_C)
|
||||
{
|
||||
Globals->Syncer->Run = false;
|
||||
}
|
||||
} while (Globals->Syncer->Run);
|
||||
|
||||
ComDestroy();
|
||||
FreeSignal(Globals->Syncer->RestartSigBit);
|
||||
DeleteTimer(Globals->Syncer->TimerInfo);
|
||||
CloseSocketLibrary();
|
||||
|
||||
if (!Globals->ShuttingDown)
|
||||
{
|
||||
SendWarningMessage("Exited synchronizer process");
|
||||
}
|
||||
|
||||
Globals->Syncer->TimerInfo = NULL;
|
||||
Globals->Syncer->Task = NULL;
|
||||
Globals->Syncer->Exited = true;
|
||||
}
|
||||
|
||||
static void ComOpen(void)
|
||||
{
|
||||
if (OpenSocketLibrary() != LIB_OK)
|
||||
{
|
||||
// Make sure socket library is open
|
||||
return;
|
||||
}
|
||||
|
||||
if (Globals->Syncer->FirstRun)
|
||||
{
|
||||
SendInfoMessage("Starting SNTP client");
|
||||
ComInit();
|
||||
Globals->Syncer->FirstRun = false;
|
||||
}
|
||||
|
||||
if (Globals->Syncer->Restart)
|
||||
{
|
||||
SendInfoMessage("Restart SNTP client");
|
||||
ComInit();
|
||||
Globals->Syncer->Restart = false;
|
||||
}
|
||||
|
||||
if (SyncClock() == COM_OK)
|
||||
{
|
||||
Globals->Syncer->FailCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Globals->Syncer->FailCount++;
|
||||
}
|
||||
|
||||
if (Globals->Syncer->FailCount != 0 && Globals->Syncer->FailCount % 5 == 0)
|
||||
{
|
||||
ComDestroy();
|
||||
Globals->Syncer->Restart = true;
|
||||
}
|
||||
|
||||
if (Globals->Syncer->FailCount == 10)
|
||||
{
|
||||
SendInfoMessage("Reinitialize socket library");
|
||||
ComDestroy();
|
||||
CloseSocketLibrary();
|
||||
Globals->Syncer->FailCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ShowStats(void)
|
||||
{
|
||||
if (Globals->Syncer->RunCount % 10 == 0)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
char timeString[10], dateString[10], dayString[10];
|
||||
SystemTimeString(timeString, dateString, dayString);
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Local time is %s %s %s",
|
||||
dayString, dateString, timeString);
|
||||
SendInfoMessage(message);
|
||||
}
|
||||
|
||||
if (Globals->Syncer->RunCount % 25 == 0)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
long blocks, size;
|
||||
MemUsage(&blocks, &size, NULL);
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Currently using %ld bytes in %ld blocks on heap",
|
||||
size, blocks);
|
||||
SendInfoMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static void ComInit(void)
|
||||
{
|
||||
if (Globals->Syncer->Client != NULL)
|
||||
{
|
||||
sntp_destroy(Globals->Syncer->Client);
|
||||
Globals->Syncer->Client = NULL;
|
||||
}
|
||||
|
||||
Globals->Syncer->Client = sntp_create(
|
||||
Globals->Settings->DestinationAddress,
|
||||
Globals->Settings->DestinationPort,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (Globals->Syncer->Client == NULL)
|
||||
{
|
||||
SendWarningMessage("Could not create SNTP client");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int SyncClock(void)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
struct timeval rtv, ltv, tv;
|
||||
long long lt, rt, dt, adt, th;
|
||||
struct ntptime nt;
|
||||
bool readOnly;
|
||||
int trace, ret;
|
||||
|
||||
th = Globals->Settings->Threshold;
|
||||
readOnly = Globals->Settings->Readonly;
|
||||
trace = TraceLogging();
|
||||
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Sending request to %s:%s",
|
||||
Globals->Settings->DestinationAddress,
|
||||
Globals->Settings->DestinationPort);
|
||||
SendInfoMessage(message);
|
||||
|
||||
ret = sntp_send(Globals->Syncer->Client);
|
||||
if (ret != SNTP_OK)
|
||||
{
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"SNTP send failed: %s",
|
||||
SntpErrorText(ret));
|
||||
SendWarningMessage(message);
|
||||
return COM_ERROR;
|
||||
}
|
||||
|
||||
if (trace)
|
||||
{
|
||||
SendTraceMessage("Waiting for response");
|
||||
}
|
||||
|
||||
ret = sntp_poll(Globals->Syncer->Client, Globals->Settings->Timeout);
|
||||
if (ret != SNTP_OK)
|
||||
{
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"SNTP poll failed: %s",
|
||||
SntpErrorText(ret));
|
||||
SendWarningMessage(message);
|
||||
return COM_ERROR;
|
||||
}
|
||||
|
||||
if (trace)
|
||||
{
|
||||
SendTraceMessage("Processing response");
|
||||
}
|
||||
|
||||
ret = sntp_recv(Globals->Syncer->Client, &nt);
|
||||
if (ret != SNTP_OK)
|
||||
{
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"SNTP recieve failed: %s",
|
||||
SntpErrorText(ret));
|
||||
SendWarningMessage(message);
|
||||
|
||||
if (ret == SNTP_BACKOFF)
|
||||
{
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Increasing polling interval: %ld -> %ld",
|
||||
Globals->Settings->Interval,
|
||||
Globals->Settings->Interval * 2);
|
||||
SendWarningMessage(message);
|
||||
Globals->Settings->Interval *= 2;
|
||||
}
|
||||
return COM_ERROR;
|
||||
}
|
||||
|
||||
nt2tv(&nt, &rtv);
|
||||
if (trace)
|
||||
{
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Got time %lu.%06lu",
|
||||
(unsigned long)rtv.tv_secs,
|
||||
(unsigned long)rtv.tv_micro);
|
||||
SendTraceMessage(message);
|
||||
}
|
||||
|
||||
GetTimeOfDay(<v);
|
||||
|
||||
lt = 1000000LL * ltv.tv_secs + ltv.tv_micro;
|
||||
rt = 1000000LL * rtv.tv_secs + rtv.tv_micro;
|
||||
dt = rt - lt;
|
||||
adt = dt < 0 ? -dt : dt;
|
||||
|
||||
if (trace)
|
||||
{
|
||||
static char out[MAXLONGLONGCHARSIZE];
|
||||
LongLongToStr(rt, out);
|
||||
SNPrintf(message, SETTINGMESSAGELEN, "True time %s", out);
|
||||
SendTraceMessage(message);
|
||||
LongLongToStr(lt, out);
|
||||
SNPrintf(message, SETTINGMESSAGELEN, "Kernel time %s", out);
|
||||
SendTraceMessage(message);
|
||||
LongLongToStr(dt, out);
|
||||
SNPrintf(message, SETTINGMESSAGELEN, "Delta %s", out);
|
||||
SendTraceMessage(message);
|
||||
}
|
||||
|
||||
if (!readOnly && adt < th)
|
||||
{
|
||||
static char out[MAXLONGLONGCHARSIZE];
|
||||
static char out2[MAXLONGLONGCHARSIZE];
|
||||
LongLongToStr(adt, out);
|
||||
LongLongToStr(th, out2);
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"%s us < %s us, not setting clock",
|
||||
out, out2);
|
||||
SendInfoMessage(message);
|
||||
}
|
||||
else if (!readOnly)
|
||||
{
|
||||
tv.tv_secs = rt / 1000000;
|
||||
tv.tv_micro = rt % 1000000;
|
||||
SetTimeOfDay(Globals->Syncer->TimerInfo, &tv);
|
||||
|
||||
{ // Log after setting clock
|
||||
static char out[MAXLONGLONGCHARSIZE];
|
||||
static char out2[MAXLONGLONGCHARSIZE];
|
||||
LongLongToStr(adt, out);
|
||||
LongLongToStr(th, out2);
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"%s us > %s us, setting software clock",
|
||||
out, out2);
|
||||
SendWarningMessage(message);
|
||||
SendWarningMessage("Setting hardware clock");
|
||||
SaveTimeOfDay(&tv);
|
||||
}
|
||||
}
|
||||
|
||||
Globals->LastNtpSync = rtv;
|
||||
Forbid();
|
||||
if (Globals->Window->Task != NULL && !Globals->ShuttingDown)
|
||||
{
|
||||
SendMessageTo(Globals->Window->UserPort, Globals->Broker->ReplyPort, ATK_REFRESH);
|
||||
}
|
||||
Permit();
|
||||
|
||||
return COM_OK;
|
||||
}
|
||||
|
||||
static const char *SntpErrorText(enum sntp_err error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case SNTP_OK:
|
||||
return "OK";
|
||||
case SNTP_SYSERR:
|
||||
return GetErrorText();
|
||||
case SNTP_DNSERR:
|
||||
return GetHostErrorText();
|
||||
case SNTP_NOREQ:
|
||||
return "No request sent";
|
||||
case SNTP_NORESP:
|
||||
return "No response received";
|
||||
case SNTP_BADRESP:
|
||||
return "Invalid response received";
|
||||
case SNTP_LAME:
|
||||
return "Server is lame / unsynchronized";
|
||||
case SNTP_BACKOFF:
|
||||
return "Polling too frequently";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
return "Unknown error";
|
||||
}
|
47
compiler.h
Normal file
47
compiler.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*-
|
||||
* Copyright (c) 2014-2018 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMPILER_H_INCLUDED
|
||||
#define COMPILER_H_INCLUDED
|
||||
|
||||
#ifndef __cplusplus
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifndef REG
|
||||
#define REG(reg, arg) arg __asm(#reg)
|
||||
#endif
|
||||
#else
|
||||
#error Need REG assembler define
|
||||
#endif
|
||||
|
||||
#define MAXLONGCHARSIZE 12
|
||||
#define MAXLONGLONGCHARSIZE 22
|
||||
|
||||
#endif
|
219
config.h
Normal file
219
config.h
Normal file
@ -0,0 +1,219 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H_INCLUDED
|
||||
#define CONFIG_H_INCLUDED
|
||||
|
||||
#include <exec/io.h>
|
||||
#include <exec/types.h>
|
||||
#include <exec/memory.h>
|
||||
#include <exec/devices.h>
|
||||
#include <exec/libraries.h>
|
||||
#include <resources/battclock.h>
|
||||
#include <libraries/asl.h>
|
||||
#include <libraries/commodities.h>
|
||||
#include <dos/dos.h>
|
||||
#include <dos/dostags.h>
|
||||
#include <proto/dos.h>
|
||||
#include <proto/asl.h>
|
||||
#include <proto/exec.h>
|
||||
#include <proto/icon.h>
|
||||
#include <proto/timer.h>
|
||||
#include <proto/locale.h>
|
||||
#include <proto/utility.h>
|
||||
#include <proto/gadtools.h>
|
||||
#include <proto/intuition.h>
|
||||
#include <proto/battclock.h>
|
||||
#include <proto/commodities.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
//#define DEBUG_BUILD 1
|
||||
|
||||
#if defined(AROS) || defined(__CLIB2__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if defined(__libnix__)
|
||||
typedef u_int8_t uint8_t;
|
||||
typedef u_int16_t uint16_t;
|
||||
typedef u_int32_t uint32_t;
|
||||
typedef u_int64_t uint64_t;
|
||||
typedef uint32_t uintptr_t;
|
||||
#endif
|
||||
|
||||
#if defined(__CLIB2__)
|
||||
#define __NO_NET_API
|
||||
#define NO_INLINE_STDARG
|
||||
#endif
|
||||
|
||||
#if defined(AROS) || defined(__CLIB2__)
|
||||
#include <proto/socket.h>
|
||||
#include <bsdsocket/socketbasetags.h>
|
||||
#endif
|
||||
|
||||
#if defined(__libnix__)
|
||||
#include <amitcp/socketbasetags.h>
|
||||
#include "clib/amitcp_protos.h"
|
||||
#endif
|
||||
|
||||
#if defined(__libnix__) || defined(__CLIB2__)
|
||||
#include "netdb.h"
|
||||
#include "sys/errno.h"
|
||||
#include "sys/socket.h"
|
||||
#include "netinet/in.h"
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef MAXPATHLEN
|
||||
#undef MAXPATHLEN
|
||||
#endif
|
||||
#ifdef MAXFILELEN
|
||||
#undef MAXFILELEN
|
||||
#endif
|
||||
#ifdef MAXFILEPATHLEN
|
||||
#undef MAXFILEPATHLEN
|
||||
#endif
|
||||
#define MAXPATHLEN 1792
|
||||
#define MAXFILELEN 256
|
||||
#define MAXFILEPATHLEN MAXPATHLEN + MAXFILELEN
|
||||
#define MAXDOSERRORLEN 256
|
||||
#define SETTINGMESSAGELEN 128
|
||||
|
||||
#ifndef HAVE_POLL
|
||||
#define POLLIN 0x0001
|
||||
struct pollfd
|
||||
{
|
||||
int fd;
|
||||
short events;
|
||||
short revents;
|
||||
};
|
||||
typedef unsigned int nfds_t;
|
||||
int poll(struct pollfd *, nfds_t, int);
|
||||
#endif
|
||||
|
||||
#if AOS3
|
||||
#define IPTR ULONG
|
||||
#endif
|
||||
#if AOS3
|
||||
#define VARSIZE 0
|
||||
#else
|
||||
#define VARSIZE 1
|
||||
#endif
|
||||
|
||||
#ifdef AROS
|
||||
#define VSNPrintf(str, n, format, args) vsnprintf(str, n, format, args)
|
||||
#define SNPrintf(str, n, format, ...) snprintf(str, n, format, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define LIB_OK 0
|
||||
#define COM_OK 0
|
||||
#define LIB_ERROR -1
|
||||
#define COM_ERROR -1
|
||||
|
||||
#define APP_SHORT_NAME "AmiTimeKeeper"
|
||||
#define APP_LONG_NAME "Amiga Time Keeper"
|
||||
#define APP_VERSION "1.05"
|
||||
#define APP_DATE_VERSION "1.05 (06.08.2018)"
|
||||
#define APP_ID APP_SHORT_NAME " " APP_DATE_VERSION
|
||||
#define APP_TITLE APP_LONG_NAME " " APP_DATE_VERSION
|
||||
#define APP_TITLE_VERSION APP_LONG_NAME " " APP_VERSION
|
||||
|
||||
#include "log.h"
|
||||
#include "state.h"
|
||||
#include "string.h"
|
||||
|
||||
#define KEYWORD_COUNT 9
|
||||
#define KEYWORD_SERVER "SERVER"
|
||||
#define KEYWORD_PORT "PORT"
|
||||
#define KEYWORD_THRESHOLD "THRESHOLD"
|
||||
#define KEYWORD_INTERVAL "INTERVAL"
|
||||
#define KEYWORD_PRIORITY "CX_PRIORITY"
|
||||
#define KEYWORD_READONLY "READONLY"
|
||||
#define KEYWORD_TIMEOUT "TIMEOUT"
|
||||
#define KEYWORD_VERBOSE "VERBOSE"
|
||||
#define KEYWORD_LOGFILE "LOGFILE"
|
||||
|
||||
#define SERVER_DEF "pool.ntp.org"
|
||||
#define PORT_DEF "123"
|
||||
#define THRESHOLD_MIN 1000LL
|
||||
#define THRESHOLD_DEF 1000000LL
|
||||
#define INTERVAL_MIN 500
|
||||
#define INTERVAL_DEF 17500
|
||||
#define PRIORITY_MIN -128
|
||||
#define PRIORITY_DEF 25
|
||||
#define PRIORITY_MAX 127
|
||||
#define READONLY_DEF 0
|
||||
#define TIMEOUT_MIN 100
|
||||
#define TIMEOUT_DEF 5000
|
||||
#define TIMEOUT_MAX 30000
|
||||
#define VERBOSE_MIN 0
|
||||
#define VERBOSE_DEF 0
|
||||
#define VERBOSE_MAX 3
|
||||
#define LOGFILE_DEF NULL
|
||||
|
||||
#define KEYWORD_TEMPLATE_1 KEYWORD_READONLY "/S," KEYWORD_SERVER "/K," KEYWORD_PORT "/K," KEYWORD_TIMEOUT "/N/K," KEYWORD_THRESHOLD "/K,"
|
||||
#define KEYWORD_TEMPLATE_2 KEYWORD_INTERVAL "/N/K," KEYWORD_VERBOSE "/N/K," KEYWORD_PRIORITY "/N/K," KEYWORD_LOGFILE "/K"
|
||||
#define KEYWORD_TEMPLATE KEYWORD_TEMPLATE_1 KEYWORD_TEMPLATE_2
|
||||
|
||||
/* broker.c */
|
||||
void StartBroker(void);
|
||||
void SetBrokerPriority(int);
|
||||
void ShutdownBroker(void);
|
||||
|
||||
/* com.c */
|
||||
void StartCom(void);
|
||||
void StopComAsync(void);
|
||||
void RestartSntpAsync(void);
|
||||
bool CheckComClosed(void);
|
||||
|
||||
/* win_main.c */
|
||||
void ShowSettingWindow(void);
|
||||
void HideSettingWindow(void);
|
||||
|
||||
/* libraries.c */
|
||||
int OpenLibraries(void);
|
||||
void CloseLibraries(void);
|
||||
|
||||
/* net.c */
|
||||
int OpenSocketLibrary(void);
|
||||
void CloseSocketLibrary(void);
|
||||
const char *GetErrorText(void);
|
||||
const char *GetHostErrorText(void);
|
||||
int GetErrorNo(void);
|
||||
int GetHostErrorNo(void);
|
||||
extern struct Library *SocketBase;
|
||||
|
||||
#endif
|
114
include/clib/amitcp_protos.h
Normal file
114
include/clib/amitcp_protos.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Carsten Larsen
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SOCKET_AMITCP_H
|
||||
#define _SOCKET_AMITCP_H
|
||||
|
||||
#define AMITCP_BASE_NAME SocketBase
|
||||
#include "inline/amitcp.h"
|
||||
|
||||
#define socket Socket
|
||||
#define bind Bind
|
||||
#define listen Listen
|
||||
#define accept Accept
|
||||
#define connect Connect
|
||||
#define send Send
|
||||
#define sendto SendTo
|
||||
#define sendmsg SendMsg
|
||||
#define recv Recv
|
||||
#define recvfrom RecvFrom
|
||||
#define recvmsg RecvMsg
|
||||
#define shutdown Shutdown
|
||||
#define setsockopt SetSockOpt
|
||||
#define getsockopt GetSockOpt
|
||||
#define getsockname GetSockName
|
||||
#define getpeername GetPeerName
|
||||
#define inet_addr Inet_Addr
|
||||
#define inet_network Inet_Network
|
||||
#define inet_ntoa Inet_NtoA
|
||||
#define gethostbyname GetHostByName
|
||||
#define gethostbyaddr GetHostByAddr
|
||||
#define getnetbyname GetNetByName
|
||||
#define getnetbyaddr GetNetByAddr
|
||||
#define getservbyname GetServByName
|
||||
#define getservbyport GetServByPort
|
||||
#define getprotobyname GetProtoByName
|
||||
#define getprotobynumber GetProtoByNumber
|
||||
#define getdtablesize GetDTableSize
|
||||
#define gethostname GetHostName
|
||||
#define gethostid GetHostId
|
||||
#define vsyslog SyslogA
|
||||
#define syslog Syslog
|
||||
|
||||
#define Accept TCP_Accept
|
||||
#define Bind TCP_Bind
|
||||
#define CloseSocket TCP_CloseSocket
|
||||
#define Connect TCP_Connect
|
||||
#define Dup2Socket TCP_Dup2Socket
|
||||
#define Errno TCP_Errno
|
||||
#define GetDTableSize TCP_GetDTableSize
|
||||
#define GetHostByAddr TCP_GetHostByAddr
|
||||
#define GetHostByName TCP_GetHostByName
|
||||
#define GetHostId TCP_GetHostId
|
||||
#define GetHostName TCP_GetHostName
|
||||
#define GetNetByAddr TCP_GetNetByAddr
|
||||
#define GetNetByName TCP_GetNetByName
|
||||
#define GetPeerName TCP_GetPeerName
|
||||
#define GetProtoByName TCP_GetProtoByName
|
||||
#define GetProtoByNumber TCP_GetProtoByNumber
|
||||
#define GetServByName TCP_GetServByName
|
||||
#define GetServByPort TCP_GetServByPort
|
||||
#define GetSockName TCP_GetSockName
|
||||
#define GetSockOpt TCP_GetSockOpt
|
||||
#define GetSocketEvents TCP_GetSocketEvents
|
||||
#define Inet_Addr TCP_Inet_Addr
|
||||
#define Inet_LnaOf TCP_Inet_LnaOf
|
||||
#define Inet_MakeAddr TCP_Inet_MakeAddr
|
||||
#define Inet_NetOf TCP_Inet_NetOf
|
||||
#define Inet_Network TCP_Inet_Network
|
||||
#define Inet_NtoA TCP_Inet_NtoA
|
||||
#define IoctlSocket TCP_IoctlSocket
|
||||
#define Listen TCP_Listen
|
||||
#define ObtainSocket TCP_ObtainSocket
|
||||
#define Recv TCP_Recv
|
||||
#define RecvFrom TCP_RecvFrom
|
||||
#define RecvMsg TCP_RecvMsg
|
||||
#define ReleaseCopyOfSocket TCP_ReleaseCopyOfSocket
|
||||
#define ReleaseSocket TCP_ReleaseSocket
|
||||
#define Send TCP_Send
|
||||
#define SendMsg TCP_SendMsg
|
||||
#define SendTo TCP_SendTo
|
||||
#define SetErrnoPtr TCP_SetErrnoPtr
|
||||
#define SetSockOpt TCP_SetSockOpt
|
||||
#define SetSocketSignals TCP_SetSocketSignals
|
||||
#define ShutDown TCP_ShutDown
|
||||
#define Socket TCP_Socket
|
||||
#define SocketBaseTagList TCP_SocketBaseTagList
|
||||
#define SocketBaseTags TCP_SocketBaseTags
|
||||
#define SyslogA TCP_SyslogA
|
||||
#define WaitSelect TCP_WaitSelect
|
||||
|
||||
#endif
|
203
include/inline/amitcp.h
Normal file
203
include/inline/amitcp.h
Normal file
@ -0,0 +1,203 @@
|
||||
/* Automatically generated header! Do not edit! */
|
||||
|
||||
#ifndef _INLINE_AMITCP_H
|
||||
#define _INLINE_AMITCP_H
|
||||
|
||||
#ifndef __INLINE_MACROS_H
|
||||
#include <inline/macros.h>
|
||||
#endif
|
||||
|
||||
#ifndef AMITCP_BASE_NAME
|
||||
#define AMITCP_BASE_NAME lss->lx_BsdSocketBase
|
||||
#endif
|
||||
|
||||
#define TCP_Accept(s, addr, addrlen) \
|
||||
LP3(0x30, LONG, TCP_Accept, LONG, s, d0, struct sockaddr *, addr, a0, int *, addrlen, a1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Bind(s, name, namelen) \
|
||||
LP3(0x24, LONG, TCP_Bind, LONG, s, d0, const struct sockaddr *, name, a0, LONG, namelen, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_CloseSocket(d) \
|
||||
LP1(0x78, LONG, TCP_CloseSocket, LONG, d, d0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Connect(s, name, namelen) \
|
||||
LP3(0x36, LONG, TCP_Connect, LONG, s, d0, const struct sockaddr *, name, a0, LONG, namelen, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Dup2Socket(fd1, fd2) \
|
||||
LP2(0x108, LONG, TCP_Dup2Socket, LONG, fd1, d0, LONG, fd2, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Errno() \
|
||||
LP0(0xa2, LONG, TCP_Errno, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetDTableSize() \
|
||||
LP0(0x8a, LONG, TCP_GetDTableSize, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetHostByAddr(addr, len, type) \
|
||||
LP3(0xd8, struct hostent *, TCP_GetHostByAddr, const UBYTE *, addr, a0, LONG, len, d0, LONG, type, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetHostByName(name) \
|
||||
LP1(0xd2, struct hostent *, TCP_GetHostByName, const UBYTE *, name, a0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetHostId() \
|
||||
LP0(0x120, ULONG, TCP_GetHostId, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetHostName(hostname, size) \
|
||||
LP2(0x11a, LONG, TCP_GetHostName, STRPTR, hostname, a0, LONG, size, d0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetNetByAddr(net, type) \
|
||||
LP2(0xe4, struct netent *, TCP_GetNetByAddr, LONG, net, d0, LONG, type, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetNetByName(name) \
|
||||
LP1(0xde, struct netent *, TCP_GetNetByName, const UBYTE *, name, a0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetPeerName(s, hostname, namelen) \
|
||||
LP3(0x6c, LONG, TCP_GetPeerName, LONG, s, d0, struct sockaddr *, hostname, a0, int *, namelen, a1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetProtoByName(name) \
|
||||
LP1(0xf6, struct protoent *, TCP_GetProtoByName, const UBYTE *, name, a0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetProtoByNumber(proto) \
|
||||
LP1(0xfc, struct protoent *, TCP_GetProtoByNumber, LONG, proto, d0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetServByName(name, proto) \
|
||||
LP2(0xea, struct servent *, TCP_GetServByName, const UBYTE *, name, a0, const UBYTE *, proto, a1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetServByPort(port, proto) \
|
||||
LP2(0xf0, struct servent *, TCP_GetServByPort, LONG, port, d0, const UBYTE *, proto, a0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetSockName(s, hostname, namelen) \
|
||||
LP3(0x66, LONG, TCP_GetSockName, LONG, s, d0, struct sockaddr *, hostname, a0, int *, namelen, a1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetSockOpt(s, level, optname, optval, optlen) \
|
||||
LP5(0x60, LONG, TCP_GetSockOpt, LONG, s, d0, LONG, level, d1, LONG, optname, d2, void *, optval, a0, int *, optlen, a1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_GetSocketEvents(eventmaskp) \
|
||||
LP1(0x12c, LONG, TCP_GetSocketEvents, ULONG *, eventmaskp, a0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Inet_Addr(cp) \
|
||||
LP1(0xb4, ULONG, TCP_Inet_Addr, const UBYTE *, cp, a0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Inet_LnaOf(in) \
|
||||
LP1(0xba, ULONG, TCP_Inet_LnaOf, LONG, in, d0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Inet_MakeAddr(net, host) \
|
||||
LP2(0xc6, ULONG, TCP_Inet_MakeAddr, ULONG, net, d0, ULONG, host, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Inet_NetOf(in) \
|
||||
LP1(0xc0, ULONG, TCP_Inet_NetOf, LONG, in, d0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Inet_Network(cp) \
|
||||
LP1(0xcc, ULONG, TCP_Inet_Network, const UBYTE *, cp, a0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Inet_NtoA(in) \
|
||||
LP1(0xae, char *, TCP_Inet_NtoA, ULONG, in, d0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_IoctlSocket(d, request, argp) \
|
||||
LP3(0x72, LONG, TCP_IoctlSocket, LONG, d, d0, ULONG, request, d1, char *, argp, a0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Listen(s, backlog) \
|
||||
LP2(0x2a, LONG, TCP_Listen, LONG, s, d0, LONG, backlog, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_ObtainSocket(id, domain, type, protocol) \
|
||||
LP4(0x90, LONG, TCP_ObtainSocket, LONG, id, d0, LONG, domain, d1, LONG, type, d2, LONG, protocol, d3, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Recv(s, buf, len, flags) \
|
||||
LP4(0x4e, LONG, TCP_Recv, LONG, s, d0, UBYTE *, buf, a0, LONG, len, d1, LONG, flags, d2, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_RecvFrom(s, buf, len, flags, from, fromlen) \
|
||||
LP6(0x48, LONG, TCP_RecvFrom, LONG, s, d0, UBYTE *, buf, a0, LONG, len, d1, LONG, flags, d2, struct sockaddr *, from, a1, int *, fromlen, a2, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_RecvMsg(s, msg, flags) \
|
||||
LP3(0x114, LONG, TCP_RecvMsg, LONG, s, d0, struct msghdr *, msg, a0, LONG, flags, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_ReleaseCopyOfSocket(fd, id) \
|
||||
LP2(0x9c, LONG, TCP_ReleaseCopyOfSocket, LONG, fd, d0, LONG, id, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_ReleaseSocket(fd, id) \
|
||||
LP2(0x96, LONG, TCP_ReleaseSocket, LONG, fd, d0, LONG, id, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Send(s, msg, len, flags) \
|
||||
LP4(0x42, LONG, TCP_Send, LONG, s, d0, const UBYTE *, msg, a0, LONG, len, d1, LONG, flags, d2, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_SendMsg(s, msg, flags) \
|
||||
LP3(0x10e, LONG, TCP_SendMsg, LONG, s, d0, const struct msghdr *, msg, a0, LONG, flags, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_SendTo(s, msg, len, flags, to, tolen) \
|
||||
LP6(0x3c, LONG, TCP_SendTo, LONG, s, d0, const UBYTE *, msg, a0, LONG, len, d1, LONG, flags, d2, const struct sockaddr *, to, a1, LONG, tolen, d3, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_SetErrnoPtr(errno_p, size) \
|
||||
LP2(0xa8, LONG, TCP_SetErrnoPtr, void *, errno_p, a0, LONG, size, d0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_SetSockOpt(s, level, optname, optval, optlen) \
|
||||
LP5(0x5a, LONG, TCP_SetSockOpt, LONG, s, d0, LONG, level, d1, LONG, optname, d2, const void *, optval, a0, LONG, optlen, d3, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_SetSocketSignals(SIGINTR, SIGIO, SIGURG) \
|
||||
LP3NR(0x84, TCP_SetSocketSignals, ULONG, SIGINTR, d0, ULONG, SIGIO, d1, ULONG, SIGURG, d2, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_ShutDown(s, how) \
|
||||
LP2(0x54, LONG, TCP_ShutDown, LONG, s, d0, LONG, how, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_Socket(domain, type, protocol) \
|
||||
LP3(0x1e, LONG, TCP_Socket, LONG, domain, d0, LONG, type, d1, LONG, protocol, d2, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_SocketBaseTagList(taglist) \
|
||||
LP1(0x126, LONG, TCP_SocketBaseTagList, struct TagItem *, taglist, a0, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#ifndef NO_INLINE_STDARG
|
||||
#define TCP_SocketBaseTags(tags...) \
|
||||
({ULONG _tags[] = { tags }; TCP_SocketBaseTagList((struct TagItem *)_tags); })
|
||||
#endif
|
||||
|
||||
#define TCP_SyslogA(level, format, ap) \
|
||||
LP3NR(0x102, TCP_SyslogA, ULONG, level, d0, const char *, format, a0, va_list, ap, a1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#define TCP_WaitSelect(nfds, readfds, writefds, execptfds, timeout, maskp) \
|
||||
LP6(0x7e, LONG, TCP_WaitSelect, LONG, nfds, d0, fd_set *, readfds, a0, fd_set *, writefds, a1, fd_set *, execptfds, a2, struct timeval *, timeout, a3, ULONG *, maskp, d1, \
|
||||
, AMITCP_BASE_NAME)
|
||||
|
||||
#endif
|
231
include/netdb.h
Normal file
231
include/netdb.h
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* :ts=8
|
||||
*
|
||||
* 'Roadshow' -- Amiga TCP/IP stack
|
||||
* Copyright (c) 2001-2016 by Olaf Barthel.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Amiga specific TCP/IP 'C' header files;
|
||||
* Freely Distributable
|
||||
*/
|
||||
|
||||
/*
|
||||
* ++Copyright++ 1980, 1983, 1988, 1993
|
||||
* -
|
||||
* Copyright (c) 1980, 1983, 1988, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
* -
|
||||
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies, and that
|
||||
* the name of Digital Equipment Corporation not be used in advertising or
|
||||
* publicity pertaining to distribution of the document or software without
|
||||
* specific, written prior permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
* -
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
/*
|
||||
* @(#)netdb.h 8.1 (Berkeley) 6/2/93
|
||||
* $NetBSD: netdb.h,v 1.8 1997/10/13 09:26:06 lukem Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETDB_H
|
||||
#define _NETDB_H
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifndef _SYS_NETINCLUDE_TYPES_H
|
||||
#include "sys/netinclude_types.h"
|
||||
#endif /* _SYS_NETINCLUDE_TYPES_H */
|
||||
|
||||
#ifndef _SYS_ERRNO_H
|
||||
#include "sys/errno.h"
|
||||
#endif /* _SYS_ERRNO_H */
|
||||
|
||||
#ifndef _NETINET_IN_H
|
||||
#include "netinet/in.h"
|
||||
#endif /* _NETINET_IN_H */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __PPC__
|
||||
#pragma pack(2)
|
||||
#endif
|
||||
#elif defined(__VBCC__)
|
||||
#pragma amiga-align
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* This used to be in <sys/param.h> */
|
||||
#define MAXHOSTNAMELEN 256 /* max hostname size */
|
||||
|
||||
/*
|
||||
* Structures returned by network data base library. All addresses are
|
||||
* supplied in host order, and returned in network order (suitable for
|
||||
* use in system calls).
|
||||
*/
|
||||
struct hostent
|
||||
{
|
||||
__STRPTR h_name; /* official name of host */
|
||||
__STRPTR * h_aliases; /* alias list */
|
||||
__LONG h_addrtype; /* host address type */
|
||||
__LONG h_length; /* length of address */
|
||||
__BYTE ** h_addr_list; /* list of addresses from name server */
|
||||
#define h_addr h_addr_list[0] /* address, for backward compatiblity */
|
||||
};
|
||||
|
||||
/*
|
||||
* Assumption here is that a network number
|
||||
* fits in an unsigned long -- probably a poor one.
|
||||
*/
|
||||
struct netent
|
||||
{
|
||||
__STRPTR n_name; /* official name of net */
|
||||
__STRPTR * n_aliases; /* alias list */
|
||||
__LONG n_addrtype; /* net address type */
|
||||
in_addr_t n_net; /* network # */
|
||||
};
|
||||
|
||||
struct servent
|
||||
{
|
||||
__STRPTR s_name; /* official service name */
|
||||
__STRPTR * s_aliases; /* alias list */
|
||||
__LONG s_port; /* port # */
|
||||
__STRPTR s_proto; /* protocol to use */
|
||||
};
|
||||
|
||||
struct protoent
|
||||
{
|
||||
__STRPTR p_name; /* official protocol name */
|
||||
__STRPTR * p_aliases; /* alias list */
|
||||
__LONG p_proto; /* protocol # */
|
||||
};
|
||||
|
||||
/*
|
||||
* Error return codes from gethostbyname() and gethostbyaddr()
|
||||
* (left in extern int h_errno).
|
||||
*/
|
||||
|
||||
#define NETDB_INTERNAL -1 /* see errno */
|
||||
#define NETDB_SUCCESS 0 /* no problem */
|
||||
#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
|
||||
#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */
|
||||
#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
|
||||
#define NO_DATA 4 /* Valid name, no data record of requested type */
|
||||
#define NO_ADDRESS NO_DATA /* no address, look for MX record */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* Values for getaddrinfo() and getnameinfo() */
|
||||
#define AI_PASSIVE 1 /* socket address is intended for bind() */
|
||||
#define AI_CANONNAME 2 /* request for canonical name */
|
||||
#define AI_NUMERICHOST 4 /* don't ever try hostname lookup */
|
||||
#define AI_EXT 8 /* enable non-portable extensions */
|
||||
#define AI_NUMERICSERV 16 /* don't ever try servname lookup */
|
||||
/* valid flags for addrinfo */
|
||||
#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV)
|
||||
|
||||
#define NI_NUMERICHOST 1 /* return the host address, not the name */
|
||||
#define NI_NUMERICSERV 2 /* return the service address, not the name */
|
||||
#define NI_NOFQDN 4 /* return a short name if in the local domain */
|
||||
#define NI_NAMEREQD 8 /* fail if either host or service name is unknown */
|
||||
#define NI_DGRAM 16 /* look up datagram service instead of stream */
|
||||
#define NI_WITHSCOPEID 32 /* KAME hack: attach scopeid to host portion */
|
||||
|
||||
#define NI_MAXHOST MAXHOSTNAMELEN /* max host name returned by getnameinfo */
|
||||
#define NI_MAXSERV 32 /* max serv. name length returned by getnameinfo */
|
||||
|
||||
#define EAI_BADFLAGS -1 /* invalid value for ai_flags */
|
||||
#define EAI_NONAME -2 /* name or service is not known */
|
||||
#define EAI_AGAIN -3 /* temporary failure in name resolution */
|
||||
#define EAI_FAIL -4 /* non-recoverable failure in name resolution */
|
||||
#define EAI_NODATA -5 /* no address associated with name */
|
||||
#define EAI_FAMILY -6 /* ai_family not supported */
|
||||
#define EAI_SOCKTYPE -7 /* ai_socktype not supported */
|
||||
#define EAI_SERVICE -8 /* service not supported for ai_socktype */
|
||||
#define EAI_ADDRFAMILY -9 /* address family for name not supported */
|
||||
#define EAI_MEMORY -10 /* memory allocation failure */
|
||||
#define EAI_SYSTEM -11 /* system error (code indicated in errno) */
|
||||
#define EAI_BADHINTS -12 /* invalid value for hints */
|
||||
#define EAI_PROTOCOL -13 /* resolved protocol is unknown */
|
||||
|
||||
struct addrinfo {
|
||||
int ai_flags; /* input flags */
|
||||
int ai_family; /* protocol family for socket */
|
||||
int ai_socktype; /* socket type */
|
||||
int ai_protocol; /* protocol for socket */
|
||||
socklen_t ai_addrlen; /* length of socket-address */
|
||||
struct sockaddr *ai_addr; /* socket-address for socket */
|
||||
char *ai_canonname; /* canonical name for service location (iff req) */
|
||||
struct addrinfo *ai_next; /* pointer to next in list */
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __PPC__
|
||||
#pragma pack()
|
||||
#endif
|
||||
#elif defined(__VBCC__)
|
||||
#pragma default-align
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#endif /* !_NETDB_H */
|
275
include/netinet/in.h
Normal file
275
include/netinet/in.h
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* :ts=8
|
||||
*
|
||||
* 'Roadshow' -- Amiga TCP/IP stack
|
||||
* Copyright (c) 2001-2016 by Olaf Barthel.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Amiga specific TCP/IP 'C' header files;
|
||||
* Freely Distributable
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)in.h 8.3 (Berkeley) 1/3/94
|
||||
*/
|
||||
|
||||
#ifndef _NETINET_IN_H
|
||||
#define _NETINET_IN_H
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifndef _SYS_NETINCLUDE_TYPES_H
|
||||
#include "sys/netinclude_types.h"
|
||||
#endif /* _SYS_NETINCLUDE_TYPES_H */
|
||||
|
||||
#ifndef _SYS_SOCKET_H
|
||||
#include "sys/socket.h"
|
||||
#endif /* _SYS_SOCKET_H */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __PPC__
|
||||
#pragma pack(2)
|
||||
#endif
|
||||
#elif defined(__VBCC__)
|
||||
#pragma amiga-align
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Constants and structures defined by the internet system,
|
||||
* Per RFC 790, September 1981, and numerous additions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Data types.
|
||||
*/
|
||||
typedef unsigned long in_addr_t;
|
||||
typedef unsigned short in_port_t;
|
||||
|
||||
/*
|
||||
* Protocols
|
||||
*/
|
||||
#define IPPROTO_IP 0 /* dummy for IP */
|
||||
#define IPPROTO_ICMP 1 /* control message protocol */
|
||||
#define IPPROTO_IGMP 2 /* group mgmt protocol */
|
||||
#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
|
||||
#define IPPROTO_TCP 6 /* tcp */
|
||||
#define IPPROTO_EGP 8 /* exterior gateway protocol */
|
||||
#define IPPROTO_PUP 12 /* pup */
|
||||
#define IPPROTO_UDP 17 /* user datagram protocol */
|
||||
#define IPPROTO_IDP 22 /* xns idp */
|
||||
#define IPPROTO_TP 29 /* tp-4 w/ class negotiation */
|
||||
#define IPPROTO_EON 80 /* ISO cnlp */
|
||||
#define IPPROTO_ENCAP 98 /* encapsulation header */
|
||||
|
||||
#define IPPROTO_RAW 255 /* raw IP packet */
|
||||
#define IPPROTO_MAX 256
|
||||
|
||||
|
||||
/*
|
||||
* Local port number conventions:
|
||||
* Ports < IPPORT_RESERVED are reserved for
|
||||
* privileged processes (e.g. root).
|
||||
* Ports > IPPORT_USERRESERVED are reserved
|
||||
* for servers, not necessarily privileged.
|
||||
*/
|
||||
#define IPPORT_RESERVED 1024
|
||||
#define IPPORT_USERRESERVED 5000
|
||||
|
||||
/*
|
||||
* Internet address (a structure for historical reasons)
|
||||
*/
|
||||
struct in_addr {
|
||||
in_addr_t s_addr;
|
||||
};
|
||||
|
||||
/*
|
||||
* Definitions of bits in internet address integers.
|
||||
* On subnets, the decomposition of addresses to host and net parts
|
||||
* is done according to subnet mask, not the masks here.
|
||||
*/
|
||||
#define IN_CLASSA(i) (((__ULONG)(i) & 0x80000000) == 0)
|
||||
#define IN_CLASSA_NET 0xff000000
|
||||
#define IN_CLASSA_NSHIFT 24
|
||||
#define IN_CLASSA_HOST 0x00ffffff
|
||||
#define IN_CLASSA_MAX 128
|
||||
|
||||
#define IN_CLASSB(i) (((__ULONG)(i) & 0xc0000000) == 0x80000000)
|
||||
#define IN_CLASSB_NET 0xffff0000
|
||||
#define IN_CLASSB_NSHIFT 16
|
||||
#define IN_CLASSB_HOST 0x0000ffff
|
||||
#define IN_CLASSB_MAX 65536
|
||||
|
||||
#define IN_CLASSC(i) (((__ULONG)(i) & 0xe0000000) == 0xc0000000)
|
||||
#define IN_CLASSC_NET 0xffffff00
|
||||
#define IN_CLASSC_NSHIFT 8
|
||||
#define IN_CLASSC_HOST 0x000000ff
|
||||
|
||||
#define IN_CLASSD(i) (((__ULONG)(i) & 0xf0000000) == 0xe0000000)
|
||||
#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */
|
||||
#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */
|
||||
#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */
|
||||
#define IN_MULTICAST(i) IN_CLASSD(i)
|
||||
|
||||
#define IN_EXPERIMENTAL(i) (((__ULONG)(i) & 0xf0000000) == 0xf0000000)
|
||||
#define IN_BADCLASS(i) (((__ULONG)(i) & 0xf0000000) == 0xf0000000)
|
||||
|
||||
#define INADDR_ANY 0x00000000UL
|
||||
#define INADDR_BROADCAST 0xffffffffUL /* must be masked */
|
||||
#define INADDR_NONE 0xffffffff /* -1 return */
|
||||
|
||||
#define INADDR_UNSPEC_GROUP 0xe0000000UL /* 224.0.0.0 */
|
||||
#define INADDR_ALLHOSTS_GROUP 0xe0000001UL /* 224.0.0.1 */
|
||||
#define INADDR_MAX_LOCAL_GROUP 0xe00000ffUL /* 224.0.0.255 */
|
||||
|
||||
#define IN_LOOPBACKNET 127 /* official! */
|
||||
|
||||
/*
|
||||
* Socket address, internet style.
|
||||
*/
|
||||
struct sockaddr_in {
|
||||
__UBYTE sin_len;
|
||||
sa_family_t sin_family;
|
||||
in_port_t sin_port;
|
||||
struct in_addr sin_addr;
|
||||
__UBYTE sin_zero[8];
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure used to describe IP options.
|
||||
* Used to store options internally, to pass them to a process,
|
||||
* or to restore options retrieved earlier.
|
||||
* The ip_dst is used for the first-hop gateway when using a source route
|
||||
* (this gets put into the header proper).
|
||||
*/
|
||||
struct ip_opts {
|
||||
struct in_addr ip_dst; /* first hop, 0 w/o src rt */
|
||||
__UBYTE ip_options[40]; /* actually variable in size */
|
||||
};
|
||||
|
||||
/*
|
||||
* Options for use with [gs]etsockopt at the IP level.
|
||||
* First word of comment is data type; bool is stored in int.
|
||||
*/
|
||||
#define IP_OPTIONS 1 /* buf/ip_opts; set/get IP options */
|
||||
#define IP_HDRINCL 2 /* __LONG; header is included with data */
|
||||
#define IP_TOS 3 /* __LONG; IP type of service and preced. */
|
||||
#define IP_TTL 4 /* __LONG; IP time to live */
|
||||
#define IP_RECVOPTS 5 /* bool; receive all IP opts w/dgram */
|
||||
#define IP_RECVRETOPTS 6 /* bool; receive IP opts for response */
|
||||
#define IP_RECVDSTADDR 7 /* bool; receive IP dst addr w/dgram */
|
||||
#define IP_RETOPTS 8 /* ip_opts; set/get IP options */
|
||||
#define IP_MULTICAST_IF 9 /* __UBYTE; set/get IP multicast i/f */
|
||||
#define IP_MULTICAST_TTL 10 /* __UBYTE; set/get IP multicast ttl */
|
||||
#define IP_MULTICAST_LOOP 11 /* __UBYTE; set/get IP multicast loopback */
|
||||
#define IP_ADD_MEMBERSHIP 12 /* ip_mreq; add an IP group membership */
|
||||
#define IP_DROP_MEMBERSHIP 13 /* ip_mreq; drop an IP group membership */
|
||||
|
||||
/*
|
||||
* Defaults and limits for options
|
||||
*/
|
||||
#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */
|
||||
#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
|
||||
#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */
|
||||
|
||||
/*
|
||||
* Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP.
|
||||
*/
|
||||
struct ip_mreq {
|
||||
struct in_addr imr_multiaddr; /* IP multicast address of group */
|
||||
struct in_addr imr_interface; /* local IP address of interface */
|
||||
};
|
||||
|
||||
/*
|
||||
* Definitions for inet sysctl operations.
|
||||
*
|
||||
* Third level is protocol number.
|
||||
* Fourth level is desired variable within that protocol.
|
||||
*/
|
||||
#define IPPROTO_MAXID (IPPROTO_IDP + 1) /* don't list to IPPROTO_MAX */
|
||||
|
||||
/*
|
||||
* Names for IP sysctl objects
|
||||
*/
|
||||
#define IPCTL_FORWARDING 1 /* act as router */
|
||||
#define IPCTL_SENDREDIRECTS 2 /* may send redirects when forwarding */
|
||||
#define IPCTL_DEFTTL 3 /* default TTL */
|
||||
#ifdef notyet
|
||||
#define IPCTL_DEFMTU 4 /* default MTU */
|
||||
#endif
|
||||
#define IPCTL_MAXID 5
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Macros for network/external number representation conversion.
|
||||
*/
|
||||
#define ntohl(x) (x)
|
||||
#define ntohs(x) (x)
|
||||
#define htonl(x) (x)
|
||||
#define htons(x) (x)
|
||||
|
||||
#define NTOHL(x) (x)
|
||||
#define NTOHS(x) (x)
|
||||
#define HTONL(x) (x)
|
||||
#define HTONS(x) (x)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __PPC__
|
||||
#pragma pack()
|
||||
#endif
|
||||
#elif defined(__VBCC__)
|
||||
#pragma default-align
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#endif /* _NETINET_IN_H */
|
189
include/sys/errno.h
Normal file
189
include/sys/errno.h
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* :ts=8
|
||||
*
|
||||
* 'Roadshow' -- Amiga TCP/IP stack
|
||||
* Copyright (c) 2001-2016 by Olaf Barthel.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Amiga specific TCP/IP 'C' header files;
|
||||
* Freely Distributable
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)errno.h 8.5 (Berkeley) 1/21/94
|
||||
*/
|
||||
|
||||
#ifndef _SYS_ERRNO_H
|
||||
#define _SYS_ERRNO_H
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* NOTE: the global 'extern int errno;' declaration below may conflict with
|
||||
what your 'C' runtime library uses for its own 'errno' declaration.
|
||||
While you should not need to #include this header file, and use
|
||||
your 'C' runtime library version instead, it is sometimes not
|
||||
possible to do without the error codes defined in this file. If
|
||||
this is the case, define the preprocessor symbol __NO_NETINCLUDE_ERRNO
|
||||
before you include this header file. */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifndef __NO_NETINCLUDE_ERRNO
|
||||
extern int errno; /* global error number */
|
||||
#endif /* __NO_NETINCLUDE_ERRNO */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* Input/output error */
|
||||
#define ENXIO 6 /* Device not configured */
|
||||
#define E2BIG 7 /* Argument list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file descriptor */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EDEADLK 11 /* Resource deadlock avoided */
|
||||
/* 11 was EAGAIN */
|
||||
#define ENOMEM 12 /* Cannot allocate memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#ifndef _POSIX_SOURCE
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#endif
|
||||
#define EBUSY 16 /* Device busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* Operation not supported by device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* Too many open files in system */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Inappropriate ioctl for device */
|
||||
#ifndef _POSIX_SOURCE
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#endif
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
|
||||
/* math software */
|
||||
#define EDOM 33 /* Numerical argument out of domain */
|
||||
#define ERANGE 34 /* Result too large */
|
||||
|
||||
/* non-blocking and interrupt i/o */
|
||||
#define EAGAIN 35 /* Resource temporarily unavailable */
|
||||
#ifndef _POSIX_SOURCE
|
||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||
#define EINPROGRESS 36 /* Operation now in progress */
|
||||
#define EALREADY 37 /* Operation already in progress */
|
||||
|
||||
/* ipc/network software -- argument errors */
|
||||
#define ENOTSOCK 38 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 39 /* Destination address required */
|
||||
#define EMSGSIZE 40 /* Message too long */
|
||||
#define EPROTOTYPE 41 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 42 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 43 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 45 /* Operation not supported */
|
||||
#define EPFNOSUPPORT 46 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */
|
||||
#define EADDRINUSE 48 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 49 /* Can't assign requested address */
|
||||
|
||||
/* ipc/network software -- operational errors */
|
||||
#define ENETDOWN 50 /* Network is down */
|
||||
#define ENETUNREACH 51 /* Network is unreachable */
|
||||
#define ENETRESET 52 /* Network dropped connection on reset */
|
||||
#define ECONNABORTED 53 /* Software caused connection abort */
|
||||
#define ECONNRESET 54 /* Connection reset by peer */
|
||||
#define ENOBUFS 55 /* No buffer space available */
|
||||
#define EISCONN 56 /* Socket is already connected */
|
||||
#define ENOTCONN 57 /* Socket is not connected */
|
||||
#define ESHUTDOWN 58 /* Can't send after socket shutdown */
|
||||
#define ETOOMANYREFS 59 /* Too many references: can't splice */
|
||||
#define ETIMEDOUT 60 /* Operation timed out */
|
||||
#define ECONNREFUSED 61 /* Connection refused */
|
||||
|
||||
#define ELOOP 62 /* Too many levels of symbolic links */
|
||||
#endif /* _POSIX_SOURCE */
|
||||
#define ENAMETOOLONG 63 /* File name too long */
|
||||
|
||||
/* should be rearranged */
|
||||
#ifndef _POSIX_SOURCE
|
||||
#define EHOSTDOWN 64 /* Host is down */
|
||||
#define EHOSTUNREACH 65 /* No route to host */
|
||||
#endif /* _POSIX_SOURCE */
|
||||
#define ENOTEMPTY 66 /* Directory not empty */
|
||||
|
||||
/* quotas & mush */
|
||||
#ifndef _POSIX_SOURCE
|
||||
#define EPROCLIM 67 /* Too many processes */
|
||||
#define EUSERS 68 /* Too many users */
|
||||
#define EDQUOT 69 /* Disc quota exceeded */
|
||||
|
||||
/* Network File System */
|
||||
#define ESTALE 70 /* Stale NFS file handle */
|
||||
#define EREMOTE 71 /* Too many levels of remote in path */
|
||||
#define EBADRPC 72 /* RPC struct is bad */
|
||||
#define ERPCMISMATCH 73 /* RPC version wrong */
|
||||
#define EPROGUNAVAIL 74 /* RPC prog. not avail */
|
||||
#define EPROGMISMATCH 75 /* Program version wrong */
|
||||
#define EPROCUNAVAIL 76 /* Bad procedure for program */
|
||||
#endif /* _POSIX_SOURCE */
|
||||
|
||||
#define ENOLCK 77 /* No locks available */
|
||||
#define ENOSYS 78 /* Function not implemented */
|
||||
|
||||
#ifndef _POSIX_SOURCE
|
||||
#define EFTYPE 79 /* Inappropriate file type or format */
|
||||
#define EAUTH 80 /* Authentication error */
|
||||
#define ENEEDAUTH 81 /* Need authenticator */
|
||||
#define ELAST 81 /* Must be equal largest errno */
|
||||
#endif /* _POSIX_SOURCE */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#endif /* _SYS_ERRNO_H */
|
64
include/sys/netinclude_types.h
Normal file
64
include/sys/netinclude_types.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* :ts=8
|
||||
*
|
||||
* 'Roadshow' -- Amiga TCP/IP stack
|
||||
* Copyright (c) 2001-2016 by Olaf Barthel.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Amiga specific TCP/IP 'C' header files;
|
||||
* Freely Distributable
|
||||
*/
|
||||
|
||||
#ifndef _SYS_NETINCLUDE_TYPES_H
|
||||
#define _SYS_NETINCLUDE_TYPES_H
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* The type definitions below mirror those in <exec/types.h>, which may
|
||||
clash with local type definitions. Hence, replacements are used which
|
||||
are rather unlikely to cause similar conflicts. Note that the definition
|
||||
of the __TEXT and __STRPTR types currently support only SAS/C and the
|
||||
GNU 'C' compiler. */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
typedef long __LONG; /* signed 32-bit quantity */
|
||||
typedef unsigned long __ULONG; /* unsigned 32-bit quantity */
|
||||
typedef short __WORD; /* signed 16-bit quantity */
|
||||
typedef unsigned short __UWORD; /* unsigned 16-bit quantity */
|
||||
typedef signed char __BYTE; /* signed 8-bit quantity */
|
||||
typedef unsigned char __UBYTE; /* unsigned 8-bit quantity */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
typedef void * __APTR; /* 32-bit untyped pointer */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#if (defined(__GNUC__) && defined(__CHAR_UNSIGNED__)) || (defined(__SASC) && defined(_UNSCHAR))
|
||||
typedef char * __STRPTR; /* string pointer (NULL terminated) */
|
||||
#else
|
||||
typedef unsigned char * __STRPTR; /* string pointer (NULL terminated) */
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && defined(__CHAR_UNSIGNED__)) || (defined(__SASC) && defined(_UNSCHAR))
|
||||
typedef char __TEXT; /* Non-negative character */
|
||||
#else
|
||||
typedef unsigned char __TEXT; /* Non-negative character */
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#endif /* !_SYS_NETINCLUDE_TYPES_H */
|
421
include/sys/socket.h
Normal file
421
include/sys/socket.h
Normal file
@ -0,0 +1,421 @@
|
||||
/*
|
||||
* :ts=8
|
||||
*
|
||||
* 'Roadshow' -- Amiga TCP/IP stack
|
||||
* Copyright (c) 2001-2016 by Olaf Barthel.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Amiga specific TCP/IP 'C' header files;
|
||||
* Freely Distributable
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1985, 1986, 1988, 1993, 1994
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)socket.h 8.6 (Berkeley) 5/3/95
|
||||
*/
|
||||
|
||||
#ifndef _SYS_SOCKET_H
|
||||
#define _SYS_SOCKET_H
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* NOTE: the 'struct timeval' structure definition differs slightly between
|
||||
the AmigaOS usage (as defined in <devices/timer.h>) and the POSIX
|
||||
usage (as defined in <sys/time.h>. By default, this header file
|
||||
will include <devices/timer.h> under the assumption that there
|
||||
will be no problem as a result of that. However, if there are
|
||||
compilation issues, you might want to define the 'struct timeval'
|
||||
separately and disable the inclusion of <devices/timer.h>,
|
||||
which can be achieved by defining the preprocessor symbol
|
||||
__NO_NETINCLUDE_TIMEVAL before you include this header file. */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifndef _SYS_NETINCLUDE_TYPES_H
|
||||
#include <sys/netinclude_types.h>
|
||||
#endif /* _SYS_NETINCLUDE_TYPES_H */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* We might reference memmove() and memset() below, which is why
|
||||
* we need to make sure that both are declared somewhere.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* 'struct iovec', as used in a 'struct msghdr' is defined in <sys/uio.h>. */
|
||||
#ifndef _SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
#endif /* _SYS_UIO_H */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __PPC__
|
||||
#pragma pack(2)
|
||||
#endif
|
||||
#elif defined(__VBCC__)
|
||||
#pragma amiga-align
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Definitions related to sockets: types, address families, options.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Data types.
|
||||
*/
|
||||
typedef unsigned char sa_family_t;
|
||||
typedef unsigned long socklen_t;
|
||||
|
||||
/*
|
||||
* Types
|
||||
*/
|
||||
#define SOCK_STREAM 1 /* stream socket */
|
||||
#define SOCK_DGRAM 2 /* datagram socket */
|
||||
#define SOCK_RAW 3 /* raw-protocol interface */
|
||||
#define SOCK_RDM 4 /* reliably-delivered message */
|
||||
#define SOCK_SEQPACKET 5 /* sequenced packet stream */
|
||||
|
||||
/*
|
||||
* Option flags per-socket.
|
||||
*/
|
||||
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
|
||||
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
|
||||
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
|
||||
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
|
||||
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
|
||||
#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
|
||||
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
|
||||
#define SO_LINGER 0x0080 /* linger on close if data present */
|
||||
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
|
||||
#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */
|
||||
|
||||
/*
|
||||
* Additional options, not kept in so_options.
|
||||
*/
|
||||
#define SO_SNDBUF 0x1001 /* send buffer size */
|
||||
#define SO_RCVBUF 0x1002 /* receive buffer size */
|
||||
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
|
||||
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
|
||||
#define SO_SNDTIMEO 0x1005 /* send timeout */
|
||||
#define SO_RCVTIMEO 0x1006 /* receive timeout */
|
||||
#define SO_ERROR 0x1007 /* get error status and clear */
|
||||
#define SO_TYPE 0x1008 /* get socket type */
|
||||
|
||||
/* This is a private option which is used exclusively
|
||||
* by this Amiga TCP/IP stack implementation and should not
|
||||
* be used by user code.
|
||||
*/
|
||||
#define SO_EVENTMASK 0x2001
|
||||
|
||||
/*
|
||||
* Structure used for manipulating linger option.
|
||||
*/
|
||||
struct linger {
|
||||
__LONG l_onoff; /* option on/off */
|
||||
__LONG l_linger; /* linger time in seconds */
|
||||
};
|
||||
|
||||
/*
|
||||
* Level number for (get/set)sockopt() to apply to socket itself.
|
||||
*/
|
||||
#define SOL_SOCKET 0xffff /* options for socket level */
|
||||
|
||||
/*
|
||||
* Address families.
|
||||
*/
|
||||
#define AF_UNSPEC 0 /* unspecified */
|
||||
#define AF_LOCAL 1 /* local to host (pipes, portals) */
|
||||
#define AF_UNIX AF_LOCAL /* backward compatibility */
|
||||
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
|
||||
#define AF_IMPLINK 3 /* arpanet imp addresses */
|
||||
#define AF_PUP 4 /* pup protocols: e.g. BSP */
|
||||
#define AF_CHAOS 5 /* mit CHAOS protocols */
|
||||
#define AF_NS 6 /* XEROX NS protocols */
|
||||
#define AF_ISO 7 /* ISO protocols */
|
||||
#define AF_OSI AF_ISO
|
||||
#define AF_ECMA 8 /* european computer manufacturers */
|
||||
#define AF_DATAKIT 9 /* datakit protocols */
|
||||
#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
|
||||
#define AF_SNA 11 /* IBM SNA */
|
||||
#define AF_DECnet 12 /* DECnet */
|
||||
#define AF_DLI 13 /* DEC Direct data link interface */
|
||||
#define AF_LAT 14 /* LAT */
|
||||
#define AF_HYLINK 15 /* NSC Hyperchannel */
|
||||
#define AF_APPLETALK 16 /* Apple Talk */
|
||||
#define AF_ROUTE 17 /* Internal Routing Protocol */
|
||||
#define AF_LINK 18 /* Link layer interface */
|
||||
#define pseudo_AF_XTP 19 /* eXpress Transfer Protocol (no AF) */
|
||||
#define AF_COIP 20 /* connection-oriented IP, aka ST II */
|
||||
#define AF_CNT 21 /* Computer Network Technology */
|
||||
#define pseudo_AF_RTIP 22 /* Help Identify RTIP packets */
|
||||
#define AF_IPX 23 /* Novell Internet Protocol */
|
||||
#define AF_SIP 24 /* Simple Internet Protocol */
|
||||
#define pseudo_AF_PIP 25 /* Help Identify PIP packets */
|
||||
|
||||
#define AF_MAX 26
|
||||
|
||||
/*
|
||||
* Structure used by kernel to store most
|
||||
* addresses.
|
||||
*/
|
||||
struct sockaddr {
|
||||
__UBYTE sa_len; /* total length */
|
||||
sa_family_t sa_family; /* address family */
|
||||
__UBYTE sa_data[14]; /* actually longer; address value */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure used by kernel to pass protocol
|
||||
* information in raw sockets.
|
||||
*/
|
||||
struct sockproto {
|
||||
__UWORD sp_family; /* address family */
|
||||
__UWORD sp_protocol; /* protocol */
|
||||
};
|
||||
|
||||
/*
|
||||
* Protocol families, same as address families for now.
|
||||
*/
|
||||
#define PF_UNSPEC AF_UNSPEC
|
||||
#define PF_LOCAL AF_LOCAL
|
||||
#define PF_UNIX PF_LOCAL /* backward compatibility */
|
||||
#define PF_INET AF_INET
|
||||
#define PF_IMPLINK AF_IMPLINK
|
||||
#define PF_PUP AF_PUP
|
||||
#define PF_CHAOS AF_CHAOS
|
||||
#define PF_NS AF_NS
|
||||
#define PF_ISO AF_ISO
|
||||
#define PF_OSI AF_ISO
|
||||
#define PF_ECMA AF_ECMA
|
||||
#define PF_DATAKIT AF_DATAKIT
|
||||
#define PF_CCITT AF_CCITT
|
||||
#define PF_SNA AF_SNA
|
||||
#define PF_DECnet AF_DECnet
|
||||
#define PF_DLI AF_DLI
|
||||
#define PF_LAT AF_LAT
|
||||
#define PF_HYLINK AF_HYLINK
|
||||
#define PF_APPLETALK AF_APPLETALK
|
||||
#define PF_ROUTE AF_ROUTE
|
||||
#define PF_LINK AF_LINK
|
||||
#define PF_XTP pseudo_AF_XTP /* really just proto family, no AF */
|
||||
#define PF_COIP AF_COIP
|
||||
#define PF_CNT AF_CNT
|
||||
#define PF_SIP AF_SIP
|
||||
#define PF_IPX AF_IPX /* same format as AF_NS */
|
||||
#define PF_RTIP pseudo_AF_FTIP /* same format as AF_INET */
|
||||
#define PF_PIP pseudo_AF_PIP
|
||||
|
||||
#define PF_MAX AF_MAX
|
||||
|
||||
/*
|
||||
* Definitions for network related sysctl, CTL_NET.
|
||||
*
|
||||
* Second level is protocol family.
|
||||
* Third level is protocol number.
|
||||
*
|
||||
* Further levels are defined by the individual families below.
|
||||
*/
|
||||
#define NET_MAXID AF_MAX
|
||||
|
||||
/*
|
||||
* PF_ROUTE - Routing table
|
||||
*
|
||||
* Three additional levels are defined:
|
||||
* Fourth: address family, 0 is wildcard
|
||||
* Fifth: type of info, defined below
|
||||
* Sixth: flag(s) to mask with for NET_RT_FLAGS
|
||||
*/
|
||||
#define NET_RT_DUMP 1 /* dump; may limit to a.f. */
|
||||
#define NET_RT_FLAGS 2 /* by flags, e.g. RESOLVING */
|
||||
#define NET_RT_IFLIST 3 /* survey interface list */
|
||||
#define NET_RT_MAXID 4
|
||||
|
||||
/*
|
||||
* Maximum queue length specifiable by listen.
|
||||
*/
|
||||
#define SOMAXCONN 5
|
||||
|
||||
/*
|
||||
* Message header for recvmsg and sendmsg calls.
|
||||
* Used value-result for recvmsg, value only for sendmsg.
|
||||
*/
|
||||
struct msghdr {
|
||||
__APTR msg_name; /* optional address */
|
||||
socklen_t msg_namelen; /* size of address */
|
||||
struct iovec * msg_iov; /* scatter/gather array */
|
||||
__ULONG msg_iovlen; /* # elements in msg_iov */
|
||||
__APTR msg_control; /* ancillary data, see below */
|
||||
socklen_t msg_controllen; /* ancillary data buffer len */
|
||||
__LONG msg_flags; /* flags on received message */
|
||||
};
|
||||
|
||||
#define MSG_OOB 0x1 /* process out-of-band data */
|
||||
#define MSG_PEEK 0x2 /* peek at incoming message */
|
||||
#define MSG_DONTROUTE 0x4 /* send without using routing tables */
|
||||
#define MSG_EOR 0x8 /* data completes record */
|
||||
#define MSG_TRUNC 0x10 /* data discarded before delivery */
|
||||
#define MSG_CTRUNC 0x20 /* control data lost before delivery */
|
||||
#define MSG_WAITALL 0x40 /* wait for full request or error */
|
||||
#define MSG_DONTWAIT 0x80 /* this message should be nonblocking */
|
||||
|
||||
/*
|
||||
* Header for ancillary data objects in msg_control buffer.
|
||||
* Used for additional information with/about a datagram
|
||||
* not expressible by flags. The format is a sequence
|
||||
* of message elements headed by cmsghdr structures.
|
||||
*/
|
||||
struct cmsghdr {
|
||||
socklen_t cmsg_len; /* data byte count, including hdr */
|
||||
__LONG cmsg_level; /* originating protocol */
|
||||
__LONG cmsg_type; /* protocol-specific type */
|
||||
/* followed by __UBYTE cmsg_data[]; */
|
||||
};
|
||||
|
||||
/* given pointer to struct cmsghdr, return pointer to data */
|
||||
#define CMSG_DATA(cmsg) ((__UBYTE *)((cmsg) + 1))
|
||||
|
||||
/* given pointer to struct cmsghdr, return pointer to next cmsghdr */
|
||||
#define CMSG_NXTHDR(mhdr, cmsg) \
|
||||
(((__APTR)(cmsg) + (cmsg)->cmsg_len + sizeof(struct cmsghdr) > \
|
||||
(mhdr)->msg_control + (mhdr)->msg_controllen) ? \
|
||||
(struct cmsghdr *)NULL : \
|
||||
(struct cmsghdr *)((__APTR)(cmsg) + ALIGN((cmsg)->cmsg_len)))
|
||||
|
||||
#define CMSG_FIRSTHDR(mhdr) ((struct cmsghdr *)(mhdr)->msg_control)
|
||||
|
||||
/* "Socket"-level control message types: */
|
||||
#define SCM_RIGHTS 0x01 /* access rights (array of __LONG) */
|
||||
|
||||
/*
|
||||
* The following comes from the original <sys/types.h> header file,
|
||||
* which has been retired in favour of the <sys/netinclude_types.h>
|
||||
* type definitions. What remains are the macros in support of the
|
||||
* "select()" call and those for endian-neutral operations.
|
||||
*/
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* In case the select() data structures and macros are already
|
||||
* defined by somebody else...
|
||||
*/
|
||||
|
||||
#ifndef FD_SET
|
||||
|
||||
#define NBBY 8 /* number of bits in a byte */
|
||||
|
||||
/*
|
||||
* Select uses bit masks of file descriptors in longs. These macros
|
||||
* manipulate such bit fields (the filesystem macros use chars).
|
||||
* FD_SETSIZE may be defined by the user, but the default here should
|
||||
* be enough for most uses.
|
||||
*/
|
||||
#ifndef FD_SETSIZE
|
||||
#define FD_SETSIZE 256
|
||||
#endif
|
||||
|
||||
typedef unsigned long fd_mask;
|
||||
#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
|
||||
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x) + ((y) - 1)) / (y))
|
||||
#endif
|
||||
|
||||
typedef struct fd_set {
|
||||
fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
|
||||
} fd_set;
|
||||
|
||||
#define FD_SET(n, p) ((void)(((unsigned long)n) < FD_SETSIZE ? (p)->fds_bits[((unsigned long)n)/NFDBITS] |= (1 << (((unsigned long)n) % NFDBITS)) : 0))
|
||||
#define FD_CLR(n, p) ((void)(((unsigned long)n) < FD_SETSIZE ? (p)->fds_bits[((unsigned long)n)/NFDBITS] &= ~(1 << (((unsigned long)n) % NFDBITS)) : 0))
|
||||
#define FD_ISSET(n, p) (((unsigned long)n) < FD_SETSIZE && ((p)->fds_bits[((unsigned long)n)/NFDBITS] & (1 << (((unsigned long)n) % NFDBITS))))
|
||||
#define FD_COPY(f, t) ((void)memmove((t), (f), sizeof(*(f))))
|
||||
#define FD_ZERO(p) ((void)memset((p), 0, sizeof(*(p))))
|
||||
|
||||
#endif /* FD_SET */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __PPC__
|
||||
#pragma pack()
|
||||
#endif
|
||||
#elif defined(__VBCC__)
|
||||
#pragma default-align
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifndef __NO_NETINCLUDE_TIMEVAL
|
||||
|
||||
/*
|
||||
* This is for compatibility with POSIX-like 'timeval' structures
|
||||
* which are remarkably similar to the Amiga 'timeval' except for
|
||||
* the structure member names...
|
||||
*/
|
||||
#ifndef DEVICES_TIMER_H
|
||||
#include <devices/timer.h>
|
||||
#endif /* DEVICES_TIMER_H */
|
||||
|
||||
#ifndef tv_sec
|
||||
#define tv_sec tv_secs
|
||||
#endif /* tv_sec */
|
||||
|
||||
#ifndef tv_usec
|
||||
#define tv_usec tv_micro
|
||||
#endif /* tv_usec */
|
||||
|
||||
#endif /* __NO_NETINCLUDE_TIMEVAL */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#endif /* !_SYS_SOCKET_H_ */
|
341
library.c
Normal file
341
library.c
Normal file
@ -0,0 +1,341 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "time.h"
|
||||
#include "mem.h"
|
||||
|
||||
/* Library identifiers */
|
||||
static const char *dosName = "dos.library";
|
||||
static const char *aslName = "asl.library";
|
||||
static const char *iconName = "icon.library";
|
||||
static const char *commoditiesName = "commodities.library";
|
||||
static const char *localeName = "locale.library";
|
||||
static const char *utilityName = "utility.library";
|
||||
static const char *gadgetName = "gadtools.library";
|
||||
static const char *intuitionName = "intuition.library";
|
||||
static const char *mathName = "mathieeedoubbas.library";
|
||||
|
||||
#if !defined(LIB_HOST)
|
||||
/* Use fake bases */
|
||||
#define DOSBase __FX_DOSBase
|
||||
#define LocaleBase __FX_LocaleBase
|
||||
#define UtilityBase __FX_UtilityBase
|
||||
#define IntuitionBase __FX_IntuitionBase
|
||||
#define CxBase __FX_CxBase
|
||||
#define AslBase __FX_AslBase
|
||||
#define IconBase __FX_IconBase
|
||||
#define GadToolsBase __FX_GadToolsBase
|
||||
#define __MathIeeeDoubBasBase __FX__MathIeeeDoubBasBase
|
||||
#define __UtilityBase __FX__UtilityBase
|
||||
#endif
|
||||
|
||||
/* Library addresses */
|
||||
//struct ExecBase *SysBase = (struct ExecBase *)4L;
|
||||
struct DosLibrary *DOSBase = NULL;
|
||||
struct LocaleBase *LocaleBase = NULL;
|
||||
struct UtilityBase *UtilityBase = NULL;
|
||||
struct IntuitionBase *IntuitionBase = NULL;
|
||||
struct Library *CxBase = NULL;
|
||||
struct Library *AslBase = NULL;
|
||||
struct Library *IconBase = NULL;
|
||||
struct Library *GadToolsBase = NULL;
|
||||
struct Library *__MathIeeeDoubBasBase = NULL;
|
||||
struct UtilityBase *__UtilityBase = NULL;
|
||||
|
||||
#define DOSLIB_NAME ((STRPTR)dosName)
|
||||
#define DOSLIB_REV 36L
|
||||
#define ASLLIB_NAME ((STRPTR)aslName)
|
||||
#define ASLLIB_REV 37L
|
||||
#define ICONLIB_NAME ((STRPTR)iconName)
|
||||
#define ICONLIB_REV 36L
|
||||
#define COMMODLIB_NAME ((STRPTR)commoditiesName)
|
||||
#define COMMODLIB_REV 37L
|
||||
#define INTUITIONLIB_NAME ((STRPTR)intuitionName)
|
||||
#define INTUITIONLIB_REV 37L
|
||||
#define LOCALELIB_NAME ((STRPTR)localeName)
|
||||
#define LOCALELIB_REV 37L
|
||||
#define UTILLIB_NAME ((STRPTR)utilityName)
|
||||
#define UTILLIB_REV 37L
|
||||
#define GADGETLIB_NAME ((STRPTR)gadgetName)
|
||||
#define GADGETLIB_REV 37L
|
||||
#define MATHLIB_NAME ((STRPTR)mathName)
|
||||
#define MATHLIB_REV 34L
|
||||
|
||||
// RTC Clock
|
||||
static const char *batteryClockName = "battclock.resource";
|
||||
#define BATTCLOCK_NAME ((STRPTR)batteryClockName)
|
||||
struct Library *BattClockBase = NULL;
|
||||
|
||||
static struct Device *TimerDevice = NULL;
|
||||
static const char *currentLocale = "Current Locale";
|
||||
|
||||
static void OpenLibrarySuccess(STRPTR name)
|
||||
{
|
||||
LogTrace("Opened %s", name);
|
||||
}
|
||||
|
||||
static void OpenLibraryError(STRPTR name, long version)
|
||||
{
|
||||
LogError("Cannot open %s %ld.0", name, version);
|
||||
}
|
||||
|
||||
static void ClosingLibrary(STRPTR name)
|
||||
{
|
||||
LogTrace("Closing %s", name);
|
||||
}
|
||||
|
||||
static void OpenResourceSuccess(const char *name)
|
||||
{
|
||||
LogTrace("Opened %s", name);
|
||||
}
|
||||
|
||||
static void OpenResourceError(const char *name)
|
||||
{
|
||||
LogError("Cannot open %s", name);
|
||||
}
|
||||
|
||||
static void ClosingResource(const char *name)
|
||||
{
|
||||
LogTrace("Closing %s", name);
|
||||
}
|
||||
|
||||
int OpenLibraries(void)
|
||||
{
|
||||
// DOS Library
|
||||
if (!(DOSBase = (struct DosLibrary *)OpenLibrary((STRPTR)DOSLIB_NAME, DOSLIB_REV)))
|
||||
{
|
||||
OpenLibraryError(DOSLIB_NAME, DOSLIB_REV);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
#ifdef AOS3
|
||||
// Library does not always provide IdString
|
||||
OpenResourceSuccess(DOSLIB_NAME);
|
||||
#else
|
||||
OpenLibrarySuccess(((struct Library *)DOSBase)->lib_IdString);
|
||||
#endif
|
||||
|
||||
// Math Library
|
||||
if (!(__MathIeeeDoubBasBase = OpenLibrary((STRPTR)MATHLIB_NAME, MATHLIB_REV)))
|
||||
{
|
||||
OpenLibraryError(MATHLIB_NAME, MATHLIB_REV);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
#ifdef AOS3
|
||||
// Library does not always provide IdString
|
||||
OpenResourceSuccess(MATHLIB_NAME);
|
||||
#else
|
||||
OpenLibrarySuccess(((struct Library *)__MathIeeeDoubBasBase)->lib_IdString);
|
||||
#endif
|
||||
|
||||
// Commodities Library
|
||||
if (!(CxBase = OpenLibrary((STRPTR)COMMODLIB_NAME, COMMODLIB_REV)))
|
||||
{
|
||||
OpenLibraryError(COMMODLIB_NAME, COMMODLIB_REV);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
OpenLibrarySuccess(CxBase->lib_IdString);
|
||||
|
||||
// Intuition Library
|
||||
if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary((STRPTR)INTUITIONLIB_NAME, INTUITIONLIB_REV)))
|
||||
{
|
||||
OpenLibraryError(INTUITIONLIB_NAME, INTUITIONLIB_REV);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
OpenLibrarySuccess(((struct Library *)IntuitionBase)->lib_IdString);
|
||||
|
||||
// Icon Library
|
||||
if (!(IconBase = OpenLibrary((STRPTR)ICONLIB_NAME, ICONLIB_REV)))
|
||||
{
|
||||
OpenLibraryError(ICONLIB_NAME, ICONLIB_REV);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
OpenLibrarySuccess(IconBase->lib_IdString);
|
||||
|
||||
// Icon Library
|
||||
if (!(AslBase = OpenLibrary((STRPTR)ASLLIB_NAME, ASLLIB_REV)))
|
||||
{
|
||||
OpenLibraryError(ASLLIB_NAME, ASLLIB_REV);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
OpenLibrarySuccess(AslBase->lib_IdString);
|
||||
|
||||
// Locale Library
|
||||
if (!(LocaleBase = (struct LocaleBase *)OpenLibrary((STRPTR)LOCALELIB_NAME, LOCALELIB_REV)))
|
||||
{
|
||||
OpenLibraryError(LOCALELIB_NAME, LOCALELIB_REV);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
OpenLibrarySuccess(((struct Library *)LocaleBase)->lib_IdString);
|
||||
|
||||
// Utility Library
|
||||
if (!(UtilityBase = (struct UtilityBase *)OpenLibrary((STRPTR)UTILLIB_NAME, UTILLIB_REV)))
|
||||
{
|
||||
OpenLibraryError(UTILLIB_NAME, UTILLIB_REV);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
__UtilityBase = UtilityBase;
|
||||
OpenLibrarySuccess(((struct Library *)UtilityBase)->lib_IdString);
|
||||
|
||||
// Gadget Library
|
||||
if (!(GadToolsBase = OpenLibrary((STRPTR)GADGETLIB_NAME, GADGETLIB_REV)))
|
||||
{
|
||||
OpenLibraryError(GADGETLIB_NAME, GADGETLIB_REV);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
OpenLibrarySuccess(GadToolsBase->lib_IdString);
|
||||
|
||||
// Locale
|
||||
if (!(Globals->Locale = OpenLocale(NULL)))
|
||||
{
|
||||
OpenResourceError(currentLocale);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
OpenResourceSuccess((const char *)Globals->Locale->loc_LocaleName);
|
||||
|
||||
// RTC Clock
|
||||
if (!(BattClockBase = OpenResource((STRPTR)BATTCLOCK_NAME)))
|
||||
{
|
||||
OpenResourceError((const char *)BATTCLOCK_NAME);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
OpenResourceSuccess((const char *)BATTCLOCK_NAME);
|
||||
|
||||
// Timer Device
|
||||
if (!(TimerDevice = OpenTimerBase()))
|
||||
{
|
||||
OpenResourceError(TIMERNAME);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
OpenResourceSuccess(TIMERNAME);
|
||||
|
||||
InitUtcOffset();
|
||||
|
||||
return LIB_OK;
|
||||
}
|
||||
|
||||
void CloseLibraries(void)
|
||||
{
|
||||
if (TimerDevice != NULL)
|
||||
{
|
||||
ClosingResource((const char *)TIMERNAME);
|
||||
CloseTimerBase();
|
||||
TimerDevice = NULL;
|
||||
}
|
||||
|
||||
if (Globals->Locale != NULL)
|
||||
{
|
||||
ClosingResource((const char *)Globals->Locale->loc_LocaleName);
|
||||
CloseLocale(Globals->Locale);
|
||||
Globals->Locale = NULL;
|
||||
}
|
||||
|
||||
if (CxBase != NULL)
|
||||
{
|
||||
ClosingLibrary(CxBase->lib_IdString);
|
||||
CloseLibrary(CxBase);
|
||||
CxBase = NULL;
|
||||
}
|
||||
|
||||
if (AslBase != NULL)
|
||||
{
|
||||
ClosingLibrary(AslBase->lib_IdString);
|
||||
CloseLibrary(AslBase);
|
||||
AslBase = NULL;
|
||||
}
|
||||
|
||||
if (IconBase != NULL)
|
||||
{
|
||||
ClosingLibrary(IconBase->lib_IdString);
|
||||
CloseLibrary(IconBase);
|
||||
IconBase = NULL;
|
||||
}
|
||||
|
||||
if (LocaleBase != NULL)
|
||||
{
|
||||
ClosingLibrary(((struct Library *)LocaleBase)->lib_IdString);
|
||||
CloseLibrary((struct Library *)LocaleBase);
|
||||
LocaleBase = NULL;
|
||||
}
|
||||
|
||||
if (UtilityBase != NULL)
|
||||
{
|
||||
ClosingLibrary(((struct Library *)UtilityBase)->lib_IdString);
|
||||
CloseLibrary((struct Library *)UtilityBase);
|
||||
UtilityBase = NULL;
|
||||
__UtilityBase = NULL;
|
||||
}
|
||||
|
||||
if (GadToolsBase != NULL)
|
||||
{
|
||||
ClosingLibrary(GadToolsBase->lib_IdString);
|
||||
CloseLibrary(GadToolsBase);
|
||||
GadToolsBase = NULL;
|
||||
}
|
||||
|
||||
if (IntuitionBase != NULL)
|
||||
{
|
||||
ClosingLibrary(((struct Library *)IntuitionBase)->lib_IdString);
|
||||
CloseLibrary((struct Library *)IntuitionBase);
|
||||
IntuitionBase = NULL;
|
||||
}
|
||||
|
||||
if (DOSBase != NULL)
|
||||
{
|
||||
#ifdef AOS3
|
||||
// Library does not always provide IdString
|
||||
ClosingResource(DOSLIB_NAME);
|
||||
#else
|
||||
ClosingLibrary(((struct Library *)DOSBase)->lib_IdString);
|
||||
#endif
|
||||
CloseLibrary((struct Library *)DOSBase);
|
||||
DOSBase = NULL;
|
||||
}
|
||||
|
||||
if (__MathIeeeDoubBasBase != NULL)
|
||||
{
|
||||
#ifdef AOS3
|
||||
// Library does not always provide IdString
|
||||
ClosingResource(MATHLIB_NAME);
|
||||
#else
|
||||
ClosingLibrary(((struct Library *)__MathIeeeDoubBasBase)->lib_IdString);
|
||||
#endif
|
||||
CloseLibrary((struct Library *)__MathIeeeDoubBasBase);
|
||||
__MathIeeeDoubBasBase = NULL;
|
||||
}
|
||||
}
|
247
log.c
Normal file
247
log.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "log.h"
|
||||
#include "mem.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#define MAXLOGLINESIZE 255
|
||||
|
||||
enum LogSeverity
|
||||
{
|
||||
ErrorMessage = 5,
|
||||
WarningMessage = 10,
|
||||
InfoMessage = 20,
|
||||
TraceMessage = 30
|
||||
};
|
||||
|
||||
struct LogEntry
|
||||
{
|
||||
enum LogSeverity level;
|
||||
char *line;
|
||||
struct LogEntry *next;
|
||||
};
|
||||
|
||||
static bool logDisabled = false;
|
||||
static bool bufferLog = false;
|
||||
static BPTR logFile = NULL;
|
||||
static struct LogEntry *firstEntry = NULL;
|
||||
static struct LogEntry *lastEntry = NULL;
|
||||
|
||||
void OpenLogFile(void)
|
||||
{
|
||||
BPTR lock;
|
||||
bool deleteFirst = false;
|
||||
|
||||
if (Globals->Settings->LogFile == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock = Lock((STRPTR)Globals->Settings->LogFile, ACCESS_READ);
|
||||
if (lock)
|
||||
{
|
||||
deleteFirst = true;
|
||||
UnLock(lock);
|
||||
}
|
||||
|
||||
if (deleteFirst)
|
||||
{
|
||||
bool success;
|
||||
LogWarning("Deleting existing log file %s", Globals->Settings->LogFile);
|
||||
success = DeleteFile((STRPTR)Globals->Settings->LogFile);
|
||||
if (!success)
|
||||
{
|
||||
char message[MAXDOSERRORLEN];
|
||||
long error = IoErr();
|
||||
Fault(error, (STRPTR) "Cannot delete existing log file %s", (STRPTR)message, MAXDOSERRORLEN);
|
||||
LogWarning(message);
|
||||
logFile = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LogInfo("Opening log file %s", Globals->Settings->LogFile);
|
||||
logFile = Open((STRPTR)Globals->Settings->LogFile, MODE_READWRITE);
|
||||
if (!logFile)
|
||||
{
|
||||
char message[MAXDOSERRORLEN];
|
||||
long error = IoErr();
|
||||
Fault(error, (STRPTR) "Cannot open log file %s", (STRPTR)message, MAXDOSERRORLEN);
|
||||
LogWarning(message);
|
||||
logFile = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CloseLogFile(void)
|
||||
{
|
||||
if (logFile == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogTrace("Closing log file %s", Globals->Settings->LogFile);
|
||||
Close(logFile);
|
||||
logFile = NULL;
|
||||
logDisabled = true;
|
||||
}
|
||||
|
||||
bool TraceLogging(void)
|
||||
{
|
||||
return Globals->Settings->Verbose * 10 >= (int)TraceMessage
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
|
||||
static void VLogLine(enum LogSeverity level, const char *format, va_list ap)
|
||||
{
|
||||
struct LogEntry *entry;
|
||||
char line[MAXLOGLINESIZE + 1];
|
||||
|
||||
if (logDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (bufferLog || Globals->Settings->Verbose * 10 >= (int)level)
|
||||
{
|
||||
int len;
|
||||
VSNPrintf(line, MAXLOGLINESIZE - 1, format, ap);
|
||||
len = TrimRight(line);
|
||||
if (len != 0)
|
||||
{
|
||||
line[len++] = '\n';
|
||||
line[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (bufferLog)
|
||||
{
|
||||
entry = (struct LogEntry *)AllocMemSafe(sizeof(struct LogEntry));
|
||||
entry->level = level;
|
||||
entry->line = StrDupSafe(line);
|
||||
entry->next = NULL;
|
||||
|
||||
if (firstEntry == NULL)
|
||||
{
|
||||
firstEntry = entry;
|
||||
lastEntry = entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastEntry->next = entry;
|
||||
lastEntry = entry;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Verbose * 10 >= (int)level)
|
||||
{
|
||||
if (logFile != NULL)
|
||||
{
|
||||
FPuts(logFile, (STRPTR)line);
|
||||
Flush(logFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf((STRPTR)line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LogTrace(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(TraceMessage, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void LogInfo(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(InfoMessage, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void LogWarning(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(WarningMessage, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void LogError(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(ErrorMessage, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void SetLogBuffer(void)
|
||||
{
|
||||
bufferLog = true;
|
||||
}
|
||||
|
||||
void FlushLogBuffer(void)
|
||||
{
|
||||
struct LogEntry *current;
|
||||
|
||||
if (!bufferLog)
|
||||
return;
|
||||
|
||||
current = firstEntry;
|
||||
while (current != NULL)
|
||||
{
|
||||
struct LogEntry *last;
|
||||
if (Globals->Settings->Verbose * 10 >= (int)current->level)
|
||||
{
|
||||
if (logFile != NULL)
|
||||
{
|
||||
FPuts(logFile, (STRPTR)current->line);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf((STRPTR)current->line);
|
||||
}
|
||||
}
|
||||
|
||||
last = current;
|
||||
current = current->next;
|
||||
|
||||
FreeMemSafe(last->line);
|
||||
FreeMemSafe(last);
|
||||
}
|
||||
|
||||
bufferLog = false;
|
||||
firstEntry = NULL;
|
||||
lastEntry = NULL;
|
||||
}
|
42
log.h
Normal file
42
log.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOG_H_INCLUDED
|
||||
#define LOG_H_INCLUDED
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
void LogTrace(const char *format, ...);
|
||||
void LogInfo(const char *format, ...);
|
||||
void LogWarning(const char *format, ...);
|
||||
void LogError(const char *format, ...);
|
||||
bool TraceLogging(void);
|
||||
void OpenLogFile(void);
|
||||
void CloseLogFile(void);
|
||||
void SetLogBuffer(void);
|
||||
void FlushLogBuffer(void);
|
||||
|
||||
#endif
|
154
main.c
Normal file
154
main.c
Normal file
@ -0,0 +1,154 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "state.h"
|
||||
#include "time.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include <workbench/startup.h>
|
||||
|
||||
const char *vers = "\0$VER: " APP_ID;
|
||||
static const char *template = KEYWORD_TEMPLATE;
|
||||
|
||||
static void LogStartMessage(void);
|
||||
static void LogLocalTime(void);
|
||||
static void GetCliSettings(void);
|
||||
static void GetWbSettings(struct WBStartup *);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
InitState();
|
||||
SetLogBuffer();
|
||||
LogStartMessage();
|
||||
LogLocalTime();
|
||||
|
||||
if (OpenLibraries() != 0)
|
||||
return RETURN_ERROR;
|
||||
|
||||
LoadSettings();
|
||||
|
||||
if (argc != 0)
|
||||
GetCliSettings();
|
||||
else
|
||||
GetWbSettings((struct WBStartup *)argv);
|
||||
|
||||
ApplySettings();
|
||||
SanitizeSettings();
|
||||
ShowSettings();
|
||||
OpenLogFile();
|
||||
FlushLogBuffer();
|
||||
|
||||
StartBroker();
|
||||
|
||||
LogLocalTime();
|
||||
CloseSocketLibrary();
|
||||
CloseLibraries();
|
||||
CloseLogFile();
|
||||
DestroyState();
|
||||
FreeAllSafe();
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
static void GetCliSettings(void)
|
||||
{
|
||||
struct AppSettings *settings;
|
||||
struct RDArgs *inArgs;
|
||||
long args[KEYWORD_COUNT];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < KEYWORD_COUNT; i++)
|
||||
args[i] = 0;
|
||||
|
||||
settings = CreateSettings(CliSettingType);
|
||||
settings->Verbose = 1;
|
||||
|
||||
inArgs = ReadArgs((void *)template, (void *)&args, NULL);
|
||||
if (inArgs)
|
||||
{
|
||||
// Keyword order in template needs to match order in settingFunctions
|
||||
for (i = 0; i < KEYWORD_COUNT; i++)
|
||||
{
|
||||
if (args[i] != 0)
|
||||
{
|
||||
settingFunctions[i].Function(settings, (void *)args[i]);
|
||||
}
|
||||
}
|
||||
FreeArgs(inArgs);
|
||||
}
|
||||
|
||||
CacheSettings(settings);
|
||||
}
|
||||
|
||||
static void GetWbSettings(struct WBStartup *wbs)
|
||||
{
|
||||
struct AppSettings *settings;
|
||||
struct DiskObject *diskObject;
|
||||
STRPTR filename, arg;
|
||||
BPTR oldDir;
|
||||
int argNo, i;
|
||||
|
||||
filename = (STRPTR)AllocMemSafe(MAXFILEPATHLEN);
|
||||
settings = CreateSettings(WbSettingType);
|
||||
|
||||
for (argNo = 0; argNo < wbs->sm_NumArgs; ++argNo)
|
||||
{
|
||||
if (wbs->sm_ArgList[argNo].wa_Lock != NULL)
|
||||
{
|
||||
oldDir = CurrentDir(wbs->sm_ArgList[argNo].wa_Lock);
|
||||
diskObject = GetDiskObjectNew((void *)wbs->sm_ArgList[argNo].wa_Name);
|
||||
if (diskObject)
|
||||
{
|
||||
for (i = 0; i < KEYWORD_COUNT; i++)
|
||||
{
|
||||
arg = FindToolType(diskObject->do_ToolTypes, (STRPTR)settingFunctions[i].Name);
|
||||
if (arg)
|
||||
{
|
||||
settingFunctions[i].Function(settings, (char *)arg);
|
||||
}
|
||||
}
|
||||
FreeDiskObject(diskObject);
|
||||
}
|
||||
CurrentDir(oldDir);
|
||||
}
|
||||
}
|
||||
|
||||
CacheSettings(settings);
|
||||
FreeMemSafe(filename);
|
||||
}
|
||||
|
||||
static void LogStartMessage(void)
|
||||
{
|
||||
LogWarning("%s", APP_TITLE);
|
||||
}
|
||||
|
||||
static void LogLocalTime(void)
|
||||
{
|
||||
char timeString[10], dateString[10], dayString[10];
|
||||
SystemTimeString(timeString, dateString, dayString);
|
||||
LogWarning("Local time is %s %s %s", dayString, dateString, timeString);
|
||||
}
|
297
mem.c
Normal file
297
mem.c
Normal file
@ -0,0 +1,297 @@
|
||||
/*-
|
||||
* Copyright (c) 2014-2018 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 <stddef.h>
|
||||
#include <exec/types.h>
|
||||
#include <exec/memory.h>
|
||||
#include <exec/semaphores.h>
|
||||
#include <proto/exec.h>
|
||||
#define ALLOC_MEM(x) AllocVec(x, MEMF_ANY | MEMF_CLEAR)
|
||||
#define FREE_MEM(x) FreeVec(x)
|
||||
|
||||
#include "compiler.h"
|
||||
#include "log.h"
|
||||
int StrLen(const char *);
|
||||
|
||||
#if defined(__x86_64__) || defined(__aarch64__) || \
|
||||
defined(_M_AMD64) || defined(_M_ARM64) || \
|
||||
defined(__powerpc64__)
|
||||
#define P64BIT
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_BUILD
|
||||
#define MEM_TRACE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Block of allocated memory.
|
||||
*/
|
||||
struct MemoryBlock
|
||||
{
|
||||
struct MemoryBlock *next;
|
||||
size_t size;
|
||||
void *address;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief List of allocated memory. Uses the LIFO principle.
|
||||
*/
|
||||
struct MemoryList
|
||||
{
|
||||
struct MemoryBlock *first;
|
||||
size_t peak;
|
||||
size_t size;
|
||||
long count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Global list of allocated memory.
|
||||
*/
|
||||
static struct MemoryList *list = NULL;
|
||||
|
||||
void AllocationError(char *, size_t);
|
||||
void DeAllocationError(char *, void *);
|
||||
|
||||
/**
|
||||
* @brief Allocate memory and add it to the global memory list.
|
||||
*/
|
||||
void *AllocMemSafe(size_t size)
|
||||
{
|
||||
struct MemoryBlock *newblock;
|
||||
size_t allocsize;
|
||||
|
||||
Forbid();
|
||||
if (list == NULL)
|
||||
{
|
||||
list = (struct MemoryList *)ALLOC_MEM(sizeof(struct MemoryList));
|
||||
if (!list)
|
||||
{
|
||||
AllocationError("list", sizeof(struct MemoryList));
|
||||
return 0;
|
||||
}
|
||||
|
||||
list->first = NULL;
|
||||
list->peak = 0;
|
||||
list->size = 0;
|
||||
list->count = 0;
|
||||
}
|
||||
|
||||
#ifdef P64BIT
|
||||
// Align to bytes of 8
|
||||
allocsize = (size + 7) & ~0x07;
|
||||
#else
|
||||
// Align to bytes of 4
|
||||
allocsize = (size + 3) & ~0x03;
|
||||
#endif
|
||||
|
||||
newblock = (struct MemoryBlock *)ALLOC_MEM(sizeof(struct MemoryBlock));
|
||||
if (!newblock)
|
||||
{
|
||||
AllocationError("block", sizeof(struct MemoryBlock));
|
||||
return 0;
|
||||
}
|
||||
|
||||
newblock->address = (struct MemoryBlock *)ALLOC_MEM(allocsize);
|
||||
if (!newblock->address)
|
||||
{
|
||||
FREE_MEM(newblock);
|
||||
AllocationError("memory", allocsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
newblock->size = allocsize;
|
||||
newblock->next = list->first;
|
||||
list->first = newblock;
|
||||
list->size += allocsize;
|
||||
list->count++;
|
||||
|
||||
if (list->size > list->peak)
|
||||
{
|
||||
list->peak = list->size;
|
||||
}
|
||||
Permit();
|
||||
|
||||
#ifdef MEM_TRACE
|
||||
Printf("Allocated memory block off %ld bytes at 0x%lx\n",
|
||||
newblock->size, newblock->address);
|
||||
#endif
|
||||
|
||||
// Memory allocated
|
||||
return newblock->address;
|
||||
}
|
||||
|
||||
void RemoveMemSafe(void *block, bool deallocate)
|
||||
{
|
||||
struct MemoryBlock *current, *previous;
|
||||
|
||||
Forbid();
|
||||
if (list == NULL || block == NULL)
|
||||
{
|
||||
DeAllocationError("list", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (block == NULL)
|
||||
{
|
||||
DeAllocationError("memory", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
previous = NULL;
|
||||
current = list->first;
|
||||
while (current != NULL && current->address != block)
|
||||
{
|
||||
previous = current;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
if (current == NULL)
|
||||
{
|
||||
DeAllocationError("address not found", block);
|
||||
return;
|
||||
}
|
||||
|
||||
if (previous == NULL)
|
||||
{
|
||||
list->first = current->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
previous->next = current->next;
|
||||
}
|
||||
|
||||
list->size -= current->size;
|
||||
list->count--;
|
||||
|
||||
if (deallocate)
|
||||
{
|
||||
FREE_MEM(current->address);
|
||||
}
|
||||
|
||||
current->address = NULL;
|
||||
current->next = NULL;
|
||||
current->size = 0;
|
||||
FREE_MEM(current);
|
||||
Permit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deallocate memory from the global memory list.
|
||||
*/
|
||||
void FreeMemSafe(void *block)
|
||||
{
|
||||
RemoveMemSafe(block, true);
|
||||
}
|
||||
|
||||
void *MemDupSafe(const void *s1, size_t len)
|
||||
{
|
||||
char *dup;
|
||||
dup = AllocMemSafe(len);
|
||||
CopyMem((void *)s1, dup, len);
|
||||
return dup;
|
||||
}
|
||||
|
||||
char *StrDupSafe(const char *s1)
|
||||
{
|
||||
char *s2;
|
||||
size_t len = s1 != NULL ? StrLen(s1) : 1;
|
||||
s2 = AllocMemSafe(++len);
|
||||
|
||||
if (s2 == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CopyMem((void *)s1, s2, --len);
|
||||
return s2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deallocate all memory in the global memory list.
|
||||
*/
|
||||
void FreeAllSafe(void)
|
||||
{
|
||||
struct MemoryBlock *current, *next;
|
||||
|
||||
Forbid();
|
||||
if (list == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
current = list->first;
|
||||
while (current != NULL)
|
||||
{
|
||||
LogTrace("Released forgotten memory block on %ld bytes at 0x%lx",
|
||||
(long)current->size,
|
||||
(unsigned long)current->address);
|
||||
next = current->next;
|
||||
FREE_MEM(current->address);
|
||||
FREE_MEM(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
FREE_MEM(list);
|
||||
list = NULL;
|
||||
Permit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get memory usage in the global memory list.
|
||||
*/
|
||||
void MemUsage(long *blocks, long *size, long *peak)
|
||||
{
|
||||
if (blocks != NULL)
|
||||
{
|
||||
*blocks = list->count;
|
||||
}
|
||||
|
||||
if (size != NULL)
|
||||
{
|
||||
*size = (long)list->size;
|
||||
}
|
||||
|
||||
if (peak != NULL)
|
||||
{
|
||||
*peak = (long)list->peak;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log a memory allocation error.
|
||||
*/
|
||||
void AllocationError(char *descr, size_t size)
|
||||
{
|
||||
LogTrace("Memory allocation error (%s) with size (%ld)", descr, (long)size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log a memory deallocation error.
|
||||
*/
|
||||
void DeAllocationError(char *descr, void *p)
|
||||
{
|
||||
LogTrace("Memory deallocation error (%s) at 0x%lx", descr, p);
|
||||
}
|
39
mem.h
Normal file
39
mem.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*-
|
||||
* Copyright (c) 2014-2018 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MEM_H_INCLUDED
|
||||
#define MEM_H_INCLUDED
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void *AllocMemSafe(size_t);
|
||||
char *StrDupSafe(const char *);
|
||||
void *MemDupSafe(const void *s1, size_t len);
|
||||
void FreeMemSafe(void *);
|
||||
void FreeAllSafe(void);
|
||||
void MemUsage(long *, long *, long *);
|
||||
|
||||
#endif
|
97
message.c
Normal file
97
message.c
Normal file
@ -0,0 +1,97 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "message.h"
|
||||
#include "mem.h"
|
||||
|
||||
static void SendTextMessage(char *text, long type)
|
||||
{
|
||||
Forbid();
|
||||
if (!Globals->ShuttingDown)
|
||||
{
|
||||
struct AppWindowMessage *message = (struct AppWindowMessage *)AllocMemSafe(sizeof(struct AppWindowMessage));
|
||||
message->Msg.mn_Node.ln_Type = NT_MESSAGE;
|
||||
message->Msg.mn_Length = sizeof(struct AppWindowMessage);
|
||||
message->Msg.mn_ReplyPort = Globals->Broker->ReplyPort;
|
||||
message->Type = type;
|
||||
message->Text = StrDupSafe(text);
|
||||
PutMsg(Globals->Broker->UserPort, (struct Message *)message);
|
||||
}
|
||||
Permit();
|
||||
}
|
||||
|
||||
void SendErrorMessage(char *text)
|
||||
{
|
||||
SendTextMessage(text, ATK_LOGERROR);
|
||||
}
|
||||
|
||||
void SendWarningMessage(char *text)
|
||||
{
|
||||
SendTextMessage(text, ATK_LOGWARN);
|
||||
}
|
||||
|
||||
void SendInfoMessage(char *text)
|
||||
{
|
||||
SendTextMessage(text, ATK_LOGINFO);
|
||||
}
|
||||
|
||||
void SendTraceMessage(char *text)
|
||||
{
|
||||
SendTextMessage(text, ATK_LOGTRACE);
|
||||
}
|
||||
|
||||
void SendMessage(long type)
|
||||
{
|
||||
Forbid();
|
||||
if (!Globals->ShuttingDown)
|
||||
{
|
||||
struct AppWindowMessage *message = (struct AppWindowMessage *)AllocMemSafe(sizeof(struct AppWindowMessage));
|
||||
message->Msg.mn_Node.ln_Type = NT_MESSAGE;
|
||||
message->Msg.mn_Length = sizeof(struct AppWindowMessage);
|
||||
message->Msg.mn_ReplyPort = Globals->Broker->ReplyPort;
|
||||
message->Type = type;
|
||||
message->Text = NULL;
|
||||
PutMsg(Globals->Broker->UserPort, (struct Message *)message);
|
||||
}
|
||||
Permit();
|
||||
}
|
||||
|
||||
void SendMessageTo(struct MsgPort *dest, struct MsgPort *reply, long type)
|
||||
{
|
||||
Forbid();
|
||||
if (!Globals->ShuttingDown)
|
||||
{
|
||||
struct AppWindowMessage *message = (struct AppWindowMessage *)AllocMemSafe(sizeof(struct AppWindowMessage));
|
||||
message->Msg.mn_Node.ln_Type = NT_MESSAGE;
|
||||
message->Msg.mn_Length = sizeof(struct AppWindowMessage);
|
||||
message->Msg.mn_ReplyPort = reply;
|
||||
message->Type = type;
|
||||
message->Text = NULL;
|
||||
PutMsg(dest, (struct Message *)message);
|
||||
}
|
||||
Permit();
|
||||
}
|
60
message.h
Normal file
60
message.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MESSAGE_H_INCLUDED
|
||||
#define MESSAGE_H_INCLUDED
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define ATK_LOGERROR 1
|
||||
#define ATK_LOGWARN 2
|
||||
#define ATK_LOGINFO 3
|
||||
#define ATK_LOGTRACE 4
|
||||
#define ATK_RESTART 10
|
||||
#define ATK_REFRESH 11
|
||||
#define ATK_STORE 13
|
||||
#define ATK_APPLY 14
|
||||
#define ATK_UNDO 15
|
||||
#define ATK_ENABLE 20
|
||||
#define ATK_DISABLE 21
|
||||
#define ATK_READONLY 22
|
||||
#define ATK_READWRITE 23
|
||||
|
||||
struct AppWindowMessage
|
||||
{
|
||||
struct Message Msg;
|
||||
long Type;
|
||||
char *Text;
|
||||
};
|
||||
|
||||
void SendMessage(long);
|
||||
void SendErrorMessage(char *);
|
||||
void SendWarningMessage(char *);
|
||||
void SendInfoMessage(char *);
|
||||
void SendTraceMessage(char *);
|
||||
void SendMessageTo(struct MsgPort *, struct MsgPort *, long);
|
||||
|
||||
#endif
|
182
net.c
Normal file
182
net.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "net_getaddrinfo.h"
|
||||
#include "message.h"
|
||||
|
||||
int errno;
|
||||
int gai_h_errno;
|
||||
|
||||
#ifdef AOS3
|
||||
int h_errno;
|
||||
#endif
|
||||
|
||||
static const char *bsdSocketName = "bsdsocket.library";
|
||||
static const char *openSocketLibraryError = "Cannot open %s %ld.0";
|
||||
static const char *openSocketResourceError = "Cannot open %s";
|
||||
struct Library *SocketBase = NULL;
|
||||
|
||||
#define BSDLIB_NAME ((STRPTR)bsdSocketName)
|
||||
#define BSDLIB_REV 03L
|
||||
|
||||
int OpenSocketLibrary(void)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
|
||||
if (SocketBase != NULL)
|
||||
{
|
||||
return LIB_OK;
|
||||
}
|
||||
|
||||
if (!(SocketBase = OpenLibrary((STRPTR)BSDLIB_NAME, BSDLIB_REV)))
|
||||
{
|
||||
SNPrintf(message, SETTINGMESSAGELEN, openSocketLibraryError, BSDLIB_NAME, BSDLIB_REV);
|
||||
SendErrorMessage(message);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
SNPrintf(message, SETTINGMESSAGELEN, "Opened %s", (char *)SocketBase->lib_IdString);
|
||||
SendTraceMessage(message);
|
||||
|
||||
if (SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (int)&errno,
|
||||
SBTM_SETVAL(SBTC_HERRNOLONGPTR), (int)&h_errno, TAG_DONE))
|
||||
{
|
||||
SNPrintf(message, SETTINGMESSAGELEN, openSocketResourceError, BSDLIB_NAME);
|
||||
SendErrorMessage(message);
|
||||
CloseLibrary(SocketBase);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
|
||||
return LIB_OK;
|
||||
}
|
||||
|
||||
void CloseSocketLibrary(void)
|
||||
{
|
||||
if (SocketBase != NULL)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
SNPrintf(message, SETTINGMESSAGELEN, "Closing %s", (char *)SocketBase->lib_IdString);
|
||||
SendTraceMessage(message);
|
||||
CloseLibrary(SocketBase);
|
||||
SocketBase = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char *GetErrorText(void)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case ENOTSOCK:
|
||||
return "Socket operation on non-socket";
|
||||
case EDESTADDRREQ:
|
||||
return "Destination address required";
|
||||
case EMSGSIZE:
|
||||
return "Message too long";
|
||||
case EPROTOTYPE:
|
||||
return "Protocol wrong type for socket";
|
||||
case ENOPROTOOPT:
|
||||
return "Protocol not available";
|
||||
case EPROTONOSUPPORT:
|
||||
return "Protocol not supported";
|
||||
case ESOCKTNOSUPPORT:
|
||||
return "Socket type not supported";
|
||||
case EOPNOTSUPP:
|
||||
return "Operation not supported";
|
||||
case EPFNOSUPPORT:
|
||||
return "Protocol family not supported";
|
||||
case EAFNOSUPPORT:
|
||||
return "Address family not supported by protocol family";
|
||||
case EADDRINUSE:
|
||||
return "Address already in use";
|
||||
case EADDRNOTAVAIL:
|
||||
return "Can't assign requested address";
|
||||
case ENETDOWN:
|
||||
return "Network is down";
|
||||
case ENETUNREACH:
|
||||
return "Network is unreachable";
|
||||
case ENETRESET:
|
||||
return "Network dropped connection on reset";
|
||||
case ECONNABORTED:
|
||||
return "Software caused connection abort";
|
||||
case ECONNRESET:
|
||||
return "Connection reset by peer";
|
||||
case ENOBUFS:
|
||||
return "No buffer space available";
|
||||
case EISCONN:
|
||||
return "Socket is already connected";
|
||||
case ENOTCONN:
|
||||
return "Socket is not connected";
|
||||
case ESHUTDOWN:
|
||||
return "Can't send after socket shutdown";
|
||||
case ETIMEDOUT:
|
||||
return "Operation timed out";
|
||||
case ECONNREFUSED:
|
||||
return "Connection refused";
|
||||
case EHOSTDOWN:
|
||||
return "Host is down";
|
||||
case EHOSTUNREACH:
|
||||
return "No route to host";
|
||||
default:
|
||||
return "Socket error";
|
||||
}
|
||||
}
|
||||
|
||||
const char *GetHostErrorText(void)
|
||||
{
|
||||
if (gai_h_errno != 0)
|
||||
{
|
||||
return gai_h_errno == EAI_SYSTEM
|
||||
? GetErrorText()
|
||||
: gai_strerror(gai_h_errno);
|
||||
}
|
||||
|
||||
switch (h_errno)
|
||||
{
|
||||
case EAI_BADFLAGS:
|
||||
return "Invalid value for ai_flags";
|
||||
case EAI_NONAME:
|
||||
return "Name or service is not known";
|
||||
case EAI_AGAIN:
|
||||
return "Temporary failure in name resolution";
|
||||
case EAI_FAIL:
|
||||
return "Non-recoverable failure in name resolution";
|
||||
case EAI_FAMILY:
|
||||
return "ai_family not supported";
|
||||
case EAI_SOCKTYPE:
|
||||
return "ai_socktype not supported";
|
||||
case EAI_SERVICE:
|
||||
return "Service not supported for ai_socktype";
|
||||
case EAI_ADDRFAMILY:
|
||||
return "Address family for name not supported";
|
||||
case EAI_MEMORY:
|
||||
return "Memory allocation failure";
|
||||
case EAI_SYSTEM:
|
||||
return GetErrorText();
|
||||
default:
|
||||
return "DNS error";
|
||||
}
|
||||
}
|
564
net_getaddrinfo.c
Normal file
564
net_getaddrinfo.c
Normal file
@ -0,0 +1,564 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 02 Motoyuki Kasahara
|
||||
* Copyright (c) 2017-2018 Carsten Sonne Larsen <cs@innolan.net>
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program provides getaddrinfo() and getnameinfo() described in
|
||||
* RFC2133, 2553 and 3493. These functions are mainly used for IPv6
|
||||
* application to resolve hostname or address.
|
||||
*
|
||||
* This program is designed to be working on traditional IPv4 systems
|
||||
* which don't have those functions. Therefore, this implementation
|
||||
* supports IPv4 only.
|
||||
*
|
||||
* This program is useful for application which should support both IPv6
|
||||
* and traditional IPv4 systems. Use genuine getaddrinfo() and getnameinfo()
|
||||
* provided by system if the system supports IPv6. Otherwise, use this
|
||||
* implementation.
|
||||
*
|
||||
* This program also provides freeaddrinfo() and gai_strerror().
|
||||
*
|
||||
* Restriction:
|
||||
* getaddrinfo() and getnameinfo() of this program are NOT thread
|
||||
* safe, unless the cpp macro ENABLE_THREAD is defined.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "net_getaddrinfo.h"
|
||||
#include "mem.h"
|
||||
|
||||
#define gettext(string) (string)
|
||||
#define _(string) (string)
|
||||
#define N_(string) (string)
|
||||
|
||||
extern int gai_h_errno;
|
||||
|
||||
#ifdef AOS3
|
||||
extern int h_errno;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Error messages for gai_strerror().
|
||||
*/
|
||||
static char *eai_errlist[] = {
|
||||
N_("Success"),
|
||||
|
||||
/* EAI_ADDRFAMILY */
|
||||
N_("Address family for hostname not supported"),
|
||||
|
||||
/* EAI_AGAIN */
|
||||
N_("Temporary failure in name resolution"),
|
||||
|
||||
/* EAI_BADFLAGS */
|
||||
N_("Invalid value for ai_flags"),
|
||||
|
||||
/* EAI_FAIL */
|
||||
N_("Non-recoverable failure in name resolution"),
|
||||
|
||||
/* EAI_FAMILY */
|
||||
N_("ai_family not supported"),
|
||||
|
||||
/* EAI_MEMORY */
|
||||
N_("Memory allocation failure"),
|
||||
|
||||
/* EAI_NONAME */
|
||||
N_("Hostname nor servname provided, or not known"),
|
||||
|
||||
/* EAI_OVERFLOW */
|
||||
N_("An argument buffer overflowed"),
|
||||
|
||||
/* EAI_SERVICE */
|
||||
N_("servname not supported for ai_socktype"),
|
||||
|
||||
/* EAI_SOCKTYPE */
|
||||
N_("ai_socktype not supported"),
|
||||
|
||||
/* EAI_SYSTEM */
|
||||
N_("System error returned in errno")};
|
||||
|
||||
/*
|
||||
* Default hints for getaddrinfo().
|
||||
*/
|
||||
static struct addrinfo default_hints = {
|
||||
0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL};
|
||||
|
||||
/*
|
||||
* Mutex.
|
||||
*/
|
||||
#ifdef ENABLE_THREAD
|
||||
struct SignalSemaphore getaddrinfoSemaphore;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* gai_strerror().
|
||||
*/
|
||||
#if defined(__CLIB2__)
|
||||
STRPTR gai_strerror(LONG ecode)
|
||||
#else
|
||||
const char *gai_strerror(int ecode)
|
||||
#endif
|
||||
{
|
||||
if (ecode < 0 || ecode > EAI_SYSTEM)
|
||||
return _("Unknown error");
|
||||
|
||||
return gettext(eai_errlist[ecode]);
|
||||
}
|
||||
|
||||
/*
|
||||
* freeaddrinfo().
|
||||
*/
|
||||
void freeaddrinfo(struct addrinfo *ai)
|
||||
{
|
||||
struct addrinfo *next_ai;
|
||||
|
||||
while (ai != NULL)
|
||||
{
|
||||
if (ai->ai_canonname != NULL)
|
||||
FreeMemSafe(ai->ai_canonname);
|
||||
if (ai->ai_addr != NULL)
|
||||
FreeMemSafe(ai->ai_addr);
|
||||
next_ai = ai->ai_next;
|
||||
FreeMemSafe(ai);
|
||||
ai = next_ai;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 1 if the string `s' represents an integer.
|
||||
*/
|
||||
static int is_integer(const char *s)
|
||||
{
|
||||
if (*s == '-' || *s == '+')
|
||||
s++;
|
||||
if (*s < '0' || '9' < *s)
|
||||
return 0;
|
||||
|
||||
s++;
|
||||
while ('0' <= *s && *s <= '9')
|
||||
s++;
|
||||
|
||||
return (*s == '\0');
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 1 if the string `s' represents an IPv4 address.
|
||||
* Unlike inet_addr(), it doesn't permit malformed nortation such
|
||||
* as "192.168".
|
||||
*/
|
||||
static int
|
||||
is_address(const char *s)
|
||||
{
|
||||
const static char delimiters[] = {'.', '.', '.', '\0'};
|
||||
int i, j;
|
||||
int octet;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (*s == '0' && *(s + 1) != delimiters[i])
|
||||
return 0;
|
||||
for (j = 0, octet = 0; '0' <= *s && *s <= '9' && j < 3; s++, j++)
|
||||
octet = octet * 10 + (*s - '0');
|
||||
if (j == 0 || octet > 255 || *s != delimiters[i])
|
||||
return 0;
|
||||
s++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* getaddrinfo().
|
||||
*/
|
||||
#if defined(__CLIB2__)
|
||||
LONG getaddrinfo(
|
||||
STRPTR nodename,
|
||||
STRPTR servname,
|
||||
struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
#else
|
||||
int getaddrinfo(
|
||||
const char *nodename,
|
||||
const char *servname,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
#endif
|
||||
{
|
||||
struct addrinfo *head_res = NULL;
|
||||
struct addrinfo *tail_res = NULL;
|
||||
struct addrinfo *new_res;
|
||||
struct sockaddr_in *sa_in;
|
||||
struct in_addr **addr_list;
|
||||
struct in_addr *addr_list_buf[2];
|
||||
struct in_addr addr_buf;
|
||||
struct in_addr **ap;
|
||||
struct servent *servent;
|
||||
struct hostent *hostent;
|
||||
const char *canonname = NULL;
|
||||
in_port_t port;
|
||||
LONG port_parse;
|
||||
int saved_h_errno;
|
||||
int result = 0;
|
||||
|
||||
#ifdef ENABLE_THREAD
|
||||
ObtainSemaphore(&getaddrinfoSemaphore);
|
||||
#endif
|
||||
|
||||
saved_h_errno = h_errno;
|
||||
|
||||
if (nodename == NULL && servname == NULL)
|
||||
{
|
||||
result = EAI_NONAME;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (hints != NULL)
|
||||
{
|
||||
if (hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC)
|
||||
{
|
||||
result = EAI_FAMILY;
|
||||
goto end;
|
||||
}
|
||||
if (hints->ai_socktype != SOCK_DGRAM && hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != 0)
|
||||
{
|
||||
result = EAI_SOCKTYPE;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hints = &default_hints;
|
||||
}
|
||||
|
||||
if (servname != NULL)
|
||||
{
|
||||
if (is_integer(servname))
|
||||
{
|
||||
StrToLong((STRPTR)servname, &port_parse);
|
||||
port = htons(port_parse);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hints->ai_flags & AI_NUMERICSERV)
|
||||
{
|
||||
result = EAI_NONAME;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (hints->ai_socktype == SOCK_DGRAM)
|
||||
servent = getservbyname((char *)servname, (char *)"udp");
|
||||
else if (hints->ai_socktype == SOCK_STREAM)
|
||||
servent = getservbyname((char *)servname, (char *)"tcp");
|
||||
else if (hints->ai_socktype == 0)
|
||||
servent = getservbyname((char *)servname, (char *)"tcp");
|
||||
else
|
||||
{
|
||||
result = EAI_SOCKTYPE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (servent == NULL)
|
||||
{
|
||||
result = EAI_SERVICE;
|
||||
goto end;
|
||||
}
|
||||
port = servent->s_port;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
port = htons(0);
|
||||
}
|
||||
|
||||
if (nodename != NULL)
|
||||
{
|
||||
if (is_address(nodename))
|
||||
{
|
||||
addr_buf.s_addr = inet_addr(nodename);
|
||||
addr_list_buf[0] = &addr_buf;
|
||||
addr_list_buf[1] = NULL;
|
||||
addr_list = addr_list_buf;
|
||||
|
||||
if (hints->ai_flags & AI_CANONNAME && !(hints->ai_flags & AI_NUMERICHOST))
|
||||
{
|
||||
hostent = gethostbyaddr((char *)&addr_buf,
|
||||
sizeof(struct in_addr), AF_INET);
|
||||
if (hostent != NULL)
|
||||
canonname = hostent->h_name;
|
||||
else
|
||||
canonname = nodename;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hints->ai_flags & AI_NUMERICHOST)
|
||||
{
|
||||
result = EAI_NONAME;
|
||||
goto end;
|
||||
}
|
||||
|
||||
hostent = gethostbyname(nodename);
|
||||
if (hostent == NULL)
|
||||
{
|
||||
switch (h_errno)
|
||||
{
|
||||
case HOST_NOT_FOUND:
|
||||
case NO_DATA:
|
||||
result = EAI_NONAME;
|
||||
goto end;
|
||||
case TRY_AGAIN:
|
||||
result = EAI_AGAIN;
|
||||
goto end;
|
||||
default:
|
||||
result = EAI_FAIL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
addr_list = (struct in_addr **)hostent->h_addr_list;
|
||||
|
||||
if (hints->ai_flags & AI_CANONNAME)
|
||||
canonname = hostent->h_name;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hints->ai_flags & AI_PASSIVE)
|
||||
addr_buf.s_addr = htonl(INADDR_ANY);
|
||||
else
|
||||
addr_buf.s_addr = htonl(0x7F000001);
|
||||
addr_list_buf[0] = &addr_buf;
|
||||
addr_list_buf[1] = NULL;
|
||||
addr_list = addr_list_buf;
|
||||
}
|
||||
|
||||
for (ap = addr_list; *ap != NULL; ap++)
|
||||
{
|
||||
new_res = (struct addrinfo *)AllocMemSafe(sizeof(struct addrinfo));
|
||||
if (new_res == NULL)
|
||||
{
|
||||
if (head_res != NULL)
|
||||
freeaddrinfo(head_res);
|
||||
result = EAI_MEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
new_res->ai_family = PF_INET;
|
||||
new_res->ai_socktype = hints->ai_socktype;
|
||||
new_res->ai_protocol = hints->ai_protocol;
|
||||
new_res->ai_addr = NULL;
|
||||
new_res->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
new_res->ai_canonname = NULL;
|
||||
new_res->ai_next = NULL;
|
||||
|
||||
new_res->ai_addr = (struct sockaddr *)
|
||||
AllocMemSafe(sizeof(struct sockaddr_in));
|
||||
if (new_res->ai_addr == NULL)
|
||||
{
|
||||
FreeMemSafe(new_res);
|
||||
if (head_res != NULL)
|
||||
freeaddrinfo(head_res);
|
||||
result = EAI_MEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
sa_in = (struct sockaddr_in *)new_res->ai_addr;
|
||||
memset(sa_in, 0, sizeof(struct sockaddr_in));
|
||||
sa_in->sin_family = PF_INET;
|
||||
sa_in->sin_port = port;
|
||||
memcpy(&sa_in->sin_addr, *ap, sizeof(struct in_addr));
|
||||
|
||||
if (head_res == NULL)
|
||||
head_res = new_res;
|
||||
else
|
||||
tail_res->ai_next = new_res;
|
||||
tail_res = new_res;
|
||||
}
|
||||
|
||||
if (canonname != NULL && head_res != NULL)
|
||||
{
|
||||
head_res->ai_canonname = (char *)AllocMemSafe(StrLen(canonname) + 1);
|
||||
if (head_res->ai_canonname != NULL)
|
||||
StrCopy(head_res->ai_canonname, canonname);
|
||||
}
|
||||
|
||||
*res = head_res;
|
||||
|
||||
end:
|
||||
h_errno = saved_h_errno;
|
||||
gai_h_errno = result;
|
||||
#ifdef ENABLE_THREAD
|
||||
ReleaseSemaphore(&getaddrinfoSemaphore);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Calcurate length of the string `s', where `s' is set by
|
||||
* sprintf(s, "%d", n).
|
||||
*/
|
||||
static int
|
||||
itoa_length(int n)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
result++;
|
||||
}
|
||||
|
||||
while (n >= 10)
|
||||
{
|
||||
result++;
|
||||
n /= 10;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(__CLIB2__)
|
||||
LONG getnameinfo(
|
||||
struct sockaddr *sa,
|
||||
ULONG salen,
|
||||
STRPTR node,
|
||||
ULONG nodelen,
|
||||
STRPTR serv,
|
||||
ULONG servlen,
|
||||
ULONG flags)
|
||||
#else
|
||||
int getnameinfo(
|
||||
const struct sockaddr *sa,
|
||||
socklen_t salen,
|
||||
char *node,
|
||||
socklen_t nodelen,
|
||||
char *serv,
|
||||
socklen_t servlen,
|
||||
int flags)
|
||||
#endif
|
||||
{
|
||||
const struct sockaddr_in *sa_in = (const struct sockaddr_in *)sa;
|
||||
struct hostent *hostent;
|
||||
struct servent *servent;
|
||||
char *ntoa_address;
|
||||
int saved_h_errno;
|
||||
int result = 0;
|
||||
|
||||
#ifdef ENABLE_PTHREAD
|
||||
pthread_mutex_lock(&gai_mutex);
|
||||
#endif
|
||||
|
||||
saved_h_errno = h_errno;
|
||||
|
||||
if (sa_in->sin_family != PF_INET)
|
||||
{
|
||||
result = EAI_FAMILY;
|
||||
goto end;
|
||||
}
|
||||
else if (node == NULL && serv == NULL)
|
||||
{
|
||||
result = EAI_NONAME;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (serv != NULL && servlen > 0)
|
||||
{
|
||||
if (flags & NI_NUMERICSERV)
|
||||
servent = NULL;
|
||||
else if (flags & NI_DGRAM)
|
||||
servent = getservbyport(sa_in->sin_port, "udp");
|
||||
else
|
||||
servent = getservbyport(sa_in->sin_port, "tcp");
|
||||
|
||||
if (servent != NULL)
|
||||
{
|
||||
if (servlen <= StrLen(servent->s_name))
|
||||
{
|
||||
result = EAI_OVERFLOW;
|
||||
goto end;
|
||||
}
|
||||
StrCopy(serv, servent->s_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (servlen <= itoa_length(ntohs(sa_in->sin_port)))
|
||||
{
|
||||
result = EAI_OVERFLOW;
|
||||
goto end;
|
||||
}
|
||||
LongToStr((long)ntohs(sa_in->sin_port), serv);
|
||||
}
|
||||
}
|
||||
|
||||
if (node != NULL && nodelen > 0)
|
||||
{
|
||||
if (flags & NI_NUMERICHOST)
|
||||
hostent = NULL;
|
||||
else
|
||||
{
|
||||
hostent = gethostbyaddr((char *)&sa_in->sin_addr,
|
||||
sizeof(struct in_addr), AF_INET);
|
||||
}
|
||||
if (hostent != NULL)
|
||||
{
|
||||
if (nodelen <= StrLen(hostent->h_name))
|
||||
{
|
||||
result = EAI_OVERFLOW;
|
||||
goto end;
|
||||
}
|
||||
StrCopy(node, hostent->h_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & NI_NAMEREQD)
|
||||
{
|
||||
result = EAI_NONAME;
|
||||
goto end;
|
||||
}
|
||||
#ifndef __libnix__
|
||||
ntoa_address = inet_ntoa(sa_in->sin_addr);
|
||||
#else
|
||||
ntoa_address = inet_ntoa((LONG)sa_in->sin_addr.s_addr);
|
||||
#endif
|
||||
if (nodelen <= StrLen(ntoa_address))
|
||||
{
|
||||
result = EAI_OVERFLOW;
|
||||
goto end;
|
||||
}
|
||||
StrCopy(node, ntoa_address);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
h_errno = saved_h_errno;
|
||||
gai_h_errno = result;
|
||||
#ifdef ENABLE_PTHREAD
|
||||
pthread_mutex_unlock(&gai_mutex);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
#endif
|
209
net_getaddrinfo.h
Normal file
209
net_getaddrinfo.h
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 02 Motoyuki Kasahara
|
||||
* Copyright (c) 2017-2018 Carsten Sonne Larsen <cs@innolan.net>
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
|
||||
*/
|
||||
|
||||
#ifndef GETADDRINFO_H_INCLUDED
|
||||
#define GETADDRINFO_H_INCLUDED
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/*
|
||||
* Undefine all the macros.
|
||||
* <netdb.h> might defines some of them.
|
||||
*/
|
||||
#ifdef EAI_ADDRFAMILY
|
||||
#undef EAI_ADDRFAMILY
|
||||
#endif
|
||||
#ifdef EAI_AGAIN
|
||||
#undef EAI_AGAIN
|
||||
#endif
|
||||
#ifdef EAI_BADFLAGS
|
||||
#undef EAI_BADFLAGS
|
||||
#endif
|
||||
#ifdef EAI_FAIL
|
||||
#undef EAI_FAIL
|
||||
#endif
|
||||
#ifdef EAI_FAMILY
|
||||
#undef EAI_FAMILY
|
||||
#endif
|
||||
#ifdef EAI_MEMORY
|
||||
#undef EAI_MEMORY
|
||||
#endif
|
||||
#ifdef EAI_NONAME
|
||||
#undef EAI_NONAME
|
||||
#endif
|
||||
#ifdef EAI_OVERFLOW
|
||||
#undef EAI_OVERFLOW
|
||||
#endif
|
||||
#ifdef EAI_SERVICE
|
||||
#undef EAI_SERVICE
|
||||
#endif
|
||||
#ifdef EAI_SOCKTYPE
|
||||
#undef EAI_SOCKTYPE
|
||||
#endif
|
||||
#ifdef EAI_SYSTEM
|
||||
#undef EAI_SYSTEM
|
||||
#endif
|
||||
|
||||
#ifdef AI_PASSIVE
|
||||
#undef AI_PASSIVE
|
||||
#endif
|
||||
#ifdef AI_CANONNAME
|
||||
#undef AI_CANONNAME
|
||||
#endif
|
||||
#ifdef AI_NUMERICHOST
|
||||
#undef AI_NUMERICHOST
|
||||
#endif
|
||||
#ifdef AI_NUMERICSERV
|
||||
#undef AI_NUMERICSERV
|
||||
#endif
|
||||
#ifdef AI_V4MAPPED
|
||||
#undef AI_V4MAPPED
|
||||
#endif
|
||||
#ifdef AI_ALL
|
||||
#undef AI_ALL
|
||||
#endif
|
||||
#ifdef AI_ADDRCONFIG
|
||||
#undef AI_ADDRCONFIG
|
||||
#endif
|
||||
#ifdef AI_DEFAULT
|
||||
#undef AI_DEFAULT
|
||||
#endif
|
||||
|
||||
#ifdef NI_NOFQDN
|
||||
#undef NI_NOFQDN
|
||||
#endif
|
||||
#ifdef NI_NUMERICHOST
|
||||
#undef NI_NUMERICHOST
|
||||
#endif
|
||||
#ifdef NI_NAMEREQD
|
||||
#undef NI_NAMEREQD
|
||||
#endif
|
||||
#ifdef NI_NUMERICSERV
|
||||
#undef NI_NUMERICSERV
|
||||
#endif
|
||||
#ifdef NI_NUMERICSCOPE
|
||||
#undef NI_NUMERICSCOPE
|
||||
#endif
|
||||
|
||||
#ifdef NI_DGRAM
|
||||
#undef NI_DGRAM
|
||||
#endif
|
||||
#ifdef NI_MAXHOST
|
||||
#undef NI_MAXHOST
|
||||
#endif
|
||||
#ifdef NI_MAXSERV
|
||||
#undef NI_MAXSERV
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Undefine Roadshow macros.
|
||||
*/
|
||||
#ifdef gai_strerror
|
||||
#undef gai_strerror
|
||||
#endif
|
||||
#ifdef freeaddrinfo
|
||||
#undef freeaddrinfo
|
||||
#endif
|
||||
#ifdef getaddrinfo
|
||||
#undef getaddrinfo
|
||||
#endif
|
||||
#ifdef getnameinfo
|
||||
#undef getnameinfo
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Error codes.
|
||||
*/
|
||||
#define EAI_ADDRFAMILY 1
|
||||
#define EAI_AGAIN 2
|
||||
#define EAI_BADFLAGS 3
|
||||
#define EAI_FAIL 4
|
||||
#define EAI_FAMILY 5
|
||||
#define EAI_MEMORY 6
|
||||
#define EAI_NONAME 7
|
||||
#define EAI_OVERFLOW 8
|
||||
#define EAI_SERVICE 9
|
||||
#define EAI_SOCKTYPE 10
|
||||
#define EAI_SYSTEM 11
|
||||
|
||||
/*
|
||||
* Flags for getaddrinfo().
|
||||
*/
|
||||
#define AI_ADDRCONFIG 0x0001
|
||||
#define AI_ALL 0x0002
|
||||
#define AI_CANONNAME 0x0004
|
||||
#define AI_NUMERICHOST 0x0008
|
||||
#define AI_NUMERICSERV 0x0010
|
||||
#define AI_PASSIVE 0x0020
|
||||
#define AI_V4MAPPED 0x0040
|
||||
#define AI_DEFAULT (AI_V4MAPPED | AI_ADDRCONFIG)
|
||||
|
||||
/*
|
||||
* Flags for getnameinfo().
|
||||
*/
|
||||
#define NI_DGRAM 0x0001
|
||||
#define NI_NAMEREQD 0x0002
|
||||
#define NI_NOFQDN 0x0004
|
||||
#define NI_NUMERICHOST 0x0008
|
||||
#define NI_NUMERICSCOPE 0x0010
|
||||
#define NI_NUMERICSERV 0x0020
|
||||
|
||||
/*
|
||||
* Maximum length of FQDN and service name for getnameinfo().
|
||||
*/
|
||||
#define NI_MAXHOST 1025
|
||||
#define NI_MAXSERV 32
|
||||
|
||||
/*
|
||||
* Address families and Protocol families.
|
||||
*/
|
||||
#ifndef AF_UNSPEC
|
||||
#define AF_UNSPEC AF_INET
|
||||
#endif
|
||||
#ifndef PF_UNSPEC
|
||||
#define PF_UNSPEC PF_INET
|
||||
#endif
|
||||
|
||||
#if defined(AROS)
|
||||
typedef uint16_t in_port_t;
|
||||
#endif
|
||||
|
||||
#if defined(__CLIB2__)
|
||||
STRPTR gai_strerror(LONG);
|
||||
LONG getaddrinfo(STRPTR, STRPTR, struct addrinfo *, struct addrinfo **);
|
||||
LONG getnameinfo(struct sockaddr *, ULONG, STRPTR, ULONG, STRPTR, ULONG, ULONG);
|
||||
#else
|
||||
const char *gai_strerror(int);
|
||||
int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **);
|
||||
int getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, int);
|
||||
#endif
|
||||
|
||||
void freeaddrinfo(struct addrinfo *);
|
||||
|
||||
#endif
|
82
net_poll.c
Normal file
82
net_poll.c
Normal file
@ -0,0 +1,82 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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"
|
||||
|
||||
#if !defined(HAVE_POLL)
|
||||
#if defined(__CLIB2__)
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
||||
{
|
||||
unsigned int i;
|
||||
int maxfds = -1, ret;
|
||||
fd_set readSet, writeSet, errorSet;
|
||||
struct timeval timeout_tv, *tvp = NULL;
|
||||
|
||||
if (timeout >= 0)
|
||||
{
|
||||
timeout_tv.tv_secs = (timeout / 1000);
|
||||
timeout_tv.tv_micro = (timeout % 1000) * 1000;
|
||||
tvp = &timeout_tv;
|
||||
}
|
||||
|
||||
FD_ZERO(&readSet);
|
||||
FD_ZERO(&writeSet);
|
||||
FD_ZERO(&errorSet);
|
||||
|
||||
for (i = 0; i < nfds; i++)
|
||||
{
|
||||
fds[i].revents = 0;
|
||||
|
||||
if (fds[i].events == 0)
|
||||
continue;
|
||||
|
||||
if (fds[i].fd > maxfds)
|
||||
maxfds = fds[i].fd;
|
||||
|
||||
if (fds[i].events & POLLIN)
|
||||
FD_SET(fds[i].fd, &readSet);
|
||||
}
|
||||
|
||||
ret = WaitSelect(maxfds + 1, &readSet, &writeSet, &errorSet, tvp, NULL);
|
||||
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < nfds; i++)
|
||||
{
|
||||
if (fds[i].events == 0)
|
||||
continue;
|
||||
|
||||
if (FD_ISSET(fds[i].fd, &readSet))
|
||||
fds[i].revents |= POLLIN;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
466
sntp.c
Normal file
466
sntp.c
Normal file
@ -0,0 +1,466 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 TANDBERG Telecom AS
|
||||
* Copyright (c) 2008-2009 Dag-Erling Smørgrav <des@des.no>
|
||||
* Copyright (c) 2017-2018 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 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 AUTHOR 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "time.h"
|
||||
#include "sntp.h"
|
||||
#include "mem.h"
|
||||
#include "net_getaddrinfo.h"
|
||||
#include "message.h"
|
||||
|
||||
/*
|
||||
* Convert a struct timeval to an NTP timestamp
|
||||
*/
|
||||
void tv2nt(struct timeval *tv, struct ntptime *nt)
|
||||
{
|
||||
uint64_t frac;
|
||||
|
||||
nt->sec = tv->tv_secs + UNIX_EPOCH;
|
||||
frac = tv->tv_micro;
|
||||
frac <<= 32;
|
||||
frac /= 1000 * 1000;
|
||||
nt->frac = frac;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an NTP timestamp to a struct timeval
|
||||
*/
|
||||
void nt2tv(struct ntptime *nt, struct timeval *tv)
|
||||
{
|
||||
uint64_t frac;
|
||||
|
||||
tv->tv_sec = nt->sec - UNIX_EPOCH;
|
||||
frac = nt->frac;
|
||||
frac *= 1000 * 1000;
|
||||
frac >>= 32;
|
||||
tv->tv_usec = frac;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert struct ntptime in-place from network to host order
|
||||
*/
|
||||
void n2h_ntp(struct ntptime *nt)
|
||||
{
|
||||
nt->sec = ntohl(nt->sec);
|
||||
nt->frac = ntohl(nt->frac);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert struct ntptime in-place from host to network order
|
||||
*/
|
||||
void h2n_ntp(struct ntptime *nt)
|
||||
{
|
||||
nt->sec = htonl(nt->sec);
|
||||
nt->frac = htonl(nt->frac);
|
||||
}
|
||||
|
||||
/*
|
||||
* SNTP client state
|
||||
*/
|
||||
struct sntp
|
||||
{
|
||||
/* parameters from sntp_create() */
|
||||
char *srcaddr;
|
||||
char *srcport;
|
||||
char *dstaddr;
|
||||
char *dstport;
|
||||
|
||||
/* DNS data */
|
||||
int family;
|
||||
int socktype;
|
||||
int protocol;
|
||||
struct sockaddr *laddr;
|
||||
socklen_t laddrlen;
|
||||
struct sockaddr *raddr;
|
||||
socklen_t raddrlen;
|
||||
|
||||
/* socket and poll structure */
|
||||
int sd;
|
||||
struct pollfd pfd;
|
||||
|
||||
/* protocol state */
|
||||
struct ntptime last_send;
|
||||
struct ntptime last_recv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize an SNTP client context
|
||||
*
|
||||
* Multiple contexts can coexist as long as they do not use the same
|
||||
* source port.
|
||||
*
|
||||
* NOTICE: Consider adding support for binding to a specific source address.
|
||||
*/
|
||||
struct sntp *
|
||||
sntp_create(const char *dstaddr, const char *dstport,
|
||||
const char *srcaddr, const char *srcport)
|
||||
{
|
||||
struct sntp *sntp;
|
||||
sntp = AllocMemSafe(sizeof(struct sntp));
|
||||
sntp->sd = -1;
|
||||
|
||||
sntp->srcaddr = srcaddr ? StrDupSafe(srcaddr) : NULL;
|
||||
sntp->srcport = StrDupSafe(srcport ? srcport : "123");
|
||||
sntp->dstaddr = StrDupSafe(dstaddr);
|
||||
sntp->dstport = StrDupSafe(dstport ? dstport : "123");
|
||||
|
||||
/* good to go */
|
||||
return (sntp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up local and remote addresses and set up the socket
|
||||
*/
|
||||
int sntp_open(struct sntp *sntp)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *aiv, *ai;
|
||||
int ret;
|
||||
|
||||
if (sntp->sd != -1)
|
||||
return (SNTP_OK);
|
||||
|
||||
/* resolve the server address */
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
if ((ret = getaddrinfo(sntp->dstaddr, sntp->dstport, &hints, &aiv)) != 0)
|
||||
return (SNTP_DNSERR);
|
||||
|
||||
/* Something went wrong */
|
||||
if (aiv == NULL)
|
||||
return (SNTP_SYSERR);
|
||||
|
||||
/*
|
||||
* Iterate over the results until we find one we can use. This is
|
||||
* sometimes necessary on systems with partial IPv6 support, where
|
||||
* the resolver may return IPv6 addresses which the network stack
|
||||
* can't handle.
|
||||
*/
|
||||
for (ai = aiv; ai; ai = ai->ai_next)
|
||||
{
|
||||
sntp->sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (sntp->sd >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (sntp->sd == -1)
|
||||
{
|
||||
SendWarningMessage("Could not get socket descriptor");
|
||||
freeaddrinfo(aiv);
|
||||
return (SNTP_SYSERR);
|
||||
}
|
||||
|
||||
sntp->raddr = MemDupSafe(ai->ai_addr, ai->ai_addrlen);
|
||||
sntp->raddrlen = ai->ai_addrlen;
|
||||
sntp->family = ai->ai_family;
|
||||
sntp->socktype = ai->ai_socktype;
|
||||
sntp->protocol = ai->ai_protocol;
|
||||
freeaddrinfo(aiv);
|
||||
|
||||
/* get a matching local address */
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = sntp->family;
|
||||
hints.ai_socktype = sntp->socktype;
|
||||
hints.ai_protocol = sntp->protocol;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
if ((ret = getaddrinfo(sntp->srcaddr, sntp->srcport, &hints, &aiv)) != 0)
|
||||
{
|
||||
sntp_close(sntp);
|
||||
return (SNTP_DNSERR);
|
||||
}
|
||||
|
||||
/* Something went wrong */
|
||||
if (aiv == NULL)
|
||||
return (SNTP_SYSERR);
|
||||
|
||||
/* NOTICE: Consider asserting that results match expectations */
|
||||
sntp->laddr = MemDupSafe(aiv->ai_addr, aiv->ai_addrlen);
|
||||
sntp->laddrlen = aiv->ai_addrlen;
|
||||
freeaddrinfo(aiv);
|
||||
|
||||
/* prepare our socket */
|
||||
/* NOTICE: Sometimes AmigaOS do not like bindings. Just leave it for now.
|
||||
if (bind(sntp->sd, sntp->laddr, sntp->laddrlen) != 0) {
|
||||
LogError("Could not bind socket");
|
||||
sntp_close(sntp);
|
||||
return (SNTP_SYSERR);
|
||||
}
|
||||
*/
|
||||
|
||||
if (connect(sntp->sd, sntp->raddr, sntp->raddrlen) != 0)
|
||||
{
|
||||
SendWarningMessage("Could not connect socket");
|
||||
sntp_close(sntp);
|
||||
return (SNTP_SYSERR);
|
||||
}
|
||||
|
||||
/* prepare our pollfd */
|
||||
sntp->pfd.fd = sntp->sd;
|
||||
sntp->pfd.events = POLLIN;
|
||||
sntp->pfd.revents = 0;
|
||||
|
||||
return (SNTP_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy an SNTP client context
|
||||
*
|
||||
* This is called several times during error handling in other parts of
|
||||
* the code, so we should save and restore errno
|
||||
*/
|
||||
void sntp_close(struct sntp *sntp)
|
||||
{
|
||||
int serrno;
|
||||
|
||||
serrno = errno;
|
||||
|
||||
sntp->family = 0;
|
||||
sntp->socktype = 0;
|
||||
sntp->protocol = 0;
|
||||
|
||||
if (sntp->laddr)
|
||||
FreeMemSafe(sntp->laddr);
|
||||
sntp->laddrlen = 0;
|
||||
|
||||
if (sntp->raddr)
|
||||
FreeMemSafe(sntp->raddr);
|
||||
sntp->raddrlen = 0;
|
||||
|
||||
if (sntp->sd != -1)
|
||||
CloseSocket(sntp->sd);
|
||||
memset(&sntp->pfd, 0, sizeof sntp->pfd);
|
||||
|
||||
nt_zero(sntp->last_send);
|
||||
nt_zero(sntp->last_recv);
|
||||
|
||||
errno = serrno;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy an SNTP client context
|
||||
*/
|
||||
void sntp_destroy(struct sntp *sntp)
|
||||
{
|
||||
(void)sntp_close(sntp);
|
||||
|
||||
if (sntp->srcaddr)
|
||||
FreeMemSafe(sntp->srcaddr);
|
||||
sntp->srcaddr = 0;
|
||||
|
||||
if (sntp->srcport)
|
||||
FreeMemSafe(sntp->srcport);
|
||||
sntp->srcport = 0;
|
||||
|
||||
if (sntp->dstaddr)
|
||||
FreeMemSafe(sntp->dstaddr);
|
||||
sntp->dstaddr = 0;
|
||||
|
||||
if (sntp->dstport)
|
||||
FreeMemSafe(sntp->dstport);
|
||||
sntp->dstport = 0;
|
||||
|
||||
FreeMemSafe(sntp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure of an NTP message without authenticator
|
||||
*/
|
||||
struct ntp_msg
|
||||
{
|
||||
uint8_t flags;
|
||||
uint8_t stratum;
|
||||
uint8_t poll;
|
||||
uint8_t precision;
|
||||
uint32_t root_delay;
|
||||
uint32_t root_dispersion;
|
||||
uint8_t reference_id[4];
|
||||
struct ntptime reference;
|
||||
struct ntptime originate;
|
||||
struct ntptime receive;
|
||||
struct ntptime transmit;
|
||||
};
|
||||
|
||||
/*
|
||||
* Send an SNTP request
|
||||
*/
|
||||
sntp_err_t
|
||||
sntp_send(struct sntp *sntp)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct ntp_msg msg;
|
||||
ssize_t ret;
|
||||
sntp_err_t se;
|
||||
|
||||
if ((se = sntp_open(sntp)) != SNTP_OK)
|
||||
return (se);
|
||||
|
||||
memset(&msg, 0, sizeof msg);
|
||||
msg.flags = 0x23; /* version 4, client */
|
||||
|
||||
GetTimeOfDay(&tv);
|
||||
tv2nt(&tv, &msg.transmit);
|
||||
|
||||
h2n_ntp(&msg.transmit);
|
||||
ret = send(sntp->sd, (void *)&msg, sizeof(struct ntp_msg), 0);
|
||||
|
||||
if (ret < 0)
|
||||
return (SNTP_SYSERR);
|
||||
|
||||
tv2nt(&tv, &sntp->last_send);
|
||||
|
||||
return (SNTP_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Have we sent a request to which we're still expecting a response?
|
||||
*/
|
||||
sntp_err_t
|
||||
sntp_pending(struct sntp *sntp)
|
||||
{
|
||||
|
||||
/* not currently open */
|
||||
if (sntp->sd == -1)
|
||||
return (SNTP_NOREQ);
|
||||
|
||||
/* last request predates last response */
|
||||
if (nt_lt(sntp->last_send, sntp->last_recv))
|
||||
return (SNTP_NOREQ);
|
||||
|
||||
return (SNTP_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Poll for the arrival of an SNTP reply
|
||||
*/
|
||||
sntp_err_t
|
||||
sntp_poll(struct sntp *sntp, int timeout)
|
||||
{
|
||||
sntp_err_t se;
|
||||
|
||||
if ((se = sntp_pending(sntp)) != SNTP_OK)
|
||||
return (se);
|
||||
|
||||
switch (poll(&sntp->pfd, 1, timeout))
|
||||
{
|
||||
case -1:
|
||||
sntp_close(sntp);
|
||||
return (SNTP_SYSERR);
|
||||
case 0:
|
||||
return (SNTP_NORESP);
|
||||
case 1:
|
||||
return (SNTP_OK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive and process an SNTP reply
|
||||
*/
|
||||
sntp_err_t
|
||||
sntp_recv(struct sntp *sntp, struct ntptime *nt)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct ntp_msg msg;
|
||||
sntp_err_t se;
|
||||
int res;
|
||||
|
||||
if ((se = sntp_pending(sntp)) != SNTP_OK)
|
||||
return (se);
|
||||
|
||||
/* NOTICE: Consider using recvmsg() instead */
|
||||
res = recv(sntp->sd, (void *)&msg, sizeof(struct ntp_msg), MSG_DONTWAIT);
|
||||
switch (res)
|
||||
{
|
||||
case -1:
|
||||
if (errno == EAGAIN)
|
||||
return (SNTP_NORESP);
|
||||
sntp_close(sntp);
|
||||
return (SNTP_SYSERR);
|
||||
case 0:
|
||||
/* can this actually occur? */
|
||||
return (SNTP_NORESP);
|
||||
case sizeof msg:
|
||||
/* good! */
|
||||
break;
|
||||
default:
|
||||
/* we got something, but bob knows what */
|
||||
return (SNTP_BADRESP);
|
||||
}
|
||||
|
||||
/* record time of arrival */
|
||||
GetTimeOfDay(&tv);
|
||||
|
||||
/* convert to host order */
|
||||
n2h_ntp(&msg.originate);
|
||||
n2h_ntp(&msg.receive);
|
||||
n2h_ntp(&msg.transmit);
|
||||
|
||||
/* look for kiss packet */
|
||||
if (msg.flags == 0xe4 && msg.stratum == 0)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"KoD: %.4s", msg.reference_id);
|
||||
SendWarningMessage(message);
|
||||
/* NOTICE: Consider taking a closer look at the kiss code */
|
||||
return (SNTP_BACKOFF);
|
||||
}
|
||||
|
||||
/* check validity: synchronized NTPv4 server */
|
||||
switch (msg.flags)
|
||||
{
|
||||
case 0x23: /* version 4 client */
|
||||
/* we're probably accidentally querying ourselves */
|
||||
return (SNTP_BADRESP);
|
||||
|
||||
case 0x24: /* no warning, version 4, server */
|
||||
case 0x64: /* subtract leap second, version 4, server */
|
||||
case 0xa4: /* add leap second, version 4, server */
|
||||
/* these are the normal, useful cases */
|
||||
break;
|
||||
|
||||
case 0xe4: /* unsynchronized, version 4, server */
|
||||
/* server not usable (yet?) */
|
||||
return (SNTP_LAME);
|
||||
|
||||
default:
|
||||
return (SNTP_BADRESP);
|
||||
}
|
||||
|
||||
/* check if this is the response we were expecting */
|
||||
if (!nt_eq(msg.originate, sntp->last_send))
|
||||
/* probably delayed response to old request */
|
||||
return (SNTP_NORESP);
|
||||
|
||||
tv2nt(&tv, &sntp->last_recv);
|
||||
*nt = msg.transmit;
|
||||
return (SNTP_OK);
|
||||
}
|
105
sntp.h
Normal file
105
sntp.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 TANDBERG Telecom AS
|
||||
* Copyright (c) 2008-2009 Dag-Erling Smørgrav <des@des.no>
|
||||
* Copyright (c) 2017-2018 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 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 AUTHOR 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SNTP_H_INCLUDED
|
||||
#define SNTP_H_INCLUDED
|
||||
|
||||
#include "config.h"
|
||||
|
||||
struct sntp;
|
||||
|
||||
/*
|
||||
* Structure of an NTP timestamp
|
||||
*/
|
||||
struct ntptime
|
||||
{
|
||||
uint32_t sec;
|
||||
uint32_t frac;
|
||||
};
|
||||
|
||||
/*
|
||||
* Useful epochs, in seconds since NTP epoch
|
||||
*/
|
||||
#define UNIX_EPOCH 2208988800UL /* 1970-01-01 00:00:00 UTC */
|
||||
#define UTC_EPOCH 2272060800UL /* 1972-01-01 00:00:00 UTC */
|
||||
|
||||
/* clear a struct ntptime */
|
||||
#define nt_zero(nt) \
|
||||
(void)((nt).sec = (nt).frac = 0)
|
||||
|
||||
/* comparison macros */
|
||||
#define nt_cmp(nt1, op, nt2) \
|
||||
((nt1).sec op(nt2).sec && (nt1).frac op(nt2).frac)
|
||||
#define nt_lt(nt1, nt2) \
|
||||
nt_cmp(nt1, <, nt2)
|
||||
#define nt_le(nt1, nt2) \
|
||||
nt_cmp(nt1, <=, nt2)
|
||||
#define nt_eq(nt1, nt2) \
|
||||
nt_cmp(nt1, ==, nt2)
|
||||
#define nt_ge(nt1, nt2) \
|
||||
nt_cmp(nt1, >=, nt2)
|
||||
#define nt_gt(nt1, nt2) \
|
||||
nt_cmp(nt1, >, nt2)
|
||||
|
||||
/*
|
||||
* Conversion functions
|
||||
*/
|
||||
void tv2nt(struct timeval *, struct ntptime *);
|
||||
void nt2tv(struct ntptime *, struct timeval *);
|
||||
void h2n_nt(struct ntptime *);
|
||||
void n2h_nt(struct ntptime *);
|
||||
|
||||
/*
|
||||
* Error codes
|
||||
*/
|
||||
typedef enum sntp_err
|
||||
{
|
||||
SNTP_OK, /* fine */
|
||||
SNTP_SYSERR, /* check errno */
|
||||
SNTP_DNSERR, /* dns error */
|
||||
SNTP_NOREQ, /* no request sent */
|
||||
SNTP_NORESP, /* no response received */
|
||||
SNTP_BADRESP, /* invalid response received */
|
||||
SNTP_LAME, /* server is lame / unsynchronized */
|
||||
SNTP_BACKOFF, /* polling too frequently */
|
||||
} sntp_err_t;
|
||||
|
||||
/*
|
||||
* SNTP client
|
||||
*/
|
||||
struct sntp *sntp_create(const char *, const char *, const char *, const char *);
|
||||
int sntp_open(struct sntp *);
|
||||
void sntp_close(struct sntp *);
|
||||
void sntp_destroy(struct sntp *);
|
||||
sntp_err_t sntp_send(struct sntp *);
|
||||
sntp_err_t sntp_pending(struct sntp *);
|
||||
sntp_err_t sntp_poll(struct sntp *, int);
|
||||
sntp_err_t sntp_recv(struct sntp *, struct ntptime *);
|
||||
|
||||
#endif
|
880
state.c
Normal file
880
state.c
Normal file
@ -0,0 +1,880 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "state.h"
|
||||
#include "mem.h"
|
||||
|
||||
struct AppState *Globals;
|
||||
struct AppSettingKeys *SettingKeys;
|
||||
|
||||
static const struct AppSettingKeys SettingKeyStruct = {
|
||||
.DestinationAddress = KEYWORD_SERVER,
|
||||
.DestinationPort = KEYWORD_PORT,
|
||||
.Threshold = KEYWORD_THRESHOLD,
|
||||
.Interval = KEYWORD_INTERVAL,
|
||||
.Priority = KEYWORD_PRIORITY,
|
||||
.Readonly = KEYWORD_READONLY,
|
||||
.Timeout = KEYWORD_TIMEOUT,
|
||||
.Verbose = KEYWORD_VERBOSE,
|
||||
.LogFile = KEYWORD_LOGFILE};
|
||||
|
||||
const struct AppSettings DefaultSettings = {
|
||||
.Type = DefaultSettingType,
|
||||
.DestinationAddress = (char *)SERVER_DEF,
|
||||
.DestinationPort = (char *)PORT_DEF,
|
||||
.Timeout = TIMEOUT_DEF,
|
||||
.Interval = INTERVAL_DEF,
|
||||
.Verbose = VERBOSE_DEF,
|
||||
.Readonly = READONLY_DEF,
|
||||
.Priority = PRIORITY_DEF,
|
||||
.Threshold = THRESHOLD_DEF,
|
||||
.LogFile = (char *)LOGFILE_DEF,
|
||||
.Values = 0xFFFF};
|
||||
|
||||
static void SetPrioritySetting(struct AppSettings *, void *);
|
||||
static void SetIntervalSetting(struct AppSettings *, void *);
|
||||
static void SetVerboseSetting(struct AppSettings *, void *);
|
||||
static void SetTimeoutSetting(struct AppSettings *, void *);
|
||||
static void SetThresholdSetting(struct AppSettings *, void *);
|
||||
static void SetDestinationAddressSetting(struct AppSettings *, void *);
|
||||
static void SetDestinationPortSetting(struct AppSettings *, void *);
|
||||
static void SetReadOnlySetting(struct AppSettings *, void *);
|
||||
static void SetLogFileSetting(struct AppSettings *, void *);
|
||||
|
||||
// Keyword order in settingFunctions needs to match order in keyword template
|
||||
const struct SettingFunc settingFunctions[] = {
|
||||
{KEYWORD_READONLY, SetReadOnlySetting},
|
||||
{KEYWORD_SERVER, SetDestinationAddressSetting},
|
||||
{KEYWORD_PORT, SetDestinationPortSetting},
|
||||
{KEYWORD_TIMEOUT, SetTimeoutSetting},
|
||||
{KEYWORD_THRESHOLD, SetThresholdSetting},
|
||||
{KEYWORD_INTERVAL, SetIntervalSetting},
|
||||
{KEYWORD_VERBOSE, SetVerboseSetting},
|
||||
{KEYWORD_PRIORITY, SetPrioritySetting},
|
||||
{KEYWORD_LOGFILE, SetLogFileSetting}};
|
||||
|
||||
static const char *prefsFile = "ENV:timekeeper.prefs";
|
||||
static const char *persistentPrefsFile = "ENVARC:timekeeper.prefs";
|
||||
static const char *prefsFileSearch = "Searching for preference in %s";
|
||||
static const char *prefsFileFound = "Found preference file";
|
||||
static const char *prefsFileNotFound = "Preference file not found";
|
||||
static const char *prefsFileSave = "Saving preferences in %s";
|
||||
static const char *fileOpenError = "Could not open preference file";
|
||||
static const char *fileSaveError = "Could not save preference file";
|
||||
static const char *fileReadError = "Error while reading file";
|
||||
static const char *fileWriteError = "Error while writing file";
|
||||
static const char *unknownSetting = "Found unknown setting in preference file: %s";
|
||||
static const char *foundSetting = "Found %s in preference file";
|
||||
static const char *foundWbSetting = "Found tooltype from icon: %s";
|
||||
static const char *foundCliSetting = "Got %s from CLI";
|
||||
static const char *integerError = "Value should be an integer: %s";
|
||||
static const char *applyDefaultSettings = "Applying default values";
|
||||
static const char *applyFileSettings = "Applying values from preference file";
|
||||
static const char *applyCliSettings = "Applying values from CLI";
|
||||
static const char *applyWbSettings = "Applying values from tooltypes";
|
||||
static const char *effectiveSettings = "Listing runtime values";
|
||||
static const char *noLogFile = "(none)";
|
||||
static const char *settingTooLow = "%s < %ld (too low)";
|
||||
static const char *settingTooHigh = "%s > %ld (too high)";
|
||||
static const char *settingGreaterThan = "%s > %s";
|
||||
static const char *settingChangedLong = "%s changed: %ld -> %ld";
|
||||
static const char *settingChangedString = "%s changed: %s -> %s";
|
||||
static const char *settingSetLong = "%s already set to %ld";
|
||||
static const char *settingSetString = "%s already set to %s";
|
||||
static const char *settingValueLong = "%s=%ld";
|
||||
static const char *settingValueString = "%s=%s";
|
||||
static const char *saveValueLong = "%s=%ld\n";
|
||||
static const char *saveValueString = "%s=%s\n";
|
||||
|
||||
#define MAXSETTINGLINELEN 256
|
||||
|
||||
static struct AppSettings *fileSettings;
|
||||
static struct AppSettings *cachedSettings;
|
||||
|
||||
void InitState(void)
|
||||
{
|
||||
Globals = (struct AppState *)AllocMemSafe(sizeof(struct AppState));
|
||||
Globals->Broker = (struct AppBroker *)AllocMemSafe(sizeof(struct AppBroker));
|
||||
Globals->Window = (struct AppSettingWindow *)AllocMemSafe(sizeof(struct AppSettingWindow));
|
||||
Globals->Settings = CreateSettings(GlobalSettingType);
|
||||
Globals->Locale = OpenLocale(NULL);
|
||||
SettingKeys = (struct AppSettingKeys *)&SettingKeyStruct;
|
||||
}
|
||||
|
||||
void DestroyState(void)
|
||||
{
|
||||
if (Globals->Syncer != NULL)
|
||||
{
|
||||
FreeMemSafe(Globals->Syncer);
|
||||
Globals->Syncer = NULL;
|
||||
}
|
||||
|
||||
FreeSettings(Globals->Settings);
|
||||
CloseLocale(Globals->Locale);
|
||||
FreeMemSafe((void *)Globals->Window);
|
||||
FreeMemSafe((void *)Globals->Broker);
|
||||
FreeMemSafe((void *)Globals);
|
||||
}
|
||||
|
||||
void ShowAppSettings(struct AppSettings *settings)
|
||||
{
|
||||
char low[MAXLONGLONGCHARSIZE];
|
||||
|
||||
LongLongToStr(settings->Threshold, low);
|
||||
LogTrace(settingValueLong, SettingKeys->Priority, settings->Priority);
|
||||
LogTrace(settingValueString, SettingKeys->Threshold, low);
|
||||
LogTrace(settingValueString, SettingKeys->DestinationAddress, settings->DestinationAddress);
|
||||
LogTrace(settingValueString, SettingKeys->DestinationPort, settings->DestinationPort);
|
||||
LogTrace(settingValueLong, SettingKeys->Timeout, settings->Timeout);
|
||||
LogTrace(settingValueLong, SettingKeys->Interval, settings->Interval);
|
||||
LogTrace(settingValueLong, SettingKeys->Verbose, settings->Verbose);
|
||||
LogTrace(settingValueLong, SettingKeys->Readonly, settings->Readonly);
|
||||
LogTrace(settingValueString, SettingKeys->LogFile,
|
||||
settings->LogFile ? settings->LogFile : noLogFile);
|
||||
}
|
||||
|
||||
void ShowSettings(void)
|
||||
{
|
||||
LogTrace(effectiveSettings);
|
||||
ShowAppSettings(Globals->Settings);
|
||||
}
|
||||
|
||||
void LogFoundSetting(long type, const char *name)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FileSettingType:
|
||||
LogTrace(foundSetting, name);
|
||||
break;
|
||||
case CliSettingType:
|
||||
LogTrace(foundCliSetting, name);
|
||||
break;
|
||||
case WbSettingType:
|
||||
LogTrace(foundWbSetting, name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void SetPrioritySetting(struct AppSettings *setting, void *value)
|
||||
{
|
||||
LogFoundSetting(setting->Type, SettingKeys->Priority);
|
||||
if (setting->Type == CliSettingType)
|
||||
{
|
||||
setting->Priority = *(long *)value;
|
||||
setting->Values |= PrioritySet;
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryParseLong((char *)value, &setting->Priority))
|
||||
{
|
||||
setting->Values |= PrioritySet;
|
||||
return;
|
||||
}
|
||||
|
||||
LogWarning(integerError, value);
|
||||
}
|
||||
|
||||
static void SetVerboseSetting(struct AppSettings *setting, void *value)
|
||||
{
|
||||
LogFoundSetting(setting->Type, SettingKeys->Verbose);
|
||||
if (setting->Type == CliSettingType)
|
||||
{
|
||||
setting->Verbose = *(long *)value;
|
||||
setting->Values |= VerboseSet;
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryParseLong((char *)value, &setting->Verbose))
|
||||
{
|
||||
setting->Values |= VerboseSet;
|
||||
return;
|
||||
}
|
||||
|
||||
LogWarning(integerError, value);
|
||||
}
|
||||
|
||||
static void SetIntervalSetting(struct AppSettings *setting, void *value)
|
||||
{
|
||||
LogFoundSetting(setting->Type, SettingKeys->Interval);
|
||||
if (setting->Type == CliSettingType)
|
||||
{
|
||||
setting->Interval = *(long *)value;
|
||||
setting->Values |= IntervalSet;
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryParseLong((char *)value, &setting->Interval))
|
||||
{
|
||||
setting->Values |= IntervalSet;
|
||||
return;
|
||||
}
|
||||
|
||||
LogWarning(integerError, value);
|
||||
}
|
||||
|
||||
static void SetTimeoutSetting(struct AppSettings *setting, void *value)
|
||||
{
|
||||
LogFoundSetting(setting->Type, SettingKeys->Timeout);
|
||||
if (setting->Type == CliSettingType)
|
||||
{
|
||||
setting->Timeout = *(long *)value;
|
||||
setting->Values |= TimeoutSet;
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryParseLong((char *)value, &setting->Timeout))
|
||||
{
|
||||
setting->Values |= TimeoutSet;
|
||||
return;
|
||||
}
|
||||
|
||||
LogWarning(integerError, value);
|
||||
}
|
||||
|
||||
static void SetThresholdSetting(struct AppSettings *setting, void *value)
|
||||
{
|
||||
LogFoundSetting(setting->Type, SettingKeys->Threshold);
|
||||
if (TryParseLongLong((char *)value, &setting->Threshold))
|
||||
{
|
||||
setting->Values |= ThresholdSet;
|
||||
return;
|
||||
}
|
||||
|
||||
LogWarning(integerError, value);
|
||||
}
|
||||
|
||||
static void SetDestinationAddressSetting(struct AppSettings *setting, void *value)
|
||||
{
|
||||
LogFoundSetting(setting->Type, SettingKeys->DestinationAddress);
|
||||
setting->DestinationAddress = StrDupSafe((const char *)value);
|
||||
setting->Values |= DestinationAddressSet;
|
||||
}
|
||||
|
||||
static void SetDestinationPortSetting(struct AppSettings *setting, void *value)
|
||||
{
|
||||
LogFoundSetting(setting->Type, SettingKeys->DestinationPort);
|
||||
setting->DestinationPort = StrDupSafe((const char *)value);
|
||||
setting->Values |= DestinationPortSet;
|
||||
}
|
||||
|
||||
static void SetReadOnlySetting(struct AppSettings *setting, void *value)
|
||||
{
|
||||
LogFoundSetting(setting->Type, SettingKeys->Readonly);
|
||||
if (setting->Type == CliSettingType)
|
||||
{
|
||||
setting->Readonly = value != 0 ? true : false;
|
||||
setting->Values |= ReadonlySet;
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryParseLong((char *)value, &setting->Readonly))
|
||||
{
|
||||
setting->Readonly = setting->Readonly != 0 ? true : false;
|
||||
setting->Values |= ReadonlySet;
|
||||
return;
|
||||
}
|
||||
|
||||
LogWarning(integerError, value);
|
||||
}
|
||||
|
||||
static void SetLogFileSetting(struct AppSettings *setting, void *value)
|
||||
{
|
||||
static const char *no = "no";
|
||||
LogFoundSetting(setting->Type, SettingKeys->LogFile);
|
||||
|
||||
if (value == NULL || *((const char *)value) == '\0' ||
|
||||
Stricmp((STRPTR)no, (STRPTR)value) == 0 ||
|
||||
Stricmp((STRPTR)noLogFile, (STRPTR)value) == 0)
|
||||
{
|
||||
setting->LogFile = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
setting->LogFile = StrDupSafe((const char *)value);
|
||||
}
|
||||
setting->Values |= LogFileSet;
|
||||
}
|
||||
|
||||
static void ParseSetting(struct AppSettings *settings, char *line)
|
||||
{
|
||||
char *value;
|
||||
char *end;
|
||||
int i;
|
||||
|
||||
value = StrChr(line, '=', MAXSETTINGLINELEN);
|
||||
if (value == NULL)
|
||||
{
|
||||
LogWarning(unknownSetting, "No assignment");
|
||||
return;
|
||||
}
|
||||
|
||||
end = StrChr(value, '\n', MAXSETTINGLINELEN);
|
||||
if (end == NULL)
|
||||
{
|
||||
LogWarning(unknownSetting, "No end of line");
|
||||
return;
|
||||
}
|
||||
|
||||
*value++ = '\0';
|
||||
*end = '\0';
|
||||
|
||||
for (i = 0; i < KEYWORD_COUNT; i++)
|
||||
{
|
||||
if (Stricmp((STRPTR)settingFunctions[i].Name, (STRPTR)line) == 0)
|
||||
{
|
||||
settingFunctions[i].Function(settings, (void *)value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LogWarning(unknownSetting, line);
|
||||
}
|
||||
|
||||
void LoadSettings(void)
|
||||
{
|
||||
struct AppSettings *settings;
|
||||
const int maxLines = 25;
|
||||
char line[MAXSETTINGLINELEN];
|
||||
char message[MAXDOSERRORLEN];
|
||||
bool eof = false;
|
||||
int count = 0;
|
||||
long error;
|
||||
BPTR file;
|
||||
|
||||
LogTrace(prefsFileSearch, prefsFile);
|
||||
file = Open((STRPTR)prefsFile, MODE_OLDFILE);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
error = IoErr();
|
||||
if (error == ERROR_OBJECT_NOT_FOUND)
|
||||
{
|
||||
LogWarning(prefsFileNotFound);
|
||||
}
|
||||
else
|
||||
{
|
||||
Fault(error, (STRPTR)fileOpenError, (STRPTR)message, MAXDOSERRORLEN);
|
||||
LogWarning(message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LogInfo(prefsFileFound);
|
||||
|
||||
settings = CreateSettings(FileSettingType);
|
||||
|
||||
do
|
||||
{
|
||||
char *c = (char *)FGets(file, (STRPTR)line, MAXSETTINGLINELEN);
|
||||
eof = (c == NULL);
|
||||
|
||||
if (!eof)
|
||||
{
|
||||
ParseSetting(settings, line);
|
||||
count++;
|
||||
}
|
||||
} while (!eof && count < maxLines);
|
||||
|
||||
// If NULL is returned for an EOF, IoErr() will return 0.
|
||||
error = IoErr();
|
||||
if (error != 0)
|
||||
{
|
||||
Fault(error, (STRPTR)fileReadError, (STRPTR)message, MAXDOSERRORLEN);
|
||||
LogError(message);
|
||||
}
|
||||
|
||||
Close(file);
|
||||
fileSettings = settings;
|
||||
}
|
||||
|
||||
static void WriteSetting(BPTR file, const char *format, ...)
|
||||
{
|
||||
long count;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
count = VFPrintf(file, (void *)format, (void *)args);
|
||||
va_end(args);
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
long error = IoErr();
|
||||
if (error != 0)
|
||||
{
|
||||
char message[MAXDOSERRORLEN];
|
||||
Fault(error, (STRPTR)fileWriteError, (STRPTR)message, MAXDOSERRORLEN);
|
||||
LogError(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SaveSettings(bool persist)
|
||||
{
|
||||
char low[MAXLONGLONGCHARSIZE];
|
||||
const char *fileName = persist ? persistentPrefsFile : prefsFile;
|
||||
BPTR file = Open((STRPTR)fileName, MODE_NEWFILE);
|
||||
if (!file)
|
||||
{
|
||||
char message[MAXDOSERRORLEN];
|
||||
long error = IoErr();
|
||||
Fault(error, (STRPTR)fileSaveError, (STRPTR)message, MAXDOSERRORLEN);
|
||||
LogWarning(message);
|
||||
return;
|
||||
}
|
||||
|
||||
LogInfo(prefsFileSave, fileName);
|
||||
|
||||
LongLongToStr(Globals->Settings->Threshold, low);
|
||||
WriteSetting(file, saveValueLong, SettingKeys->Priority, Globals->Settings->Priority);
|
||||
WriteSetting(file, saveValueString, SettingKeys->Threshold, low);
|
||||
WriteSetting(file, saveValueString, SettingKeys->DestinationAddress, Globals->Settings->DestinationAddress);
|
||||
WriteSetting(file, saveValueString, SettingKeys->DestinationPort, Globals->Settings->DestinationPort);
|
||||
WriteSetting(file, saveValueLong, SettingKeys->Timeout, Globals->Settings->Timeout);
|
||||
WriteSetting(file, saveValueLong, SettingKeys->Interval, Globals->Settings->Interval);
|
||||
WriteSetting(file, saveValueLong, SettingKeys->Verbose, Globals->Settings->Verbose);
|
||||
WriteSetting(file, saveValueLong, SettingKeys->Readonly, Globals->Settings->Readonly);
|
||||
WriteSetting(file, saveValueString, SettingKeys->LogFile, Globals->Settings->LogFile);
|
||||
|
||||
Close(file);
|
||||
}
|
||||
|
||||
struct AppSettings *CreateSettings(long type)
|
||||
{
|
||||
struct AppSettings *settings;
|
||||
settings = (struct AppSettings *)AllocMemSafe(sizeof(struct AppSettings));
|
||||
settings->Type = type;
|
||||
return settings;
|
||||
}
|
||||
|
||||
struct AppSettings *CopySettings(const struct AppSettings *settings)
|
||||
{
|
||||
struct AppSettings *s = CreateSettings(settings->Type);
|
||||
CopyMem((void *)settings, s, sizeof(struct AppSettings));
|
||||
s->DestinationAddress = StrDupSafe(settings->DestinationAddress);
|
||||
s->DestinationPort = StrDupSafe(settings->DestinationPort);
|
||||
if (s->LogFile != NULL)
|
||||
{
|
||||
s->LogFile = StrDupSafe(settings->LogFile);
|
||||
}
|
||||
s->Values = 0xFFFF;
|
||||
return s;
|
||||
}
|
||||
|
||||
void FreeSettings(struct AppSettings *settings)
|
||||
{
|
||||
if (settings->DestinationAddress != NULL)
|
||||
{
|
||||
FreeMemSafe(settings->DestinationAddress);
|
||||
}
|
||||
|
||||
if (settings->DestinationPort != NULL)
|
||||
{
|
||||
FreeMemSafe(settings->DestinationPort);
|
||||
}
|
||||
|
||||
if (settings->LogFile != NULL)
|
||||
{
|
||||
FreeMemSafe(settings->LogFile);
|
||||
}
|
||||
|
||||
FreeMemSafe(settings);
|
||||
}
|
||||
|
||||
void ApplyAppSettings(struct AppSettings *settings, bool quiet)
|
||||
{
|
||||
switch (settings->Type)
|
||||
{
|
||||
case DefaultSettingType:
|
||||
LogInfo(applyDefaultSettings);
|
||||
break;
|
||||
case FileSettingType:
|
||||
LogInfo(applyFileSettings);
|
||||
break;
|
||||
case CliSettingType:
|
||||
LogInfo(applyCliSettings);
|
||||
break;
|
||||
case WbSettingType:
|
||||
LogInfo(applyWbSettings);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((settings->Values & PrioritySet) == PrioritySet)
|
||||
{
|
||||
if (settings->Type == DefaultSettingType)
|
||||
{
|
||||
LogTrace(settingValueLong, SettingKeys->Priority, settings->Priority);
|
||||
}
|
||||
else if (Globals->Settings->Priority != settings->Priority)
|
||||
{
|
||||
LogInfo(settingChangedLong, SettingKeys->Priority, Globals->Settings->Priority,
|
||||
settings->Priority);
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
LogTrace(settingSetLong, SettingKeys->Priority, settings->Priority);
|
||||
}
|
||||
Globals->Settings->Priority = settings->Priority;
|
||||
}
|
||||
|
||||
if ((settings->Values & VerboseSet) == VerboseSet)
|
||||
{
|
||||
if (settings->Type == DefaultSettingType)
|
||||
{
|
||||
LogTrace(settingValueLong, SettingKeys->Verbose, settings->Verbose);
|
||||
}
|
||||
else if (Globals->Settings->Verbose != settings->Verbose)
|
||||
{
|
||||
LogInfo(settingChangedLong, SettingKeys->Verbose, Globals->Settings->Verbose,
|
||||
settings->Verbose);
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
LogTrace(settingSetLong, SettingKeys->Verbose, settings->Verbose);
|
||||
}
|
||||
Globals->Settings->Verbose = settings->Verbose;
|
||||
}
|
||||
|
||||
if ((settings->Values & TimeoutSet) == TimeoutSet)
|
||||
{
|
||||
if (settings->Type == DefaultSettingType)
|
||||
{
|
||||
LogTrace(settingValueLong, SettingKeys->Timeout, settings->Timeout);
|
||||
}
|
||||
else if (Globals->Settings->Timeout != settings->Timeout)
|
||||
{
|
||||
LogInfo(settingChangedLong, SettingKeys->Timeout, Globals->Settings->Timeout,
|
||||
settings->Timeout);
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
LogTrace(settingSetLong, SettingKeys->Timeout, settings->Timeout);
|
||||
}
|
||||
Globals->Settings->Timeout = settings->Timeout;
|
||||
}
|
||||
|
||||
if ((settings->Values & IntervalSet) == IntervalSet)
|
||||
{
|
||||
if (settings->Type == DefaultSettingType)
|
||||
{
|
||||
LogTrace(settingValueLong, SettingKeys->Interval, settings->Interval);
|
||||
}
|
||||
else if (Globals->Settings->Interval != settings->Interval)
|
||||
{
|
||||
LogInfo(settingChangedLong, SettingKeys->Interval, Globals->Settings->Interval,
|
||||
settings->Interval);
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
LogTrace(settingSetLong, SettingKeys->Interval, settings->Interval);
|
||||
}
|
||||
Globals->Settings->Interval = settings->Interval;
|
||||
}
|
||||
|
||||
if ((settings->Values & ReadonlySet) == ReadonlySet)
|
||||
{
|
||||
if (settings->Type == DefaultSettingType)
|
||||
{
|
||||
LogTrace(settingValueLong, SettingKeys->Readonly, settings->Readonly);
|
||||
}
|
||||
else if (Globals->Settings->Readonly != settings->Readonly)
|
||||
{
|
||||
LogInfo(settingChangedLong, SettingKeys->Readonly, Globals->Settings->Readonly,
|
||||
settings->Readonly);
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
LogTrace(settingSetLong, SettingKeys->Readonly, settings->Readonly);
|
||||
}
|
||||
Globals->Settings->Readonly = settings->Readonly;
|
||||
}
|
||||
|
||||
if ((settings->Values & DestinationAddressSet) == DestinationAddressSet)
|
||||
{
|
||||
if (settings->Type == DefaultSettingType)
|
||||
{
|
||||
LogTrace(settingValueString, SettingKeys->DestinationAddress,
|
||||
settings->DestinationAddress);
|
||||
}
|
||||
else if (Stricmp((STRPTR)Globals->Settings->DestinationAddress,
|
||||
(STRPTR)settings->DestinationAddress) != 0)
|
||||
{
|
||||
LogInfo(settingChangedString, SettingKeys->DestinationAddress,
|
||||
Globals->Settings->DestinationAddress, settings->DestinationAddress);
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
LogTrace(settingSetString, SettingKeys->DestinationAddress, settings->DestinationAddress);
|
||||
}
|
||||
|
||||
if (Globals->Settings->DestinationAddress != NULL)
|
||||
{
|
||||
FreeMemSafe(Globals->Settings->DestinationAddress);
|
||||
}
|
||||
Globals->Settings->DestinationAddress = StrDupSafe(settings->DestinationAddress);
|
||||
}
|
||||
|
||||
if ((settings->Values & DestinationPortSet) == DestinationPortSet)
|
||||
{
|
||||
if (settings->Type == DefaultSettingType)
|
||||
{
|
||||
LogTrace(settingValueString, SettingKeys->DestinationPort,
|
||||
settings->DestinationPort);
|
||||
}
|
||||
else if (Stricmp((STRPTR)Globals->Settings->DestinationPort,
|
||||
(STRPTR)settings->DestinationPort) != 0)
|
||||
{
|
||||
LogInfo(settingChangedString, SettingKeys->DestinationPort,
|
||||
Globals->Settings->DestinationPort, settings->DestinationPort);
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
LogTrace(settingSetString, SettingKeys->DestinationPort, settings->DestinationPort);
|
||||
}
|
||||
|
||||
if (Globals->Settings->DestinationPort != NULL)
|
||||
{
|
||||
FreeMemSafe(Globals->Settings->DestinationPort);
|
||||
}
|
||||
Globals->Settings->DestinationPort = StrDupSafe(settings->DestinationPort);
|
||||
}
|
||||
|
||||
if ((settings->Values & ThresholdSet) == ThresholdSet)
|
||||
{
|
||||
char before[MAXLONGLONGCHARSIZE];
|
||||
char after[MAXLONGLONGCHARSIZE];
|
||||
|
||||
if (settings->Type == DefaultSettingType)
|
||||
{
|
||||
LongLongToStr(settings->Threshold, after);
|
||||
LogTrace(settingValueString, SettingKeys->Threshold, after);
|
||||
}
|
||||
else if (Globals->Settings->Threshold != settings->Threshold)
|
||||
{
|
||||
LongLongToStr(Globals->Settings->Threshold, before);
|
||||
LongLongToStr(settings->Threshold, after);
|
||||
LogInfo(settingChangedString, SettingKeys->Threshold, before, after);
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
LongLongToStr(Globals->Settings->Threshold, before);
|
||||
LogTrace(settingSetString, SettingKeys->Threshold, before);
|
||||
}
|
||||
Globals->Settings->Threshold = settings->Threshold;
|
||||
}
|
||||
|
||||
if ((settings->Values & LogFileSet) == LogFileSet)
|
||||
{
|
||||
if (settings->Type == DefaultSettingType)
|
||||
{
|
||||
LogTrace(settingValueString, SettingKeys->LogFile,
|
||||
settings->LogFile != NULL ? settings->LogFile : noLogFile);
|
||||
}
|
||||
else if (!(Globals->Settings->LogFile == NULL && settings->LogFile == NULL) ||
|
||||
StrnCmp(Globals->Locale,
|
||||
(STRPTR)Globals->Settings->LogFile,
|
||||
(STRPTR)settings->LogFile,
|
||||
(LONG)MAXSETTINGLINELEN, SC_ASCII) != 0)
|
||||
{
|
||||
LogInfo(settingChangedString, SettingKeys->LogFile,
|
||||
Globals->Settings->LogFile != NULL ? Globals->Settings->LogFile : noLogFile,
|
||||
settings->LogFile != NULL ? settings->LogFile : noLogFile);
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
LogTrace(settingSetString, SettingKeys->LogFile,
|
||||
settings->LogFile != NULL ? settings->LogFile : noLogFile);
|
||||
}
|
||||
|
||||
if (Globals->Settings->LogFile != NULL)
|
||||
{
|
||||
FreeMemSafe(Globals->Settings->LogFile);
|
||||
}
|
||||
Globals->Settings->LogFile = settings->LogFile != NULL
|
||||
? StrDupSafe(settings->LogFile)
|
||||
: NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CacheSettings(struct AppSettings *settings)
|
||||
{
|
||||
if (cachedSettings != NULL)
|
||||
{
|
||||
FreeSettings(cachedSettings);
|
||||
}
|
||||
cachedSettings = settings;
|
||||
}
|
||||
|
||||
void ApplySettings()
|
||||
{
|
||||
ApplyAppSettings((struct AppSettings *)&DefaultSettings, false);
|
||||
|
||||
if (fileSettings != NULL)
|
||||
{
|
||||
ApplyAppSettings(fileSettings, false);
|
||||
FreeSettings(fileSettings);
|
||||
}
|
||||
|
||||
if (cachedSettings != NULL)
|
||||
{
|
||||
ApplyAppSettings(cachedSettings, false);
|
||||
FreeSettings(cachedSettings);
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateInterval(void)
|
||||
{
|
||||
if (Globals->Settings->Interval < INTERVAL_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Interval,
|
||||
INTERVAL_MIN);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Interval,
|
||||
Globals->Settings->Interval,
|
||||
INTERVAL_MIN);
|
||||
Globals->Settings->Interval = INTERVAL_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateTimeout(void)
|
||||
{
|
||||
if (Globals->Settings->Timeout < TIMEOUT_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Timeout,
|
||||
TIMEOUT_MIN);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Timeout,
|
||||
Globals->Settings->Timeout,
|
||||
TIMEOUT_MIN);
|
||||
Globals->Settings->Timeout = TIMEOUT_MIN;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Timeout > Globals->Settings->Interval)
|
||||
{
|
||||
LogInfo(settingGreaterThan,
|
||||
SettingKeys->Timeout,
|
||||
SettingKeys->Interval);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Timeout,
|
||||
Globals->Settings->Timeout,
|
||||
Globals->Settings->Interval);
|
||||
Globals->Settings->Timeout = Globals->Settings->Interval;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Timeout > TIMEOUT_MAX)
|
||||
{
|
||||
LogInfo(settingTooHigh,
|
||||
SettingKeys->Timeout,
|
||||
TIMEOUT_MAX);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Timeout,
|
||||
Globals->Settings->Timeout,
|
||||
TIMEOUT_MAX);
|
||||
Globals->Settings->Timeout = TIMEOUT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidatePriority(void)
|
||||
{
|
||||
if (Globals->Settings->Priority < PRIORITY_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Priority,
|
||||
PRIORITY_MIN);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Priority,
|
||||
Globals->Settings->Priority,
|
||||
PRIORITY_MIN);
|
||||
Globals->Settings->Priority = PRIORITY_MIN;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Priority > PRIORITY_MAX)
|
||||
{
|
||||
LogInfo(settingTooHigh,
|
||||
SettingKeys->Priority,
|
||||
PRIORITY_MAX);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Priority,
|
||||
Globals->Settings->Priority,
|
||||
PRIORITY_MAX);
|
||||
Globals->Settings->Priority = PRIORITY_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateThreshold(void)
|
||||
{
|
||||
if (Globals->Settings->Threshold < THRESHOLD_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Threshold,
|
||||
THRESHOLD_MIN);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Threshold,
|
||||
Globals->Settings->Threshold,
|
||||
THRESHOLD_MIN);
|
||||
Globals->Settings->Threshold = THRESHOLD_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateVerbose(void)
|
||||
{
|
||||
if (Globals->Settings->Verbose < VERBOSE_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Verbose,
|
||||
VERBOSE_MIN);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Verbose,
|
||||
Globals->Settings->Verbose,
|
||||
VERBOSE_MIN);
|
||||
Globals->Settings->Verbose = VERBOSE_MIN;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Verbose > VERBOSE_MAX)
|
||||
{
|
||||
LogInfo(settingTooHigh,
|
||||
SettingKeys->Verbose,
|
||||
VERBOSE_MAX);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Verbose,
|
||||
Globals->Settings->Verbose,
|
||||
VERBOSE_MAX);
|
||||
Globals->Settings->Verbose = VERBOSE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
void SanitizeSettings(void)
|
||||
{
|
||||
ValidateInterval();
|
||||
ValidateTimeout();
|
||||
ValidatePriority();
|
||||
ValidateThreshold();
|
||||
ValidateVerbose();
|
||||
}
|
146
state.h
Normal file
146
state.h
Normal file
@ -0,0 +1,146 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STATE_H_INCLUDED
|
||||
#define STATE_H_INCLUDED
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define PrioritySet 0x001
|
||||
#define VerboseSet 0x002
|
||||
#define TimeoutSet 0x004
|
||||
#define IntervalSet 0x008
|
||||
#define ReadonlySet 0x010
|
||||
#define DestinationAddressSet 0x020
|
||||
#define DestinationPortSet 0x040
|
||||
#define ThresholdSet 0x080
|
||||
#define LogFileSet 0x200
|
||||
|
||||
#define DefaultSettingType 0x01
|
||||
#define FileSettingType 0x02
|
||||
#define CliSettingType 0x03
|
||||
#define WbSettingType 0x04
|
||||
#define GlobalSettingType 0x10
|
||||
|
||||
struct AppBroker
|
||||
{
|
||||
CxObj *Object;
|
||||
short ShutdownSigBit;
|
||||
struct Task *Task;
|
||||
struct MsgPort *BrokerPort;
|
||||
struct MsgPort *UserPort;
|
||||
struct MsgPort *ReplyPort;
|
||||
};
|
||||
|
||||
struct AppCom;
|
||||
struct AppSettingWindowGadgets;
|
||||
|
||||
struct AppSettingWindow
|
||||
{
|
||||
struct Process *Task;
|
||||
struct Screen *Screen;
|
||||
struct Window *SettingWindow;
|
||||
struct Gadget *GadgetList;
|
||||
struct MsgPort *UserPort;
|
||||
void *VisualInfo;
|
||||
char *PriorityText;
|
||||
char *ThresholdText;
|
||||
char *TimeZoneText;
|
||||
long Width;
|
||||
long Height;
|
||||
struct AppSettings *Settings;
|
||||
struct AppSettingWindowGadgets *Gadgets;
|
||||
};
|
||||
|
||||
struct AppSettings
|
||||
{
|
||||
long Priority;
|
||||
long Verbose;
|
||||
long Timeout;
|
||||
long Interval;
|
||||
long Readonly;
|
||||
long long Threshold;
|
||||
char *DestinationAddress;
|
||||
char *DestinationPort;
|
||||
char *LogFile;
|
||||
long Values;
|
||||
long Type;
|
||||
};
|
||||
|
||||
struct AppState
|
||||
{
|
||||
bool Active;
|
||||
bool ShuttingDown;
|
||||
struct timeval LastNtpSync;
|
||||
struct Locale *Locale;
|
||||
struct AppCom *Syncer;
|
||||
struct AppBroker *Broker;
|
||||
struct AppSettingWindow *Window;
|
||||
struct AppSignals *Signals;
|
||||
struct AppSettings *Settings;
|
||||
};
|
||||
|
||||
struct AppSettingKeys
|
||||
{
|
||||
const char *Priority;
|
||||
const char *Verbose;
|
||||
const char *Timeout;
|
||||
const char *Interval;
|
||||
const char *Readonly;
|
||||
const char *DestinationAddress;
|
||||
const char *DestinationPort;
|
||||
const char *Threshold;
|
||||
const char *LogFile;
|
||||
};
|
||||
|
||||
typedef void (*ParseSettingFunction)(struct AppSettings *, void *);
|
||||
|
||||
struct SettingFunc
|
||||
{
|
||||
const char *Name;
|
||||
ParseSettingFunction Function;
|
||||
};
|
||||
|
||||
extern struct AppState *Globals;
|
||||
extern struct AppSettingKeys *SettingKeys;
|
||||
extern const struct SettingFunc settingFunctions[];
|
||||
extern const struct AppSettings DefaultSettings;
|
||||
|
||||
void InitState(void);
|
||||
void DestroyState(void);
|
||||
void SanitizeSettings(void);
|
||||
void ShowSettings(void);
|
||||
void LoadSettings(void);
|
||||
void SaveSettings(bool);
|
||||
|
||||
struct AppSettings *CreateSettings(long);
|
||||
struct AppSettings *CopySettings(const struct AppSettings *);
|
||||
void ApplyAppSettings(struct AppSettings *, bool);
|
||||
void FreeSettings(struct AppSettings *);
|
||||
void CacheSettings(struct AppSettings *);
|
||||
void ApplySettings(void);
|
||||
|
||||
#endif
|
391
string.c
Normal file
391
string.c
Normal file
@ -0,0 +1,391 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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"
|
||||
|
||||
static const char *alphaNumerics = "0123456789";
|
||||
static const int base = 10;
|
||||
|
||||
struct RawDoFmtStream
|
||||
{
|
||||
char *buf;
|
||||
int size;
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the length of a null terminated string.
|
||||
*/
|
||||
int StrLen(const char *string)
|
||||
{
|
||||
char *i = (char *)string;
|
||||
char *s = i;
|
||||
while (*i)
|
||||
i++;
|
||||
return (int)(i - s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies the string pointed to by src to dest.
|
||||
*/
|
||||
char *StrCopy(char *dest, const char *src)
|
||||
{
|
||||
char *q = (char *)src;
|
||||
char *p = dest;
|
||||
|
||||
while ((*p++ = *q++))
|
||||
;
|
||||
|
||||
*p = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *AppendText(char *start, const char *text)
|
||||
{
|
||||
char *p = start;
|
||||
char *q = (char *)text;
|
||||
|
||||
while (*q != '\0')
|
||||
*p++ = *q++;
|
||||
|
||||
*p = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
int TrimRight(char *string)
|
||||
{
|
||||
char *i = string;
|
||||
char *s = i;
|
||||
|
||||
while (*i)
|
||||
i++;
|
||||
|
||||
if (i == s)
|
||||
return 0;
|
||||
|
||||
i--;
|
||||
while (*i == ' ' || *i == '\r' || *i == '\n' || *i == '\t')
|
||||
*i-- = '\0';
|
||||
|
||||
return (int)(i - s + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the first occurrence of a character.
|
||||
*/
|
||||
char *StrChr(const char *start, const char c, int len)
|
||||
{
|
||||
char *i = (char *)start;
|
||||
int j = 0;
|
||||
|
||||
if (i == NULL)
|
||||
return NULL;
|
||||
|
||||
do
|
||||
{
|
||||
if (*i == c)
|
||||
return i;
|
||||
|
||||
i++;
|
||||
j++;
|
||||
} while (j < len);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the last occurrence of a character.
|
||||
*/
|
||||
char *StrRChr(const char *start, const char c, int len)
|
||||
{
|
||||
char *i = (char *)start;
|
||||
char *l = NULL;
|
||||
int j = 0;
|
||||
|
||||
if (i == NULL)
|
||||
return NULL;
|
||||
|
||||
do
|
||||
{
|
||||
if (*i == c)
|
||||
l = i;
|
||||
|
||||
i++;
|
||||
j++;
|
||||
} while (j < len);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a long to a null terminated string.
|
||||
*/
|
||||
int LongToStr(signed long value, char *string)
|
||||
{
|
||||
unsigned int len, count = 0;
|
||||
unsigned long current = value;
|
||||
char chars[12];
|
||||
char *p = chars;
|
||||
char *q = string;
|
||||
bool negative = false;
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
current = -value;
|
||||
negative = true;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
unsigned long remainder = current % base;
|
||||
*p++ = alphaNumerics[remainder];
|
||||
current /= base;
|
||||
count++;
|
||||
} while (current >= 1);
|
||||
|
||||
p--;
|
||||
len = count;
|
||||
|
||||
if (negative)
|
||||
{
|
||||
*q++ = '-';
|
||||
len++;
|
||||
}
|
||||
|
||||
while (count-- != 0)
|
||||
*q++ = *p--;
|
||||
|
||||
*q = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a long long to a null terminated string.
|
||||
*/
|
||||
int LongLongToStr(signed long long value, char *string)
|
||||
{
|
||||
unsigned int len, count = 0;
|
||||
unsigned long long current = value;
|
||||
char chars[MAXLONGLONGCHARSIZE];
|
||||
char *p = chars;
|
||||
char *q = string;
|
||||
bool negative = false;
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
current = -value;
|
||||
negative = true;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
unsigned long long remainder = current % base;
|
||||
*p++ = alphaNumerics[remainder];
|
||||
current /= base;
|
||||
count++;
|
||||
} while (current >= 1);
|
||||
|
||||
p--;
|
||||
len = count;
|
||||
|
||||
if (negative)
|
||||
{
|
||||
*q++ = '-';
|
||||
len++;
|
||||
}
|
||||
|
||||
while (count-- != 0)
|
||||
*q++ = *p--;
|
||||
|
||||
*q = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a null terminated string to a long long.
|
||||
*/
|
||||
int StrToLongLong(char *string, unsigned long long *value)
|
||||
{
|
||||
signed long long result = 0;
|
||||
bool negative = false;
|
||||
char *p = string;
|
||||
int count = 0;
|
||||
|
||||
if (*p == '-')
|
||||
{
|
||||
negative = true;
|
||||
p++;
|
||||
}
|
||||
|
||||
while (*p != '\0')
|
||||
{
|
||||
if (*p < '0' || *p > '9' || count > 20)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
result *= 10;
|
||||
result += (*p++) - '0';
|
||||
}
|
||||
|
||||
*value = negative ? -result : result;
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to parse a null terminated string to a long.
|
||||
*/
|
||||
bool TryParseLong(char *string, long *value)
|
||||
{
|
||||
LONG characters, parsedValue;
|
||||
characters = StrToLong((STRPTR)string, &parsedValue);
|
||||
if (characters != -1)
|
||||
{
|
||||
*value = parsedValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
*value = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to parse a null terminated string to a long.
|
||||
*/
|
||||
bool TryParseLongLong(char *string, long long *value)
|
||||
{
|
||||
unsigned long long parsedValue;
|
||||
long characters;
|
||||
characters = StrToLongLong(string, &parsedValue);
|
||||
if (characters != -1)
|
||||
{
|
||||
*value = parsedValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
*value = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef AOS3
|
||||
|
||||
static void RawDoFmtChar(REG(d0, UBYTE c), REG(a3, struct RawDoFmtStream *s))
|
||||
{
|
||||
if (s->size > 0)
|
||||
{
|
||||
*(s->buf)++ = c;
|
||||
(s->size)--;
|
||||
|
||||
if (s->size == 1)
|
||||
{
|
||||
*(s->buf) = '\0';
|
||||
s->size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Formats and stores a series of characters and values.
|
||||
*/
|
||||
int VSNPrintf(char *str, size_t size, const char *format, va_list ap)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (str != NULL)
|
||||
{
|
||||
struct RawDoFmtStream s;
|
||||
|
||||
s.buf = str;
|
||||
s.size = size;
|
||||
|
||||
RawDoFmt(format, (void *)ap, (void (*)())RawDoFmtChar, (void *)&s);
|
||||
|
||||
if ((result = (size - s.size)) != size)
|
||||
--result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Formats and stores a series of characters and values in the array buffer.
|
||||
*/
|
||||
int SNPrintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
int result;
|
||||
|
||||
va_start(args, format);
|
||||
result = VSNPrintf(str, size, format, args);
|
||||
va_end(args);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Split filename in path and filename.
|
||||
*/
|
||||
void SplitFileName(const char *s, char *path, char *name)
|
||||
{
|
||||
int len, x, y;
|
||||
char *c;
|
||||
|
||||
if (s == NULL || *s == '\0')
|
||||
{
|
||||
*path = '\0';
|
||||
*name = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
len = StrLen(s);
|
||||
c = StrRChr(s, '/', len);
|
||||
if (c == NULL)
|
||||
{
|
||||
c = StrChr(s, ':', len);
|
||||
if (c == NULL)
|
||||
{
|
||||
*path = '\0';
|
||||
CopyMem((char *)s, name, len);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Include :
|
||||
x = (c - s + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = (c - s);
|
||||
}
|
||||
|
||||
y = len - (c - s);
|
||||
|
||||
*(char *)(path + x) = '\0';
|
||||
CopyMem((char *)s, path, x);
|
||||
CopyMem(++c, name, y);
|
||||
}
|
49
string.h
Normal file
49
string.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STRING_H_INCLUDED
|
||||
#define STRING_H_INCLUDED
|
||||
|
||||
#include "compiler.h"
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int StrLen(const char *);
|
||||
char *StrCopy(char *, const char *);
|
||||
char *AppendText(char *, const char *);
|
||||
int TrimRight(char *);
|
||||
char *StrChr(const char *, const char, int);
|
||||
char *StrRChr(const char *, const char, int);
|
||||
int LongToStr(signed long, char *);
|
||||
int LongLongToStr(signed long long, char *);
|
||||
int StrToLongLong(char *, unsigned long long *);
|
||||
bool TryParseLong(char *, long *);
|
||||
bool TryParseLongLong(char *, long long *);
|
||||
int VSNPrintf(char *, size_t, const char *, va_list);
|
||||
int SNPrintf(char *, size_t, const char *, ...);
|
||||
void SplitFileName(const char *, char *, char *);
|
||||
|
||||
#endif
|
235
time.c
Normal file
235
time.c
Normal file
@ -0,0 +1,235 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "time.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include <clib/alib_protos.h>
|
||||
|
||||
/*
|
||||
* 2922 is the number of days between 1.1.1970 and 1.1.1978
|
||||
* (2 leap years and 6 normal)
|
||||
* 2922 * 24 * 60 * 60 = 252460800
|
||||
*/
|
||||
#define AMIGA_OFFSET 252460800
|
||||
#define TIMER_ERROR 10
|
||||
#define TIMER_OK 0
|
||||
|
||||
struct TimerInfo
|
||||
{
|
||||
bool TimerTrigged;
|
||||
struct MsgPort *TimerPort;
|
||||
struct timerequest *TimerIO;
|
||||
};
|
||||
|
||||
struct Device *TimerBase = NULL;
|
||||
static struct timerequest *TimerIO = NULL;
|
||||
static long utcOffset = 0;
|
||||
|
||||
/*
|
||||
* Set up pointer for timer functions.
|
||||
*/
|
||||
struct Device *OpenTimerBase(void)
|
||||
{
|
||||
LONG error;
|
||||
|
||||
TimerIO = (struct timerequest *)AllocMemSafe(sizeof(struct timerequest));
|
||||
if (TimerIO == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error = OpenDevice((STRPTR)TIMERNAME, UNIT_MICROHZ, (struct IORequest *)TimerIO, 0);
|
||||
if (error != 0)
|
||||
{
|
||||
FreeMemSafe(TimerIO);
|
||||
TimerIO = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TimerBase = TimerIO->tr_node.io_Device;
|
||||
return TimerBase;
|
||||
}
|
||||
|
||||
void CloseTimerBase(void)
|
||||
{
|
||||
if (TimerBase != NULL && TimerIO != NULL)
|
||||
{
|
||||
CloseDevice((struct IORequest *)TimerIO);
|
||||
}
|
||||
|
||||
if (TimerIO != NULL)
|
||||
{
|
||||
FreeMemSafe(TimerIO);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a timer device with UNIT_VBLANK.
|
||||
*/
|
||||
struct TimerInfo *CreateTimer(bool setTimerBase)
|
||||
{
|
||||
LONG error;
|
||||
static const char *name = APP_SHORT_NAME " Timer Message Port";
|
||||
struct TimerInfo *info = (struct TimerInfo *)AllocMemSafe(sizeof(struct TimerInfo));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
info->TimerPort = CreateMsgPort();
|
||||
if (info->TimerPort == NULL)
|
||||
{
|
||||
DeleteTimer(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info->TimerPort->mp_Node.ln_Name = (char *)name;
|
||||
info->TimerPort->mp_Node.ln_Pri = 0;
|
||||
|
||||
info->TimerIO = (struct timerequest *)CreateExtIO(info->TimerPort, sizeof(struct timerequest));
|
||||
if (info->TimerIO == NULL)
|
||||
{
|
||||
DeleteTimer(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error = OpenDevice(
|
||||
(STRPTR)TIMERNAME, UNIT_MICROHZ,
|
||||
(struct IORequest *)info->TimerIO, 0);
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
DeleteTimer(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void SetTimer(struct TimerInfo *info)
|
||||
{
|
||||
info->TimerIO->tr_node.io_Command = TR_ADDREQUEST;
|
||||
info->TimerIO->tr_time.tv_secs = Globals->Settings->Interval / 1000;
|
||||
info->TimerIO->tr_time.tv_micro = Globals->Settings->Interval % 1000;
|
||||
SendIO((struct IORequest *)info->TimerIO);
|
||||
info->TimerTrigged = true;
|
||||
}
|
||||
|
||||
ULONG GetTimerSigMask(struct TimerInfo *info)
|
||||
{
|
||||
return (1 << info->TimerPort->mp_SigBit);
|
||||
}
|
||||
|
||||
void DeleteTimer(struct TimerInfo *info)
|
||||
{
|
||||
if (info->TimerIO != NULL)
|
||||
{
|
||||
AbortIO((struct IORequest *)info->TimerIO);
|
||||
if (info->TimerTrigged)
|
||||
{
|
||||
WaitIO((struct IORequest *)info->TimerIO);
|
||||
}
|
||||
CloseDevice((struct IORequest *)info->TimerIO);
|
||||
DeleteExtIO((struct IORequest *)info->TimerIO);
|
||||
info->TimerIO = NULL;
|
||||
}
|
||||
|
||||
if (info->TimerPort != NULL)
|
||||
{
|
||||
DeleteMsgPort(info->TimerPort);
|
||||
}
|
||||
|
||||
FreeMemSafe(info);
|
||||
}
|
||||
|
||||
void InitUtcOffset(void)
|
||||
{
|
||||
char timeZone[10];
|
||||
int gmtoffset = Globals->Locale->loc_GMTOffset * 60;
|
||||
utcOffset = gmtoffset + AMIGA_OFFSET;
|
||||
GetTimeZoneText(timeZone);
|
||||
LogWarning("Local time zone is %s", timeZone);
|
||||
}
|
||||
|
||||
void GetTimeZoneText(char *text)
|
||||
{
|
||||
SNPrintf(text, 10, "UTC%s%ld:%02ld",
|
||||
-Globals->Locale->loc_GMTOffset > 0 ? "+" : "",
|
||||
(long)-Globals->Locale->loc_GMTOffset / 60,
|
||||
(long)-Globals->Locale->loc_GMTOffset % 60);
|
||||
}
|
||||
|
||||
void Unix2Amiga(struct timeval *unix, struct timeval *tv)
|
||||
{
|
||||
tv->tv_secs = unix->tv_secs + AMIGA_OFFSET;
|
||||
tv->tv_micro = unix->tv_micro;
|
||||
}
|
||||
|
||||
void Utc2Local(struct timeval *utc, struct timeval *tv)
|
||||
{
|
||||
int gmtoffset = Globals->Locale->loc_GMTOffset * 60;
|
||||
tv->tv_secs = utc->tv_secs - gmtoffset;
|
||||
tv->tv_micro = utc->tv_micro;
|
||||
}
|
||||
|
||||
void GetTimeOfDay(struct timeval *tv)
|
||||
{
|
||||
GetSysTime(tv);
|
||||
tv->tv_secs = tv->tv_secs + utcOffset;
|
||||
}
|
||||
|
||||
void GetLocalTimeOfDay(struct timeval *tv)
|
||||
{
|
||||
GetSysTime(tv);
|
||||
}
|
||||
|
||||
void SetTimeOfDay(const struct TimerInfo *info, const struct timeval *tv)
|
||||
{
|
||||
info->TimerIO->tr_node.io_Command = TR_SETSYSTIME;
|
||||
info->TimerIO->tr_time.tv_secs = (long)tv->tv_secs - utcOffset;
|
||||
info->TimerIO->tr_time.tv_micro = tv->tv_micro;
|
||||
DoIO((struct IORequest *)info->TimerIO);
|
||||
}
|
||||
|
||||
void SaveTimeOfDay(const struct timeval *tv)
|
||||
{
|
||||
WriteBattClock((long)tv->tv_secs - utcOffset);
|
||||
}
|
||||
|
||||
void SystemTimeString(char *time, char *date, char *day)
|
||||
{
|
||||
struct DateTime dt;
|
||||
|
||||
DateStamp(&dt.dat_Stamp);
|
||||
|
||||
dt.dat_Format = FORMAT_DOS;
|
||||
dt.dat_Flags = 0;
|
||||
dt.dat_StrDay = (void *)day;
|
||||
dt.dat_StrDate = (void *)date;
|
||||
dt.dat_StrTime = (void *)time;
|
||||
|
||||
DateToStr(&dt);
|
||||
}
|
51
time.h
Normal file
51
time.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TIME_H_INCLUDED
|
||||
#define TIME_H_INCLUDED
|
||||
|
||||
#include "config.h"
|
||||
|
||||
struct TimerInfo;
|
||||
|
||||
struct Device *OpenTimerBase(void);
|
||||
void CloseTimerBase(void);
|
||||
struct TimerInfo *CreateTimer(bool);
|
||||
void SetTimer(struct TimerInfo *);
|
||||
void DeleteTimer(struct TimerInfo *);
|
||||
ULONG GetTimerSigMask(struct TimerInfo *info);
|
||||
|
||||
void InitUtcOffset(void);
|
||||
void GetTimeZoneText(char *text);
|
||||
void GetTimeOfDay(struct timeval *tv);
|
||||
void SetTimeOfDay(const struct TimerInfo *, const struct timeval *tv);
|
||||
void SaveTimeOfDay(const struct timeval *tv);
|
||||
void GetLocalTimeOfDay(struct timeval *tv);
|
||||
void Unix2Amiga(struct timeval *unix, struct timeval *tv);
|
||||
void Utc2Local(struct timeval *utc, struct timeval *tv);
|
||||
void SystemTimeString(char *time, char *date, char *day);
|
||||
|
||||
#endif
|
65
win.h
Normal file
65
win.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WIN_H_INCLUDED
|
||||
#define WIN_H_INCLUDED
|
||||
|
||||
#include <clib/intuition_protos.h>
|
||||
#include <proto/intuition.h>
|
||||
#include <clib/gadtools_protos.h>
|
||||
#include <proto/gadtools.h>
|
||||
|
||||
#define GID_SERVER 1001
|
||||
#define GID_PORT 1002
|
||||
#define GID_TIMEOUT 1003
|
||||
#define GID_INTERVAL 1004
|
||||
#define GID_THRESHOLD 1005
|
||||
#define GID_VERBOSE 1006
|
||||
#define GID_READONLY 1007
|
||||
#define GID_PRIORITY 1008
|
||||
#define GID_SAVE 1009
|
||||
#define GID_USE 1010
|
||||
#define GID_CANCEL 1011
|
||||
|
||||
/* win_main.c */
|
||||
void ShowSettingWindow(void);
|
||||
void HideSettingWindow(void);
|
||||
bool CheckSettingWindowClosed(void);
|
||||
|
||||
/* win_gad.c */
|
||||
bool CreateGadgets(void);
|
||||
void UseSettings(void);
|
||||
void SetServer(void);
|
||||
void SetPort(void);
|
||||
void SetTimeout(void);
|
||||
void SetInterval(void);
|
||||
void SetThreshold(void);
|
||||
void SetVerbose(void);
|
||||
void SetCxPriority(void);
|
||||
void ShowLastSync(void);
|
||||
void SetDefaultSettings(void);
|
||||
|
||||
#endif
|
686
win_gad.c
Normal file
686
win_gad.c
Normal file
@ -0,0 +1,686 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "message.h"
|
||||
#include "state.h"
|
||||
#include "time.h"
|
||||
#include "mem.h"
|
||||
#include "win.h"
|
||||
|
||||
struct AppSettingWindowGadgets
|
||||
{
|
||||
struct Gadget *ServerGadget;
|
||||
struct Gadget *PortGadget;
|
||||
struct Gadget *TimeoutGadget;
|
||||
struct Gadget *IntervalGadget;
|
||||
struct Gadget *ThresholdGadget;
|
||||
struct Gadget *VerboseGadget;
|
||||
struct Gadget *PriorityGadget;
|
||||
struct Gadget *TimeZoneGadget;
|
||||
struct Gadget *LastSyncGadget;
|
||||
};
|
||||
|
||||
static const char *serverLabel = "Server address";
|
||||
static const char *portLabel = "Server port";
|
||||
static const char *timeoutLabel = "Timeout (ms)";
|
||||
static const char *intervalLabel = "Interval (ms)";
|
||||
static const char *thresholdLabel = "Threshold (us)";
|
||||
static const char *verboseLabel = "Verbose level";
|
||||
static const char *priorityLabel = "CX priority";
|
||||
static const char *timeZoneLabel = "Time zone";
|
||||
static const char *lastSyncLabel = "Last sync";
|
||||
static const char *saveLabel = "Save";
|
||||
static const char *useLabel = "Use";
|
||||
static const char *cancelLabel = "Cancel";
|
||||
|
||||
static char *verboseLevel[] = {
|
||||
"Show none (0)",
|
||||
"Show some (1)",
|
||||
"Show more (2)",
|
||||
"Show all (3)",
|
||||
NULL};
|
||||
|
||||
bool CreateGadgets(void)
|
||||
{
|
||||
struct Gadget *gadget;
|
||||
struct NewGadget *ng;
|
||||
long x, y, w, h;
|
||||
long textWidth, boxWidth;
|
||||
long col1, col2;
|
||||
long labelId;
|
||||
long tmp1, tmp2;
|
||||
|
||||
Globals->Window->Gadgets = (struct AppSettingWindowGadgets *)
|
||||
AllocMemSafe(sizeof(struct AppSettingWindowGadgets));
|
||||
|
||||
ng = (struct NewGadget *)AllocMemSafe(sizeof(struct NewGadget));
|
||||
if (!ng)
|
||||
return false;
|
||||
|
||||
gadget = CreateContext(&Globals->Window->GadgetList);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_VisualInfo = Globals->Window->VisualInfo;
|
||||
ng->ng_TextAttr = Globals->Window->Screen->Font;
|
||||
ng->ng_Flags = 0;
|
||||
|
||||
w = Globals->Window->Screen->RastPort.TxWidth;
|
||||
h = Globals->Window->Screen->RastPort.TxHeight;
|
||||
|
||||
x = Globals->Window->Screen->WBorLeft + 8;
|
||||
y = Globals->Window->Screen->WBorTop + h + 9;
|
||||
|
||||
col1 = x;
|
||||
textWidth = 13 + VARSIZE;
|
||||
|
||||
col2 = col1 + w * textWidth;
|
||||
boxWidth = 13 + VARSIZE * 2;
|
||||
|
||||
ng->ng_TopEdge = y;
|
||||
ng->ng_Height = h + 6;
|
||||
|
||||
labelId = 5000;
|
||||
|
||||
// Server
|
||||
ng->ng_LeftEdge = col1;
|
||||
ng->ng_Width = textWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
GTTX_Text, (IPTR)serverLabel,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge = col2;
|
||||
ng->ng_Width = boxWidth * w + 20;
|
||||
ng->ng_GadgetID = GID_SERVER;
|
||||
gadget = CreateGadget(
|
||||
STRING_KIND, gadget, ng,
|
||||
GTST_String, (IPTR)Globals->Settings->DestinationAddress,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
Globals->Window->Gadgets->ServerGadget = gadget;
|
||||
|
||||
// Port
|
||||
ng->ng_LeftEdge = col1;
|
||||
ng->ng_TopEdge += ng->ng_Height + 4;
|
||||
ng->ng_Width = textWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
GTTX_Text, (IPTR)portLabel,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge = col2;
|
||||
ng->ng_Width = boxWidth * w + 20;
|
||||
ng->ng_GadgetID = GID_PORT;
|
||||
gadget = CreateGadget(
|
||||
STRING_KIND, gadget, ng,
|
||||
GTST_String, (IPTR)Globals->Settings->DestinationPort,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
Globals->Window->Gadgets->PortGadget = gadget;
|
||||
|
||||
// Interval
|
||||
ng->ng_LeftEdge = col1;
|
||||
ng->ng_TopEdge += ng->ng_Height + 4;
|
||||
ng->ng_Width = textWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
GTNM_MaxNumberLen, 8,
|
||||
GTTX_Text, (IPTR)intervalLabel,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge = col2;
|
||||
ng->ng_Width = boxWidth * w + 20;
|
||||
ng->ng_GadgetID = GID_INTERVAL;
|
||||
gadget = CreateGadget(
|
||||
INTEGER_KIND, gadget, ng,
|
||||
GTNM_MaxNumberLen, 8,
|
||||
GTIN_Number, Globals->Settings->Interval,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
gadget->Flags |= GFLG_TABCYCLE;
|
||||
Globals->Window->Gadgets->IntervalGadget = gadget;
|
||||
|
||||
// Timeout
|
||||
ng->ng_LeftEdge = col1;
|
||||
ng->ng_TopEdge += ng->ng_Height + 4;
|
||||
ng->ng_Width = textWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
GTTX_Text, (IPTR)timeoutLabel,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge = col2;
|
||||
ng->ng_Width = boxWidth * w + 20;
|
||||
ng->ng_GadgetID = GID_TIMEOUT;
|
||||
gadget = CreateGadget(
|
||||
INTEGER_KIND, gadget, ng,
|
||||
GTNM_MaxNumberLen, 8,
|
||||
GTIN_Number, Globals->Settings->Timeout,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
gadget->Flags |= GFLG_TABCYCLE;
|
||||
Globals->Window->Gadgets->TimeoutGadget = gadget;
|
||||
|
||||
// Threshold
|
||||
ng->ng_LeftEdge = col1;
|
||||
ng->ng_TopEdge += ng->ng_Height + 4;
|
||||
ng->ng_Width = textWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
GTTX_Text, (IPTR)thresholdLabel,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge = col2;
|
||||
ng->ng_Width = boxWidth * w + 20;
|
||||
ng->ng_GadgetID = GID_THRESHOLD;
|
||||
gadget = CreateGadget(
|
||||
STRING_KIND, gadget, ng,
|
||||
GTST_String, (IPTR)Globals->Window->ThresholdText,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
gadget->Flags |= GFLG_TABCYCLE;
|
||||
Globals->Window->Gadgets->ThresholdGadget = gadget;
|
||||
|
||||
// Verbose
|
||||
ng->ng_LeftEdge = col1;
|
||||
ng->ng_TopEdge += ng->ng_Height + 4;
|
||||
ng->ng_Width = textWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
GTTX_Text, (IPTR)verboseLabel,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge = col2;
|
||||
ng->ng_Width = boxWidth * w + 20;
|
||||
ng->ng_GadgetID = GID_VERBOSE;
|
||||
gadget = CreateGadget(
|
||||
CYCLE_KIND, gadget, ng,
|
||||
GTCY_Labels, (IPTR)verboseLevel,
|
||||
GTCY_Active, Globals->Settings->Verbose,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
gadget->Flags |= GFLG_TABCYCLE;
|
||||
Globals->Window->Gadgets->VerboseGadget = gadget;
|
||||
|
||||
// Priority
|
||||
ng->ng_LeftEdge = col1;
|
||||
ng->ng_TopEdge += ng->ng_Height + 4;
|
||||
ng->ng_Width = textWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
GTTX_Text, (IPTR)priorityLabel,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge = col2;
|
||||
ng->ng_Width = (boxWidth * w + 20) / 2;
|
||||
ng->ng_GadgetID = GID_PRIORITY;
|
||||
|
||||
gadget = CreateGadget(
|
||||
STRING_KIND, gadget, ng,
|
||||
GTST_String, (IPTR)Globals->Window->PriorityText,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
gadget->Flags |= GFLG_TABCYCLE;
|
||||
Globals->Window->Gadgets->PriorityGadget = gadget;
|
||||
|
||||
// Time zone
|
||||
ng->ng_LeftEdge = col1;
|
||||
ng->ng_TopEdge += ng->ng_Height + 4;
|
||||
ng->ng_Width = textWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
GTTX_Text, (IPTR)timeZoneLabel,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge = col2;
|
||||
ng->ng_Width = boxWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
GTTX_Text, (IPTR)Globals->Window->TimeZoneText,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
Globals->Window->Gadgets->TimeZoneGadget = gadget;
|
||||
|
||||
// Last sync
|
||||
ng->ng_LeftEdge = col1;
|
||||
ng->ng_TopEdge += ng->ng_Height + 4;
|
||||
ng->ng_Width = textWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
GTTX_Text, (IPTR)lastSyncLabel,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge = col2;
|
||||
ng->ng_Width = boxWidth * w + 20;
|
||||
ng->ng_GadgetID = labelId++;
|
||||
gadget = CreateGadget(
|
||||
TEXT_KIND, gadget, ng,
|
||||
TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
Globals->Window->Gadgets->LastSyncGadget = gadget;
|
||||
|
||||
tmp1 = ng->ng_LeftEdge + ng->ng_Width - 18; // Why is this 18?
|
||||
tmp2 = tmp1 / 3;
|
||||
|
||||
ng->ng_TopEdge += ng->ng_Height + 6;
|
||||
ng->ng_Width = tmp2;
|
||||
ng->ng_LeftEdge = col1;
|
||||
ng->ng_GadgetText = (STRPTR)saveLabel;
|
||||
ng->ng_GadgetID = GID_SAVE;
|
||||
ng->ng_Flags = 0;
|
||||
gadget = CreateGadget(BUTTON_KIND, gadget, ng, TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge += ng->ng_Width + 4;
|
||||
ng->ng_GadgetText = (STRPTR)useLabel;
|
||||
ng->ng_GadgetID = GID_USE;
|
||||
gadget = CreateGadget(BUTTON_KIND, gadget, ng, TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
ng->ng_LeftEdge += ng->ng_Width + 4;
|
||||
ng->ng_GadgetText = (STRPTR)cancelLabel;
|
||||
ng->ng_GadgetID = GID_CANCEL;
|
||||
gadget = CreateGadget(BUTTON_KIND, gadget, ng, TAG_END);
|
||||
if (!gadget)
|
||||
return false;
|
||||
|
||||
Globals->Window->Height = ng->ng_TopEdge + ng->ng_Height;
|
||||
Globals->Window->Width = textWidth * w + boxWidth * w;
|
||||
|
||||
FreeMemSafe(ng);
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *BuildLogText(const char *setting, char *oldValue, char *newValue)
|
||||
{
|
||||
static const char *txt1 = " changed: ";
|
||||
static const char *txt2 = " -> ";
|
||||
char *p = AllocMemSafe(SETTINGMESSAGELEN);
|
||||
char *s = p;
|
||||
p = AppendText(p, (char *)setting);
|
||||
p = AppendText(p, (char *)txt1);
|
||||
p = AppendText(p, oldValue);
|
||||
p = AppendText(p, (char *)txt2);
|
||||
p = AppendText(p, newValue);
|
||||
return s;
|
||||
}
|
||||
|
||||
void UseSettings(void)
|
||||
{
|
||||
SetServer();
|
||||
SetPort();
|
||||
SetInterval();
|
||||
SetTimeout();
|
||||
SetThreshold();
|
||||
SetVerbose();
|
||||
SetCxPriority();
|
||||
}
|
||||
|
||||
void SetServer(void)
|
||||
{
|
||||
char *server, *text;
|
||||
|
||||
GT_GetGadgetAttrs(
|
||||
Globals->Window->Gadgets->ServerGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTST_String, (IPTR)&server,
|
||||
TAG_END);
|
||||
|
||||
if (Stricmp((STRPTR)server, (STRPTR)Globals->Settings->DestinationAddress) == 0)
|
||||
return;
|
||||
|
||||
text = BuildLogText(SettingKeys->DestinationAddress,
|
||||
Globals->Settings->DestinationAddress,
|
||||
server);
|
||||
FreeMemSafe(Globals->Settings->DestinationAddress);
|
||||
Globals->Settings->DestinationAddress = StrDupSafe(server);
|
||||
SendInfoMessage(text);
|
||||
SendMessage(ATK_RESTART);
|
||||
}
|
||||
|
||||
void SetPort(void)
|
||||
{
|
||||
char *port, *text;
|
||||
|
||||
GT_GetGadgetAttrs(
|
||||
Globals->Window->Gadgets->PortGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTST_String, (IPTR)&port,
|
||||
TAG_END);
|
||||
|
||||
if (Stricmp((STRPTR)port, (STRPTR)Globals->Settings->DestinationPort) == 0)
|
||||
return;
|
||||
|
||||
text = BuildLogText(SettingKeys->DestinationPort,
|
||||
Globals->Settings->DestinationPort,
|
||||
port);
|
||||
FreeMemSafe(Globals->Settings->DestinationPort);
|
||||
Globals->Settings->DestinationPort = StrDupSafe(port);
|
||||
SendInfoMessage(text);
|
||||
SendMessage(ATK_RESTART);
|
||||
}
|
||||
|
||||
void SetInterval(void)
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
GT_GetGadgetAttrs(
|
||||
Globals->Window->Gadgets->IntervalGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTIN_Number, (IPTR)&value,
|
||||
TAG_END);
|
||||
|
||||
if (value < INTERVAL_MIN)
|
||||
value = INTERVAL_MIN;
|
||||
|
||||
if (Globals->Settings->Interval != value)
|
||||
{
|
||||
char *text;
|
||||
char newValue[MAXLONGCHARSIZE];
|
||||
char oldValue[MAXLONGCHARSIZE];
|
||||
|
||||
LongToStr(Globals->Settings->Interval, oldValue);
|
||||
LongToStr(value, newValue);
|
||||
Globals->Settings->Interval = value;
|
||||
text = BuildLogText(SettingKeys->Interval, oldValue, newValue);
|
||||
SendInfoMessage(text);
|
||||
}
|
||||
}
|
||||
|
||||
void SetTimeout(void)
|
||||
{
|
||||
unsigned long value;
|
||||
GT_GetGadgetAttrs(
|
||||
Globals->Window->Gadgets->TimeoutGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTIN_Number, (IPTR)&value,
|
||||
TAG_END);
|
||||
|
||||
if (value < TIMEOUT_MIN)
|
||||
value = TIMEOUT_MIN;
|
||||
else if (value > TIMEOUT_MAX)
|
||||
value = TIMEOUT_MAX;
|
||||
|
||||
if (Globals->Settings->Timeout != value)
|
||||
{
|
||||
char *text;
|
||||
char newValue[MAXLONGCHARSIZE];
|
||||
char oldValue[MAXLONGCHARSIZE];
|
||||
|
||||
LongToStr(Globals->Settings->Timeout, oldValue);
|
||||
LongToStr(value, newValue);
|
||||
Globals->Settings->Timeout = value;
|
||||
text = BuildLogText(SettingKeys->Timeout, oldValue, newValue);
|
||||
SendInfoMessage(text);
|
||||
}
|
||||
}
|
||||
|
||||
void SetThreshold(void)
|
||||
{
|
||||
unsigned long long value;
|
||||
char *tempString;
|
||||
int result;
|
||||
|
||||
GT_GetGadgetAttrs(
|
||||
Globals->Window->Gadgets->ThresholdGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTST_String, (IPTR)&tempString,
|
||||
TAG_END);
|
||||
|
||||
result = StrToLongLong(tempString, &value);
|
||||
if (result != -1 && Globals->Settings->Threshold != value)
|
||||
{
|
||||
char *text;
|
||||
char newValue[MAXLONGLONGCHARSIZE];
|
||||
char oldValue[MAXLONGLONGCHARSIZE];
|
||||
|
||||
LongLongToStr(Globals->Settings->Threshold, oldValue);
|
||||
LongLongToStr(value, newValue);
|
||||
Globals->Settings->Threshold = value;
|
||||
text = BuildLogText(SettingKeys->Threshold, oldValue, newValue);
|
||||
SendInfoMessage(text);
|
||||
SendMessage(ATK_RESTART);
|
||||
}
|
||||
}
|
||||
|
||||
void SetVerbose(void)
|
||||
{
|
||||
long value;
|
||||
GT_GetGadgetAttrs(
|
||||
Globals->Window->Gadgets->VerboseGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTCY_Active, (IPTR)&value,
|
||||
TAG_END);
|
||||
|
||||
if (value < VERBOSE_MIN)
|
||||
value = VERBOSE_MIN;
|
||||
else if (value > VERBOSE_MAX)
|
||||
value = VERBOSE_MAX;
|
||||
|
||||
if (Globals->Settings->Verbose != value)
|
||||
{
|
||||
char *text;
|
||||
char newValue[MAXLONGCHARSIZE];
|
||||
char oldValue[MAXLONGCHARSIZE];
|
||||
|
||||
LongToStr(Globals->Settings->Verbose, oldValue);
|
||||
LongToStr(value, newValue);
|
||||
text = BuildLogText(SettingKeys->Verbose, oldValue, newValue);
|
||||
SendInfoMessage(text);
|
||||
Globals->Settings->Verbose = value;
|
||||
}
|
||||
}
|
||||
|
||||
void SetCxPriority(void)
|
||||
{
|
||||
LONG value;
|
||||
char *tempString;
|
||||
int result;
|
||||
|
||||
GT_GetGadgetAttrs(
|
||||
Globals->Window->Gadgets->PriorityGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTST_String, (IPTR)&tempString,
|
||||
TAG_END);
|
||||
|
||||
result = StrToLong((STRPTR)tempString, &value);
|
||||
if (result != -1)
|
||||
{
|
||||
if (value < PRIORITY_MIN)
|
||||
value = PRIORITY_MIN;
|
||||
else if (value > PRIORITY_MAX)
|
||||
value = PRIORITY_MAX;
|
||||
|
||||
if (Globals->Settings->Priority != value)
|
||||
{
|
||||
char *text;
|
||||
char newValue[MAXLONGCHARSIZE];
|
||||
char oldValue[MAXLONGCHARSIZE];
|
||||
|
||||
LongToStr(Globals->Settings->Priority, oldValue);
|
||||
LongToStr(value, newValue);
|
||||
Globals->Settings->Priority = value;
|
||||
text = BuildLogText(SettingKeys->Priority, oldValue, newValue);
|
||||
SetBrokerPriority(value);
|
||||
SendInfoMessage(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShowLastSync(void)
|
||||
{
|
||||
static char label[10];
|
||||
struct timeval nowLocal, last, lastLocal;
|
||||
struct ClockData clockdata;
|
||||
struct DateTime dateTime = {
|
||||
.dat_Stamp = {.ds_Days = 0},
|
||||
.dat_Format = FORMAT_DOS,
|
||||
.dat_Flags = 0,
|
||||
.dat_StrDay = NULL,
|
||||
.dat_StrDate = NULL,
|
||||
.dat_StrTime = (STRPTR)label};
|
||||
long seconds;
|
||||
|
||||
if (Globals->LastNtpSync.tv_secs == 0)
|
||||
{
|
||||
static const char *never = "Not synced yet";
|
||||
GT_SetGadgetAttrs(
|
||||
Globals->Window->Gadgets->LastSyncGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTTX_Text, (IPTR)never,
|
||||
TAG_END);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GetLocalTimeOfDay(&nowLocal);
|
||||
Unix2Amiga(&Globals->LastNtpSync, &last);
|
||||
Utc2Local(&last, &lastLocal);
|
||||
seconds = nowLocal.tv_secs - lastLocal.tv_secs;
|
||||
|
||||
if (seconds > 60 * 60 * 24)
|
||||
{
|
||||
static const char *tooOld = "> 24 hours";
|
||||
GT_SetGadgetAttrs(
|
||||
Globals->Window->Gadgets->LastSyncGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTTX_Text, (IPTR)tooOld,
|
||||
TAG_END);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Amiga2Date(lastLocal.tv_secs, &clockdata);
|
||||
dateTime.dat_Stamp.ds_Minute = clockdata.hour * 60 + clockdata.min;
|
||||
dateTime.dat_Stamp.ds_Tick = clockdata.sec * 50;
|
||||
DateToStr(&dateTime);
|
||||
|
||||
GT_SetGadgetAttrs(
|
||||
Globals->Window->Gadgets->LastSyncGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTTX_Text, (IPTR)label,
|
||||
TAG_END);
|
||||
}
|
||||
|
||||
void SetDefaultSettings(void)
|
||||
{
|
||||
static char priorityText[MAXLONGCHARSIZE];
|
||||
static char thresholdText[MAXLONGLONGCHARSIZE];
|
||||
|
||||
GT_SetGadgetAttrs(
|
||||
Globals->Window->Gadgets->ServerGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTST_String, (IPTR)DefaultSettings.DestinationAddress,
|
||||
TAG_END);
|
||||
|
||||
GT_SetGadgetAttrs(
|
||||
Globals->Window->Gadgets->PortGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTST_String, (IPTR)DefaultSettings.DestinationPort,
|
||||
TAG_END);
|
||||
|
||||
GT_SetGadgetAttrs(
|
||||
Globals->Window->Gadgets->TimeoutGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTIN_Number, DefaultSettings.Timeout,
|
||||
TAG_END);
|
||||
|
||||
GT_SetGadgetAttrs(
|
||||
Globals->Window->Gadgets->IntervalGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTIN_Number, DefaultSettings.Interval,
|
||||
TAG_END);
|
||||
|
||||
LongLongToStr(DefaultSettings.Threshold, thresholdText);
|
||||
GT_SetGadgetAttrs(
|
||||
Globals->Window->Gadgets->ThresholdGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTST_String, (IPTR)thresholdText,
|
||||
TAG_END);
|
||||
|
||||
GT_SetGadgetAttrs(
|
||||
Globals->Window->Gadgets->VerboseGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTCY_Active, DefaultSettings.Verbose,
|
||||
TAG_END);
|
||||
|
||||
LongToStr(DefaultSettings.Priority, priorityText);
|
||||
GT_SetGadgetAttrs(
|
||||
Globals->Window->Gadgets->PriorityGadget,
|
||||
Globals->Window->SettingWindow, NULL,
|
||||
GTST_String, (IPTR)priorityText,
|
||||
TAG_END);
|
||||
}
|
343
win_main.c
Normal file
343
win_main.c
Normal file
@ -0,0 +1,343 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2018 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 "message.h"
|
||||
#include "state.h"
|
||||
#include "time.h"
|
||||
#include "mem.h"
|
||||
#include "win.h"
|
||||
|
||||
static void SettingsProc(void);
|
||||
static void ProcessMsg(void);
|
||||
static void HandleGadgetUp(struct Gadget *);
|
||||
|
||||
void ShowSettingWindow(void)
|
||||
{
|
||||
bool running;
|
||||
|
||||
Forbid();
|
||||
running = Globals->Window->Task != NULL;
|
||||
if (!running)
|
||||
{
|
||||
Globals->Window->Task = CreateNewProcTags(
|
||||
NP_Entry, (IPTR)SettingsProc,
|
||||
NP_Name, (IPTR)APP_SHORT_NAME " Window",
|
||||
NP_StackSize, 64 * 1024,
|
||||
TAG_DONE);
|
||||
}
|
||||
Permit();
|
||||
|
||||
if (running)
|
||||
{
|
||||
LogTrace("Setting process is already running");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Globals->Window->Task != NULL)
|
||||
{
|
||||
LogTrace("Created setting process");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("Failed to create setting process");
|
||||
}
|
||||
}
|
||||
|
||||
void HideSettingWindow(void)
|
||||
{
|
||||
Forbid();
|
||||
if (Globals->Window->Task != NULL)
|
||||
{
|
||||
Signal((void *)Globals->Window->Task, SIGBREAKF_CTRL_C);
|
||||
}
|
||||
Permit();
|
||||
}
|
||||
|
||||
bool CheckSettingWindowClosed(void)
|
||||
{
|
||||
return (Globals->Window->Task == NULL);
|
||||
}
|
||||
|
||||
static bool InitWindow(void)
|
||||
{
|
||||
Globals->Window->Screen = LockPubScreen(NULL);
|
||||
if (!Globals->Window->Screen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Globals->Window->UserPort = CreateMsgPort();
|
||||
if (Globals->Window->UserPort == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Globals->Window->VisualInfo = GetVisualInfo(Globals->Window->Screen, NULL);
|
||||
if (Globals->Window->VisualInfo == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Globals->Window->PriorityText = AllocMemSafe(15);
|
||||
Globals->Window->TimeZoneText = AllocMemSafe(10);
|
||||
Globals->Window->ThresholdText = AllocMemSafe(MAXLONGLONGCHARSIZE);
|
||||
if (Globals->Window->PriorityText == NULL ||
|
||||
Globals->Window->TimeZoneText == NULL ||
|
||||
Globals->Window->ThresholdText == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LongToStr(Globals->Settings->Priority, Globals->Window->PriorityText);
|
||||
LongLongToStr(Globals->Settings->Threshold, Globals->Window->ThresholdText);
|
||||
GetTimeZoneText(Globals->Window->TimeZoneText);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void DestroyWindow(void)
|
||||
{
|
||||
if (Globals->Window->SettingWindow != NULL)
|
||||
{
|
||||
struct Message *msg;
|
||||
while ((msg = GetMsg(Globals->Window->SettingWindow->UserPort)))
|
||||
ReplyMsg(msg);
|
||||
|
||||
CloseWindow(Globals->Window->SettingWindow);
|
||||
Globals->Window->SettingWindow = NULL;
|
||||
}
|
||||
|
||||
if (Globals->Window->GadgetList != NULL)
|
||||
{
|
||||
FreeGadgets(Globals->Window->GadgetList);
|
||||
Globals->Window->GadgetList = NULL;
|
||||
}
|
||||
|
||||
if (Globals->Window->VisualInfo != NULL)
|
||||
{
|
||||
FreeVisualInfo(Globals->Window->VisualInfo);
|
||||
Globals->Window->VisualInfo = NULL;
|
||||
}
|
||||
|
||||
if (Globals->Window->UserPort != NULL)
|
||||
{
|
||||
struct Message *msg;
|
||||
while ((msg = GetMsg(Globals->Window->UserPort)))
|
||||
ReplyMsg(msg);
|
||||
|
||||
DeleteMsgPort(Globals->Window->UserPort);
|
||||
Globals->Window->UserPort = NULL;
|
||||
}
|
||||
|
||||
if (Globals->Window->Screen != NULL)
|
||||
{
|
||||
UnlockPubScreen(NULL, Globals->Window->Screen);
|
||||
Globals->Window->Screen = NULL;
|
||||
}
|
||||
|
||||
FreeSettings(Globals->Window->Settings);
|
||||
FreeMemSafe(Globals->Window->Gadgets);
|
||||
FreeMemSafe(Globals->Window->PriorityText);
|
||||
FreeMemSafe(Globals->Window->ThresholdText);
|
||||
FreeMemSafe(Globals->Window->TimeZoneText);
|
||||
Globals->Window->Gadgets = NULL;
|
||||
Globals->Window->PriorityText = NULL;
|
||||
Globals->Window->ThresholdText = NULL;
|
||||
Globals->Window->TimeZoneText = NULL;
|
||||
|
||||
Forbid();
|
||||
Globals->Window->Task = NULL;
|
||||
Permit();
|
||||
}
|
||||
|
||||
static bool CreateWindow(void)
|
||||
{
|
||||
long w = Globals->Window->Screen->WBorLeft + Globals->Window->Screen->WBorRight + Globals->Window->Width + 38; // Why is this 38?
|
||||
long h = Globals->Window->Height + 8 + Globals->Window->Screen->WBorBottom;
|
||||
struct Window *x = OpenWindowTags(NULL,
|
||||
WA_Width, w,
|
||||
WA_Height, h,
|
||||
WA_Left, (Globals->Window->Screen->Width - w) / 2,
|
||||
WA_Top, (Globals->Window->Screen->Height - h) / 2,
|
||||
WA_PubScreen, (IPTR)Globals->Window->Screen,
|
||||
WA_Title, (IPTR)APP_LONG_NAME,
|
||||
WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_ACTIVATE | WFLG_SIMPLE_REFRESH,
|
||||
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_VANILLAKEY | IDCMP_GADGETUP | IDCMP_MENUPICK,
|
||||
WA_Gadgets, (IPTR)Globals->Window->GadgetList,
|
||||
TAG_END);
|
||||
Globals->Window->SettingWindow = x;
|
||||
if (!x)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void InitWindowSettings()
|
||||
{
|
||||
if (Globals->Window->Settings != NULL)
|
||||
{
|
||||
FreeSettings(Globals->Window->Settings);
|
||||
}
|
||||
Globals->Window->Settings = CopySettings(Globals->Settings);
|
||||
}
|
||||
|
||||
static void SyncExit()
|
||||
{
|
||||
if (!Globals->ShuttingDown)
|
||||
{
|
||||
struct MsgPort *replyPort = CreateMsgPort();
|
||||
if (replyPort)
|
||||
{
|
||||
SendMessageTo(Globals->Broker->UserPort, replyPort, ATK_UNDO);
|
||||
WaitPort(replyPort);
|
||||
GetMsg(replyPort);
|
||||
DeleteMsgPort(replyPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SettingsProc(void)
|
||||
{
|
||||
if (!InitWindow() || !CreateGadgets() || !CreateWindow())
|
||||
{
|
||||
DestroyWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
InitWindowSettings();
|
||||
ShowLastSync();
|
||||
ProcessMsg();
|
||||
SyncExit();
|
||||
DestroyWindow();
|
||||
}
|
||||
|
||||
static void ProcessMsg(void)
|
||||
{
|
||||
bool loop = true;
|
||||
|
||||
GT_RefreshWindow(Globals->Window->SettingWindow, NULL);
|
||||
|
||||
do
|
||||
{
|
||||
ULONG sigrcvd = Wait(SIGBREAKF_CTRL_C |
|
||||
(1 << Globals->Window->UserPort->mp_SigBit) |
|
||||
(1 << Globals->Window->SettingWindow->UserPort->mp_SigBit));
|
||||
|
||||
if (sigrcvd & (1 << Globals->Window->SettingWindow->UserPort->mp_SigBit))
|
||||
{
|
||||
struct IntuiMessage *msg;
|
||||
while ((msg = GT_GetIMsg(Globals->Window->SettingWindow->UserPort)))
|
||||
{
|
||||
switch (msg->Class)
|
||||
{
|
||||
case IDCMP_REFRESHWINDOW:
|
||||
GT_BeginRefresh(Globals->Window->SettingWindow);
|
||||
GT_EndRefresh(Globals->Window->SettingWindow, TRUE);
|
||||
break;
|
||||
case IDCMP_GADGETUP:
|
||||
HandleGadgetUp((struct Gadget *)msg->IAddress);
|
||||
break;
|
||||
case IDCMP_VANILLAKEY:
|
||||
if (msg->Code == 0x1b)
|
||||
loop = false;
|
||||
break;
|
||||
case IDCMP_CLOSEWINDOW:
|
||||
loop = false;
|
||||
break;
|
||||
}
|
||||
|
||||
GT_ReplyIMsg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (sigrcvd & (1 << Globals->Window->UserPort->mp_SigBit))
|
||||
{
|
||||
struct AppWindowMessage *msg;
|
||||
while ((msg = (struct AppWindowMessage *)GetMsg(Globals->Window->UserPort)))
|
||||
{
|
||||
switch (msg->Type)
|
||||
{
|
||||
case ATK_REFRESH:
|
||||
ShowLastSync();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ReplyMsg((struct Message *)msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (sigrcvd & SIGBREAKF_CTRL_C)
|
||||
{
|
||||
loop = false;
|
||||
}
|
||||
} while (loop);
|
||||
}
|
||||
|
||||
static void HandleGadgetUp(struct Gadget *gadget)
|
||||
{
|
||||
switch (gadget->GadgetID)
|
||||
{
|
||||
case GID_SERVER:
|
||||
SetServer();
|
||||
break;
|
||||
case GID_PORT:
|
||||
SetPort();
|
||||
break;
|
||||
case GID_INTERVAL:
|
||||
SetInterval();
|
||||
break;
|
||||
case GID_TIMEOUT:
|
||||
SetTimeout();
|
||||
break;
|
||||
case GID_THRESHOLD:
|
||||
SetThreshold();
|
||||
break;
|
||||
case GID_VERBOSE:
|
||||
SetVerbose();
|
||||
break;
|
||||
case GID_PRIORITY:
|
||||
SetCxPriority();
|
||||
break;
|
||||
case GID_SAVE:
|
||||
SendMessage(ATK_STORE);
|
||||
break;
|
||||
case GID_USE:
|
||||
UseSettings();
|
||||
InitWindowSettings();
|
||||
SendMessage(ATK_APPLY);
|
||||
break;
|
||||
case GID_CANCEL:
|
||||
SendMessage(ATK_UNDO);
|
||||
HideSettingWindow();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user