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