1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**  NAME
80**
81**      comutil.c
82**
83**  FACILITY:
84**
85**      Remote Procedure Call (RPC)
86**
87**  ABSTRACT:
88**
89**  Utility services.
90**
91**
92*/
93
94#include <commonp.h>    /* Common declarations for all RPC runtime */
95#include <com.h>        /* Common communications services */
96
97
98/*
99 *****************************************************************************
100 *
101 * ASCII to EBCDIC (and vice versa) conversion tables.
102 *
103 * These tables were snarfed from the V2 ndr_chars.c module
104 * from the IDL stub runtime support.
105 * INTERNAL for use by the rpc_util_strcvt() routine.
106 *
107 *****************************************************************************
108 */
109
110INTERNAL unsigned_char_t cvt_ascii_to_ebcdic[] = {
111     0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 0x00 - 0x07 */
112     0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 0x08 - 0x0F */
113     0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 0x10 - 0x17 */
114     0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 0x18 - 0x1F */
115     0x40, 0x4F, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 0x20 - 0x27 */
116     0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 0x28 - 0x2F */
117     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 0x30 - 0x37 */
118     0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 0x38 - 0x3F */
119     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 0x40 - 0x47 */
120     0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 0x48 - 0x4F */
121     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 0x50 - 0x57 */
122     0xE7, 0xE8, 0xE9, 0x4A, 0xE0, 0x5A, 0x5F, 0x6D, /* 0x58 - 0x5F */
123     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x60 - 0x67 */
124     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 0x68 - 0x6F */
125     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 0x70 - 0x77 */
126     0xA7, 0xA8, 0xA9, 0xC0, 0xBB, 0xD0, 0xA1, 0x07, /* 0x78 - 0x7F */
127     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0x80 - 0x87 */
128     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0x88 - 0x8F */
129     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0x90 - 0x97 */
130     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0x98 - 0x9F */
131     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xA0 - 0xA7 */
132     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xA8 - 0xAF */
133     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xB0 - 0xB7 */
134     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xB8 - 0xBF */
135     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xC0 - 0xC7 */
136     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xC8 - 0xCF */
137     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xD0 - 0xD7 */
138     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xD8 - 0xDF */
139     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xE0 - 0xE7 */
140     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xE8 - 0xEF */
141     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 0xF0 - 0xF7 */
142     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF  /* 0xF8 - 0xFF */
143};
144
145INTERNAL unsigned_char_t cvt_ebcdic_to_ascii[] = {
146     0x00, 0x01, 0x02, 0x03, 0x1A, 0x09, 0x1A, 0x7F, /* 0x00 - 0x07 */
147     0x1A, 0x1A, 0x1A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 0x08 - 0x0F */
148     0x10, 0x11, 0x12, 0x13, 0x1A, 0x1A, 0x08, 0x1A, /* 0x10 - 0x17 */
149     0x18, 0x19, 0x1A, 0x1A, 0x1C, 0x1D, 0x1E, 0x1F, /* 0x18 - 0x1F */
150     0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x0A, 0x17, 0x1B, /* 0x20 - 0x27 */
151     0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x05, 0x06, 0x07, /* 0x28 - 0x2F */
152     0x1A, 0x1A, 0x16, 0x1A, 0x1A, 0x1A, 0x1A, 0x04, /* 0x30 - 0x37 */
153     0x1A, 0x1A, 0x1A, 0x1A, 0x14, 0x15, 0x1A, 0x1A, /* 0x38 - 0x3F */
154     0x20, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0x40 - 0x47 */
155     0x1A, 0x1A, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21, /* 0x48 - 0x4F */
156     0x26, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0x50 - 0x57 */
157     0x1A, 0x1A, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E, /* 0x58 - 0x5F */
158     0x2D, 0x2F, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0x60 - 0x67 */
159     0x1A, 0x1A, 0x1A, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 0x68 - 0x6F */
160     0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0x70 - 0x77 */
161     0x1A, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 0x78 - 0x7F */
162     0x1A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x80 - 0x87 */
163     0x68, 0x69, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0x88 - 0x8F */
164     0x1A, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 0x90 - 0x97 */
165     0x71, 0x72, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0x98 - 0x9F */
166     0x1A, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* 0xA0 - 0xA7 */
167     0x79, 0x7A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xA8 - 0xAF */
168     0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xB0 - 0xB7 */
169     0x1A, 0x1A, 0x1A, 0x7C, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xB8 - 0xBF */
170     0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0xC0 - 0xC7 */
171     0x48, 0x49, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xC8 - 0xCF */
172     0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* 0xD0 - 0xD7 */
173     0x51, 0x52, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xD8 - 0xDF */
174     0x5C, 0x1A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* 0xE0 - 0xE7 */
175     0x59, 0x5A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xE8 - 0xEF */
176     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0xF0 - 0xF7 */
177     0x38, 0x39, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0xFF  /* 0xF8 - 0xFF */
178};
179
180/*
181**++
182**
183**  ROUTINE NAME:       rpc_string_free
184**
185**  SCOPE:              PUBLIC - declared in rpc.idl
186**
187**  DESCRIPTION:
188**
189**  This routine will free the memory allocated for a string data structure.
190**  A NULL pointer will be returned.
191**
192**  INPUTS:             none
193**
194**  INPUTS/OUTPUTS:
195**
196**      string          A pointer to the string pointer for the memory to
197**                      be freed.
198**
199**  OUTPUTS:
200**
201**      status          A value indicating the result of the routine.
202**
203**          rpc_s_ok        The call was successful.
204**          rpc_s_coding_error
205**
206**  IMPLICIT INPUTS:    none
207**
208**  IMPLICIT OUTPUTS:   none
209**
210**  FUNCTION VALUE:     void
211**
212**  SIDE EFFECTS:       none
213**
214**--
215**/
216
217PUBLIC void rpc_string_free
218(
219    unsigned_char_p_t       *string,
220    unsigned32              *status
221)
222{
223    CODING_ERROR (status);
224
225    if (*string != NULL)
226    {
227        RPC_MEM_FREE (*string, RPC_C_MEM_STRING);
228        *string = NULL;
229    }
230
231    *status = rpc_s_ok;
232    return;
233}
234
235/* Reads a token from string into the token variable. The token starts at
236 * string and ends when any character in deliminators is encountered.
237 *
238 * Zero length tokens will be returned if the first character in string is a
239 * deliminator.
240 *
241 * If escape is not '\0', then it will escape itself and any deliminators. If
242 * an escape character is followed by a non-special character (not a
243 * deliminator and not the escape character), then the escape character is
244 * stored in the string. Parsing is always stopped at a '\0', whether or not
245 * it is escaped.
246 *
247 * The token variable may be null, in which case the function performs
248 * normally, but the token is not returned.
249 *
250 * The return value is the number of raw characters (including escapes) that
251 * occur before the first deliminator. The deliminator that terminated the
252 * token can be found by looking at string[retvalue].
253 */
254PRIVATE size_t rpc__get_token(
255    const unsigned char *string,
256    unsigned_char_t	    escape,
257    const char *            deliminators,
258    unsigned_char_p_t       *token,
259    unsigned32              *status
260)
261{
262    size_t raw_size = 0, escaped_size = 0, read_pos = 0, write_pos = 0;
263    unsigned_char_t is_deliminator[256];
264
265    CODING_ERROR (status);
266
267    if (string == NULL)
268        string = (const unsigned char *)"";
269
270    memset(is_deliminator, 0, sizeof(is_deliminator));
271    for(raw_size = 0; deliminators[raw_size] != '\0'; raw_size++)
272    {
273        is_deliminator[(int) deliminators[raw_size]] = 1;
274    }
275    is_deliminator[0] = 1;
276
277    //Figure out how long token should be before writing it
278    escaped_size = 0;
279    for(raw_size = 0; !is_deliminator[string[raw_size]]; raw_size++)
280    {
281        if(string[raw_size] == escape)
282        {
283            unsigned_char_t next_char = string[raw_size + 1];
284            if((is_deliminator[next_char] && next_char != '\0') ||
285                    next_char == escape)
286            {
287                //This character is an escape because it is the escape
288                //character and the next character is special.
289                raw_size++;
290            }
291        }
292        escaped_size++;
293    }
294
295    if(token == NULL)
296        return raw_size;
297
298    RPC_MEM_ALLOC (
299        *token,
300        unsigned_char_p_t,
301        escaped_size + 1,
302        RPC_C_MEM_STRING,
303        RPC_C_MEM_NOWAIT);
304    if(*token == NULL)
305    {
306        *status = rpc_s_no_memory;
307        return raw_size;
308    }
309
310    write_pos = 0;
311    for(read_pos = 0; read_pos < raw_size && write_pos < escaped_size; read_pos++)
312    {
313        if(string[read_pos] == escape)
314        {
315            unsigned_char_t next_char = string[read_pos + 1];
316            if((is_deliminator[next_char] && next_char != '\0') ||
317                    next_char == escape)
318            {
319                //This character is an escape because it is the escape
320                //character and the next character is special.
321                read_pos++;
322            }
323        }
324        token[0][write_pos++] = string[read_pos];
325    }
326
327    token[0][write_pos] = '\0';
328
329    if(read_pos != raw_size || write_pos != escaped_size)
330    {
331        //Some other thread concurrently modified the string. It shouldn't do
332        //that
333        RPC_MEM_FREE (*token, RPC_C_MEM_STRING);
334        *status = rpc_s_invalid_arg;
335        *token = NULL;
336        return raw_size;
337    }
338
339    *status = rpc_s_ok;
340    return raw_size;
341}
342
343
344/*
345**++
346**
347**  ROUTINE NAME:       rpc__strcspn
348**
349**  SCOPE:              PRIVATE - declared in com.h
350**
351**  DESCRIPTION:
352**
353**  Searches a given string for any of a set of given terminating
354**  characters and returns a count of the number of non-terminating
355**  characters in the string preceding the first occurrance of any
356**  member of the terminating set.
357**
358**  The same signature and basically the same semantics as strcspn,
359**  except that members of the terminator set will not terminate the
360**  string if preceded by an escape (\) character.  Note that the escape
361**  character cannot be used as a member of the terminator set.
362**
363**  INPUTS:
364**
365**      string          A pointer to the string to be searched.
366**
367**      terms           A string of characters which are to be treated
368**                      as terminators.
369**
370**  INPUTS/OUTPUTS:     none
371**
372**  OUTPUTS:            none
373**
374**  IMPLICIT INPUTS:    none
375**
376**  IMPLICIT OUTPUTS:   none
377**
378**  FUNCTION VALUE:
379**
380**      A count of the number of character in the string preceding the
381**      first occurrance of any member of the terminating set. The count
382**      will be set to zero if no member of the terminating set is found
383**      in the string, or the string pointer is NULL. If a member of the
384**      terminating set is escaped ('\') in "string", it will be skipped
385**      over.
386**
387**  SIDE EFFECTS:       none
388**
389**--
390**/
391
392PRIVATE unsigned32 rpc__strcspn
393(
394    unsigned_char_p_t       string,
395    const char              *term_set
396)
397{
398    unsigned_char_p_t   ptr;
399    unsigned_char_p_t   term_ptr;
400    unsigned32          count;
401    unsigned32          escaped;
402
403    /*
404     * make sure there's something to do before we start
405     */
406    if (string == NULL)
407    {
408        return (0);
409    }
410
411    /*
412     * search for one of the given terminators
413     */
414    for (count = 1, escaped = false, ptr = string; *ptr != '\0'; count++, ptr++)
415    {
416        /*
417         * Check to see if the current character is an escape character
418         * and if so, skip over it to the next character, setting the flag.
419         */
420        if (*ptr == '\\')
421        {
422            escaped = true;
423            ptr++;
424            count++;
425        }
426
427        /*
428         * make sure it's not the end of the line
429         */
430        if (*ptr == '\0')
431        {
432            break;
433        }
434
435        if (escaped == true)
436        {
437            escaped = false;
438            continue;
439        }
440
441        if (escaped == false)
442        {
443            /*
444             * search the terminator set for a match
445             */
446            for (term_ptr = (unsigned_char_p_t) term_set;
447                 *term_ptr != '\0';
448                 term_ptr++)
449            {
450                if (*ptr == *term_ptr)
451                {
452                    return (count);
453                }
454            }
455        }
456    }
457
458    /*
459     * if no terminator in the set was found...
460     */
461    return (0);
462}
463
464/*
465**++
466**
467**  ROUTINE NAME:       rpc__strncpy
468**
469**  SCOPE:              PRIVATE - declared in com.h
470**
471**  DESCRIPTION:
472**
473**  Copies n characters from one string into another.
474**  The same signature and basically the same semantics as strncpy,
475**  except that the destination string is *always* null terminated.
476**  For this reason care must be taken that the value n is always
477**  one less than the available size for the target. Also, this routine
478**  doesn't bother to return useless information like strncpy.
479**
480**  INPUTS:
481**
482**      dst_string      A pointer to the destination string.
483**
484**      src_string      A pointer to the source string.
485**
486**      max_len         The maximum number of characters to be copied
487**                      from the source to the destination.
488**
489**  INPUTS/OUTPUTS:     none
490**
491**  OUTPUTS:            none
492**
493**  IMPLICIT INPUTS:    none
494**
495**  IMPLICIT OUTPUTS:   none
496**
497**  FUNCTION VALUE:     void
498**
499**  SIDE EFFECTS:       none
500**
501**--
502**/
503
504PRIVATE void rpc__strncpy
505(
506    unsigned_char_p_t       dst_string,
507    unsigned_char_p_t       src_string,
508    size_t                  max_len
509)
510{
511    /*
512     * make sure there's something to do before we start
513     */
514    if (src_string == NULL || dst_string == NULL || max_len == 0)
515    {
516        if (dst_string != NULL) *dst_string = '\0';
517        return;
518    }
519
520    /*
521     * just use strncpy, but unlike strncpy, add in a null terminator
522     */
523    strncpy ((char *) dst_string, (char *) src_string, max_len);
524    *(dst_string + max_len) = '\0';
525}
526
527/*
528**++
529**
530**  ROUTINE NAME:       rpc__strsqz
531**
532**  SCOPE:              PRIVATE - declared in com.h
533**
534**  DESCRIPTION:
535**
536**  Compress white space (space and tab characters) out of a given
537**  string. An escaped space or tab will be preserved in the result.
538**  Spaces, tabs and escapes within quoted strings will be preserved
539**  in the result. The opening quote character can be included in the
540**  quote by preceding it with the same character.
541**
542**  INPUTS:             none
543**
544**  INPUTS/OUTPUTS:
545**
546**      string          A pointer to the string to be compressed.
547**
548**  OUTPUTS:            none
549**
550**  IMPLICIT INPUTS:    none
551**
552**  IMPLICIT OUTPUTS:   none
553**
554**  FUNCTION VALUE:
555**
556**      A count of the number of character in the string after it has
557**      been compressed. The count will be set to zero if the string
558**      pointer is NULL.
559**
560**  SIDE EFFECTS:       none
561**
562**--
563**/
564
565PRIVATE unsigned32 rpc__strsqz
566(
567    unsigned_char_t         *string
568)
569{
570    unsigned_char_p_t   ptr1, ptr2;
571     unsigned32          count;
572
573    /*
574     * make sure there's something to do before we start
575     */
576    if (string == NULL)
577    {
578        return (0);
579    }
580
581    for (count = 0, ptr1 = ptr2 = string; *ptr1 != '\0'; ptr1++)
582    {
583        /*
584         * immediately after an escape all characters are valid
585         */
586        if (*ptr1 == '\\')
587        {
588            /*
589             * get the escape character itself
590             */
591            *(ptr2++) = *(ptr1++);
592            count++;
593
594            /*
595             * if the next character is not the end of the line, get that too
596             */
597            if (*ptr1 != '\0')
598            {
599                *(ptr2++) = *ptr1;
600                count++;
601            }
602        }
603        else
604        {
605            /*
606             * if we're not escaped, eliminate spaces and tabs
607             */
608            if (*ptr1 != ' ' && *ptr1 != '\t')
609            {
610                *(ptr2++) = *ptr1;
611                count++;
612            }
613        }
614    }
615
616    /*
617     * terminate the destination and return its size
618     */
619    *ptr2 = '\0';
620    return (count);
621}
622
623
624
625/*
626**++
627**
628**  ROUTINE NAME:       rpc_stralloc
629**
630**  SCOPE:              PUBLIC - declared in rpcpvt.idl
631**
632**  DESCRIPTION:
633**
634**  Make a copy of the input string into alloc'd storage.
635**
636**  INPUTS:
637**
638**      string          A pointer to the string to be copied.
639**
640**  INPUTS/OUTPUTS:
641**
642**  OUTPUTS:            none
643**
644**  IMPLICIT INPUTS:    none
645**
646**  IMPLICIT OUTPUTS:   none
647**
648**  FUNCTION VALUE:
649**
650**      Pointer to alloc'd string.
651**
652**  SIDE EFFECTS:       none
653**
654**--
655**/
656
657PUBLIC unsigned_char_p_t rpc_stralloc (string)
658
659unsigned_char_p_t       string;
660
661{
662    unsigned_char_p_t   cstring;
663    size_t len;
664
665    len = strlen ((char *) string) + 1;
666
667    RPC_MEM_ALLOC (
668        cstring,
669        unsigned_char_p_t,
670        len,
671        RPC_C_MEM_STRING,
672        RPC_C_MEM_WAITOK);
673
674    strlcpy ((char *) cstring, (char *) string, len);
675
676    return (cstring);
677}
678
679/*
680**++
681**
682**  ROUTINE NAME:       rpc__stralloc
683**
684**  SCOPE:              PRIVATE - declared in com.h
685**
686**  DESCRIPTION:
687**
688**  Old routine whose functionality has been replaced
689**  by rpc_stralloc.
690**
691**  INPUTS:
692**
693**      string          A pointer to the string to be copied.
694**
695**  INPUTS/OUTPUTS:
696**
697**  OUTPUTS:            none
698**
699**  IMPLICIT INPUTS:    none
700**
701**  IMPLICIT OUTPUTS:   none
702**
703**  FUNCTION VALUE:
704**
705**      Pointer to alloc'd string.
706**
707**  SIDE EFFECTS:       none
708**
709**--
710**/
711
712PRIVATE unsigned_char_p_t rpc__stralloc
713(
714    unsigned_char_p_t       string
715)
716{
717
718    return (rpc_stralloc (string));
719
720}
721
722
723/*
724**++
725**
726**  ROUTINE NAME:       rpc_util_strcvt
727**
728**  SCOPE:              PUBLIC - declared in rpc.idl
729**
730**  DESCRIPTION:
731**
732**  Routine to convert between ASCII and EBCDIC character representations.
733**
734**  INPUTS:
735**
736**	to_ascii	boolean flag indicating which conversion to make
737**			a 'true' value indicates to convert from ebcdic to
738**			ascii
739**
740**	len		length of string to be converted
741**
742**  INPUTS/OUTPUTS:     none
743**
744**      src		pointer to source string pointer
745**	dst		pointer to destination string pointer
746**
747**  OUTPUTS:            none
748**
749**  IMPLICIT INPUTS:    none
750**
751**  IMPLICIT OUTPUTS:   none
752**
753**  FUNCTION VALUE:	none
754**
755**  SIDE EFFECTS:       none
756**
757**--
758**/
759
760PUBLIC void rpc_util_strcvt
761(
762    boolean32		to_ascii,
763    unsigned32		len,
764    unsigned_char_p_t	src,
765    unsigned_char_p_t	dst
766)
767{
768    unsigned_char_p_t cvt_tbl;
769
770    RPC_VERIFY_INIT ();
771
772    cvt_tbl = to_ascii ? cvt_ebcdic_to_ascii : cvt_ascii_to_ebcdic;
773
774    while ( len-- )
775    {
776    	*dst++ = cvt_tbl[*src++];
777    }
778}
779