1/*	$NetBSD: recipient_list.c,v 1.2 2017/02/14 01:16:45 christos Exp $	*/
2
3/*++
4/* NAME
5/*	recipient_list 3
6/* SUMMARY
7/*	in-core recipient structures
8/* SYNOPSIS
9/*	#include <recipient_list.h>
10/*
11/*	typedef struct {
12/* .in +4
13/*		long    offset;
14/*		char	*dsn_orcpt;
15/*		int	dsn_notify;
16/*		char   *orig_addr;
17/*		char   *address;
18/*		union {
19/* .in +4
20/*			int	status;
21/*			struct QMGR_QUEUE *queue;
22/*			char	*addr_type;
23/* .in -4
24/*		}
25/* .in -4
26/*	} RECIPIENT;
27/*
28/*	typedef struct {
29/* .in +4
30/*		RECIPIENT *info;
31/*		private members...
32/* .in -4
33/*	} RECIPIENT_LIST;
34/*
35/*	void	recipient_list_init(list, variant)
36/*	RECIPIENT_LIST *list;
37/*	int	variant;
38/*
39/*	void	recipient_list_add(list, offset, dsn_orcpt, dsn_notify,
40/*					orig_rcpt, recipient)
41/*	RECIPIENT_LIST *list;
42/*	long	offset;
43/*	const char *dsn_orcpt;
44/*	int	dsn_notify;
45/*	const char *orig_rcpt;
46/*	const char *recipient;
47/*
48/*	void	recipient_list_swap(a, b)
49/*	RECIPIENT_LIST *a;
50/*	RECIPIENT_LIST *b;
51/*
52/*	void	recipient_list_free(list)
53/*	RECIPIENT_LIST *list;
54/*
55/*	void	RECIPIENT_ASSIGN(rcpt, offset, dsn_orcpt, dsn_notify,
56/*					orig_rcpt, recipient)
57/*	RECIPIENT *rcpt;
58/*	long	offset;
59/*	char	*dsn_orcpt;
60/*	int	dsn_notify;
61/*	char	*orig_rcpt;
62/*	char	*recipient;
63/* DESCRIPTION
64/*	This module maintains lists of recipient structures. Each
65/*	recipient is characterized by a destination address and
66/*	by the queue file offset of its delivery status record.
67/*	The per-recipient status is initialized to zero, and exists
68/*	solely for the convenience of the application. It is not used
69/*	by the recipient_list module itself.
70/*
71/*	recipient_list_init() creates an empty recipient structure list.
72/*	The list argument is initialized such that it can be given to
73/*	recipient_list_add() and to recipient_list_free(). The variant
74/*	argument specifies how list elements should be initialized;
75/*	specify RCPT_LIST_INIT_STATUS to zero the status field, and
76/*	RCPT_LIST_INIT_QUEUE to zero the queue field.
77/*
78/*	recipient_list_add() adds a recipient to the specified list.
79/*	Recipient address information is copied with mystrdup().
80/*
81/*	recipient_list_swap() swaps the recipients between
82/*	the given two recipient lists.
83/*
84/*	recipient_list_free() releases memory for the specified list
85/*	of recipient structures.
86/*
87/*	RECIPIENT_ASSIGN() assigns the fields of a recipient structure
88/*	without making copies of its arguments.
89/*
90/*	Arguments:
91/* .IP list
92/*	Recipient list initialized by recipient_list_init().
93/* .IP offset
94/*	Queue file offset of a recipient delivery status record.
95/* .IP dsn_orcpt
96/*	DSN original recipient.
97/* .IP notify
98/*	DSN notify flags.
99/* .IP recipient
100/*	Recipient destination address.
101/* SEE ALSO
102/*	recipient_list(3h) data structure
103/* DIAGNOSTICS
104/*	Fatal errors: memory allocation.
105/* LICENSE
106/* .ad
107/* .fi
108/*	The Secure Mailer license must be distributed with this software.
109/* AUTHOR(S)
110/*	Wietse Venema
111/*	IBM T.J. Watson Research
112/*	P.O. Box 704
113/*	Yorktown Heights, NY 10598, USA
114/*--*/
115
116/* System library. */
117
118#include <sys_defs.h>
119
120/* Utility library. */
121
122#include <mymalloc.h>
123#include <msg.h>
124
125/* Global library. */
126
127#include "recipient_list.h"
128
129/* recipient_list_init - initialize */
130
131void    recipient_list_init(RECIPIENT_LIST *list, int variant)
132{
133    list->avail = 1;
134    list->len = 0;
135    list->info = (RECIPIENT *) mymalloc(sizeof(RECIPIENT));
136    list->variant = variant;
137}
138
139/* recipient_list_add - add rcpt to list */
140
141void    recipient_list_add(RECIPIENT_LIST *list, long offset,
142			           const char *dsn_orcpt, int dsn_notify,
143			           const char *orig_rcpt, const char *rcpt)
144{
145    int     new_avail;
146
147    if (list->len >= list->avail) {
148	new_avail = list->avail * 2;
149	list->info = (RECIPIENT *)
150	    myrealloc((void *) list->info, new_avail * sizeof(RECIPIENT));
151	list->avail = new_avail;
152    }
153    list->info[list->len].orig_addr = mystrdup(orig_rcpt);
154    list->info[list->len].address = mystrdup(rcpt);
155    list->info[list->len].offset = offset;
156    list->info[list->len].dsn_orcpt = mystrdup(dsn_orcpt);
157    list->info[list->len].dsn_notify = dsn_notify;
158    if (list->variant == RCPT_LIST_INIT_STATUS)
159	list->info[list->len].u.status = 0;
160    else if (list->variant == RCPT_LIST_INIT_QUEUE)
161	list->info[list->len].u.queue = 0;
162    else if (list->variant == RCPT_LIST_INIT_ADDR)
163	list->info[list->len].u.addr_type = 0;
164    list->len++;
165}
166
167/* recipient_list_swap - swap recipients between the two recipient lists */
168
169void    recipient_list_swap(RECIPIENT_LIST *a, RECIPIENT_LIST *b)
170{
171    if (b->variant != a->variant)
172	msg_panic("recipient_lists_swap: incompatible recipient list variants");
173
174#define SWAP(t, x)  do { t x = b->x; b->x = a->x ; a->x = x; } while (0)
175
176    SWAP(RECIPIENT *, info);
177    SWAP(int, len);
178    SWAP(int, avail);
179}
180
181/* recipient_list_free - release memory for in-core recipient structure */
182
183void    recipient_list_free(RECIPIENT_LIST *list)
184{
185    RECIPIENT *rcpt;
186
187    for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) {
188	myfree((void *) rcpt->dsn_orcpt);
189	myfree((void *) rcpt->orig_addr);
190	myfree((void *) rcpt->address);
191    }
192    myfree((void *) list->info);
193}
194