vp_prints now returns the number of characters it wrote,
[freeradius.git] / src / lib / print.c
1 /*
2  * print.c      Routines to print stuff.
3  *
4  * Version:     @(#)print.c  1.00  26-Oct-1998  miquels@cistron.nl
5  *
6  */
7
8 #include        "autoconf.h"
9
10 #include        <stdio.h>
11 #include        <stdlib.h>
12 #include        <sys/types.h>
13 #include        <time.h>
14 #include        <pwd.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 static 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(str);
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                                         sprintf(out, "\\%03o", *str);
60                                         done += 4;
61                                         out  += 4;
62                                 } else {
63                                         *out++ = *str;
64                                         done++;
65                                 }
66                 }
67                 if (sp) {
68                         *out++ = '\\';
69                         *out++ = sp;
70                         done += 2;
71                 }
72                 str++;
73         }
74         *out = 0;
75 }
76
77
78 /*
79  *      Print one attribute and value into a string.
80  */
81 int vp_prints(char *out, int outlen, VALUE_PAIR *vp)
82 {
83         DICT_VALUE      *v;
84         char            buf[1024];
85         char            *a;
86         time_t          t;
87         int             len;
88         char            *orig = out;
89
90         if (!vp) return 0;
91
92         out[0] = 0;
93         if (strlen(vp->name) + 3 > outlen) {
94                 return 0;
95         }
96
97         sprintf(out, "%s = ", vp->name);
98         len = strlen(out);
99         outlen -= len;
100         out += len;
101
102         switch (vp->type) {
103                 case PW_TYPE_STRING:
104                         if (vp->attribute == PW_NAS_PORT_ID)
105                                 a = vp->strvalue;
106                         else {
107                                 buf[0] = '"';
108                                 librad_safeprint(vp->strvalue, vp->length,
109                                         buf + 1, sizeof(buf) - 2);
110                                 strcat(buf, "\"");
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                                 sprintf(buf, "%d", vp->lvalue);
120                                 a = buf;
121                         }
122                         break;
123                 case PW_TYPE_DATE:
124                         t = vp->lvalue;
125                         strftime(buf, sizeof(buf), "\"%b %e %Y\"",
126                                 gmtime(&t));
127                         a = buf;
128                         break;
129                 case PW_TYPE_IPADDR:
130                         if (vp->strvalue[0])
131                                 a = vp->strvalue;
132                         else
133                                 a = ip_ntoa(NULL, vp->lvalue);
134                         break;
135                 default:
136                         a = "UNKNOWN";
137                         break;
138         }
139         strncpy(out, a, outlen);
140         out[outlen - 1] = 0;
141         return strlen(orig);
142 }
143
144
145 /*
146  *      Print one attribute and value.
147  */
148 void vp_print(FILE *fp, VALUE_PAIR *vp)
149 {
150         char    buf[1024];
151
152         vp_prints(buf, sizeof(buf), vp);
153         fputs(buf, fp);
154 }
155
156
157 /*
158  *      Print a whole list of attributes, indented by a TAB
159  *      and with a newline at the end.
160  */
161 void vp_printlist(FILE *fp, VALUE_PAIR *vp)
162 {
163         for (; vp; vp = vp->next) {
164                 fprintf(fp, "\t");
165                 vp_print(fp, vp);
166                 fprintf(fp, "\n");
167         }
168 }
169