1/* This file is part of Mailfromd. -*- c -*- 2 Copyright (C) 2009-2021 Sergey Poznyakoff 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17MF_BUILTIN_MODULE 18 19#ifndef ENAMETOOLONG 20# define ENAMETOOLONG 0 21#endif 22 23#ifndef INITIAL_HOSTNAME_LENGTH 24# define INITIAL_HOSTNAME_LENGTH 34 25#endif 26 27#ifndef INITIAL_DOMAINNAME_LENGTH 28# define INITIAL_DOMAINNAME_LENGTH 34 29#endif 30 31/* string gethostname() 32 33 This implementation is based on xgethostname by Jim Meyering 34*/ 35MF_DEFUN(gethostname, STRING, OPTIONAL, NUMBER dns) 36{ 37 size_t size = INITIAL_HOSTNAME_LENGTH; 38 39 MF_OBSTACK_BEGIN(); 40 while (1) { 41 size_t nsize; 42 size_t size_1; 43 char *hostname; 44 45 MF_OBSTACK_GROW(NULL, size); 46 hostname = MF_OBSTACK_BASE(); 47 48 /* Use SIZE_1 here rather than SIZE to work around the bug in 49 SunOS 5.5's gethostname whereby it NUL-terminates HOSTNAME 50 even when the name is as long as the supplied buffer. */ 51 size_1 = size - 1; 52 hostname[size_1 - 1] = '\0'; 53 errno = 0; 54 55 if (gethostname(hostname, size_1) == 0) { 56 if (!hostname[size_1 - 1]) 57 break; 58 } else if (errno != 0 59 && errno != ENAMETOOLONG && errno != EINVAL 60 /* OSX/Darwin does this when the buffer is not 61 large enough */ 62 && errno != ENOMEM) { 63 int saved_errno = errno; 64 MF_OBSTACK_CANCEL(); 65 MF_THROW(mfe_failure, 66 "%s", mu_strerror(saved_errno)); 67 } 68 69 nsize = size * 2; 70 if (nsize <= size) { 71 MF_OBSTACK_CANCEL(); 72 MF_THROW(mfe_failure, 73 "%s", mu_strerror(ENOMEM)); 74 } 75 size = nsize; 76 } 77 78 if (MF_OPTVAL(dns)) { 79 struct hostent *hp; 80 char *ptr = MF_OBSTACK_BASE; 81 82 hp = gethostbyname(ptr); 83 if (hp) { 84 size_t nlen = strlen(hp->h_name); 85 if (nlen >= size) 86 MF_OBSTACK_GROW(NULL, 87 nlen - size + 1); 88 strcpy(ptr, hp->h_name); 89 } 90 } 91 92 MF_RETURN_OBSTACK(); 93} 94END 95 96/* string getdomainname() 97 98 This implementation is based on xgetdomainname by Jim Meyering 99*/ 100MF_DEFUN(getdomainname, STRING) 101{ 102 size_t size = INITIAL_DOMAINNAME_LENGTH; 103 104 MF_OBSTACK_BEGIN(); 105 while (1) { 106 size_t nsize; 107 size_t size_1; 108 char *domainname; 109 int rc; 110 111 MF_OBSTACK_GROW(NULL, size); 112 domainname = MF_OBSTACK_BASE(); 113 114 size_1 = size - 1; 115 domainname[size_1 - 1] = '\0'; 116 errno = 0; 117 118 rc = getdomainname(domainname, size); 119 if (rc >= 0 && domainname[size_1] == '\0') 120 break; 121 else if (rc < 0 && errno != EINVAL) { 122 int saved_errno = errno; 123 MF_OBSTACK_CANCEL(); 124 MF_THROW(mfe_failure, 125 "%s", mu_strerror(saved_errno)); 126 } 127 128 nsize = size * 2; 129 if (nsize <= size) { 130 MF_OBSTACK_CANCEL(); 131 MF_THROW(mfe_failure, 132 "%s", mu_strerror(ENOMEM)); 133 } 134 size = nsize; 135 } 136 MF_RETURN_OBSTACK(); 137} 138END 139 140