2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1995 Digital Equipment Corporation.
25 * (c) Copyright 1995 Hewlett-Packard Company.
26 * (c) Copyright 1995 International Business Machines Corp.
27 * (c) Copyright 1995 Sun Microsystems, Inc.
28 * (c) Copyright 1995 Novell, Inc.
29 * (c) Copyright 1995 FUJITSU LIMITED.
30 * (c) Copyright 1995 Hitachi.
32 * MsgLog.c - public interfaces for the Message Logging Service
34 * NOTE: the cpp define MSGLOG_CLIENT_ONLY is not defined when this
35 * file is compiled for the DtSvc library. MSGLOG_CLIENT_ONLY
36 * is only defined when an application intends to use these
37 * routines directly because the application does not to build
38 * in a dependecy to the DtSvc library (e.g. dtexec).
40 * $TOG: MsgLog.c /main/21 1998/10/26 17:23:21 mgreess $
48 #define X_INCLUDE_PWD_H
49 #define X_INCLUDE_TIME_H
50 #define XOS_USE_XT_LOCKING
51 #include <X11/Xos_r.h>
52 #include <sys/param.h>
55 #include <Dt/DtPStrings.h>
56 #ifndef MSGLOG_CLIENT_ONLY
57 # include <Dt/UserMsg.h>
58 # include <DtSvcLock.h>
59 #endif /* MSGLOG_CLIENT_ONLY */
60 #include <Dt/DtGetMessageP.h>
61 #include <Dt/MsgLog.h>
62 #include <Dt/MsgLogI.h>
64 #define MAX_DATE_TIME_STRING 256
69 static char * information_string = NULL;
70 static char * stderr_string = NULL;
71 static char * debug_string = NULL;
72 static char * warning_string = NULL;
73 static char * error_string = NULL;
74 static char * unknown_string = NULL;
75 #ifndef MSGLOG_CLIENT_ONLY
76 static DtMsgLogHandler saved_msglog_handler = NULL;
77 #endif /* MSGLOG_CLIENT_ONLY */
83 static const char * LOGFILE_NAME = DtERRORLOG_FILE;
84 static const char * TMP_DIR = "/tmp";
85 static const char * OPEN_FLAG = "a+";
86 static const int SET_NUM = 50;
88 #ifdef CDE_LOGFILES_TOP
89 static const char * CDE_VAR_TMP_DIR = CDE_LOGFILES_TOP ;
91 static const char * CDE_VAR_TMP_DIR = "/var/dt/tmp";
96 * Static function forward declarations
98 static char * get_file_name (
103 static char * check_possible_files (
106 static void initialize_message_strings (void);
110 * initialize_message_string -
112 * Modified: initializes the static message string variables
115 static void initialize_message_strings (void)
117 information_string = strdup (Dt11GETMESSAGE (SET_NUM, 1, "INFORMATION"));
118 stderr_string = strdup (Dt11GETMESSAGE (SET_NUM, 2, "STDERR"));
119 debug_string = strdup (Dt11GETMESSAGE (SET_NUM, 3, "DEBUG"));
120 warning_string = strdup (Dt11GETMESSAGE (SET_NUM, 4, "WARNING"));
121 error_string = strdup (Dt11GETMESSAGE (SET_NUM, 5, "ERROR"));
122 unknown_string = strdup (Dt11GETMESSAGE (SET_NUM, 6, "UNKNOWN"));
127 * get_file_name - given a sprintf-like format and a variable
128 * list of args, create a filename and open the file.
132 * fp - set to the opened file or NULL if the open
135 * Returns: a filename or NULL if the filename cannot be opened
138 static char * get_file_name (
140 FILE ** fp, /* MODIFIED */
147 file = malloc(MAXPATHLEN+1);
150 Va_start (args, format);
152 (void) vsprintf (file, format, args);
155 if ((*fp = fopen (file, type)) == NULL)
165 * check_possible_files - generates possible filenames to use for
166 * the message logging.
168 * The first one of the following files that is append'able is
171 * o $HOME/DtPERSONAL_CONFIG_DIRECTORY/LOGFILE_NAME
173 * o CDE_VAR_TMP_DIR/$DTUSERSESSION/LOGFILE_NAME
175 * o TMP_DIR/<login_name_from_passwd_file>/LOGFILE_NAME
177 * Note: #2 is only checked if $DTUSERSESSION is defined
181 * fp - set to the opened file or NULL if the open
184 * Returns: a filename if one if found that is append'able or NULL
185 * if such a file cannot be determined.
187 static char * check_possible_files (
189 FILE ** fp ) /* MODIFIED */
193 _Xgetpwparams pwd_buf;
194 struct passwd * pwd_ret;
196 if ((file = get_file_name (type,
200 DtPERSONAL_CONFIG_DIRECTORY,
201 LOGFILE_NAME)) != NULL)
204 if ((env = getenv ("DTUSERSESSION")) != NULL) {
205 if ((file = get_file_name (type,
210 LOGFILE_NAME)) != NULL)
214 if ((env = getenv ("LOGNAME")) != NULL) {
215 if ((file = get_file_name (type,
220 LOGFILE_NAME)) != NULL)
224 if ((env = getenv ("USER")) != NULL) {
225 if ((file = get_file_name (type,
230 LOGFILE_NAME)) != NULL)
234 if ((pwd_ret = _XGetpwuid (getuid(), pwd_buf)) != NULL) {
235 if ((file = get_file_name (type,
240 LOGFILE_NAME)) != NULL)
250 * Returns: 0 if the message is successfully logged or 1 if an
251 * error occurs and the message is not logged.
253 void DtMsgLogMessage (
254 const char * program_name,
255 DtMsgLogType msg_type,
263 char * msg_string; /* temp msg type string */
265 char buf[MAX_DATE_TIME_STRING];
269 _Xctimeparams ctime_buf;
271 _Xltimeparams localtime_buf;
272 struct tm * current_time;
274 Va_start (args, format);
276 #ifndef MSGLOG_CLIENT_ONLY
278 if (saved_msglog_handler != NULL) {
280 (*saved_msglog_handler) (program_name ? program_name :
285 _DtSvcProcessUnlock();
290 _DtSvcProcessUnlock();
291 #endif /* MSGLOG_CLIENT_ONLY */
293 if (!information_string) {
294 #ifndef MSGLOG_CLIENT_ONLY
296 #endif /* MSGLOG_CLIENT_ONLY */
297 if (!information_string)
298 initialize_message_strings ();
299 #ifndef MSGLOG_CLIENT_ONLY
300 _DtSvcProcessUnlock();
301 #endif /* MSGLOG_CLIENT_ONLY */
305 * Need to get a copy of the string in case another
306 * thread calls catgets and puts a different
307 * string in catgets's static buffer before
308 * msg_string is output
311 case DtMsgLogInformation:
312 msg_string = information_string;
315 msg_string = stderr_string;
318 msg_string = debug_string;
320 case DtMsgLogWarning:
321 msg_string = warning_string;
324 msg_string = error_string;
327 msg_string = unknown_string;
331 now = time ((time_t)0);
334 * Write to stderr if a log file cannot be determined
335 * or if it isn't writeable.
337 if ((fp = DtMsgLogOpenFile (OPEN_FLAG, &file)) == NULL)
341 current_time = _XLocaltime(&now, localtime_buf);
343 * Need to save format because the next call to catgets
344 * may overwrite it on some platforms (if format itself
345 * is the result of a call to catgets).
347 tmp_format = strdup ((char *) format);
349 (void) strftime (buf,
350 MAX_DATE_TIME_STRING,
351 Dt11GETMESSAGE (48, 1, "%a %b %d %H:%M:%S %Y\n"),
354 num_bytes = fprintf (fp, "*** %s(%d): %s: PID %d: %s",
355 msg_string, msg_type,
356 #ifndef MSGLOG_CLIENT_ONLY
357 program_name ? program_name : DtProgName,
359 program_name ? program_name : "",
360 #endif /* MSGLOG_CLIENT_ONLY */
363 result = _XCtime(&now, ctime_buf);
364 num_bytes = fprintf (fp, "*** %s(%d): %s: PID %ld: %s",
365 msg_string, msg_type,
366 #ifndef MSGLOG_CLIENT_ONLY
367 program_name ? program_name : DtProgName,
369 program_name ? program_name : "",
370 #endif /* MSGLOG_CLIENT_ONLY */
371 (long)getpid(), result);
375 num_bytes += vfprintf (fp, tmp_format, args);
378 num_bytes += vfprintf (fp, format, args);
382 fprintf (fp, "\n*** [%d]\n\n", num_bytes);
394 #ifndef MSGLOG_CLIENT_ONLY
396 * DtMsgLogSetHandler - caches an alternate message logging
401 * saved_msglog_handler - set to the given handler
403 * Returns: if handler is NULL, the default handler is restored;
404 * returns a pointer to the previous handler
407 DtMsgLogHandler DtMsgLogSetHandler (
408 DtMsgLogHandler handler )
410 DtMsgLogHandler previous_handler;
413 if (handler == NULL) {
414 if (saved_msglog_handler) {
415 previous_handler = saved_msglog_handler;
416 saved_msglog_handler = NULL;
417 return (previous_handler);
420 saved_msglog_handler = NULL;
421 return (DtMsgLogHandler) DtMsgLogMessage;
425 if (saved_msglog_handler)
426 previous_handler = saved_msglog_handler;
428 previous_handler = (DtMsgLogHandler) DtMsgLogMessage;
430 saved_msglog_handler = handler;
431 _DtSvcProcessUnlock();
432 return (previous_handler);
434 #endif /* MSGLOG_CLIENT_ONLY */
438 * DtMsgLogOpenFile - opens the logfile
440 * Returns: returns a pointer to the opened logfile; if a logfile
441 * cannot be opened, stderr is returned
445 * fp - is set to the opened file
447 * filename_return - will be set to the filename if it
448 * if it is not NULL and a file is opened. If filename_return
449 * is not NULL and and a file is opened, the calling function
450 * should free the space allocated for the filename.
452 FILE * DtMsgLogOpenFile (
454 char ** filename_return) /* MODIFIED */
459 pch = check_possible_files (type, &fp);
462 *filename_return = pch;