File: mail_print.c

package info (click to toggle)
postfix 0.0.19991231pl11-2
  • links: PTS
  • area: main
  • in suites: potato
  • size: 5,044 kB
  • ctags: 4,401
  • sloc: ansic: 33,767; makefile: 5,099; sh: 1,790; awk: 19
file content (206 lines) | stat: -rw-r--r-- 5,052 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*++
/* NAME
/*	mail_print 3
/* SUMMARY
/*	intra-mail system write routine
/* SYNOPSIS
/*	#include <mail_proto.h>
/*
/*	int	mail_print(stream, format, ...)
/*	VSTREAM *stream;
/*	const char *format;
/*
/*	int	mail_vprint(stream, format, ap)
/*	VSTREAM *stream;
/*	const char *format;
/*	va_list	ap;
/*
/*	void	mail_print_register(letter, name, print_fn)
/*	int	letter;
/*	const char *name;
/*	void	(*print_fn)(VSTREAM *stream, const char *data);
/* DESCRIPTION
/*	mail_print() prints one or more null-delimited strings to
/*	the named stream, each string being converted according to the
/*	contents of the \fIformat\fR argument.
/*
/*	mail_vprint() provides an alternative interface.
/*
/*	mail_print_register() registers the named print function for
/*	the specified letter, for the named type.
/*
/*	Arguments:
/* .IP stream
/*	The stream to print to.
/* .IP format
/*	Format string, which is interpreted as follows:
/* .RS
/* .IP "white space"
/*	White space in the format string is ignored.
/* .IP %s
/*	The corresponding argument has type (char *).
/* .IP %d
/*	The corresponding argument has type (int).
/* .IP %ld
/*	The corresponding argument has type (long).
/* .IP %letter
/*	Call the print routine that was registered for the specified letter.
/* .PP
/*	Anything else in a format string is a fatal error.
/* .RE
/* .IP letter
/*	Format letter that is bound to the \fIprint_fn\fR print function.
/* .IP name
/*	Descriptive string for verbose logging.
/* .IP print_fn
/*	A print function. It takes as arguments:
/* .RS
/* .IP stream
/*	The stream to print to.
/* .IP data
/*	A generic data pointer. It is up to the function
/*	to do any necessary casts to the data-specific type.
/* .RE
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*--*/

/* System library. */

#include <sys_defs.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>

/* Utility library. */

#include <msg.h>
#include <mymalloc.h>
#include <vstream.h>

/* Global library. */

#include "mail_proto.h"

 /*
  * Provision for the user to register type-specific scanners for
  * applications with unusual requirements.
  */
typedef struct {
    int     letter;
    char   *name;
    MAIL_PRINT_FN print_fn;
} MAIL_PRINT;

MAIL_PRINT *mail_print_tab = 0;
int     mail_print_tablen = 0;

/* mail_print_register - register printer function */

void    mail_print_register(int letter, const char *name, MAIL_PRINT_FN print_fn)
{
    MAIL_PRINT *tp;

    for (tp = 0; tp < mail_print_tab + mail_print_tablen; tp++)
	if (tp->letter == letter)
	    msg_panic("mail_print_register: redefined letter: %c", letter);

    /*
     * Tight fit allocation. We're not registering lots of characters.
     */
    if (mail_print_tab == 0) {
	mail_print_tablen = 1;
	mail_print_tab = (MAIL_PRINT *)
	    mymalloc(sizeof(*mail_print_tab) * mail_print_tablen);
    } else {
	mail_print_tablen++;
	mail_print_tab = (MAIL_PRINT *)
	    myrealloc((char *) mail_print_tab,
		      sizeof(*mail_print_tab) * mail_print_tablen);
    }
    tp = mail_print_tab + mail_print_tablen - 1;
    tp->letter = letter;
    tp->name = mystrdup(name);
    tp->print_fn = print_fn;
}

/* mail_vprint - print null-delimited data to stream */

int     mail_vprint(VSTREAM *stream, const char *fmt, va_list ap)
{
    const char *cp;
    int     lflag;
    char   *sval;
    int     ival;
    long    lval;
    int     error;
    MAIL_PRINT *tp;

    for (cp = fmt; (error = vstream_ferror(stream)) == 0 && *cp != 0; cp++) {
	if (ISSPACE(*cp))
	    continue;
	if (*cp != '%')
	    msg_fatal("mail_vprint: bad format: %.*s>%c<%s",
		      cp - fmt, fmt, *cp, cp + 1);
	if ((lflag = (*++cp == 'l')) != 0)
	    cp++;

	switch (*cp) {
	case 's':
	    sval = va_arg(ap, char *);
	    if (msg_verbose)
		msg_info("print string: %s", sval);
	    vstream_fputs(sval, stream);
	    VSTREAM_PUTC(0, stream);
	    break;
	case 'd':
	    if (lflag) {
		lval = va_arg(ap, long);
		if (msg_verbose)
		    msg_info("print long: %ld", lval);
		vstream_fprintf(stream, "%ld", lval);
	    } else {
		ival = va_arg(ap, int);
		if (msg_verbose)
		    msg_info("print int: %d", ival);
		vstream_fprintf(stream, "%d", ival);
	    }
	    VSTREAM_PUTC(0, stream);
	    break;
	default:
	    for (tp = mail_print_tab; tp < mail_print_tab + mail_print_tablen; tp++)
		if (tp->letter == *cp) {
		    if (msg_verbose)
			msg_info("print %s", tp->name);
		    tp->print_fn(stream, va_arg(ap, char *));
		    break;
		}
	    if (tp >= mail_print_tab + mail_print_tablen)
		msg_fatal("mail_vprint: bad format: %.*s>%c<%s",
			  cp - fmt, fmt, *cp, cp + 1);
	}
    }
    return (error);
}

/* mail_print - print null-delimited data to stream */

int     mail_print(VSTREAM *stream, const char *fmt,...)
{
    int     status;
    va_list ap;

    va_start(ap, fmt);
    status = mail_vprint(stream, fmt, ap);
    va_end(ap);
    return (status);
}