1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2 /*
3  * lib/krb5/krb/copy_addrs.c
4  *
5  * Copyright 1990 by the Massachusetts Institute of Technology.
6  * All Rights Reserved.
7  *
8  * Export of this software from the United States of America may
9  *   require a specific license from the United States Government.
10  *   It is the responsibility of any person or organization contemplating
11  *   export to obtain such a license before exporting.
12  *
13  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14  * distribute this software and its documentation for any purpose and
15  * without fee is hereby granted, provided that the above copyright
16  * notice appear in all copies and that both that copyright notice and
17  * this permission notice appear in supporting documentation, and that
18  * the name of M.I.T. not be used in advertising or publicity pertaining
19  * to distribution of the software without specific, written prior
20  * permission.  Furthermore if you modify this software you must label
21  * your software as modified software and not distribute it in such a
22  * fashion that it might be confused with the original M.I.T. software.
23  * M.I.T. makes no representations about the suitability of
24  * this software for any purpose.  It is provided "as is" without express
25  * or implied warranty.
26  *
27  *
28  * krb5_copy_addresses()
29  */
30 
31 #include <k5-int.h>
32 
33 /*ARGSUSED*/
34 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
35 krb5_copy_addr(context, inad, outad)
36     krb5_context context;
37     const krb5_address FAR *inad;
38     krb5_address FAR * FAR *outad;
39 {
40     krb5_address FAR *tmpad;
41 
42     if (!(tmpad = (krb5_address FAR *)malloc(sizeof(*tmpad))))
43 	return ENOMEM;
44 #ifdef HAVE_C_STRUCTURE_ASSIGNMENT
45     *tmpad = *inad;
46 #else
47     memcpy(tmpad, inad, sizeof(krb5_address));
48 #endif
49     if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) {
50 	krb5_xfree(tmpad);
51 	return ENOMEM;
52     }
53     memcpy((char *)tmpad->contents, (char *)inad->contents, inad->length);
54     *outad = tmpad;
55     return 0;
56 }
57 
58 /*
59  * Copy an address array, with fresh allocation.
60  */
61 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
62 krb5_copy_addresses(context, inaddr, outaddr)
63     krb5_context context;
64     krb5_address FAR * const FAR * inaddr;
65     krb5_address FAR * FAR * FAR *outaddr;
66 {
67     krb5_error_code retval;
68     krb5_address ** tempaddr;
69     register int nelems = 0;
70 
71     if (!inaddr) {
72 	    *outaddr = 0;
73 	    return 0;
74     }
75 
76     while (inaddr[nelems]) nelems++;
77 
78     /* one more for a null terminated list */
79     if (!(tempaddr = (krb5_address **) calloc(nelems+1, sizeof(*tempaddr))))
80 	return ENOMEM;
81 
82     for (nelems = 0; inaddr[nelems]; nelems++) {
83 	retval = krb5_copy_addr(context, inaddr[nelems], &tempaddr[nelems]);
84         if (retval) {
85 	    krb5_free_addresses(context, tempaddr);
86 	    return retval;
87 	}
88     }
89 
90     *outaddr = tempaddr;
91     return 0;
92 }
93 
94 #if 0
95 /*
96  * Append an address array, to another address array, with fresh allocation.
97  * Note that this function may change the value of *outaddr even if it
98  * returns failure, but it will not change the contents of the list.
99  */
100 krb5_error_code
101 krb5_append_addresses(context, inaddr, outaddr)
102     krb5_context context;
103 	krb5_address * const * inaddr;
104 	krb5_address ***outaddr;
105 {
106     krb5_error_code retval;
107     krb5_address ** tempaddr;
108     krb5_address ** tempaddr2;
109     register int nelems = 0;
110     register int norigelems = 0;
111 
112     if (!inaddr)
113 	return 0;
114 
115     tempaddr2 = *outaddr;
116 
117     while (inaddr[nelems]) nelems++;
118     while (tempaddr2[norigelems]) norigelems++;
119 
120     tempaddr = (krb5_address **) realloc((char *)*outaddr,
121 		       (nelems + norigelems + 1) * sizeof(*tempaddr));
122     if (!tempaddr)
123 	return ENOMEM;
124 
125     /* The old storage has been freed.  */
126     *outaddr = tempaddr;
127 
128 
129     for (nelems = 0; inaddr[nelems]; nelems++) {
130 	retval = krb5_copy_addr(context, inaddr[nelems],
131 				&tempaddr[norigelems + nelems]);
132 	if (retval)
133 	    goto cleanup;
134     }
135 
136     tempaddr[norigelems + nelems] = 0;
137     return 0;
138 
139   cleanup:
140     while (--nelems >= 0)
141 	krb5_free_address(context, tempaddr[norigelems + nelems]);
142 
143     /* Try to allocate a smaller amount of memory for *outaddr.  */
144     tempaddr = (krb5_address **) realloc((char *)tempaddr,
145 					 (norigelems + 1) * sizeof(*tempaddr));
146     if (tempaddr)
147 	*outaddr = tempaddr;
148     return retval;
149 }
150 #endif
151 
152