454 lines
10 KiB
C
454 lines
10 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these librararies and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* *
|
|
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
|
|
* (c) Copyright 1993, 1994 International Business Machines Corp. *
|
|
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
|
|
* (c) Copyright 1993, 1994 Novell, Inc. *
|
|
*/
|
|
/*
|
|
* xdm - display manager daemon
|
|
*
|
|
* $XConsortium: error.c /main/6 1996/10/21 12:50:31 mgreess $
|
|
*
|
|
* Copyright 1988 Massachusetts Institute of Technology
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software and its
|
|
* documentation for any purpose and without fee is hereby granted, provided
|
|
* that the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of M.I.T. not be used in advertising or
|
|
* publicity pertaining to distribution of the software without specific,
|
|
* written prior permission. M.I.T. makes no representations about the
|
|
* suitability of this software for any purpose. It is provided "as is"
|
|
* without express or implied warranty.
|
|
*
|
|
* Author: Keith Packard, MIT X Consortium
|
|
*/
|
|
|
|
/*
|
|
* error.c
|
|
*
|
|
* Log display manager errors to a file as
|
|
* we generally do not have a terminal to talk to
|
|
*/
|
|
|
|
# include <sys/stat.h>
|
|
# include <time.h>
|
|
# include "dm.h"
|
|
# include "vgmsg.h"
|
|
|
|
# include <stdarg.h>
|
|
# define Va_start(a,b) va_start(a,b)
|
|
|
|
extern char DisplayName[];
|
|
|
|
void
|
|
InitErrorLog( void )
|
|
{
|
|
int i;
|
|
|
|
static char tz[32];
|
|
|
|
|
|
/*
|
|
* add TimeZone to our environment so error message time stamps
|
|
* have the correct value...
|
|
*/
|
|
|
|
if (timeZone != NULL && strlen(timeZone) < 29) {
|
|
strcpy(tz,"TZ=");
|
|
strcat(tz,timeZone);
|
|
putenv(tz);
|
|
}
|
|
|
|
|
|
if (errorLogFile && errorLogFile[0]) {
|
|
i = creat (errorLogFile, 0666);
|
|
if (i != -1) {
|
|
if (i != 2) {
|
|
dup2 (i, 2);
|
|
close (i);
|
|
}
|
|
} else
|
|
LogError(ReadCatalog(
|
|
MC_LOG_SET,MC_LOG_NO_ERRLOG,MC_DEF_LOG_NO_ERRLOG),
|
|
errorLogFile);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CheckErrorFile
|
|
*
|
|
* Just a quick check to verify that we can open an error log.
|
|
* Do this before we do BecomeDeamon.
|
|
*
|
|
****************************************************************************/
|
|
void
|
|
CheckErrorFile( void )
|
|
{
|
|
int i;
|
|
|
|
if (errorLogFile && errorLogFile[0]) {
|
|
i = creat (errorLogFile, 0666);
|
|
if (i != -1) {
|
|
close (i);
|
|
} else {
|
|
fprintf(stderr, (char *)ReadCatalog(
|
|
MC_LOG_SET,MC_LOG_NO_ERRLOG,MC_DEF_LOG_NO_ERRLOG),
|
|
errorLogFile);
|
|
}
|
|
} else {
|
|
fprintf(stderr, (char *)ReadCatalog(
|
|
MC_LOG_SET,MC_LOG_NO_ERRLOG,MC_DEF_LOG_NO_ERRLOG),
|
|
"\"\"");
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* SyncErrorFile
|
|
*
|
|
* point the stderr stream to the most current Error Log File. This allows
|
|
* the user to muck with the file while XDM is running and have everything
|
|
* sync up later.
|
|
*
|
|
* optionally, write a time stamp to the file
|
|
****************************************************************************/
|
|
|
|
int
|
|
SyncErrorFile( int stamp )
|
|
{
|
|
time_t timer;
|
|
|
|
TrimErrorFile();
|
|
if (errorLogFile && errorLogFile[0] &&
|
|
(freopen(errorLogFile, "a", stderr) != NULL)) {
|
|
|
|
if (stamp) {
|
|
timer = time(NULL);
|
|
fprintf(stderr, "\n%s", ctime(&timer));
|
|
}
|
|
return(1);
|
|
}
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* TrimErrorFile
|
|
*
|
|
* Trim the length of the error log file until it is 75% of the maximum
|
|
* specified by the resource "errorLogSize".
|
|
*
|
|
****************************************************************************/
|
|
|
|
void
|
|
TrimErrorFile( void )
|
|
{
|
|
|
|
int f1, f2;
|
|
int deleteBytes;
|
|
|
|
char buf[BUFSIZ];
|
|
char *p;
|
|
int n;
|
|
|
|
off_t status;
|
|
struct stat statb;
|
|
|
|
|
|
/*
|
|
* convert user-specified units of 1Kb to bytes...
|
|
* put an upper cap of 200Kb on the file...
|
|
*/
|
|
|
|
if (errorLogSize < 1024) errorLogSize *= 1024;
|
|
|
|
if (errorLogSize > (200*1024) ) {
|
|
errorLogSize = 200*1024;
|
|
LogError(ReadCatalog(
|
|
MC_LOG_SET,MC_LOG_MAX_LOGFILE,MC_DEF_LOG_MAX_LOGFILE));
|
|
}
|
|
|
|
if ( errorLogFile && errorLogFile[0] &&
|
|
(stat(errorLogFile, &statb) == 0) &&
|
|
(statb.st_size > errorLogSize) ) {
|
|
|
|
deleteBytes = (statb.st_size - errorLogSize) + (errorLogSize / 4);
|
|
|
|
Debug("TrimErrorLog(): discarding oldest %d bytes from logfile %s\n",
|
|
deleteBytes, errorLogFile);
|
|
|
|
|
|
/*
|
|
* get two pointers to the file...
|
|
*/
|
|
|
|
if ( (f1 = open(errorLogFile, O_RDWR)) < 0 ||
|
|
(f2 = open(errorLogFile, O_RDWR)) < 0 ) {
|
|
Debug("TrimErrorLog(): Cannot open file %s, error number = %d\n",
|
|
errorLogFile, errno);
|
|
if(f1 >= 0) {
|
|
close(f1);
|
|
}
|
|
if(f2 >= 0) {
|
|
close(f2);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* position read pointer to the first full line after the trim
|
|
* point...
|
|
*/
|
|
|
|
if ( (status = lseek(f2, deleteBytes, SEEK_SET)) < 0 ) {
|
|
Debug("TrimErrorLog(): Cannot lseek() in file %s, error number = %d\n",
|
|
errorLogFile, errno);
|
|
close(f1);
|
|
close(f2);
|
|
return;
|
|
}
|
|
|
|
n = read(f2, buf, BUFSIZ);
|
|
|
|
if ( (p = strchr(buf,'\n')) != NULL ) {
|
|
p++;
|
|
n -= p - buf;
|
|
deleteBytes += p - buf;
|
|
}
|
|
else {
|
|
p = buf;
|
|
}
|
|
|
|
|
|
/*
|
|
* shift bytes to be saved to the beginning of the file...
|
|
*/
|
|
|
|
write (f1, p, n);
|
|
|
|
while ( (n = read(f2, buf, BUFSIZ)) > 0 )
|
|
write(f1, buf, n);
|
|
|
|
/*
|
|
* truncate file to new length and close file pointers...
|
|
*/
|
|
|
|
truncate(errorLogFile, statb.st_size - deleteBytes);
|
|
close(f1);
|
|
close(f2);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* LogInfo
|
|
*
|
|
* Write an information message to the log file
|
|
*
|
|
****************************************************************************/
|
|
|
|
void
|
|
LogInfo( unsigned char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
Va_start(args,fmt);
|
|
|
|
if ( SyncErrorFile(1) ) {
|
|
fprintf (stderr, "info (pid %ld): ", (long)getpid());
|
|
vfprintf (stderr, (char *)fmt, args);
|
|
fflush (stderr);
|
|
}
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* LogError
|
|
*
|
|
* Write an error message to the log file.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void
|
|
LogError( unsigned char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
Va_start(args,fmt);
|
|
|
|
if ( SyncErrorFile(1) ) {
|
|
fprintf (stderr, "error (pid %ld): ", (long)getpid());
|
|
vfprintf (stderr, (char *)fmt, args);
|
|
fflush (stderr);
|
|
}
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* LogOutOfMem
|
|
*
|
|
* Write an "out of memory" message to the log file.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void
|
|
LogOutOfMem( unsigned char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
Va_start(args,fmt);
|
|
|
|
if ( SyncErrorFile(1) ) {
|
|
fprintf(stderr, "%s", (char *)ReadCatalog(MC_ERROR_SET,MC_NO_MEMORY,MC_DEF_NO_MEMORY));
|
|
vfprintf (stderr, (char *)fmt, args);
|
|
fflush (stderr);
|
|
}
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* CODE DISABLED!!! The following routines...
|
|
*
|
|
* getLocalAddress()
|
|
* scanHostList()
|
|
* indirectAlias()
|
|
* ForEachMatchingIndirectHost()
|
|
* UseChooser()
|
|
* ForEachChooserHost()
|
|
*
|
|
* are disabled until indirect queries are supported...
|
|
*
|
|
***************************************************************************/
|
|
#if 0
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* LogPanic
|
|
*
|
|
* Write a panic message to the log file.
|
|
*
|
|
****************************************************************************/
|
|
void
|
|
LogPanic( char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
Va_start(args,fmt);
|
|
|
|
if ( SyncErrorFile(1) ) {
|
|
fprintf (stderr, "panic (pid %ld): ", (long)getpid());
|
|
vfprintf (stderr, fmt, args);
|
|
fflush (stderr);
|
|
}
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Panic
|
|
*
|
|
* Write a panic message to the console
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
Panic( char *mesg )
|
|
{
|
|
int i;
|
|
|
|
i = creat ("/dev/console", 0666);
|
|
write (i, "panic: ", 7);
|
|
write (i, mesg, strlen (mesg));
|
|
exit (1);
|
|
}
|
|
#endif /* DISABLED CODE */
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Debug
|
|
*
|
|
* Write a debug message to stdout
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int DoName=True;
|
|
|
|
void
|
|
Debug( char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
Va_start(args,fmt);
|
|
|
|
if (debugLevel > 0)
|
|
{
|
|
if ( strlen(DisplayName) > 0 && DoName)
|
|
fprintf(stdout, "(%s) ", DisplayName);
|
|
|
|
vprintf (fmt, args);
|
|
fflush (stdout);
|
|
|
|
/*
|
|
* don't prepend the display name next time if this debug message
|
|
* does not contain a "new line" character...
|
|
*/
|
|
|
|
if ( strchr(fmt,'\n') == NULL )
|
|
DoName=False;
|
|
else
|
|
DoName=True;
|
|
|
|
}
|
|
|
|
va_end(args);
|
|
}
|