---
name: "radcli_avp_concat_str"
section: "3"
platform: "linux"
package: "radcli"
version: "2.0.1-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/radcli_avp_concat_str"
---

# radcli\_avp\_concat\_str(3)

Concatenate every occurrence of an attribute into a bounded buffer.

## NAME

radcli\_avp\_concat\_str - Concatenate every occurrence of an attribute into a bounded buffer.

## SYNOPSIS

```
#include <radcli/>

int radcli_avp_concat_str(
    char                   *buf,
    size_t                  buflen,
    const radcli_avp_list  *list,
    const radcli_attr_def  *def,
    const char             *sep
);
```

## DESCRIPTION

Generalizes the one convenience legacy radcli.h's rc\_aaa() folded into its own call signature (its msg parameter: "will contain the

concatenation of any PW\_REPLY\_MESSAGE received", lib/buildreq.c) to any attribute, since the pattern  walk every occurrence of one attribute in a reply, join as text  is not specific to Reply-Message. A caller wanting rc\_aaa()'s old convenience no longer needs to hand-roll the radcli\_avp\_get()-in-a-loop this replaces.

If no occurrence of def is present in list, buf is set to an empty string and 0 is returned  this is not a failure, the same way rc\_aaa()'s msg started as ' ' and simply stayed that way when no Reply-Message arrived. An attribute whose value contains an embedded NUL byte, or (for a RADCLI\_TYPE\_TEXT attribute) invalid UTF-8, is skipped (radcli\_avp\_get\_cstr()'s policy), not treated as a failure either.

Follows snprintf()'s buffer-sizing contract exactly: buf may be NULL and/or buflen may be 0 to size a buffer before allocating one (nothing is written in that case), and the return value is always the number of bytes the joined result would occupy, whether or not it fit  a return \>= buflen means the result was truncated, and buf (if non-NULL and buflen \> 0) then holds only a valid NUL-terminated prefix of what fits, never garbage and never unterminated.

## PARAMETERS

- **buf**

  destination buffer, or NULL to only compute the needed size; always left NUL-terminated on return (including on truncation, containing whatever fit), whenever buf is non-NULL and buflen \> 0.

- **buflen**

  size of buf, in bytes; may be 0.

- **list**

  the list to search.

- **def**

  the attribute to concatenate occurrences of.

- **sep**

  separator inserted between occurrences; NULL or "" for none.

## RETURN VALUE

the number of bytes the joined result occupies (excluding the NUL terminator), whether or not it fit in buf  or -1 if def is NULL.

## SEE ALSO

[*radcli\_avp\_add\_bytes*(3)](/radcli_avp_add_bytes/3.md), [*radcli\_avp\_add\_bytes\_by\_num*(3)](/radcli_avp_add_bytes_by_num/3.md), [*radcli\_avp\_add\_gigawords64*(3)](/radcli_avp_add_gigawords64/3.md), [*radcli\_avp\_add\_gigawords64\_by\_num*(3)](/radcli_avp_add_gigawords64_by_num/3.md), [*radcli\_avp\_add\_ip4*(3)](/radcli_avp_add_ip4/3.md), [*radcli\_avp\_add\_ip4\_by\_num*(3)](/radcli_avp_add_ip4_by_num/3.md), [*radcli\_avp\_add\_ip4prefix*(3)](/radcli_avp_add_ip4prefix/3.md), [*radcli\_avp\_add\_ip4prefix\_by\_num*(3)](/radcli_avp_add_ip4prefix_by_num/3.md), [*radcli\_avp\_add\_ip6*(3)](/radcli_avp_add_ip6/3.md), [*radcli\_avp\_add\_ip6\_by\_num*(3)](/radcli_avp_add_ip6_by_num/3.md), [*radcli\_avp\_add\_str*(3)](/radcli_avp_add_str/3.md), [*radcli\_avp\_add\_str\_by\_num*(3)](/radcli_avp_add_str_by_num/3.md), [*radcli\_avp\_add\_uint32*(3)](/radcli_avp_add_uint32/3.md), [*radcli\_avp\_add\_uint32\_by\_num*(3)](/radcli_avp_add_uint32_by_num/3.md), [*radcli\_avp\_add\_uint64*(3)](/radcli_avp_add_uint64/3.md), [*radcli\_avp\_add\_uint64\_by\_num*(3)](/radcli_avp_add_uint64_by_num/3.md), [*radcli\_avp\_add\_username*(3)](/radcli_avp_add_username/3.md), [*radcli\_avp\_concat\_str\_by\_num*(3)](/radcli_avp_concat_str_by_num/3.md), [*radcli\_avp\_def*(3)](/radcli_avp_def/3.md), [*radcli\_avp\_get*(3)](/radcli_avp_get/3.md), [*radcli\_avp\_get\_by\_num*(3)](/radcli_avp_get_by_num/3.md), [*radcli\_avp\_get\_bytes*(3)](/radcli_avp_get_bytes/3.md), [*radcli\_avp\_get\_bytes\_by\_num*(3)](/radcli_avp_get_bytes_by_num/3.md), [*radcli\_avp\_get\_cstr*(3)](/radcli_avp_get_cstr/3.md), [*radcli\_avp\_get\_cstr\_by\_num*(3)](/radcli_avp_get_cstr_by_num/3.md), [*radcli\_avp\_get\_gigawords64*(3)](/radcli_avp_get_gigawords64/3.md), [*radcli\_avp\_get\_gigawords64\_by\_num*(3)](/radcli_avp_get_gigawords64_by_num/3.md), [*radcli\_avp\_get\_ip4prefix*(3)](/radcli_avp_get_ip4prefix/3.md), [*radcli\_avp\_get\_ip4prefix\_by\_num*(3)](/radcli_avp_get_ip4prefix_by_num/3.md), [*radcli\_avp\_get\_ip6*(3)](/radcli_avp_get_ip6/3.md), [*radcli\_avp\_get\_ip6\_by\_num*(3)](/radcli_avp_get_ip6_by_num/3.md), [*radcli\_avp\_get\_uint32*(3)](/radcli_avp_get_uint32/3.md), [*radcli\_avp\_get\_uint32\_by\_num*(3)](/radcli_avp_get_uint32_by_num/3.md), [*radcli\_avp\_get\_uint64*(3)](/radcli_avp_get_uint64/3.md), [*radcli\_avp\_get\_uint64\_by\_num*(3)](/radcli_avp_get_uint64_by_num/3.md), [*radcli\_avp\_iter\_next*(3)](/radcli_avp_iter_next/3.md), [*radcli\_avp\_list\_error*(3)](/radcli_avp_list_error/3.md), [*radcli\_avp\_list\_free*(3)](/radcli_avp_list_free/3.md), [*radcli\_avp\_list\_iter*(3)](/radcli_avp_list_iter/3.md), [*radcli\_avp\_list\_new*(3)](/radcli_avp_list_new/3.md)
