Preliminary support for displaying Tunnel attributes as defined in
[freeradius.git] / src / lib / print.c
1 /*
2  * print.c      Routines to print stuff.
3  *
4  * Version:     $Id$
5  *
6  */
7
8 static const char rcsid[] = "$Id$";
9
10 #include        "autoconf.h"
11
12 #include        <stdio.h>
13 #include        <stdlib.h>
14 #include        <sys/types.h>
15 #include        <ctype.h>
16 #include        <string.h>
17
18 #include        "libradius.h"
19
20 /*
21  *      Convert a string to something printable.
22  *      The output string has to be _at least_ 4x the size
23  *      of the input string!
24  */
25 void librad_safeprint(char *in, int inlen, char *out, int outlen)
26 {
27         unsigned char   *str = (unsigned char *)in;
28         int             done = 0;
29         int             sp = 0;
30
31         if (inlen < 0) inlen = strlen(in);
32
33         while (inlen-- > 0 && (done + 3) < outlen) {
34                 /*
35                  *      Hack: never print trailing zero.
36                  *      Some clients send strings with an off-by-one
37                  *      length (confused with strings in C).
38                  */
39                 if (inlen == 0 && *str == 0)
40                         break;
41
42                 sp = 0;
43
44                 switch (*str) {
45                         case '\\':
46                                 sp = '\\';
47                                 break;
48                         case '\r':
49                                 sp = 'r';
50                                 break;
51                         case '\n':
52                                 sp = 'n';
53                                 break;
54                         case '\t':
55                                 sp = 't';
56                                 break;
57                         default:
58                                 if (*str < 32 || (*str >= 128)){
59                                         snprintf(out, outlen, "\\%03o", *str);
60                                         done += 4;
61                                         out  += 4;
62                                         outlen -= 4;
63                                 } else {
64                                         *out++ = *str;
65                                         outlen--;
66                                         done++;
67                                 }
68                 }
69                 if (sp) {
70                         *out++ = '\\';
71                         *out++ = sp;
72                         outlen -= 2;
73                         done += 2;
74                 }
75                 str++;
76         }
77         *out = 0;
78 }
79
80
81 /*
82  *  Print one value into a string.
83  *  delimitst will define if strings and dates will be delimited by '"'
84  */
85 int vp_prints_value(char * out, int outlen, VALUE_PAIR *vp, int delimitst)
86 {
87         DICT_VALUE  *v;
88         char        buf[1024];
89         char        *a;
90         time_t      t;
91         int         offset;
92
93         out[0] = 0;
94         if (!vp) return 0;
95
96         switch (vp->type) {
97                 case PW_TYPE_STRING:
98                         if (vp->attribute == PW_NAS_PORT_ID)
99                                 a = (char *)vp->strvalue;
100                         else {
101                                 if (delimitst) {
102                                   buf[0] = '"';
103                                   librad_safeprint((char *)vp->strvalue,
104                                           vp->length, buf + 1, sizeof(buf) - 2);
105                                   strcat(buf, "\"");
106                                 } else {
107                                   librad_safeprint((char *)vp->strvalue,
108                                           vp->length, buf, sizeof(buf));
109                                 }
110
111                                 a = buf;
112                         }
113                         break;
114                 case PW_TYPE_INTEGER:
115                         if ((v = dict_valbyattr(vp->attribute, vp->lvalue))
116                                 != NULL)
117                                 a = v->name;
118                         else {
119                                 snprintf(buf, sizeof(buf), "%u", vp->lvalue);
120                                 a = buf;
121                         }
122                         break;
123                 case PW_TYPE_DATE:
124                         t = vp->lvalue;
125                         if (delimitst) {
126                           strftime(buf, sizeof(buf), "\"%b %e %Y\"", gmtime(&t));
127                         } else {
128                           strftime(buf, sizeof(buf), "%b %e %Y", gmtime(&t));
129                         }
130                         a = buf;
131                         break;
132                 case PW_TYPE_IPADDR:
133                         if (vp->strvalue[0])
134                                 a = (char *)vp->strvalue;
135                         else
136                                 a = ip_hostname((char *)vp->strvalue,
137                                                 sizeof(vp->strvalue),
138                                                 vp->lvalue);
139                         break;
140                 case PW_TYPE_ABINARY:
141 #ifdef ASCEND_BINARY
142                   a = buf;
143                   print_abinary(vp, (unsigned char *)buf, sizeof(buf));
144                   break;
145 #else
146                   /* FALL THROUGH */
147 #endif
148                 case PW_TYPE_OCTETS:
149                   strcpy(buf, "0x");
150                   a = buf + 2;
151                   for (t = 0; t < vp->length; t++) {
152                         sprintf(a, "%02x", vp->strvalue[t]);
153                         a += 2;
154                   }
155                   a = buf;
156                   break;
157
158                 case PW_TYPE_T_STRING:
159                         if (delimitst) {
160                                  offset = snprintf(buf, sizeof(buf), 
161                                                    "\"%u:", vp->strvalue[0]);
162                                  librad_safeprint((char *)(vp->strvalue + 1),
163                                                   vp->length - 1, 
164                                                   buf + offset, 
165                                                   sizeof(buf) - offset);
166                                  strcat(buf, "\"");
167                         } else {
168                                  offset = snprintf(buf, sizeof(buf), 
169                                                    "%u:", vp->strvalue[0]);
170                                  librad_safeprint((char *)(vp->strvalue + 1),
171                                                   vp->length - 1, 
172                                                   buf + offset, 
173                                                   sizeof(buf) - offset);
174                         }
175
176                         a = buf;
177
178                         break;
179
180                 case PW_TYPE_T_INTEGER:
181                         offset = snprintf(buf,  sizeof(buf), "%u:", (vp->lvalue >> 24));
182                         if ((v = dict_valbyattr(vp->attribute, (vp->lvalue)))
183                                 != NULL)
184                                 snprintf(buf + offset, sizeof(buf) - offset, 
185                                          "%s", v->name);
186                         else {
187                                 snprintf(buf + offset, sizeof(buf) - offset, 
188                                          "%u", vp->lvalue);
189                                
190                         }
191
192                         a = buf;
193
194                         break;
195                 default:
196                         a = 0;
197                         break;
198         }
199         strNcpy(out, a?a:"UNKNOWN-TYPE", outlen);
200         
201         return strlen(out);
202 }
203
204
205 /*
206  *      Print one attribute and value into a string.
207  */
208 int vp_prints(char *out, int outlen, VALUE_PAIR *vp)
209 {
210         int             len;
211
212         out[0] = 0;
213         if (!vp) return 0;
214
215         if (strlen(vp->name) + 3 > (size_t)outlen) {
216                 return 0;
217         }
218
219         snprintf(out, outlen, "%s = ", vp->name);
220         len = strlen(out);
221         vp_prints_value(out + len, outlen - len, vp, 1);
222
223         return strlen(out);
224 }
225
226
227 /*
228  *      Print one attribute and value.
229  */
230 void vp_print(FILE *fp, VALUE_PAIR *vp)
231 {
232         char    buf[1024];
233
234         vp_prints(buf, sizeof(buf), vp);
235         fputs(buf, fp);
236 }
237
238
239 /*
240  *      Print a whole list of attributes, indented by a TAB
241  *      and with a newline at the end.
242  */
243 void vp_printlist(FILE *fp, VALUE_PAIR *vp)
244 {
245         for (; vp; vp = vp->next) {
246                 fprintf(fp, "\t");
247                 vp_print(fp, vp);
248                 fprintf(fp, "\n");
249         }
250 }
251