dtlogin: Two additional coverity fixes
[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 = -1;
175     int  f2 = -1;
176     int  deleteBytes;
177     
178     char buf[BUFSIZ];
179     char *p;
180     int  n;
181
182     off_t status;
183     struct stat statb;
184
185
186     /*
187      *  convert user-specified units of 1Kb to bytes...
188      *  put an upper cap of 200Kb on the file...
189      */
190
191     if (errorLogSize < 1024) errorLogSize *= 1024;
192          
193     if (errorLogSize > (200*1024) ) {
194         errorLogSize = 200*1024;
195         LogError(ReadCatalog(
196                 MC_LOG_SET,MC_LOG_MAX_LOGFILE,MC_DEF_LOG_MAX_LOGFILE));
197     }
198             
199     if ( errorLogFile && errorLogFile[0]  && 
200         (stat(errorLogFile, &statb) == 0) && 
201         (statb.st_size > errorLogSize)           ) {
202     
203         deleteBytes = (statb.st_size - errorLogSize) + (errorLogSize / 4);
204
205         Debug("TrimErrorLog(): discarding oldest %d bytes from logfile %s\n",
206                  deleteBytes, errorLogFile);
207
208
209         /*
210          *  get two pointers to the file...
211          */
212          
213         if ( (f1 = open(errorLogFile, O_RDWR)) < 0 ||
214              (f2 = open(errorLogFile, O_RDWR)) < 0    ) {
215             Debug("TrimErrorLog(): Cannot open file %s, error number = %d\n",
216                    errorLogFile, errno);
217             if(f1 >= 0) {
218                 close(f1);
219             }
220             if(f2 >= 0) {
221                 close(f2);
222             }
223             return;
224         }
225                             
226
227         /*
228          *  position read pointer to the first full line after the trim
229          *  point...
230          */
231                  
232         if ( (status = lseek(f2, deleteBytes, SEEK_SET)) < 0 ) {
233             Debug("TrimErrorLog(): Cannot lseek() in file %s, error number = %d\n",
234                    errorLogFile, errno);
235             close(f1);
236             close(f2);
237             return;
238         }
239
240         memset(buf, 0, BUFSIZ);
241         n = read(f2, buf, BUFSIZ - 1);
242
243         if ( (p = strchr(buf,'\n')) != NULL ) {
244             p++; 
245             n -= p - buf;
246             deleteBytes += p - buf;
247         }           
248         else {
249             p = buf;
250         }
251         
252
253         /*
254          *  shift bytes to be saved to the beginning of the file...
255          */
256          
257         if(-1 == write (f1, p, n)) {
258             perror(strerror(errno));
259         }
260         
261         while ( (n = read(f2, buf, BUFSIZ)) > 0 ) {
262             if(-1 == write(f1, buf, n)) {
263                 perror(strerror(errno));
264             }
265         }
266
267         /*
268          *  truncate file to new length and close file pointers...
269          */
270          
271         if(-1 == truncate(errorLogFile, statb.st_size - deleteBytes)) {
272             perror(strerror(errno));
273         }
274         close(f1);
275         close(f2);
276     }
277
278 }
279
280
281
282 /****************************************************************************
283  *
284  *  LogInfo
285  *
286  *  Write an information message to the log file
287  *
288  ****************************************************************************/
289
290 void 
291 LogInfo( unsigned char *fmt, ...)
292 {
293     va_list  args;
294
295     Va_start(args,fmt);
296
297     if ( SyncErrorFile(1) ) {
298         fprintf (stderr, "info (pid %ld): ", (long)getpid());
299         vfprintf (stderr, (char *)fmt, args);
300         fflush (stderr);
301     }
302
303     va_end(args);
304 }
305
306
307
308 /****************************************************************************
309  *
310  *  LogError
311  *
312  *  Write an error message to the log file.
313  *
314  ****************************************************************************/
315
316 void 
317 LogError( unsigned char *fmt, ...)
318 {
319     va_list  args;
320
321     Va_start(args,fmt);
322
323     if ( SyncErrorFile(1) ) {
324         fprintf (stderr, "error (pid %ld): ", (long)getpid());
325         vfprintf (stderr, (char *)fmt, args);
326         fflush (stderr);
327     }
328
329     va_end(args);
330 }
331
332
333
334 /****************************************************************************
335  *
336  *  LogOutOfMem
337  *
338  *  Write an "out of memory" message to the log file.
339  *
340  ****************************************************************************/
341
342 void 
343 LogOutOfMem( unsigned char *fmt, ...)
344 {
345     va_list  args;
346
347     Va_start(args,fmt);
348
349     if ( SyncErrorFile(1) ) {
350         fprintf(stderr, "%s", (char *)ReadCatalog(MC_ERROR_SET,MC_NO_MEMORY,MC_DEF_NO_MEMORY));
351         vfprintf (stderr, (char *)fmt, args);
352         fflush (stderr);
353     }
354
355     va_end(args);
356 }
357
358
359
360 /***************************************************************************
361  *
362  *  CODE DISABLED!!! The following routines...
363  *
364  *                      getLocalAddress()
365  *                      scanHostList()
366  *                      indirectAlias()
367  *                      ForEachMatchingIndirectHost()
368  *                      UseChooser()
369  *                      ForEachChooserHost()
370  *
371  *                   are disabled until indirect queries are supported...
372  *
373  ***************************************************************************/
374 #if 0
375
376
377 /****************************************************************************
378  *
379  *  LogPanic
380  *
381  *  Write a panic message to the log file.
382  *
383  ****************************************************************************/
384 void 
385 LogPanic( char *fmt, ...)
386 {
387     va_list  args;
388
389     Va_start(args,fmt);
390
391     if ( SyncErrorFile(1) ) {
392         fprintf (stderr, "panic (pid %ld): ", (long)getpid());
393         vfprintf (stderr, fmt, args);
394         fflush (stderr);
395     }
396
397     va_end(args);
398 }
399
400
401
402 /****************************************************************************
403  *
404  *  Panic
405  *
406  *  Write a panic message to the console
407  *
408  ****************************************************************************/
409
410 int 
411 Panic( char *mesg )
412 {
413     int i;
414
415     i = creat ("/dev/console", 0666);
416     write (i, "panic: ", 7);
417     write (i, mesg, strlen (mesg));
418     exit (1);
419 }
420 #endif /* DISABLED CODE */
421
422
423
424 /****************************************************************************
425  *
426  *  Debug
427  *
428  *  Write a debug message to stdout
429  *
430  ****************************************************************************/
431
432 static int  DoName=True;
433
434 void 
435 Debug( char *fmt, ...)
436 {
437     va_list  args;
438
439     Va_start(args,fmt);
440
441     if (debugLevel > 0)
442     {
443         if ( strlen(DisplayName) > 0 && DoName)
444             fprintf(stdout, "(%s) ", DisplayName);
445
446         vprintf (fmt, args);
447         fflush (stdout);
448
449         /*
450          * don't prepend the display name next time if this debug message
451          * does not contain a "new line" character...
452          */
453
454         if ( strchr(fmt,'\n') == NULL )
455             DoName=False;
456         else
457             DoName=True;
458             
459     }
460
461     va_end(args);
462 }