/* * Copyright (c) 2002, 2003, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: rfc2821dom.c,v 1.8 2005/03/15 19:56:07 ca Exp $") #include "sm/assert.h" #include "sm/error.h" #include "sm/memops.h" #include "sm/ctype.h" #include "sm/rfc2821.h" #include "sm/rfc2822.h" /* ** T2821_CP_TOKEN -- copy a token ** ** Parameters: ** rpool -- rpool ** src_tok -- source token ** dst_tok -- destination token (output) ** ** Returns: ** usual error code */ sm_ret_T t2821_cp_token(sm_rpool_P rpool, sm_t2821_P src_tok,sm_t2821_P *pdst_tok) { sm_t2821_P new_tok; int curtype; SM_REQUIRE(pdst_tok != NULL); curtype = src_tok->sm_t2821_type; new_tok = (sm_t2821_P) sm_rpool_zalloc(rpool, sizeof(*new_tok)); if (new_tok == NULL) goto error; new_tok->sm_t2821_type = curtype; if (curtype >= T2821_MINTOK) { new_tok->sm_t2821_val = sm_str_dup(rpool, src_tok->sm_t2821_val); if (new_tok->sm_t2821_val == NULL) goto error; } *pdst_tok = new_tok; return SM_SUCCESS; error: /* remove unconnected token */ if (new_tok != NULL) t2821_free(rpool, new_tok); return sm_error_temp(SM_EM_ADDR, ENOMEM); } /* ** T2821_EXTRACT_DOMAIN -- extract a domain from a valid address ** ** Parameters: ** rpool -- rpool ** addr -- address ** pdomain -- domain part of address (output) ** ** Returns: ** usual error code */ sm_ret_T t2821_extract_domain(sm_rpool_P rpool, sm_a2821_T *addr, sm_a2821_T **pdomain) { sm_t2821_P tok; sm_t2821_P t; sm_ret_T ret; SM_REQUIRE(addr != NULL); SM_REQUIRE(pdomain != NULL); tok = A2821_FIRST(addr); /* ** Search for '@'. This doesn't work for "route addresses", but ** those are supposed to be stripped before this function is called. */ while (tok != NULL && tok != A2821_END(addr) && tok->sm_t2821_type != T2821_AT) tok = T2821_NEXT(tok); if (tok == NULL || tok == A2821_END(addr)) return sm_error_perm(SM_EM_ADDR, R2821_ERR_FQDN); /* XXX? */ /* skip over '@' */ tok = T2821_NEXT(tok); /* copy rest of address (domain part) */ while (tok != NULL && tok != A2821_END(addr) && tok->sm_t2821_type != T2821_RIGHT) { ret = t2821_cp_token(rpool, tok, &t); if (sm_is_err(ret)) goto error; tok = T2821_NEXT(tok); A2821_INSERT_TAIL(*pdomain, t); } return SM_SUCCESS; error: /* remove unconnected token */ if (t != NULL) t2821_free(rpool, t); /* should cleanup addr, need to remember old value, free new ones */ return ret; }