]> granicus.if.org Git - linux-pam/blob - libpam/pam_log.c
Relevant BUGIDs: 490938
[linux-pam] / libpam / pam_log.c
1 /*
2  * pam_log.c -- PAM system logging
3  *
4  * $Id$
5  *
6  */
7
8 #include "pam_private.h"
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stdarg.h>
13
14 #ifdef __hpux
15 # include <stdio.h>
16 # include <syslog.h>
17 # ifdef __STDC__
18 #  ifndef __P
19 #   define __P(p)  p
20 #  endif /* __P */
21 #  include <stdarg.h>
22 #  define VA_LOCAL_DECL va_list ap;
23 #  define VA_START(f)   va_start(ap, f)
24 #  define VA_END        va_end(ap)
25 # else /* __STDC__ */
26 #  ifndef __P
27 #   define __P(p)  ()
28 #  endif /* __P */
29 #  include <varargs.h>
30 #  define VA_LOCAL_DECL va_list ap;
31 #  define VA_START(f)   va_start(ap)
32 #  define VA_END        va_end(ap)
33 # endif /* __STDC__ */
34 /**************************************************************
35  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
36  * A bombproof version of doprnt (dopr) included.
37  * Sigh.  This sort of thing is always nasty do deal with.  Note that
38  * the version here does not include floating point...
39  *
40  * snprintf() is used instead of sprintf() as it does limit checks
41  * for string length.  This covers a nasty loophole.
42  *
43  * The other functions are there to prevent NULL pointers from
44  * causing nast effects.
45  **************************************************************/
46
47 static void dopr();
48 static char *end;
49 # ifndef _SCO_DS
50 /* VARARGS3 */
51 int
52 #  ifdef __STDC__
53 snprintf(char *str, size_t count, const char *fmt, ...)
54 #  else /* __STDC__ */
55 snprintf(str, count, fmt, va_alist)
56         char *str;
57         size_t count;
58         const char *fmt;
59         va_dcl
60 #  endif /* __STDC__ */
61 {
62         int len;
63         VA_LOCAL_DECL
64
65         VA_START(fmt);
66         len = vsnprintf(str, count, fmt, ap);
67         VA_END;
68         return len;
69 }
70 # endif /* _SCO_DS */
71
72 int
73 # ifdef __STDC__
74 vsnprintf(char *str, size_t count, const char *fmt, va_list args)
75 # else /* __STDC__ */
76 vsnprintf(str, count, fmt, args)
77         char *str;
78         int count;
79         char *fmt;
80         va_list args;
81 # endif /* __STDC__ */
82 {
83         str[0] = 0;
84         end = str + count - 1;
85         dopr( str, fmt, args );
86         if (count > 0)
87                 end[0] = 0;
88         return strlen(str);
89 }
90
91 /*
92  * dopr(): poor man's version of doprintf
93  */
94
95 static void fmtstr __P((char *value, int ljust, int len, int zpad,
96                         int maxwidth));
97 static void fmtnum __P((long value, int base, int dosign, int ljust, int len,
98                         int zpad));
99 static void dostr __P(( char * , int ));
100 static char *output;
101 static void dopr_outch __P(( int c ));
102
103 static void
104 # ifdef __STDC__
105 dopr(char  * buffer, const char * format, va_list args )
106 # else /* __STDC__ */
107 dopr( buffer, format, args )
108        char *buffer;
109        char *format;
110        va_list args;
111 # endif /* __STDC__ */
112 {
113        int ch;
114        long value;
115        int longflag  = 0;
116        int pointflag = 0;
117        int maxwidth  = 0;
118        char *strvalue;
119        int ljust;
120        int len;
121        int zpad;
122
123        output = buffer;
124        while( (ch = *format++) ){
125                switch( ch ){
126                case '%':
127                        ljust = len = zpad = maxwidth = 0;
128                        longflag = pointflag = 0;
129                nextch:
130                        ch = *format++;
131                        switch( ch ){
132                        case 0:
133                                dostr( "**end of format**" , 0);
134                                return;
135                        case '-': ljust = 1; goto nextch;
136                        case '0': /* set zero padding if len not set */
137                                if(len==0 && !pointflag) zpad = '0';
138                        case '1': case '2': case '3':
139                        case '4': case '5': case '6':
140                        case '7': case '8': case '9':
141                                if (pointflag)
142                                  maxwidth = maxwidth*10 + ch - '0';
143                                else
144                                  len = len*10 + ch - '0';
145                                goto nextch;
146                        case '*': 
147                                if (pointflag)
148                                  maxwidth = va_arg( args, int );
149                                else
150                                  len = va_arg( args, int );
151                                goto nextch;
152                        case '.': pointflag = 1; goto nextch;
153                        case 'l': longflag = 1; goto nextch;
154                        case 'u': case 'U':
155                                /*fmtnum(value,base,dosign,ljust,len,zpad) */
156                                if( longflag ){
157                                        value = va_arg( args, long );
158                                } else {
159                                        value = va_arg( args, int );
160                                }
161                                fmtnum( value, 10,0, ljust, len, zpad ); break;
162                        case 'o': case 'O':
163                                /*fmtnum(value,base,dosign,ljust,len,zpad) */
164                                if( longflag ){
165                                        value = va_arg( args, long );
166                                } else {
167                                        value = va_arg( args, int );
168                                }
169                                fmtnum( value, 8,0, ljust, len, zpad ); break;
170                        case 'd': case 'D':
171                                if( longflag ){
172                                        value = va_arg( args, long );
173                                } else {
174                                        value = va_arg( args, int );
175                                }
176                                fmtnum( value, 10,1, ljust, len, zpad ); break;
177                        case 'x':
178                                if( longflag ){
179                                        value = va_arg( args, long );
180                                } else {
181                                        value = va_arg( args, int );
182                                }
183                                fmtnum( value, 16,0, ljust, len, zpad ); break;
184                        case 'X':
185                                if( longflag ){
186                                        value = va_arg( args, long );
187                                } else {
188                                        value = va_arg( args, int );
189                                }
190                                fmtnum( value,-16,0, ljust, len, zpad ); break;
191                        case 's':
192                                strvalue = va_arg( args, char *);
193                                if (maxwidth > 0 || !pointflag) {
194                                  if (pointflag && len > maxwidth)
195                                    len = maxwidth; /* Adjust padding */
196                                  fmtstr( strvalue,ljust,len,zpad, maxwidth);
197                                }
198                                break;
199                        case 'c':
200                                ch = va_arg( args, int );
201                                dopr_outch( ch ); break;
202                        case '%': dopr_outch( ch ); continue;
203                        default:
204                                dostr(  "???????" , 0);
205                        }
206                        break;
207                default:
208                        dopr_outch( ch );
209                        break;
210                }
211        }
212        *output = 0;
213 }
214
215 static void
216 fmtstr(  value, ljust, len, zpad, maxwidth )
217        char *value;
218        int ljust, len, zpad, maxwidth;
219 {
220        int padlen, strlen;     /* amount to pad */
221
222        if( value == 0 ){
223                value = "<NULL>";
224        }
225        for( strlen = 0; value[strlen]; ++ strlen ); /* strlen */
226        if (strlen > maxwidth && maxwidth)
227          strlen = maxwidth;
228        padlen = len - strlen;
229        if( padlen < 0 ) padlen = 0;
230        if( ljust ) padlen = -padlen;
231        while( padlen > 0 ) {
232                dopr_outch( ' ' );
233                --padlen;
234        }
235        dostr( value, maxwidth );
236        while( padlen < 0 ) {
237                dopr_outch( ' ' );
238                ++padlen;
239        }
240 }
241
242 static void
243 fmtnum(  value, base, dosign, ljust, len, zpad )
244        long value;
245        int base, dosign, ljust, len, zpad;
246 {
247        int signvalue = 0;
248        unsigned long uvalue;
249        char convert[20];
250        int place = 0;
251        int padlen = 0; /* amount to pad */
252        int caps = 0;
253
254        /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
255                value, base, dosign, ljust, len, zpad )); */
256        uvalue = value;
257        if( dosign ){
258                if( value < 0 ) {
259                        signvalue = '-';
260                        uvalue = -value;
261                }
262        }
263        if( base < 0 ){
264                caps = 1;
265                base = -base;
266        }
267        do{
268                convert[place++] =
269                        (caps? "0123456789ABCDEF":"0123456789abcdef")
270                         [uvalue % (unsigned)base  ];
271                uvalue = (uvalue / (unsigned)base );
272        }while(uvalue);
273        convert[place] = 0;
274        padlen = len - place;
275        if( padlen < 0 ) padlen = 0;
276        if( ljust ) padlen = -padlen;
277        /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
278                convert,place,signvalue,padlen)); */
279        if( zpad && padlen > 0 ){
280                if( signvalue ){
281                        dopr_outch( signvalue );
282                        --padlen;
283                        signvalue = 0;
284                }
285                while( padlen > 0 ){
286                        dopr_outch( zpad );
287                        --padlen;
288                }
289        }
290        while( padlen > 0 ) {
291                dopr_outch( ' ' );
292                --padlen;
293        }
294        if( signvalue ) dopr_outch( signvalue );
295        while( place > 0 ) dopr_outch( convert[--place] );
296        while( padlen < 0 ){
297                dopr_outch( ' ' );
298                ++padlen;
299        }
300 }
301
302 static void
303 dostr( str , cut)
304      char *str;
305      int cut;
306 {
307   if (cut) {
308     while(*str && cut-- > 0) dopr_outch(*str++);
309   } else {
310     while(*str) dopr_outch(*str++);
311   }
312 }
313
314 static void
315 dopr_outch( c )
316        int c;
317 {
318        if( end == 0 || output < end )
319                *output++ = c;
320 }
321
322 int 
323 # ifdef __STDC__
324 vsyslog(int priority, const char *fmt, ...)
325 # else /* __STDC__ */
326 vsyslog(priority, fmt, va_alist)
327   int priority;
328   const char *fmt;
329   va_dcl
330 # endif /* __STDC__ */
331 {
332     VA_LOCAL_DECL
333     char logbuf[BUFSIZ];
334     
335     VA_START(fmt);
336
337     vsnprintf(logbuf, BUFSIZ, fmt, ap);
338     syslog(priority, "%s", logbuf);
339
340     VA_END;
341 }
342 #endif /* __hpux */
343
344 /* internal logging function */
345
346 void _pam_system_log(int priority, const char *format, ... )
347 {
348     va_list args;
349     char *eformat;
350
351     D(("pam_system_log called"));
352
353     if (format == NULL) {
354         D(("NULL format to _pam_system_log() call"));
355         return;
356     }
357
358     va_start(args, format);
359
360     eformat = malloc(sizeof(_PAM_SYSTEM_LOG_PREFIX)+strlen(format));
361     if (eformat != NULL) {
362         strcpy(eformat, _PAM_SYSTEM_LOG_PREFIX);
363         strcpy(eformat + sizeof(_PAM_SYSTEM_LOG_PREFIX) - 1, format);
364         vsyslog(priority, eformat, args);
365         _pam_overwrite(eformat);
366         _pam_drop(eformat);
367     } else {
368         vsyslog(priority, format, args);
369     }
370
371     va_end(args);
372
373     D(("done."));
374 }
375