|
Packit Service |
31306d |
/*
|
|
Packit Service |
31306d |
* token.c - Token list handling functions
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* This file is part of the SSH Library
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* Copyright (c) 2003-2008 by Aris Adamantiadis
|
|
Packit Service |
31306d |
* Copyright (c) 2019 by Anderson Toshiyuki Sasaki - Red Hat, Inc.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* The SSH Library is free software; you can redistribute it and/or modify
|
|
Packit Service |
31306d |
* it under the terms of the GNU Lesser General Public License as published by
|
|
Packit Service |
31306d |
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
|
Packit Service |
31306d |
* option) any later version.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* The SSH Library is distributed in the hope that it will be useful, but
|
|
Packit Service |
31306d |
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
Packit Service |
31306d |
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
Packit Service |
31306d |
* License for more details.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
31306d |
* along with the SSH Library; see the file COPYING. If not, write to
|
|
Packit Service |
31306d |
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
Packit Service |
31306d |
* MA 02111-1307, USA.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#include "config.h"
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#include <stdio.h>
|
|
Packit Service |
31306d |
#include <string.h>
|
|
Packit Service |
31306d |
#include <stdbool.h>
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#include "libssh/priv.h"
|
|
Packit Service |
31306d |
#include "libssh/token.h"
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief Free the given tokens list structure. The used buffer is overwritten
|
|
Packit Service |
31306d |
* with zeroes before freed.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] tokens The pointer to a structure to be freed;
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_tokens_free(struct ssh_tokens_st *tokens)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
int i;
|
|
Packit Service |
31306d |
if (tokens == NULL) {
|
|
Packit Service |
31306d |
return;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (tokens->tokens != NULL) {
|
|
Packit Service |
31306d |
for (i = 0; tokens->tokens[i] != NULL; i++) {
|
|
Packit Service |
31306d |
explicit_bzero(tokens->tokens[i], strlen(tokens->tokens[i]));
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SAFE_FREE(tokens->buffer);
|
|
Packit Service |
31306d |
SAFE_FREE(tokens->tokens);
|
|
Packit Service |
31306d |
SAFE_FREE(tokens);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief Split a given string on the given separator character. The returned
|
|
Packit Service |
31306d |
* structure holds an array of pointers (tokens) pointing to the obtained
|
|
Packit Service |
31306d |
* parts and a buffer where all the content of the list is stored. The last
|
|
Packit Service |
31306d |
* element of the array will always be set as NULL.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] chain The string to split
|
|
Packit Service |
31306d |
* @param[in] separator The character used to separate the tokens.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return A newly allocated tokens list structure; NULL in case of error.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
struct ssh_tokens_st *ssh_tokenize(const char *chain, char separator)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
struct ssh_tokens_st *tokens = NULL;
|
|
Packit Service |
31306d |
size_t num_tokens = 1, i = 1;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
char *found, *c;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (chain == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
tokens = calloc(1, sizeof(struct ssh_tokens_st));
|
|
Packit Service |
31306d |
if (tokens == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
tokens->buffer= strdup(chain);
|
|
Packit Service |
31306d |
if (tokens->buffer == NULL) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
c = tokens->buffer;
|
|
Packit Service |
31306d |
do {
|
|
Packit Service |
31306d |
found = strchr(c, separator);
|
|
Packit Service |
31306d |
if (found != NULL) {
|
|
Packit Service |
31306d |
c = found + 1;
|
|
Packit Service |
31306d |
num_tokens++;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
} while(found != NULL);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Allocate tokens list */
|
|
Packit Service |
31306d |
tokens->tokens = calloc(num_tokens + 1, sizeof(char *));
|
|
Packit Service |
31306d |
if (tokens->tokens == NULL) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* First token starts in the beginning of the chain */
|
|
Packit Service |
31306d |
tokens->tokens[0] = tokens->buffer;
|
|
Packit Service |
31306d |
c = tokens->buffer;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (i = 1; i < num_tokens; i++) {
|
|
Packit Service |
31306d |
/* Find next separator */
|
|
Packit Service |
31306d |
found = strchr(c, separator);
|
|
Packit Service |
31306d |
if (found == NULL) {
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Replace it with a string terminator */
|
|
Packit Service |
31306d |
*found = '\0';
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* The next token starts in the next byte */
|
|
Packit Service |
31306d |
c = found + 1;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* If we did not reach the end of the chain yet, set the next token */
|
|
Packit Service |
31306d |
if (*c != '\0') {
|
|
Packit Service |
31306d |
tokens->tokens[i] = c;
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return tokens;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
error:
|
|
Packit Service |
31306d |
ssh_tokens_free(tokens);
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief Given two strings, the first containing a list of available tokens and
|
|
Packit Service |
31306d |
* the second containing a list of tokens to be searched ordered by preference,
|
|
Packit Service |
31306d |
* returns a copy of the first preferred token present in the available list.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] available_list The list of available tokens
|
|
Packit Service |
31306d |
* @param[in] preferred_list The list of tokens to search, ordered by
|
|
Packit Service |
31306d |
* preference
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return A newly allocated copy of the token if found; NULL otherwise
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
char *ssh_find_matching(const char *available_list,
|
|
Packit Service |
31306d |
const char *preferred_list)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
struct ssh_tokens_st *a_tok = NULL, *p_tok = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int i, j;
|
|
Packit Service |
31306d |
char *ret = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if ((available_list == NULL) || (preferred_list == NULL)) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
a_tok = ssh_tokenize(available_list, ',');
|
|
Packit Service |
31306d |
if (a_tok == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
p_tok = ssh_tokenize(preferred_list, ',');
|
|
Packit Service |
31306d |
if (p_tok == NULL) {
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (i = 0; p_tok->tokens[i]; i++) {
|
|
Packit Service |
31306d |
for (j = 0; a_tok->tokens[j]; j++) {
|
|
Packit Service |
31306d |
if (strcmp(a_tok->tokens[j], p_tok->tokens[i]) == 0) {
|
|
Packit Service |
31306d |
ret = strdup(a_tok->tokens[j]);
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
out:
|
|
Packit Service |
31306d |
ssh_tokens_free(a_tok);
|
|
Packit Service |
31306d |
ssh_tokens_free(p_tok);
|
|
Packit Service |
31306d |
return ret;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief Given two strings, the first containing a list of available tokens and
|
|
Packit Service |
31306d |
* the second containing a list of tokens to be searched ordered by preference,
|
|
Packit Service |
31306d |
* returns a list of all matching tokens ordered by preference.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] available_list The list of available tokens
|
|
Packit Service |
31306d |
* @param[in] preferred_list The list of tokens to search, ordered by
|
|
Packit Service |
31306d |
* preference
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return A newly allocated string containing the list of all matching tokens;
|
|
Packit Service |
31306d |
* NULL otherwise
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
char *ssh_find_all_matching(const char *available_list,
|
|
Packit Service |
31306d |
const char *preferred_list)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
struct ssh_tokens_st *a_tok = NULL, *p_tok = NULL;
|
|
Packit Service |
31306d |
int i, j;
|
|
Packit Service |
31306d |
char *ret = NULL;
|
|
Packit Service |
31306d |
size_t max, len, pos = 0;
|
|
Packit Service |
31306d |
int match;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if ((available_list == NULL) || (preferred_list == NULL)) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
max = MAX(strlen(available_list), strlen(preferred_list));
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ret = calloc(1, max + 1);
|
|
Packit Service |
31306d |
if (ret == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
a_tok = ssh_tokenize(available_list, ',');
|
|
Packit Service |
31306d |
if (a_tok == NULL) {
|
|
Packit Service |
31306d |
SAFE_FREE(ret);
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
p_tok = ssh_tokenize(preferred_list, ',');
|
|
Packit Service |
31306d |
if (p_tok == NULL) {
|
|
Packit Service |
31306d |
SAFE_FREE(ret);
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (i = 0; p_tok->tokens[i] ; i++) {
|
|
Packit Service |
31306d |
for (j = 0; a_tok->tokens[j]; j++) {
|
|
Packit Service |
31306d |
match = !strcmp(a_tok->tokens[j], p_tok->tokens[i]);
|
|
Packit Service |
31306d |
if (match) {
|
|
Packit Service |
31306d |
if (pos != 0) {
|
|
Packit Service |
31306d |
ret[pos] = ',';
|
|
Packit Service |
31306d |
pos++;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
len = strlen(a_tok->tokens[j]);
|
|
Packit Service |
31306d |
memcpy(&ret[pos], a_tok->tokens[j], len);
|
|
Packit Service |
31306d |
pos += len;
|
|
Packit Service |
31306d |
ret[pos] = '\0';
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (ret[0] == '\0') {
|
|
Packit Service |
31306d |
SAFE_FREE(ret);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
out:
|
|
Packit Service |
31306d |
ssh_tokens_free(a_tok);
|
|
Packit Service |
31306d |
ssh_tokens_free(p_tok);
|
|
Packit Service |
31306d |
return ret;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief Given a string containing a list of elements, remove all duplicates
|
|
Packit Service |
31306d |
* and return in a newly allocated string.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] list The list to be freed of duplicates
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return A newly allocated copy of the string free of duplicates; NULL in
|
|
Packit Service |
31306d |
* case of error.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
char *ssh_remove_duplicates(const char *list)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
struct ssh_tokens_st *tok = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
size_t i, j, num_tokens, max_len;
|
|
Packit Service |
31306d |
char *ret = NULL;
|
|
Packit Service |
31306d |
bool *should_copy = NULL, need_comma = false;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (list == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* The maximum number of tokens is the size of the list */
|
|
Packit Service |
31306d |
max_len = strlen(list);
|
|
Packit Service |
31306d |
if (max_len == 0) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Add space for ending '\0' */
|
|
Packit Service |
31306d |
max_len++;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
tok = ssh_tokenize(list, ',');
|
|
Packit Service |
31306d |
if ((tok == NULL) || (tok->tokens == NULL) || (tok->tokens[0] == NULL)) {
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
should_copy = calloc(1, max_len);
|
|
Packit Service |
31306d |
if (should_copy == NULL) {
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (strlen(tok->tokens[0]) > 0) {
|
|
Packit Service |
31306d |
should_copy[0] = true;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (i = 1; tok->tokens[i]; i++) {
|
|
Packit Service |
31306d |
for (j = 0; j < i; j++) {
|
|
Packit Service |
31306d |
if (strcmp(tok->tokens[i], tok->tokens[j]) == 0) {
|
|
Packit Service |
31306d |
/* Found a duplicate; do not copy */
|
|
Packit Service |
31306d |
should_copy[i] = false;
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* No matching token before */
|
|
Packit Service |
31306d |
if (j == i) {
|
|
Packit Service |
31306d |
/* Only copy if it is not an empty string */
|
|
Packit Service |
31306d |
if (strlen(tok->tokens[i]) > 0) {
|
|
Packit Service |
31306d |
should_copy[i] = true;
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
should_copy[i] = false;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
num_tokens = i;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ret = calloc(1, max_len);
|
|
Packit Service |
31306d |
if (ret == NULL) {
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (i = 0; i < num_tokens; i++) {
|
|
Packit Service |
31306d |
if (should_copy[i]) {
|
|
Packit Service |
31306d |
if (need_comma) {
|
|
Packit Service |
31306d |
strncat(ret, ",", (max_len - strlen(ret) - 1));
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
strncat(ret, tok->tokens[i], (max_len - strlen(ret) - 1));
|
|
Packit Service |
31306d |
need_comma = true;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* If no comma is needed, nothing was copied */
|
|
Packit Service |
31306d |
if (!need_comma) {
|
|
Packit Service |
31306d |
SAFE_FREE(ret);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
out:
|
|
Packit Service |
31306d |
SAFE_FREE(should_copy);
|
|
Packit Service |
31306d |
ssh_tokens_free(tok);
|
|
Packit Service |
31306d |
return ret;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief Given two strings containing lists of tokens, return a newly
|
|
Packit Service |
31306d |
* allocated string containing all the elements of the first list appended with
|
|
Packit Service |
31306d |
* all the elements of the second list, without duplicates. The order of the
|
|
Packit Service |
31306d |
* elements will be preserved.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] list The first list
|
|
Packit Service |
31306d |
* @param[in] appended_list The list to be appended
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return A newly allocated copy list containing all the elements of the
|
|
Packit Service |
31306d |
* kept_list appended with the elements of the appended_list without duplicates;
|
|
Packit Service |
31306d |
* NULL in case of error.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
char *ssh_append_without_duplicates(const char *list,
|
|
Packit Service |
31306d |
const char *appended_list)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
size_t concat_len = 0;
|
|
Packit Service |
31306d |
char *ret = NULL, *concat = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (list != NULL) {
|
|
Packit Service |
31306d |
concat_len = strlen(list);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (appended_list != NULL) {
|
|
Packit Service |
31306d |
concat_len += strlen(appended_list);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (concat_len == 0) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Add room for ending '\0' and for middle ',' */
|
|
Packit Service |
31306d |
concat_len += 2;
|
|
Packit Service |
31306d |
concat = calloc(1, concat_len);
|
|
Packit Service |
31306d |
if (concat == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (list != NULL) {
|
|
Packit Service |
31306d |
strcpy(concat, list);
|
|
Packit Service |
31306d |
strncat(concat, ",", concat_len - strlen(concat) - 1);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (appended_list != NULL) {
|
|
Packit Service |
31306d |
strncat(concat, appended_list, concat_len - strlen(concat) - 1);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ret = ssh_remove_duplicates(concat);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SAFE_FREE(concat);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return ret;
|
|
Packit Service |
31306d |
}
|