AmiTimeKeeper/ctrl.c

299 lines
6.4 KiB
C

/*-
* Copyright (c) 2020-2021 Carsten Sonne Larsen <cs@innolan.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stddef.h>
#include <stdarg.h>
#include <stdbool.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include "global.h"
#include "message.h"
#include "string.h"
const char *vers = "\0$VER: TimeControl 1.12 (31.01.2021)";
#define ARGSFORMAT "ID/S,VERSION/S,STATUS/S,TIME/S,ZONE/S,START/S,STOP/S,SHOW/S,HIDE/S,SHUTDOWN/S"
struct RDArgs *rdargs = NULL;
struct MsgPort *replyPort = NULL;
LONG returnCode = 0;
struct progargs
{
long id;
long version;
long status;
long time;
long timezone;
long start;
long stop;
long show;
long hide;
long shutdown;
};
void InitializeArgs(struct progargs *args)
{
args->id = FALSE;
args->version = FALSE;
args->status = FALSE;
args->time = FALSE;
args->timezone = FALSE;
args->start = FALSE;
args->stop = FALSE;
args->show = FALSE;
args->hide = FALSE;
args->shutdown = FALSE;
}
struct ControlMesage *CreateControlMessage(long messageId)
{
struct ControlMesage *message;
message = (struct ControlMesage *)AllocVec(sizeof(struct ControlMesage), MEMF_ANY | MEMF_CLEAR);
if (message)
{
message->AppMsg.Msg.mn_Node.ln_Type = NT_MESSAGE;
message->AppMsg.Msg.mn_Length = sizeof(struct ControlMesage);
message->AppMsg.Msg.mn_ReplyPort = replyPort;
message->AppMsg.MsgType = MSGTYPE_CTRL;
message->AppMsg.MsgId = messageId;
message->Args = NULL;
message->Result = AllocVec(128, MEMF_ANY | MEMF_CLEAR);
}
return message;
}
void SendControlMessage(struct ControlMesage *message)
{
struct MsgPort *port;
Forbid();
port = FindPort((CONST_STRPTR)CONTROL_PORT_NAME);
if (port != NULL)
{
PutMsg(port, (struct Message *)message);
}
Permit();
if (port != NULL)
{
WaitPort(replyPort);
GetMsg(replyPort);
if (message->Code == ATK_CTRL_UNKNOWN)
{
Printf((STRPTR)APP_SHORT_NAME " could not process control command.\n");
}
else if (*message->Result != '\0')
{
Printf((STRPTR)message->Result);
Printf((STRPTR) "\n");
}
if (message->Code > returnCode)
{
returnCode = message->Code;
}
}
else
{
Printf((STRPTR) "Could not send control message.\n");
}
}
void FreeControlMessage(struct ControlMesage *message)
{
if (!message)
{
return;
}
if (message->Args)
{
FreeVec(message->Args);
}
if (message->Result)
{
FreeVec(message->Result);
}
FreeVec(message);
}
void SendSimpleMessage(long messageId)
{
struct ControlMesage *message = CreateControlMessage(messageId);
if (message)
{
SendControlMessage(message);
FreeControlMessage(message);
}
}
void ValidateArgs(struct progargs *args)
{
if (args->start && args->stop)
{
Printf((STRPTR) "Please either START or STOP in arguments.\n");
args->start = FALSE;
args->stop = FALSE;
}
if (args->show && args->hide)
{
Printf((STRPTR) "Please either SHOW or HIDE in arguments.\n");
args->show = FALSE;
args->hide = FALSE;
}
}
void ProcessArgs(struct progargs *args)
{
BOOL processed = FALSE;
if (args->id)
{
SendSimpleMessage(ATK_ID);
processed = TRUE;
}
if (args->version)
{
SendSimpleMessage(ATK_VERSION);
processed = TRUE;
}
if (args->status)
{
SendSimpleMessage(ATK_STATUS);
processed = TRUE;
}
if (args->time)
{
SendSimpleMessage(ATK_TIME);
processed = TRUE;
}
if (args->timezone)
{
SendSimpleMessage(ATK_TIMEZONE);
processed = TRUE;
}
if (args->show)
{
SendSimpleMessage(ATK_SHOW);
processed = TRUE;
}
if (args->hide)
{
SendSimpleMessage(ATK_HIDE);
processed = TRUE;
}
if (args->start)
{
SendSimpleMessage(ATK_ENABLE);
processed = TRUE;
}
if (args->stop)
{
SendSimpleMessage(ATK_DISABLE);
processed = TRUE;
}
if (args->shutdown)
{
SendSimpleMessage(ATK_SHUTDOWN);
processed = TRUE;
}
if (!processed)
{
Printf((STRPTR) "Please specify arguments.\n");
}
}
void Cleanup(void)
{
if (replyPort)
{
DeleteMsgPort(replyPort);
}
if (rdargs)
{
FreeArgs(rdargs);
}
}
int main(int argc, char **argv)
{
struct progargs args;
struct MsgPort *port;
InitializeArgs(&args);
rdargs = ReadArgs((STRPTR)ARGSFORMAT, (APTR)&args, NULL);
if (!rdargs)
{
PrintFault(IoErr(), (APTR)argv[0]);
Cleanup();
exit(5);
}
port = FindPort((CONST_STRPTR)CONTROL_PORT_NAME);
if (port == NULL)
{
Printf((STRPTR)APP_SHORT_NAME " is not running.\n");
Cleanup();
exit(1);
}
replyPort = CreateMsgPort();
if (replyPort == NULL)
{
Cleanup();
exit(5);
}
ValidateArgs(&args);
ProcessArgs(&args);
Cleanup();
return returnCode;
}