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