/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- main
- parse_comline
- srv_initialize
- process_request
- s_message
- s_terminate
- s_trans_num
- s_connect_num
- sys_log_reply
- output_log
- output_log_nf
- open_log
- open_alt_log
- term_app
- usage
/* sys_log - A system log server. This program will take messages
sent to it and log the message text in the system log file.
Program works by receiving messages, acting on them
and replying. Most messages are instructions to send
a string to the system log file. There are actually
two log files, the primary and alternate. When the
primary log file is locked, data will be written
to the alternate log file. The primary log file
is normally left closed just in case. You can,
however, manually open and close this file.
Rick Smereka, Copyright (C) 1997-2006.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, get a copy via the Internet at
http://gnu.org/copyleft/gpl.html or write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
You can contact the author via email at rsmereka@future-lab.com
Original QNX version Feb/97, Rick Smereka
Changed to receive the node ID (nid) in the send
message structure and print this and the calling
process ID (pid) on the output line. Dec/97,
Rick Smereka
Resolved a bug that caused the incorrect 'nid' and
'pid' of the system logger process to be output to
the log. Added function 'output_log_local' which will
preload the system logger process 'nid' and 'tid'.
Jan/98, Rick Smereka
Ported to 32bit Windows under CodeWarrior. See
'sys_log.h' for message types and explaination
of syntax. Server is TCP connection oriented
iterative. TCP communication is accomplished
through the library files 'ipcomm.c' (low level
send/receive) and 'ipcsrv.c' (application
level). TCP configuration is managed by
'ipconfig.c'. Dec/98, Rick Smereka
Ported to HP-UX under GNU C 2.8.1.
Jan/99, Rick Smereka
Implemented multi-platform program logo.
Feb/99, Rick Smereka
Ported to Red Hat Linux 5.2, Jul/99, Rick Smereka
Corrected situations in 'process_request' where a
reply would not be sent back upon certain error
conditions. Changed to use the 'socloc' interface
instead of the 'sys_log.ipc' config file. Changed
to allow command line options consisting of
the TCP port number that the server will listen to.
Also added processing of all common socket send codes.
Program syntax now is:
sys_log [-l log_file] [-a alternate_log_file] port
Where 'port' is the TCP port to listen, '-l log_file'
is the optional name of the server primary log file and
'-a alternate_log_file' is the optional name of the server
alternate log file. If no primary log file is given, the
log file name will be 'SYS_LOG_FNAME' in the current
directory. If no alternate log file is given, the
log file name will be 'SYS_LOG_ALT_FNAME' in the current
directory. Note that the switch character ('-')
is based on the platform (see include file 'stdhead.h').
Mar/2000, Rick Smereka
Re-compiled after re-structuring the definition of the common
send and repy codes. Added the option '-q' to control message
output to the console. Program syntax now is:
sys_log [-q] [-l log_file] [-a alt_log_file] port
Default value for console output is on, the '-q' parameter
(quiet) will turn it off. When console output is off, no
messages will be output to 'stdout' or 'stderr'. All output
will appear only in the log. Apr/2000, Rick Smereka
Modified function 'srv_initialize' to obtain the IP address of
the current machine and pass this to the socloc function
'sloc_add'. Jul/2000, Rick Smereka
Modified for use by both sockets and QNX message passing IPC.
Since the QNX message passing variant does not use a TCP port
number, its syntax is:
sys_log [-q] [-l log_file] [-a alt_log_file]
Oct/2001, Rick Smereka
Coded to use the 'appinit' API. May/2002, Rick Smereka
Modified function 'output_log' to obtain the date/time
string from function 'get_time'. Sep/2002, Rick Smereka
Ported to Debian Linux. Jan/2003, Rick Smereka
Changed to in accordance with the modifications in 'ipcsrv.c'.
Modified for use with the updated socloc client API ('sloc.c').
May/2003, Rick Smereka
Added function 'term_app'. Moved all shutdown code to this
function. Placed call to this function upon termination.
Re-wrote function 'output_log' to take a variable number of
parameters and added function 'output_log_nf'.
Jun/2003, Rick Smereka
Changed message when unable to receive data from client
connection in 'process_request'. Dec/2003,
Rick Smereka
Re-compile after changing the 'socloc' API. Added function
's_message' and changed how message text is obtained. Everything
passed the message command number is now taken as the message
text. Jan/2005, Rick Smereka
Re-compile after modifications to low level TCP socket communication
module (ipcomm.c). Feb/2006, Rick Smereka */
#include "stdhead.h"
#include "flsocket.h"
#include "ipcsrv.h"
#include "appinit.h"
#ifdef IPC_TCP
#include "socloc.h"
#include "sloc.h"
#include "slconfig.h"
#include "sliocode.h"
#include "ip.h"
#endif
#define VERSION "1.16.01-2006.02.23"
#define APNAME "sys_log"
#ifdef OS_UNIX
#define SYS_LOG_FNAME "/home/rick/logs/system.log"
#define SYS_LOG_ALT_FNAME "/home/rick/logs/altsys.log"
#else
#define SYS_LOG_FNAME "C:\\LOGS\\SYSTEM.LOG"
#define SYS_LOG_ALT_FNAME "C:\\LOGS\\ALTSYS.LOG"
#endif
#define SYS_LOG_TERM_PASSWD "rdsWin32"
int main(int, char **);
int parse_comline(int, char **);
int srv_initialize(void);
int process_request(void);
int s_message(char *);
int s_terminate(char *);
void s_trans_num(void);
void s_connect_num(void);
void sys_log_reply(int, char *);
int output_log(char *,...);
int output_log_nf(char *);
int open_alt_log(void);
int open_log(void);
void term_app(void);
#ifdef IPC_TCP
void usage();
#endif
/* global data */
int islocked; /* is the primary log file locked */
int isopen; /* is the log file already open */
int console_output = TRUE; /* output to console as well as log? */
FILE *out; /* output file pointer */
char server_log[128]; /* server log file name */
char server_alt_log[128]; /* server alternate log file name */
#ifdef IPC_TCP
char server_host[128]; /* server host name */
int server_port = 0; /* TCP port that server is using */
/* WinSock specific global data structure */
#ifdef OS_WIN32
WSADATA wsaData; /* struct used by 'WSAStartup()' */
#endif
#else
// QNX transaction counter
long server_trans_num = 0L;
#endif
int main(int argc, char **argv)
{
char mess[128];
int isterm;
/* indicate that we are initializing */
if (!appinit_start(SYS_LOG_SERVICE_NAME))
{
printf("%s:error creating init lock file. Program abort\n", APNAME);
return(0);
}
/* check for 'socloc' server (TCP) initializing and wait until this is
complete */
#ifdef IPC_TCP
if (!appinit_waitfor(SL_SERVICE_NAME, 5))
{
printf("%s:timeout waiting for 'socloc' to complete "
"initialization. Program abort\n", APNAME);
return(0);
}
#endif
/* check for command line parameters */
#ifdef IPC_TCP
if (argc == 1)
{
(void)appinit_stop(SYS_LOG_SERVICE_NAME);
usage();
return(0);
}
#endif
/* parse command line */
if (!parse_comline(argc, argv))
{
(void)appinit_stop(SYS_LOG_SERVICE_NAME);
return(0);
}
// initialize
islocked = isopen = FALSE;
// validate primary log file by attempting to open it
if (open_log() != SYS_LOG_OK)
{
printf("%s:unable to open log file %s, program abort\n", APNAME,
SYS_LOG_FNAME);
(void)appinit_stop(SYS_LOG_SERVICE_NAME);
return(2);
}
fclose(out);
/* build logo string based on platform */
#ifndef OS_UNIX
/* non-Unix */
(void)output_log("%s System Logger for %s Version %s", APNAME,
PLATFORM_STRING, VERSION);
#else
/* Unix */
(void)output_log("%s System Logger for %s Version %s", APNAME,
SUB_PLATFORM_STRING, VERSION);
#endif
(void)output_log_nf("By Rick Smereka, Copyright (c) 1997-2006");
(void)output_log_nf("sys_log comes with ABSOLUTELY NO WARRANTY");
(void)output_log_nf("This is free software, and you are welcome to "
"redistribute it");
(void)output_log_nf("under certain conditions; see 'gpl.txt' for "
"information.");
/* read IPC config file and validate other 'socloc' servers
(if any) */
if (!srv_initialize())
{
(void)appinit_stop(SYS_LOG_SERVICE_NAME);
term_app();
return(4);
}
#ifdef IPC_TCP
(void)output_log("%s:server on '%s' servicing TCP port %d (decimal)",
APNAME, server_host, server_port);
#endif
(void)output_log("%s:primary log file is %s", APNAME, server_log);
(void)output_log("%s:alternate log file is %s", APNAME, server_alt_log);
(void)output_log("%s:log server started", APNAME);
(void)appinit_stop(SYS_LOG_SERVICE_NAME);
#ifdef IPC_TCP
ipc_server_wait();
#else
// QNX, process each connection (infinite loop)
while(1)
{
isterm = process_request();
server_trans_num++;
if (isterm)
break;
}
#endif
term_app();
return(0);
}
int parse_comline(int c_count, char **c_parm)
{
/* Parse the command line for parameters. Function
returns 'TRUE' if no error was detected, 'FALSE'
otherwise. */
int parms = 1, done = FALSE;
/* set default log files */
strcpy(server_log, SYS_LOG_FNAME);
strcpy(server_alt_log, SYS_LOG_ALT_FNAME);
#ifdef IPC_QNX
if (c_count == 1)
return(TRUE);
#endif
while(!done)
{
if (c_parm[parms][0] == SWITCH_CHAR)
{
switch(toupper(c_parm[parms][1]))
{
case 'L':
if (strlen(c_parm[parms]) > 2)
printf("%s:extraneous input with log switch, ignoring\n",
SYS_LOG_SERVICE_NAME);
parms++;
if (parms >= c_count)
{
printf("%s:log switch with no file name, "
"program abort\n", SYS_LOG_SERVICE_NAME);
return(FALSE);
}
strcpy(server_log, c_parm[parms]);
parms++;
break;
case 'A':
if (strlen(c_parm[parms]) > 2)
printf("%s:extraneous input with alt log switch, "
"ignoring\n", SYS_LOG_SERVICE_NAME);
parms++;
if (parms >= c_count)
{
printf("%s:alt log switch with no file name, "
"program abort\n", SYS_LOG_SERVICE_NAME);
return(FALSE);
}
strcpy(server_alt_log, c_parm[parms]);
parms++;
break;
case 'Q':
console_output = FALSE;
parms++;
break;
default:
printf("%s:unknown switch[%s], program abort\n",
SYS_LOG_SERVICE_NAME, c_parm[parms]);
return(FALSE);
};
}
#ifdef IPC_TCP
else
{
if (!qatoi(c_parm[parms], &server_port))
{
printf("%s:server port is non-numeric, "
"program abort\n", SYS_LOG_SERVICE_NAME);
return(FALSE);
}
if (server_port <= 0)
{
printf("%s:server port is out of range, "
"program abort\n", SYS_LOG_SERVICE_NAME);
return(FALSE);
}
parms++;
}
#endif
if (parms >= c_count)
done = TRUE;
}
#ifdef IPC_TCP
if (server_port == 0)
{
printf("%s:server port missing, program abort\n",
SYS_LOG_SERVICE_NAME);
return(FALSE);
}
#endif
/* make sure log file names are valid */
if (open_log() != SYS_LOG_OK)
{
printf("%s:parse_comline:primary log file name is invalid, "
"program abort\n", SYS_LOG_SERVICE_NAME);
return(FALSE);
}
fclose(out);
if (open_alt_log() != SYS_LOG_OK)
{
printf("%s:parse_comline:alternate log file name is invalid, "
"program abort\n", SYS_LOG_SERVICE_NAME);
return(FALSE);
}
fclose(out);
return(TRUE);
}
int srv_initialize(void)
{
/* Initialize the server. Function returns 'TRUE' upon
success, 'FALSE' otherwise. */
char mes[128], mname[] = "srv_initialize";
int ret;
/* startup WinSock (if Windoze) */
#ifdef OS_WIN32
if (WSAStartup(WINSOCK_VERSION, &wsaData))
{
(void)output_log("%s:%s:unable to start WinSock, program abort",
APNAME, mname);
return(FALSE);
}
#endif
/* initialize the server on the IPC level, note that
the hostname 'server_host' is returned to us (TCP only) */
#ifdef IPC_TCP
if (!ipc_init(server_host, server_port))
#else
if (!ipc_init(SYS_LOG_SERVICE_NAME))
#endif
{
(void)output_log("%s:%s:ipc_init initialization failure, "
"program abort", APNAME, mname);
return(FALSE);
}
/* initialize 'socloc' client API */
#ifdef IPC_TCP
if ((ret = sloc_initialize()) != SL_OK)
{
sl_code_string(ret, mes);
(void)output_log("%s:%s:socloc init failure,rc[%s]", APNAME, mname, mes);
(void)output_log("%s:%s:program abort", APNAME, mname);
return(FALSE);
}
/* get IP address of this machine */
if (!ip_host2ip(server_host, mes))
{
(void)output_log("%s:%s:unable to obtain IP address "
"of this machine", APNAME, mname);
(void)output_log("%s:%s:program abort", APNAME, mname);
return(FALSE);
}
/* register with 'socloc' */
if ((ret = sloc_add(SYS_LOG_SERVICE_NAME, server_host, server_port,
mes)) != SL_OK)
{
sl_code_string(ret, mes);
(void)output_log("%s:%s:socloc add failure,rc[%s]", APNAME, mname, mes);
(void)output_log("%s:%s:program abort", APNAME, mname);
return(FALSE);
}
#endif
return(TRUE);
}
int process_request(void)
{
/* Process a single request. Function returns 'TRUE'
upon success, 'FALSE' otherwise. */
char *messbuf, *tmp, mname[] = "process_request";
int nbytes, nwords, mestype, slreply, ret;
if ((messbuf = malloc(SYS_LOG_MAXMES)) == NULL)
{
(void)output_log("%s:%s:alloc fail[messbuf]", APNAME, mname);
return(FALSE);
}
memset(messbuf, 0, SYS_LOG_MAXMES);
// get the message from the client
#ifdef IPC_TCP
if ((nbytes = ipc_recv_data(messbuf)) == 0)
#else
if ((nbytes = ipc_recv_data(messbuf, SYS_LOG_MAXMES)) == 0)
#endif
{
free(messbuf);
(void)output_log("%s:%s:connection closed by client", APNAME, mname);
#ifdef IPC_TCP
return(-1);
#else
return(FALSE);
#endif
}
messbuf[nbytes] = EOS;
nwords = command_words(messbuf);
// no command words, empty string
if (!nwords)
{
sys_log_reply(SYS_LOG_UNKNOWN, (char *)NULL);
free(messbuf);
return(FALSE);
}
// first command word must be a number
if ((tmp = (char *)malloc(SYS_LOG_MAXMES)) == NULL)
{
(void)output_log("%s:%s:alloc fail[tmp]", APNAME, mname);
sys_log_reply(SYS_LOG_ALLOC_FAIL, (char *)NULL);
free(messbuf);
return(FALSE);
}
if (!command_word(messbuf, tmp, 1))
{
(void)output_log("%s:%s:error getting message type", APNAME, mname);
sys_log_reply(SYS_LOG_PARM_ERROR, (char *)NULL);
free(tmp);
free(messbuf);
return(FALSE);
}
if (!qatoi(tmp, &mestype))
{
(void)output_log("%s:%s:received an invalid message type",
APNAME, mname);
sys_log_reply(SYS_LOG_UNKNOWN, (char *)NULL);
free(tmp);
free(messbuf);
return(FALSE);
}
free(tmp);
switch(mestype)
{
case SYS_LOG_SEND:
if (nwords < 2)
{
(void)output_log("%s:%s:send:no message to log", APNAME, mname);
sys_log_reply(SYS_LOG_NOMES, (char *)NULL);
free(messbuf);
return(FALSE);
}
slreply = s_message(messbuf);
break;
case SYS_LOG_SEND_STATUS:
slreply = SYS_LOG_OK;
break;
case SYS_LOG_SEND_STOP:
ret = s_terminate(messbuf);
free(messbuf);
return(ret);
break;
case SYS_LOG_SEND_LOCK:
/* refuse to lock if already locked or log
file has been left open */
if (islocked || isopen)
slreply = SYS_LOG_ALREADY_LOCKED;
else
{
islocked = TRUE;
slreply = SYS_LOG_OK;
}
break;
case SYS_LOG_SEND_UNLOCK:
if (!islocked)
slreply = SYS_LOG_ALREADY_UNLOCKED;
else
{
islocked = FALSE;
slreply = SYS_LOG_OK;
}
break;
case SYS_LOG_SEND_OPEN:
/* refuse to open if already open or log
file has been locked */
if (isopen || islocked)
slreply = SYS_LOG_ALREADY_OPEN;
else
{
isopen = TRUE;
slreply = open_log();
}
break;
case SYS_LOG_SEND_CLOSE:
/* refuse to close if already closed or log
file has been locked */
if (!isopen || islocked)
slreply = SYS_LOG_ALREADY_CLOSED;
else
{
isopen = FALSE;
fclose(out);
slreply = SYS_LOG_OK;
}
break;
case SYS_LOG_SEND_DELETE:
/* refuse to delete if file is open or locked */
if (isopen)
slreply = SYS_LOG_ALREADY_OPEN;
else
if (islocked)
slreply = SYS_LOG_ALREADY_LOCKED;
else
{
if ((tmp = (char *)malloc(SYS_LOG_MAXMES)) == NULL)
{
(void)output_log("%s:%s:delete:alloc fail[tmp]",
APNAME, mname);
sys_log_reply(SYS_LOG_ALLOC_FAIL, (char *)NULL);
free(messbuf);
return(FALSE);
}
if (!command_word(messbuf, tmp, 2))
{
(void)output_log("%s:%s:delete:error getting password",
APNAME, mname);
sys_log_reply(SYS_LOG_PARM_ERROR, (char *)NULL);
free(tmp);
free(messbuf);
return(FALSE);
}
if (strcmp(tmp, SYS_LOG_TERM_PASSWD))
slreply = SYS_LOG_NO_ACCESS;
else
{
unlink(server_log);
(void)output_log("%s:%s:delete:primary log deleted",
APNAME, mname);
slreply = SYS_LOG_OK;
}
free(tmp);
}
break;
case SYS_LOG_SEND_LOG_OFF:
/* common socket code turn log off, does not make sense
and is not implemented */
slreply = SYS_LOG_NOT_IMPLEMENTED;
break;
case SYS_LOG_SEND_LOG_ON:
/* common socket code turn log on, does not make sense
and is not implemented */
slreply = SYS_LOG_NOT_IMPLEMENTED;
break;
case SYS_LOG_SEND_LOG_STATUS:
/* reply with ok and the primary and alternate log file
names */
if (words(server_log) > 1 || words(server_alt_log) > 1)
sprintf(messbuf, "1 '%s,%s'", server_log, server_alt_log);
else
sprintf(messbuf, "1 %s,%s", server_log, server_alt_log);
sys_log_reply(SYS_LOG_OK, messbuf);
free(messbuf);
return(FALSE);
break;
case SYS_LOG_SEND_SERVICE_NAME:
sys_log_reply(SYS_LOG_OK, SYS_LOG_SERVICE_NAME);
free(messbuf);
return(FALSE);
break;
case SYS_LOG_SEND_VERSION:
sys_log_reply(SYS_LOG_OK, VERSION);
free(messbuf);
return(FALSE);
break;
case SYS_LOG_SEND_TRANS_NUM:
s_trans_num();
free(messbuf);
return(FALSE);
break;
case SYS_LOG_SEND_CONNECT_NUM:
s_connect_num();
free(messbuf);
return(FALSE);
break;
default:
(void)output_log("%s:%s:received unknown message", APNAME, mname);
slreply = SYS_LOG_UNKNOWN;
break;
};
sys_log_reply(slreply, (char *)NULL);
free(messbuf);
return(FALSE);
}
int s_message(char *comm)
{
// Output a message to the log. Function returns a reply code.
char mname[] = "s_message", *tmp;
int ret, pos, len, newlen;
if ((tmp = (char *)malloc(SYS_LOG_MAXMES)) == (char *)NULL)
{
(void)output_log("%s:%s:send:alloc fail[tmp]", APNAME, mname);
sys_log_reply(SYS_LOG_ALLOC_FAIL, (char *)NULL);
return(SYS_LOG_ALLOC_FAIL);
}
// message starts in second command word
len = strlen(comm);
pos = command_indxword(comm, 2);
newlen = len - pos;
// copy all of message into buffer
strncpy(tmp, &comm[pos], newlen);
tmp[newlen] = EOS;
// if message ends in a quote (single or double), remove it
if (tmp[newlen - 1] == '\'' || tmp[newlen - 1] == '\"')
tmp[newlen - 1] = EOS;
ret = output_log_nf(tmp);
free(tmp);
return(ret);
}
int s_terminate(char *comm)
{
/* Terminate the server. Check the supplied password first.
Syntax:
SL_SEND_TERM password
Function returns 'TRUE' if correct password was supplied,
'FALSE' otherwise. */
char wrd[128], mname[] = "s_terminate";
int ret;
if (command_words(comm) < 2)
{
sys_log_reply(SYS_LOG_PARM_ERROR, (char *)NULL);
(void)output_log("%s:%s:no password", APNAME, mname);
return(FALSE);
}
if (!command_word(comm, wrd, 2))
{
sys_log_reply(SYS_LOG_PARM_ERROR, (char *)NULL);
(void)output_log("%s:%s:error getting password", APNAME, mname);
return(FALSE);
}
if (!strcmp(wrd, SYS_LOG_TERM_PASSWD))
{
sys_log_reply(SYS_LOG_OK, (char *)NULL);
return(TRUE);
}
(void)output_log("%s:%s:illegal terminate request", APNAME, mname);
sys_log_reply(SYS_LOG_NO_ACCESS, (char *)NULL);
return(FALSE);
}
void s_trans_num(void)
{
/* Get the current transaction count. Syntax:
SYS_LOG_SEND_TRANS_NUM */
char mess[128];
long count;
#ifdef IPC_TCP
count = ipc_trans_num();
#else
count = server_trans_num;
#endif
sprintf(mess, "%ld", count);
sys_log_reply(SYS_LOG_OK, mess);
}
void s_connect_num(void)
{
/* Get the current connection count. Syntax:
SYS_LOG_SEND_CONNECT_NUM */
#ifdef IPC_TCP
char mess[128];
int count;
count = ipc_connect_num();
sprintf(mess, "%d", count);
sys_log_reply(SYS_LOG_OK, mess);
#else
sys_log_reply(SYS_LOG_NOT_IMPLEMENTED, (char *)NULL);
#endif
}
void sys_log_reply(int reply_type, char *mess)
{
// Send the reply to the client.
char *reply_char, mname[] = "sys_log_reply";
int len;
len = (mess == (char *)NULL) ? 25 : strlen(mess) + 25;
if ((reply_char = (char *)malloc(len)) == (char *)NULL)
{
output_log("%s:%s:alloc fail[reply_char]", APNAME, mname);
return;
}
memset(reply_char, 0, len);
if (mess != (char *)NULL && strlen(mess))
sprintf(reply_char, "%d %s", reply_type, mess);
else
sprintf(reply_char, "%d", reply_type);
if (ipc_send_data(reply_char) == 0)
output_log("%s:%s:error sending data", APNAME, mname);
free(reply_char);
}
int output_log(char *fmt,...)
{
/* Output 'mess' to the system log file and to the screen.
The message will be prefixed with a header containing
the current date and time. */
va_list argptr;
char *mes;
int ret;
va_start(argptr, fmt);
if ((mes = (char *)malloc(SYS_LOG_MAXMES)) == (char *)NULL)
return(SYS_LOG_ALLOC_FAIL);
vsprintf(mes, fmt, argptr);
ret = output_log_nf(mes);
free(mes);
return(ret);
}
int output_log_nf(char *mes)
{
/* Output 'mess' to the system log file and to the screen.
The message will be prefixed with a header containing
the current date and time. */
char tmch[15];
int ret;
if (mes == (char *)NULL || !strlen(mes))
return(SYS_LOG_PARM_ERROR);
if (!isopen)
if (islocked)
{
if ((out = fopen(server_alt_log, "a")) == NULL)
return(SYS_LOG_WERR);
}
else
if ((ret = open_log()) != SYS_LOG_OK)
return(ret);
get_time(tmch);
fprintf(out, "[%s]%s\n", tmch, mes);
if (console_output)
printf("[%s]%s\n", tmch, mes);
if (!isopen)
fclose(out);
return(SYS_LOG_OK);
}
int open_log(void)
{
/* Open the primary log file. */
if ((out = fopen(server_log, "a")) == NULL)
return(SYS_LOG_WERR);
return(SYS_LOG_OK);
}
int open_alt_log(void)
{
/* Open the alternate log file. */
if ((out = fopen(server_alt_log, "a")) == (FILE *)NULL)
return(SYS_LOG_WERR);
return(SYS_LOG_OK);
}
void term_app(void)
{
// Shutdown anything left open.
#ifdef IPC_TCP
(void)sloc_delete(server_port);
sloc_term_api();
#ifdef OS_WIN32
WSACleanup();
#endif
#else
(void)ipc_close();
#endif
(void)output_log("%s:term_app:server down", APNAME);
}
#ifdef IPC_TCP
void usage(void)
{
/* Display program usage. */
printf("usage:%s [%cq] [%cl server_log][%ca server_alt_log] port\n",
APNAME, SWITCH_CHAR, SWITCH_CHAR, SWITCH_CHAR);
}
#endif