Use C++ linker
[oweals/cde.git] / cde / programs / dtlogin / error.c
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 librararies 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 1993, 1994 Hewlett-Packard Company                     *
25  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
26  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
27  * (c) Copyright 1993, 1994 Novell, Inc.                                *
28  */
29 /*
30  * xdm - display manager daemon
31  *
32  * $XConsortium: error.c /main/6 1996/10/21 12:50:31 mgreess $
33  *
34  * Copyright 1988 Massachusetts Institute of Technology
35  *
36  * Permission to use, copy, modify, and distribute this software and its
37  * documentation for any purpose and without fee is hereby granted, provided
38  * that the above copyright notice appear in all copies and that both that
39  * copyright notice and this permission notice appear in supporting
40  * documentation, and that the name of M.I.T. not be used in advertising or
41  * publicity pertaining to distribution of the software without specific,
42  * written prior permission.  M.I.T. makes no representations about the
43  * suitability of this software for any purpose.  It is provided "as is"
44  * without express or implied warranty.
45  *
46  * Author:  Keith Packard, MIT X Consortium
47  */
48
49 /*
50  * error.c
51  *
52  * Log display manager errors to a file as
53  * we generally do not have a terminal to talk to
54  */
55
56 # include <sys/stat.h>
57 # include <time.h>
58 # include "dm.h"
59 # include "vgmsg.h"
60
61 # include <stdarg.h>
62 # define Va_start(a,b) va_start(a,b)
63
64 extern char     DisplayName[];
65
66 void
67 InitErrorLog( void )
68 {
69         int     i;
70
71         static  char tz[32];
72         
73         
74         /*
75          *  add TimeZone to our environment so error message time stamps
76          *  have the correct value...
77          */
78          
79         if (timeZone != NULL && strlen(timeZone) < 29) {
80             strcpy(tz,"TZ=");
81             strcat(tz,timeZone);
82             putenv(tz);
83         }
84
85
86         if (errorLogFile && errorLogFile[0]) {
87                 i = creat (errorLogFile, 0666);
88                 if (i != -1) {
89                         if (i != 2) {
90                                 dup2 (i, 2);
91                                 close (i);
92                         }
93                 } else
94                         LogError(ReadCatalog(
95                           MC_LOG_SET,MC_LOG_NO_ERRLOG,MC_DEF_LOG_NO_ERRLOG),
96                           errorLogFile);
97         }
98 }
99
100 /****************************************************************************
101  *
102  * CheckErrorFile
103  *
104  * Just a quick check to verify that we can open an error log.
105  * Do this before we do BecomeDeamon.
106  *
107  ****************************************************************************/
108 void
109 CheckErrorFile( void )
110 {
111         int     i;
112
113         if (errorLogFile && errorLogFile[0]) {
114                 i = creat (errorLogFile, 0666);
115                 if (i != -1) {
116                         close (i);
117                 } else {
118                         fprintf(stderr, (char *)ReadCatalog(
119                               MC_LOG_SET,MC_LOG_NO_ERRLOG,MC_DEF_LOG_NO_ERRLOG),
120                               errorLogFile);
121                 }
122         } else {
123                 fprintf(stderr, (char *)ReadCatalog(
124                         MC_LOG_SET,MC_LOG_NO_ERRLOG,MC_DEF_LOG_NO_ERRLOG),
125                         "\"\"");
126         }
127 }
128
129
130 /****************************************************************************
131  *
132  *  SyncErrorFile
133  *
134  *  point the stderr stream to the most current Error Log File. This allows
135  *  the user to muck with the file while XDM is running and have everything
136  *  sync up later.
137  *
138  *  optionally, write a time stamp to the file
139  ****************************************************************************/
140
141 int 
142 SyncErrorFile( int stamp )
143 {
144     time_t   timer;
145     
146     TrimErrorFile();
147     if (errorLogFile && errorLogFile[0] && 
148         (freopen(errorLogFile, "a", stderr) != NULL)) {
149
150         if (stamp) {
151             timer = time(NULL);
152             fprintf(stderr, "\n%s", ctime(&timer));
153         }           
154         return(1);
155     }
156     else
157         return(0);
158 }
159
160
161 /****************************************************************************
162  *
163  *  TrimErrorFile
164  *
165  *  Trim the length of the error log file until it is 75% of the maximum
166  *  specified by the resource "errorLogSize".
167  *
168  ****************************************************************************/
169
170 void
171 TrimErrorFile( void )
172 {
173
174     int  f1, f2;
175     int  deleteBytes;
176     
177     char buf[BUFSIZ];
178     char *p;
179     int  n;
180
181     off_t status;
182     struct stat statb;
183
184
185     /*
186      *  convert user-specified units of 1Kb to bytes...
187      *  put an upper cap of 200Kb on the file...
188      */
189
190     if (errorLogSize < 1024) errorLogSize *= 1024;
191          
192     if (errorLogSize > (200*1024) ) {
193         errorLogSize = 200*1024;
194         LogError(ReadCatalog(
195                 MC_LOG_SET,MC_LOG_MAX_LOGFILE,MC_DEF_LOG_MAX_LOGFILE));
196     }
197             
198     if ( errorLogFile && errorLogFile[0]  && 
199         (stat(errorLogFile, &statb) == 0) && 
200         (statb.st_size > errorLogSize)           ) {
201     
202         deleteBytes = (statb.st_size - errorLogSize) + (errorLogSize / 4);
203
204         Debug("TrimErrorLog(): discarding oldest %d bytes from logfile %s\n",
205                  deleteBytes, errorLogFile);
206
207
208         /*
209          *  get two pointers to the file...
210          */
211          
212         if ( (f1 = open(errorLogFile, O_RDWR)) < 0 ||
213              (f2 = open(errorLogFile, O_RDWR)) < 0    ) {
214             Debug("TrimErrorLog(): Cannot open file %s, error number = %d\n",
215                    errorLogFile, errno);
216             return;
217         }
218                             
219
220         /*
221          *  position read pointer to the first full line after the trim
222          *  point...
223          */
224                  
225         if ( (status = lseek(f2, deleteBytes, SEEK_SET)) < 0 ) {
226             Debug("TrimErrorLog(): Cannot lseek() in file %s, error number = %d\n",
227                    errorLogFile, errno);
228             return;
229         }
230
231         n = read(f2, buf, BUFSIZ);
232
233         if ( (p = strchr(buf,'\n')) != NULL ) {
234             p++; 
235             n -= p - buf;
236             deleteBytes += p - buf;
237         }           
238         else {
239             p = buf;
240         }
241         
242
243         /*
244          *  shift bytes to be saved to the beginning of the file...
245          */
246          
247         write (f1, p, n);
248         
249         while ( (n = read(f2, buf, BUFSIZ)) > 0 )
250             write(f1, buf, n);
251
252         /*
253          *  truncate file to new length and close file pointers...
254          */
255          
256         truncate(errorLogFile, statb.st_size - deleteBytes);
257         close(f1);
258         close(f2);
259     }
260
261 }
262
263
264
265 /****************************************************************************
266  *
267  *  LogInfo
268  *
269  *  Write an information message to the log file
270  *
271  ****************************************************************************/
272
273 void 
274 LogInfo( unsigned char *fmt, ...)
275 {
276     va_list  args;
277
278     Va_start(args,fmt);
279
280     if ( SyncErrorFile(1) ) {
281         fprintf (stderr, "info (pid %ld): ", (long)getpid());
282         vfprintf (stderr, (char *)fmt, args);
283         fflush (stderr);
284     }
285
286     va_end(args);
287 }
288
289
290
291 /****************************************************************************
292  *
293  *  LogError
294  *
295  *  Write an error message to the log file.
296  *
297  ****************************************************************************/
298
299 void 
300 LogError( unsigned char *fmt, ...)
301 {
302     va_list  args;
303
304     Va_start(args,fmt);
305
306     if ( SyncErrorFile(1) ) {
307         fprintf (stderr, "error (pid %ld): ", (long)getpid());
308         vfprintf (stderr, (char *)fmt, args);
309         fflush (stderr);
310     }
311
312     va_end(args);
313 }
314
315
316
317 /****************************************************************************
318  *
319  *  LogOutOfMem
320  *
321  *  Write an "out of memory" message to the log file.
322  *
323  ****************************************************************************/
324
325 void 
326 LogOutOfMem( unsigned char *fmt, ...)
327 {
328     va_list  args;
329
330     Va_start(args,fmt);
331
332     if ( SyncErrorFile(1) ) {
333         fprintf(stderr,(char *)ReadCatalog(MC_ERROR_SET,MC_NO_MEMORY,MC_DEF_NO_MEMORY));
334         vfprintf (stderr, (char *)fmt, args);
335         fflush (stderr);
336     }
337
338     va_end(args);
339 }
340
341
342
343 /***************************************************************************
344  *
345  *  CODE DISABLED!!! The following routines...
346  *
347  *                      getLocalAddress()
348  *                      scanHostList()
349  *                      indirectAlias()
350  *                      ForEachMatchingIndirectHost()
351  *                      UseChooser()
352  *                      ForEachChooserHost()
353  *
354  *                   are disabled until indirect queries are supported...
355  *
356  ***************************************************************************/
357 #if 0
358
359
360 /****************************************************************************
361  *
362  *  LogPanic
363  *
364  *  Write a panic message to the log file.
365  *
366  ****************************************************************************/
367 void 
368 LogPanic( char *fmt, ...)
369 {
370     va_list  args;
371
372     Va_start(args,fmt);
373
374     if ( SyncErrorFile(1) ) {
375         fprintf (stderr, "panic (pid %ld): ", (long)getpid());
376         vfprintf (stderr, fmt, args);
377         fflush (stderr);
378     }
379
380     va_end(args);
381 }
382
383
384
385 /****************************************************************************
386  *
387  *  Panic
388  *
389  *  Write a panic message to the console
390  *
391  ****************************************************************************/
392
393 int 
394 Panic( char *mesg )
395 {
396     int i;
397
398     i = creat ("/dev/console", 0666);
399     write (i, "panic: ", 7);
400     write (i, mesg, strlen (mesg));
401     exit (1);
402 }
403 #endif /* DISABLED CODE */
404
405
406
407 /****************************************************************************
408  *
409  *  Debug
410  *
411  *  Write a debug message to stdout
412  *
413  ****************************************************************************/
414
415 static int  DoName=True;
416
417 void 
418 Debug( char *fmt, ...)
419 {
420     va_list  args;
421
422     Va_start(args,fmt);
423
424     if (debugLevel > 0)
425     {
426         if ( strlen(DisplayName) > 0 && DoName)
427             fprintf(stdout, "(%s) ", DisplayName);
428
429         vprintf (fmt, args);
430         fflush (stdout);
431
432         /*
433          * don't prepend the display name next time if this debug message
434          * does not contain a "new line" character...
435          */
436
437         if ( strchr(fmt,'\n') == NULL )
438             DoName=False;
439         else
440             DoName=True;
441             
442     }
443
444     va_end(args);
445 }