17c478bd9Sstevel@tonic-gate /* 2*1dd3983cSYuri Pankov * Copyright (c) 1980, 1993 3*1dd3983cSYuri Pankov * The Regents of the University of California. All rights reserved. 47c478bd9Sstevel@tonic-gate * 5*1dd3983cSYuri Pankov * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 67c478bd9Sstevel@tonic-gate * 7*1dd3983cSYuri Pankov * Redistribution and use in source and binary forms, with or without 8*1dd3983cSYuri Pankov * modification, are permitted provided that the following conditions 9*1dd3983cSYuri Pankov * are met: 10*1dd3983cSYuri Pankov * 1. Redistributions of source code must retain the above copyright 11*1dd3983cSYuri Pankov * notice, this list of conditions and the following disclaimer. 12*1dd3983cSYuri Pankov * 2. Redistributions in binary form must reproduce the above copyright 13*1dd3983cSYuri Pankov * notice, this list of conditions and the following disclaimer in the 14*1dd3983cSYuri Pankov * documentation and/or other materials provided with the distribution. 15*1dd3983cSYuri Pankov * 4. Neither the name of the University nor the names of its contributors 16*1dd3983cSYuri Pankov * may be used to endorse or promote products derived from this software 17*1dd3983cSYuri Pankov * without specific prior written permission. 187c478bd9Sstevel@tonic-gate * 19*1dd3983cSYuri Pankov * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20*1dd3983cSYuri Pankov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21*1dd3983cSYuri Pankov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22*1dd3983cSYuri Pankov * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23*1dd3983cSYuri Pankov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24*1dd3983cSYuri Pankov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25*1dd3983cSYuri Pankov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26*1dd3983cSYuri Pankov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27*1dd3983cSYuri Pankov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28*1dd3983cSYuri Pankov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29*1dd3983cSYuri Pankov * SUCH DAMAGE. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <sys/types.h> 337c478bd9Sstevel@tonic-gate #include <sys/socket.h> 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include <netinet/in.h> 36*1dd3983cSYuri Pankov #include <arpa/inet.h> 37*1dd3983cSYuri Pankov #include <ctype.h> 38*1dd3983cSYuri Pankov #include <err.h> 39*1dd3983cSYuri Pankov #include <limits.h> 407c478bd9Sstevel@tonic-gate #include <netdb.h> 41*1dd3983cSYuri Pankov #include <stdarg.h> 42*1dd3983cSYuri Pankov #include <stdio.h> 43f098c48bSDerek Morr #include <stdlib.h> 44*1dd3983cSYuri Pankov #include <string.h> 45*1dd3983cSYuri Pankov #include <sysexits.h> 46f098c48bSDerek Morr #include <unistd.h> 477c478bd9Sstevel@tonic-gate 48*1dd3983cSYuri Pankov #define ABUSEHOST "whois.abuse.net" 49*1dd3983cSYuri Pankov #define NICHOST "whois.crsnic.net" 50*1dd3983cSYuri Pankov #define INICHOST "whois.networksolutions.com" 51*1dd3983cSYuri Pankov #define GNICHOST "whois.nic.gov" 52*1dd3983cSYuri Pankov #define ANICHOST "whois.arin.net" 53*1dd3983cSYuri Pankov #define LNICHOST "whois.lacnic.net" 54*1dd3983cSYuri Pankov #define KNICHOST "whois.krnic.net" 55*1dd3983cSYuri Pankov #define RNICHOST "whois.ripe.net" 56*1dd3983cSYuri Pankov #define PNICHOST "whois.apnic.net" 57*1dd3983cSYuri Pankov #define MNICHOST "whois.ra.net" 58*1dd3983cSYuri Pankov #define QNICHOST_TAIL ".whois-servers.net" 59*1dd3983cSYuri Pankov #define BNICHOST "whois.registro.br" 60*1dd3983cSYuri Pankov #define NORIDHOST "whois.norid.no" 61*1dd3983cSYuri Pankov #define IANAHOST "whois.iana.org" 62*1dd3983cSYuri Pankov #define GERMNICHOST "de.whois-servers.net" 63*1dd3983cSYuri Pankov #define FNICHOST "whois.afrinic.net" 64*1dd3983cSYuri Pankov #define DEFAULT_PORT "whois" 65*1dd3983cSYuri Pankov #define WHOIS_SERVER_ID "Whois Server: " 66*1dd3983cSYuri Pankov #define WHOIS_ORG_SERVER_ID "Registrant Street1:Whois Server:" 67*1dd3983cSYuri Pankov 68*1dd3983cSYuri Pankov #define WHOIS_RECURSE 0x01 69*1dd3983cSYuri Pankov #define WHOIS_QUICK 0x02 70*1dd3983cSYuri Pankov 71*1dd3983cSYuri Pankov #define ishost(h) (isalnum((unsigned char)h) || h == '.' || h == '-') 72*1dd3983cSYuri Pankov 73*1dd3983cSYuri Pankov const char *ip_whois[] = { LNICHOST, RNICHOST, PNICHOST, BNICHOST, 74*1dd3983cSYuri Pankov FNICHOST, NULL }; 75*1dd3983cSYuri Pankov const char *port = DEFAULT_PORT; 76*1dd3983cSYuri Pankov 77*1dd3983cSYuri Pankov static char *choose_server(char *); 78*1dd3983cSYuri Pankov static struct addrinfo *gethostinfo(char const *host, int exit_on_error); 79*1dd3983cSYuri Pankov static void s_asprintf(char **ret, const char *format, ...); 80*1dd3983cSYuri Pankov static void usage(void); 81*1dd3983cSYuri Pankov static void whois(const char *, const char *, int); 82*1dd3983cSYuri Pankov static char *getln(FILE *in, size_t *lenp); 837c478bd9Sstevel@tonic-gate 84740638c8Sbw int 85f098c48bSDerek Morr main(int argc, char *argv[]) 867c478bd9Sstevel@tonic-gate { 87*1dd3983cSYuri Pankov const char *country, *host; 88*1dd3983cSYuri Pankov char *qnichost; 89*1dd3983cSYuri Pankov int ch, flags, use_qnichost; 907c478bd9Sstevel@tonic-gate 91*1dd3983cSYuri Pankov country = host = qnichost = NULL; 92*1dd3983cSYuri Pankov flags = use_qnichost = 0; 93*1dd3983cSYuri Pankov while ((ch = getopt(argc, argv, "aAbc:fgh:iIklmp:Qr")) != -1) { 94*1dd3983cSYuri Pankov switch (ch) { 95*1dd3983cSYuri Pankov case 'a': 96*1dd3983cSYuri Pankov host = ANICHOST; 97f098c48bSDerek Morr break; 98*1dd3983cSYuri Pankov case 'A': 99*1dd3983cSYuri Pankov host = PNICHOST; 100*1dd3983cSYuri Pankov break; 101*1dd3983cSYuri Pankov case 'b': 102*1dd3983cSYuri Pankov host = ABUSEHOST; 103*1dd3983cSYuri Pankov break; 104*1dd3983cSYuri Pankov case 'c': 105*1dd3983cSYuri Pankov country = optarg; 106*1dd3983cSYuri Pankov break; 107*1dd3983cSYuri Pankov case 'f': 108*1dd3983cSYuri Pankov host = FNICHOST; 109*1dd3983cSYuri Pankov break; 110*1dd3983cSYuri Pankov case 'g': 111*1dd3983cSYuri Pankov host = GNICHOST; 112*1dd3983cSYuri Pankov break; 113*1dd3983cSYuri Pankov case 'h': 114*1dd3983cSYuri Pankov host = optarg; 115*1dd3983cSYuri Pankov break; 116*1dd3983cSYuri Pankov case 'i': 117*1dd3983cSYuri Pankov host = INICHOST; 118*1dd3983cSYuri Pankov break; 119*1dd3983cSYuri Pankov case 'I': 120*1dd3983cSYuri Pankov host = IANAHOST; 121*1dd3983cSYuri Pankov break; 122*1dd3983cSYuri Pankov case 'k': 123*1dd3983cSYuri Pankov host = KNICHOST; 124*1dd3983cSYuri Pankov break; 125*1dd3983cSYuri Pankov case 'l': 126*1dd3983cSYuri Pankov host = LNICHOST; 127*1dd3983cSYuri Pankov break; 128*1dd3983cSYuri Pankov case 'm': 129*1dd3983cSYuri Pankov host = MNICHOST; 130*1dd3983cSYuri Pankov break; 131*1dd3983cSYuri Pankov case 'p': 132*1dd3983cSYuri Pankov port = optarg; 133*1dd3983cSYuri Pankov break; 134*1dd3983cSYuri Pankov case 'Q': 135*1dd3983cSYuri Pankov flags |= WHOIS_QUICK; 136*1dd3983cSYuri Pankov break; 137*1dd3983cSYuri Pankov case 'r': 138*1dd3983cSYuri Pankov host = RNICHOST; 139*1dd3983cSYuri Pankov break; 140*1dd3983cSYuri Pankov case '?': 141*1dd3983cSYuri Pankov default: 142*1dd3983cSYuri Pankov usage(); 143*1dd3983cSYuri Pankov /* NOTREACHED */ 144f098c48bSDerek Morr } 145f098c48bSDerek Morr } 146*1dd3983cSYuri Pankov argc -= optind; 147*1dd3983cSYuri Pankov argv += optind; 148f098c48bSDerek Morr 149*1dd3983cSYuri Pankov if (!argc || (country != NULL && host != NULL)) 150*1dd3983cSYuri Pankov usage(); 151*1dd3983cSYuri Pankov 152*1dd3983cSYuri Pankov /* 153*1dd3983cSYuri Pankov * If no host or country is specified determine the top level domain 154*1dd3983cSYuri Pankov * from the query. If the TLD is a number, query ARIN. Otherwise, use 155*1dd3983cSYuri Pankov * TLD.whois-server.net. If the domain does not contain '.', fall 156*1dd3983cSYuri Pankov * back to NICHOST. 157*1dd3983cSYuri Pankov */ 158*1dd3983cSYuri Pankov if (host == NULL && country == NULL) { 159*1dd3983cSYuri Pankov use_qnichost = 1; 160*1dd3983cSYuri Pankov host = NICHOST; 161*1dd3983cSYuri Pankov if (!(flags & WHOIS_QUICK)) 162*1dd3983cSYuri Pankov flags |= WHOIS_RECURSE; 1637c478bd9Sstevel@tonic-gate } 164*1dd3983cSYuri Pankov while (argc-- > 0) { 165*1dd3983cSYuri Pankov if (country != NULL) { 166*1dd3983cSYuri Pankov s_asprintf(&qnichost, "%s%s", country, QNICHOST_TAIL); 167*1dd3983cSYuri Pankov whois(*argv, qnichost, flags); 168*1dd3983cSYuri Pankov } else if (use_qnichost) 169*1dd3983cSYuri Pankov if ((qnichost = choose_server(*argv)) != NULL) 170*1dd3983cSYuri Pankov whois(*argv, qnichost, flags); 171*1dd3983cSYuri Pankov if (qnichost == NULL) 172*1dd3983cSYuri Pankov whois(*argv, host, flags); 173*1dd3983cSYuri Pankov free(qnichost); 174*1dd3983cSYuri Pankov qnichost = NULL; 175*1dd3983cSYuri Pankov argv++; 176*1dd3983cSYuri Pankov } 177*1dd3983cSYuri Pankov 178*1dd3983cSYuri Pankov return (0); 179*1dd3983cSYuri Pankov } 180*1dd3983cSYuri Pankov 181*1dd3983cSYuri Pankov /* 182*1dd3983cSYuri Pankov * This function will remove any trailing periods from domain, after which it 183*1dd3983cSYuri Pankov * returns a pointer to newly allocated memory containing the whois server to 184*1dd3983cSYuri Pankov * be queried, or a NULL if the correct server couldn't be determined. The 185*1dd3983cSYuri Pankov * caller must remember to free(3) the allocated memory. 186*1dd3983cSYuri Pankov */ 187*1dd3983cSYuri Pankov static char * 188*1dd3983cSYuri Pankov choose_server(char *domain) 189*1dd3983cSYuri Pankov { 190*1dd3983cSYuri Pankov char *pos, *retval; 191*1dd3983cSYuri Pankov 192*1dd3983cSYuri Pankov if (strchr(domain, ':')) { 193*1dd3983cSYuri Pankov s_asprintf(&retval, "%s", ANICHOST); 194*1dd3983cSYuri Pankov return (retval); 195*1dd3983cSYuri Pankov } 196*1dd3983cSYuri Pankov for (pos = strchr(domain, '\0'); pos > domain && *--pos == '.'; ) 197*1dd3983cSYuri Pankov *pos = '\0'; 198*1dd3983cSYuri Pankov if (*domain == '\0') 199*1dd3983cSYuri Pankov errx(EX_USAGE, "can't search for a null string"); 200*1dd3983cSYuri Pankov if (strlen(domain) > sizeof ("-NORID")-1 && 201*1dd3983cSYuri Pankov strcasecmp(domain + strlen(domain) - sizeof ("-NORID") + 1, 202*1dd3983cSYuri Pankov "-NORID") == 0) { 203*1dd3983cSYuri Pankov s_asprintf(&retval, "%s", NORIDHOST); 204*1dd3983cSYuri Pankov return (retval); 205*1dd3983cSYuri Pankov } 206*1dd3983cSYuri Pankov while (pos > domain && *pos != '.') 207*1dd3983cSYuri Pankov --pos; 208*1dd3983cSYuri Pankov if (pos <= domain) 209*1dd3983cSYuri Pankov return (NULL); 210*1dd3983cSYuri Pankov if (isdigit((unsigned char)*++pos)) 211*1dd3983cSYuri Pankov s_asprintf(&retval, "%s", ANICHOST); 212*1dd3983cSYuri Pankov else 213*1dd3983cSYuri Pankov s_asprintf(&retval, "%s%s", pos, QNICHOST_TAIL); 214*1dd3983cSYuri Pankov return (retval); 215*1dd3983cSYuri Pankov } 216*1dd3983cSYuri Pankov 217*1dd3983cSYuri Pankov static struct addrinfo * 218*1dd3983cSYuri Pankov gethostinfo(char const *host, int exit_on_error) 219*1dd3983cSYuri Pankov { 220*1dd3983cSYuri Pankov struct addrinfo hints, *res; 221*1dd3983cSYuri Pankov int error; 222*1dd3983cSYuri Pankov 223*1dd3983cSYuri Pankov (void) memset(&hints, 0, sizeof (hints)); 224*1dd3983cSYuri Pankov hints.ai_flags = 0; 225*1dd3983cSYuri Pankov hints.ai_family = AF_UNSPEC; 226*1dd3983cSYuri Pankov hints.ai_socktype = SOCK_STREAM; 227*1dd3983cSYuri Pankov error = getaddrinfo(host, port, &hints, &res); 228*1dd3983cSYuri Pankov if (error) { 229*1dd3983cSYuri Pankov warnx("%s: %s", host, gai_strerror(error)); 230*1dd3983cSYuri Pankov if (exit_on_error) 231*1dd3983cSYuri Pankov exit(EX_NOHOST); 232*1dd3983cSYuri Pankov return (NULL); 233*1dd3983cSYuri Pankov } 234*1dd3983cSYuri Pankov return (res); 235*1dd3983cSYuri Pankov } 236*1dd3983cSYuri Pankov 237*1dd3983cSYuri Pankov /* 238*1dd3983cSYuri Pankov * Wrapper for asprintf(3) that exits on error. 239*1dd3983cSYuri Pankov */ 240*1dd3983cSYuri Pankov /* PRINTFLIKE2 */ 241*1dd3983cSYuri Pankov static void 242*1dd3983cSYuri Pankov s_asprintf(char **ret, const char *format, ...) 243*1dd3983cSYuri Pankov { 244*1dd3983cSYuri Pankov va_list ap; 245*1dd3983cSYuri Pankov 246*1dd3983cSYuri Pankov va_start(ap, format); 247*1dd3983cSYuri Pankov if (vasprintf(ret, format, ap) == -1) { 248*1dd3983cSYuri Pankov va_end(ap); 249*1dd3983cSYuri Pankov err(EX_OSERR, "vasprintf()"); 250*1dd3983cSYuri Pankov } 251*1dd3983cSYuri Pankov va_end(ap); 252*1dd3983cSYuri Pankov } 253*1dd3983cSYuri Pankov 254*1dd3983cSYuri Pankov static void 255*1dd3983cSYuri Pankov whois(const char *query, const char *hostname, int flags) 256*1dd3983cSYuri Pankov { 257*1dd3983cSYuri Pankov FILE *sfi, *sfo; 258*1dd3983cSYuri Pankov struct addrinfo *hostres, *res; 259*1dd3983cSYuri Pankov char *buf, *host, *nhost, *p; 260*1dd3983cSYuri Pankov int i, s; 261*1dd3983cSYuri Pankov size_t c, len; 262*1dd3983cSYuri Pankov 263*1dd3983cSYuri Pankov s = -1; 264*1dd3983cSYuri Pankov hostres = gethostinfo(hostname, 1); 265*1dd3983cSYuri Pankov for (res = hostres; res; res = res->ai_next) { 266*1dd3983cSYuri Pankov s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 267*1dd3983cSYuri Pankov if (s < 0) 268*1dd3983cSYuri Pankov continue; 269*1dd3983cSYuri Pankov if (connect(s, res->ai_addr, res->ai_addrlen) == 0) 270*1dd3983cSYuri Pankov break; 271*1dd3983cSYuri Pankov (void) close(s); 272*1dd3983cSYuri Pankov } 273*1dd3983cSYuri Pankov freeaddrinfo(hostres); 274*1dd3983cSYuri Pankov if (res == NULL) 275*1dd3983cSYuri Pankov err(EX_OSERR, "connect()"); 276f098c48bSDerek Morr 2777c478bd9Sstevel@tonic-gate sfi = fdopen(s, "r"); 2787c478bd9Sstevel@tonic-gate sfo = fdopen(s, "w"); 279*1dd3983cSYuri Pankov if (sfi == NULL || sfo == NULL) 280*1dd3983cSYuri Pankov err(EX_OSERR, "fdopen()"); 281*1dd3983cSYuri Pankov if (strcmp(hostname, GERMNICHOST) == 0) { 282*1dd3983cSYuri Pankov (void) fprintf(sfo, "-T dn,ace -C US-ASCII %s\r\n", query); 283*1dd3983cSYuri Pankov } else if (strcmp(hostname, "dk" QNICHOST_TAIL) == 0) { 284*1dd3983cSYuri Pankov (void) fprintf(sfo, "--show-handles %s\r\n", query); 285*1dd3983cSYuri Pankov } else { 286*1dd3983cSYuri Pankov (void) fprintf(sfo, "%s\r\n", query); 2877c478bd9Sstevel@tonic-gate } 28843f842b8SMilan Jurik (void) fflush(sfo); 289*1dd3983cSYuri Pankov nhost = NULL; 290*1dd3983cSYuri Pankov while ((buf = getln(sfi, &len)) != NULL) { 291*1dd3983cSYuri Pankov while (len > 0 && isspace((unsigned char)buf[len - 1])) 292*1dd3983cSYuri Pankov buf[--len] = '\0'; 293*1dd3983cSYuri Pankov (void) printf("%.*s\n", (int)len, buf); 294*1dd3983cSYuri Pankov 295*1dd3983cSYuri Pankov if ((flags & WHOIS_RECURSE) && nhost == NULL) { 296*1dd3983cSYuri Pankov host = strnstr(buf, WHOIS_SERVER_ID, len); 297*1dd3983cSYuri Pankov if (host != NULL) { 298*1dd3983cSYuri Pankov host += sizeof (WHOIS_SERVER_ID) - 1; 299*1dd3983cSYuri Pankov for (p = host; p < buf + len; p++) { 300*1dd3983cSYuri Pankov if (!ishost(*p)) { 301*1dd3983cSYuri Pankov *p = '\0'; 302*1dd3983cSYuri Pankov break; 303*1dd3983cSYuri Pankov } 304*1dd3983cSYuri Pankov } 305*1dd3983cSYuri Pankov s_asprintf(&nhost, "%.*s", 306*1dd3983cSYuri Pankov (int)(buf + len - host), host); 307*1dd3983cSYuri Pankov } else if ((host = 308*1dd3983cSYuri Pankov strnstr(buf, WHOIS_ORG_SERVER_ID, len)) != NULL) { 309*1dd3983cSYuri Pankov host += sizeof (WHOIS_ORG_SERVER_ID) - 1; 310*1dd3983cSYuri Pankov for (p = host; p < buf + len; p++) { 311*1dd3983cSYuri Pankov if (!ishost(*p)) { 312*1dd3983cSYuri Pankov *p = '\0'; 313*1dd3983cSYuri Pankov break; 314*1dd3983cSYuri Pankov } 315*1dd3983cSYuri Pankov } 316*1dd3983cSYuri Pankov s_asprintf(&nhost, "%.*s", 317*1dd3983cSYuri Pankov (int)(buf + len - host), host); 318*1dd3983cSYuri Pankov } else if (strcmp(hostname, ANICHOST) == 0) { 319*1dd3983cSYuri Pankov for (c = 0; c <= len; c++) 320*1dd3983cSYuri Pankov buf[c] = tolower((unsigned char)buf[c]); 321*1dd3983cSYuri Pankov for (i = 0; ip_whois[i] != NULL; i++) { 322*1dd3983cSYuri Pankov if (strnstr(buf, ip_whois[i], len) != 323*1dd3983cSYuri Pankov NULL) { 324*1dd3983cSYuri Pankov s_asprintf(&nhost, "%s", 325*1dd3983cSYuri Pankov ip_whois[i]); 326*1dd3983cSYuri Pankov break; 327*1dd3983cSYuri Pankov } 328*1dd3983cSYuri Pankov } 329*1dd3983cSYuri Pankov } 330*1dd3983cSYuri Pankov } 331*1dd3983cSYuri Pankov } 332*1dd3983cSYuri Pankov if (nhost != NULL) { 333*1dd3983cSYuri Pankov whois(query, nhost, 0); 334*1dd3983cSYuri Pankov free(nhost); 335*1dd3983cSYuri Pankov } 336*1dd3983cSYuri Pankov } 337*1dd3983cSYuri Pankov 338*1dd3983cSYuri Pankov static void 339*1dd3983cSYuri Pankov usage(void) 340*1dd3983cSYuri Pankov { 341*1dd3983cSYuri Pankov (void) fprintf(stderr, 342*1dd3983cSYuri Pankov "usage: whois [-aAbfgiIklmQr] [-c country-code | -h hostname] " 343*1dd3983cSYuri Pankov "[-p port] name ...\n"); 344*1dd3983cSYuri Pankov exit(EX_USAGE); 345*1dd3983cSYuri Pankov } 346*1dd3983cSYuri Pankov 347*1dd3983cSYuri Pankov static char * 348*1dd3983cSYuri Pankov getln(FILE *in, size_t *lenp) 349*1dd3983cSYuri Pankov { 350*1dd3983cSYuri Pankov static char *buffer = NULL; 351*1dd3983cSYuri Pankov static size_t sz = 0; 352*1dd3983cSYuri Pankov 353*1dd3983cSYuri Pankov size_t len = 0; 354*1dd3983cSYuri Pankov 355*1dd3983cSYuri Pankov for (;;) { 356*1dd3983cSYuri Pankov if (sz <= (len + 1)) { 357*1dd3983cSYuri Pankov char *nb; 358*1dd3983cSYuri Pankov if ((nb = realloc(buffer, sz + LINE_MAX)) == NULL) { 359*1dd3983cSYuri Pankov err(1, "realloc"); 360*1dd3983cSYuri Pankov } 361*1dd3983cSYuri Pankov buffer = nb; 362*1dd3983cSYuri Pankov sz += LINE_MAX; 363*1dd3983cSYuri Pankov } 364*1dd3983cSYuri Pankov 365*1dd3983cSYuri Pankov buffer[len] = 0; 366*1dd3983cSYuri Pankov 367*1dd3983cSYuri Pankov if (fgets(buffer + len, sz - len, in) == NULL) { 368*1dd3983cSYuri Pankov /* END OF FILE */ 369*1dd3983cSYuri Pankov *lenp = len; 370*1dd3983cSYuri Pankov if (len == 0) 371*1dd3983cSYuri Pankov return (NULL); 372*1dd3983cSYuri Pankov break; 373*1dd3983cSYuri Pankov } 374*1dd3983cSYuri Pankov 375*1dd3983cSYuri Pankov len += strlen(buffer + len); 376*1dd3983cSYuri Pankov 377*1dd3983cSYuri Pankov if (buffer[len - 1] == '\n') { 378*1dd3983cSYuri Pankov /* got the new line */ 379*1dd3983cSYuri Pankov *lenp = len; 380*1dd3983cSYuri Pankov break; 381*1dd3983cSYuri Pankov } 382*1dd3983cSYuri Pankov } 383*1dd3983cSYuri Pankov 384*1dd3983cSYuri Pankov return (buffer); 3857c478bd9Sstevel@tonic-gate } 386