MsgLog.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  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)
  10. * any later version.
  11. *
  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
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*
  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.
  31. *
  32. * MsgLog.c - public interfaces for the Message Logging Service
  33. *
  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).
  39. *
  40. * $TOG: MsgLog.c /main/21 1998/10/26 17:23:21 mgreess $
  41. *
  42. */
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include <stdlib.h>
  46. #include <unistd.h>
  47. #define X_INCLUDE_PWD_H
  48. #define X_INCLUDE_TIME_H
  49. #define XOS_USE_XT_LOCKING
  50. #include <X11/Xos_r.h>
  51. #include <sys/param.h>
  52. #include <limits.h>
  53. #include <Dt/DtPStrings.h>
  54. #ifndef MSGLOG_CLIENT_ONLY
  55. # include <Dt/UserMsg.h>
  56. # include <DtSvcLock.h>
  57. #endif /* MSGLOG_CLIENT_ONLY */
  58. #include <Dt/DtGetMessageP.h>
  59. #include <Dt/MsgLog.h>
  60. #include <Dt/MsgLogI.h>
  61. #define MAX_DATE_TIME_STRING 256
  62. /*
  63. * Static variables
  64. */
  65. static char * information_string = NULL;
  66. static char * stderr_string = NULL;
  67. static char * debug_string = NULL;
  68. static char * warning_string = NULL;
  69. static char * error_string = NULL;
  70. static char * unknown_string = NULL;
  71. #ifndef MSGLOG_CLIENT_ONLY
  72. static DtMsgLogHandler saved_msglog_handler = NULL;
  73. #endif /* MSGLOG_CLIENT_ONLY */
  74. /*
  75. * Static constants
  76. */
  77. static const char * LOGFILE_NAME = DtERRORLOG_FILE;
  78. static const char * TMP_DIR = "/tmp";
  79. static const char * OPEN_FLAG = "a+";
  80. static const int SET_NUM = 50;
  81. #ifdef CDE_LOGFILES_TOP
  82. static const char * CDE_VAR_TMP_DIR = CDE_LOGFILES_TOP ;
  83. #else
  84. static const char * CDE_VAR_TMP_DIR = "/var/dt/tmp";
  85. #endif
  86. /*
  87. * Static function forward declarations
  88. */
  89. static char * get_file_name (
  90. const char * type,
  91. FILE ** fp,
  92. const char * format,
  93. ... );
  94. static char * check_possible_files (
  95. const char * type,
  96. FILE ** fp );
  97. static void initialize_message_strings (void);
  98. /*
  99. * initialize_message_string -
  100. *
  101. * Modified: initializes the static message string variables
  102. *
  103. */
  104. static void initialize_message_strings (void)
  105. {
  106. information_string = strdup (Dt11GETMESSAGE (SET_NUM, 1, "INFORMATION"));
  107. stderr_string = strdup (Dt11GETMESSAGE (SET_NUM, 2, "STDERR"));
  108. debug_string = strdup (Dt11GETMESSAGE (SET_NUM, 3, "DEBUG"));
  109. warning_string = strdup (Dt11GETMESSAGE (SET_NUM, 4, "WARNING"));
  110. error_string = strdup (Dt11GETMESSAGE (SET_NUM, 5, "ERROR"));
  111. unknown_string = strdup (Dt11GETMESSAGE (SET_NUM, 6, "UNKNOWN"));
  112. }
  113. /*
  114. * get_file_name - given a sprintf-like format and a variable
  115. * list of args, create a filename and open the file.
  116. *
  117. * Modified:
  118. *
  119. * fp - set to the opened file or NULL if the open
  120. * fails
  121. *
  122. * Returns: a filename or NULL if the filename cannot be opened
  123. * with mode 'type'.
  124. */
  125. static char * get_file_name (
  126. const char * type,
  127. FILE ** fp, /* MODIFIED */
  128. const char * format,
  129. ... )
  130. {
  131. char *file;
  132. va_list args;
  133. file = malloc(MAXPATHLEN+1);
  134. if (! file) return NULL;
  135. Va_start (args, format);
  136. (void) vsprintf (file, format, args);
  137. va_end (args);
  138. if ((*fp = fopen (file, type)) == NULL)
  139. {
  140. free(file);
  141. return (NULL);
  142. }
  143. return file;
  144. }
  145. /*
  146. * check_possible_files - generates possible filenames to use for
  147. * the message logging.
  148. *
  149. * The first one of the following files that is append'able is
  150. * returned:
  151. *
  152. * o $HOME/DtPERSONAL_CONFIG_DIRECTORY/LOGFILE_NAME
  153. *
  154. * o CDE_VAR_TMP_DIR/$DTUSERSESSION/LOGFILE_NAME
  155. *
  156. * o TMP_DIR/<login_name_from_passwd_file>/LOGFILE_NAME
  157. *
  158. * Note: #2 is only checked if $DTUSERSESSION is defined
  159. *
  160. * Modified:
  161. *
  162. * fp - set to the opened file or NULL if the open
  163. * fails
  164. *
  165. * Returns: a filename if one if found that is append'able or NULL
  166. * if such a file cannot be determined.
  167. */
  168. static char * check_possible_files (
  169. const char * type,
  170. FILE ** fp ) /* MODIFIED */
  171. {
  172. char * file;
  173. char * env;
  174. _Xgetpwparams pwd_buf;
  175. struct passwd * pwd_ret;
  176. if ((file = get_file_name (type,
  177. fp,
  178. "%s/%s/%s",
  179. getenv("HOME"),
  180. DtPERSONAL_CONFIG_DIRECTORY,
  181. LOGFILE_NAME)) != NULL)
  182. return (file);
  183. if ((env = getenv ("DTUSERSESSION")) != NULL) {
  184. if ((file = get_file_name (type,
  185. fp,
  186. "%s/%s/%s",
  187. CDE_VAR_TMP_DIR,
  188. env,
  189. LOGFILE_NAME)) != NULL)
  190. return (file);
  191. }
  192. if ((env = getenv ("LOGNAME")) != NULL) {
  193. if ((file = get_file_name (type,
  194. fp,
  195. "%s/%s.%s",
  196. TMP_DIR,
  197. env,
  198. LOGFILE_NAME)) != NULL)
  199. return (file);
  200. }
  201. if ((env = getenv ("USER")) != NULL) {
  202. if ((file = get_file_name (type,
  203. fp,
  204. "%s/%s.%s",
  205. TMP_DIR,
  206. env,
  207. LOGFILE_NAME)) != NULL)
  208. return (file);
  209. }
  210. if ((pwd_ret = _XGetpwuid (getuid(), pwd_buf)) != NULL) {
  211. if ((file = get_file_name (type,
  212. fp,
  213. "%s/%s.%s",
  214. TMP_DIR,
  215. pwd_ret->pw_name,
  216. LOGFILE_NAME)) != NULL)
  217. return (file);
  218. }
  219. return (NULL);
  220. }
  221. /*
  222. * DtMsgLogMessage -
  223. *
  224. * Returns: 0 if the message is successfully logged or 1 if an
  225. * error occurs and the message is not logged.
  226. */
  227. void DtMsgLogMessage (
  228. const char * program_name,
  229. DtMsgLogType msg_type,
  230. const char * format,
  231. ... )
  232. {
  233. va_list args;
  234. FILE * fp = NULL;
  235. char * file = NULL;
  236. time_t now;
  237. char * msg_string; /* temp msg type string */
  238. int num_bytes;
  239. char buf[MAX_DATE_TIME_STRING];
  240. #ifdef NLS16
  241. char * tmp_format;
  242. #endif
  243. _Xctimeparams ctime_buf;
  244. char * result;
  245. _Xltimeparams localtime_buf;
  246. struct tm * current_time;
  247. Va_start (args, format);
  248. #ifndef MSGLOG_CLIENT_ONLY
  249. _DtSvcProcessLock();
  250. if (saved_msglog_handler != NULL) {
  251. (*saved_msglog_handler) (program_name ? program_name :
  252. DtProgName,
  253. msg_type,
  254. format,
  255. args);
  256. _DtSvcProcessUnlock();
  257. va_end (args);
  258. return;
  259. }
  260. _DtSvcProcessUnlock();
  261. #endif /* MSGLOG_CLIENT_ONLY */
  262. if (!information_string) {
  263. #ifndef MSGLOG_CLIENT_ONLY
  264. _DtSvcProcessLock();
  265. #endif /* MSGLOG_CLIENT_ONLY */
  266. if (!information_string)
  267. initialize_message_strings ();
  268. #ifndef MSGLOG_CLIENT_ONLY
  269. _DtSvcProcessUnlock();
  270. #endif /* MSGLOG_CLIENT_ONLY */
  271. }
  272. /*
  273. * Need to get a copy of the string in case another
  274. * thread calls catgets and puts a different
  275. * string in catgets's static buffer before
  276. * msg_string is output
  277. */
  278. switch (msg_type) {
  279. case DtMsgLogInformation:
  280. msg_string = information_string;
  281. break;
  282. case DtMsgLogStderr:
  283. msg_string = stderr_string;
  284. break;
  285. case DtMsgLogDebug:
  286. msg_string = debug_string;
  287. break;
  288. case DtMsgLogWarning:
  289. msg_string = warning_string;
  290. break;
  291. case DtMsgLogError:
  292. msg_string = error_string;
  293. break;
  294. default:
  295. msg_string = unknown_string;
  296. break;
  297. }
  298. now = time ((time_t)0);
  299. /*
  300. * Write to stderr if a log file cannot be determined
  301. * or if it isn't writeable.
  302. */
  303. if ((fp = DtMsgLogOpenFile (OPEN_FLAG, &file)) == NULL)
  304. fp = stderr;
  305. #ifdef NLS16
  306. current_time = _XLocaltime(&now, localtime_buf);
  307. /*
  308. * Need to save format because the next call to catgets
  309. * may overwrite it on some platforms (if format itself
  310. * is the result of a call to catgets).
  311. */
  312. tmp_format = strdup ((char *) format);
  313. (void) strftime (buf,
  314. MAX_DATE_TIME_STRING,
  315. Dt11GETMESSAGE (48, 1, "%a %b %d %H:%M:%S %Y\n"),
  316. current_time);
  317. num_bytes = fprintf (fp, "*** %s(%d): %s: PID %d: %s",
  318. msg_string, msg_type,
  319. #ifndef MSGLOG_CLIENT_ONLY
  320. program_name ? program_name : DtProgName,
  321. #else
  322. program_name ? program_name : "",
  323. #endif /* MSGLOG_CLIENT_ONLY */
  324. getpid(), buf);
  325. #else
  326. result = _XCtime(&now, ctime_buf);
  327. num_bytes = fprintf (fp, "*** %s(%d): %s: PID %ld: %s",
  328. msg_string, msg_type,
  329. #ifndef MSGLOG_CLIENT_ONLY
  330. program_name ? program_name : DtProgName,
  331. #else
  332. program_name ? program_name : "",
  333. #endif /* MSGLOG_CLIENT_ONLY */
  334. (long)getpid(), result);
  335. #endif
  336. #ifdef NLS16
  337. num_bytes += vfprintf (fp, tmp_format, args);
  338. free (tmp_format);
  339. #else
  340. num_bytes += vfprintf (fp, format, args);
  341. #endif
  342. va_end (args);
  343. // JET - extraneous noise, just output the count
  344. // fprintf (fp, "\n*** [%d]\n\n", num_bytes);
  345. fprintf (fp, "[%d bytes]\n\n", num_bytes);
  346. if (fp != stderr) {
  347. (void) fflush (fp);
  348. (void) fclose(fp);
  349. }
  350. if (file)
  351. free (file);
  352. }
  353. #ifndef MSGLOG_CLIENT_ONLY
  354. /*
  355. * DtMsgLogSetHandler - caches an alternate message logging
  356. * handler
  357. *
  358. * Modified:
  359. *
  360. * saved_msglog_handler - set to the given handler
  361. *
  362. * Returns: if handler is NULL, the default handler is restored;
  363. * returns a pointer to the previous handler
  364. *
  365. */
  366. DtMsgLogHandler DtMsgLogSetHandler (
  367. DtMsgLogHandler handler )
  368. {
  369. DtMsgLogHandler previous_handler;
  370. _DtSvcProcessLock();
  371. if (handler == NULL) {
  372. if (saved_msglog_handler) {
  373. previous_handler = saved_msglog_handler;
  374. saved_msglog_handler = NULL;
  375. return (previous_handler);
  376. }
  377. else {
  378. saved_msglog_handler = NULL;
  379. return (DtMsgLogHandler) DtMsgLogMessage;
  380. }
  381. }
  382. if (saved_msglog_handler)
  383. previous_handler = saved_msglog_handler;
  384. else
  385. previous_handler = (DtMsgLogHandler) DtMsgLogMessage;
  386. saved_msglog_handler = handler;
  387. _DtSvcProcessUnlock();
  388. return (previous_handler);
  389. }
  390. #endif /* MSGLOG_CLIENT_ONLY */
  391. /*
  392. * DtMsgLogOpenFile - opens the logfile
  393. *
  394. * Returns: returns a pointer to the opened logfile; if a logfile
  395. * cannot be opened, stderr is returned
  396. *
  397. * Modified:
  398. *
  399. * fp - is set to the opened file
  400. *
  401. * filename_return - will be set to the filename if it
  402. * if it is not NULL and a file is opened. If filename_return
  403. * is not NULL and and a file is opened, the calling function
  404. * should free the space allocated for the filename.
  405. */
  406. FILE * DtMsgLogOpenFile (
  407. const char * type,
  408. char ** filename_return) /* MODIFIED */
  409. {
  410. FILE * fp = NULL;
  411. char * pch;
  412. pch = check_possible_files (type, &fp);
  413. if (filename_return)
  414. *filename_return = pch;
  415. else if (pch)
  416. free (pch);
  417. if (!fp)
  418. fp = stderr;
  419. return (fp);
  420. }