Sat Aug 27 15:45:52 2011 UTC ()
ANSIfy. staticfy. Bail out on command line error. Use __dead.


(joerg)
diff -r1.39 -r1.40 src/libexec/rlogind/rlogind.c

cvs diff -r1.39 -r1.40 src/libexec/rlogind/rlogind.c (expand / switch to unified diff)

--- src/libexec/rlogind/rlogind.c 2009/03/16 02:18:39 1.39
+++ src/libexec/rlogind/rlogind.c 2011/08/27 15:45:52 1.40
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: rlogind.c,v 1.39 2009/03/16 02:18:39 lukem Exp $ */ 1/* $NetBSD: rlogind.c,v 1.40 2011/08/27 15:45:52 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright (C) 1998 WIDE Project. 4 * Copyright (C) 1998 WIDE Project.
5 * All rights reserved. 5 * All rights reserved.
6 *  6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -59,27 +59,27 @@ @@ -59,27 +59,27 @@
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE. 62 * SUCH DAMAGE.
63 */ 63 */
64 64
65#include <sys/cdefs.h> 65#include <sys/cdefs.h>
66#ifndef lint 66#ifndef lint
67__COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1989, 1993\ 67__COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1989, 1993\
68 The Regents of the University of California. All rights reserved."); 68 The Regents of the University of California. All rights reserved.");
69#if 0 69#if 0
70static char sccsid[] = "@(#)rlogind.c 8.2 (Berkeley) 4/28/95"; 70static char sccsid[] = "@(#)rlogind.c 8.2 (Berkeley) 4/28/95";
71#else 71#else
72__RCSID("$NetBSD: rlogind.c,v 1.39 2009/03/16 02:18:39 lukem Exp $"); 72__RCSID("$NetBSD: rlogind.c,v 1.40 2011/08/27 15:45:52 joerg Exp $");
73#endif 73#endif
74#endif /* not lint */ 74#endif /* not lint */
75 75
76/* 76/*
77 * remote login server: 77 * remote login server:
78 * \0 78 * \0
79 * remuser\0 79 * remuser\0
80 * locuser\0 80 * locuser\0
81 * terminal_type/speed\0 81 * terminal_type/speed\0
82 * data 82 * data
83 */ 83 */
84 84
85#include <sys/param.h> 85#include <sys/param.h>
@@ -103,61 +103,58 @@ __RCSID("$NetBSD: rlogind.c,v 1.39 2009/ @@ -103,61 +103,58 @@ __RCSID("$NetBSD: rlogind.c,v 1.39 2009/
103#include <stdio.h> 103#include <stdio.h>
104#include <unistd.h> 104#include <unistd.h>
105#include <stdlib.h> 105#include <stdlib.h>
106#include <string.h> 106#include <string.h>
107#include <util.h> 107#include <util.h>
108#include "pathnames.h" 108#include "pathnames.h"
109 109
110#ifndef TIOCPKT_WINDOW 110#ifndef TIOCPKT_WINDOW
111#define TIOCPKT_WINDOW 0x80 111#define TIOCPKT_WINDOW 0x80
112#endif 112#endif
113 113
114#define OPTIONS "alnL" 114#define OPTIONS "alnL"
115 115
116char *env[2]; 116static char *env[2];
117#define NMAX 30 117#define NMAX 30
118char lusername[NMAX+1], rusername[NMAX+1]; 118static char lusername[NMAX+1], rusername[NMAX+1];
119static char term[64] = "TERM="; 119static char term[64] = "TERM=";
120#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 120#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */
121int keepalive = 1; 121static int keepalive = 1;
122int check_all = 0; 122static int check_all = 0;
123int log_success = 0; 123static int log_success = 0;
124 124
125struct passwd *pwd; 125static struct passwd *pwd;
126 126
127void doit __P((int, struct sockaddr_storage *)); 127__dead static void doit(int, struct sockaddr_storage *);
128int control __P((int, char *, int)); 128static int control(int, char *, int);
129void protocol __P((int, int)); 129static void protocol(int, int);
130void cleanup __P((int)); 130__dead static void cleanup(int);
131void fatal __P((int, const char *, int)); 131__dead static void fatal(int, const char *, int);
132int do_rlogin __P((struct sockaddr *, char *)); 132static int do_rlogin(struct sockaddr *, char *);
133void getstr __P((char *, int, const char *)); 133static void getstr(char *, int, const char *);
134void setup_term __P((int)); 134static void setup_term(int);
135#if 0 135#if 0
136int do_krb_login __P((union sockunion *)); 136static int do_krb_login(union sockunion *);
137#endif 137#endif
138void usage __P((void)); 138__dead static void usage(void);
139int local_domain __P((char *)); 139static int local_domain(char *);
140char *topdomain __P((char *)); 140static char *topdomain(char *);
141int main __P((int, char *[])); 
142 141
143extern int __check_rhosts_file; 142extern int __check_rhosts_file;
144extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c */ 143extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c */
145extern char **environ; 144extern char **environ;
146 145
147int 146int
148main(argc, argv) 147main(int argc, char *argv[])
149 int argc; 
150 char *argv[]; 
151{ 148{
152 struct sockaddr_storage from; 149 struct sockaddr_storage from;
153 int ch, on; 150 int ch, on;
154 socklen_t fromlen = sizeof(from); 151 socklen_t fromlen = sizeof(from);
155 152
156 openlog("rlogind", LOG_PID, LOG_AUTH); 153 openlog("rlogind", LOG_PID, LOG_AUTH);
157 154
158 opterr = 0; 155 opterr = 0;
159 while ((ch = getopt(argc, argv, OPTIONS)) != -1) 156 while ((ch = getopt(argc, argv, OPTIONS)) != -1)
160 switch (ch) { 157 switch (ch) {
161 case 'a': 158 case 'a':
162 check_all = 1; 159 check_all = 1;
163 break; 160 break;
@@ -220,38 +217,34 @@ main(argc, argv) @@ -220,38 +217,34 @@ main(argc, argv)
220 if (from.ss_family == AF_INET) { 217 if (from.ss_family == AF_INET) {
221 on = IPTOS_LOWDELAY; 218 on = IPTOS_LOWDELAY;
222 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 219 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
223 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 220 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
224 } 221 }
225#endif 222#endif
226 doit(0, &from); 223 doit(0, &from);
227 /* NOTREACHED */ 224 /* NOTREACHED */
228#ifdef __GNUC__ 225#ifdef __GNUC__
229 exit(0); 226 exit(0);
230#endif 227#endif
231} 228}
232 229
233int child; 230static int netf;
234int netf; 231static char line[MAXPATHLEN];
235char line[MAXPATHLEN]; 232static int confirmed;
236int confirmed; 
237 
238struct winsize win = { 0, 0, 0, 0 }; 
239 233
 234static struct winsize win = { 0, 0, 0, 0 };
240 235
241void 236static void
242doit(f, fromp) 237doit(int f, struct sockaddr_storage *fromp)
243 int f; 
244 struct sockaddr_storage *fromp; 
245{ 238{
246 int master, pid, on = 1; 239 int master, pid, on = 1;
247 int authenticated = 0; 240 int authenticated = 0;
248 char *hostname; 241 char *hostname;
249 char hostnamebuf[2 * MAXHOSTNAMELEN + 1]; 242 char hostnamebuf[2 * MAXHOSTNAMELEN + 1];
250 char hostaddrbuf[sizeof(*fromp) * 4 + 1]; 243 char hostaddrbuf[sizeof(*fromp) * 4 + 1];
251 char c; 244 char c;
252 char naddr[NI_MAXHOST]; 245 char naddr[NI_MAXHOST];
253 char saddr[NI_MAXHOST]; 246 char saddr[NI_MAXHOST];
254 char raddr[NI_MAXHOST]; 247 char raddr[NI_MAXHOST];
255 int af = fromp->ss_family; 248 int af = fromp->ss_family;
256 u_int16_t *portp; 249 u_int16_t *portp;
257 struct addrinfo hints, *res, *res0; 250 struct addrinfo hints, *res, *res0;
@@ -411,60 +404,56 @@ doit(f, fromp) @@ -411,60 +404,56 @@ doit(f, fromp)
411 "--", lusername, (char *)0); 404 "--", lusername, (char *)0);
412 fatal(STDERR_FILENO, _PATH_LOGIN, 1); 405 fatal(STDERR_FILENO, _PATH_LOGIN, 1);
413 /*NOTREACHED*/ 406 /*NOTREACHED*/
414 } 407 }
415 ioctl(f, FIONBIO, &on); 408 ioctl(f, FIONBIO, &on);
416 ioctl(master, FIONBIO, &on); 409 ioctl(master, FIONBIO, &on);
417 ioctl(master, TIOCPKT, &on); 410 ioctl(master, TIOCPKT, &on);
418 signal(SIGCHLD, cleanup); 411 signal(SIGCHLD, cleanup);
419 protocol(f, master); 412 protocol(f, master);
420 signal(SIGCHLD, SIG_IGN); 413 signal(SIGCHLD, SIG_IGN);
421 cleanup(0); 414 cleanup(0);
422} 415}
423 416
424char magic[2] = { 0377, 0377 }; 417static char magic[2] = { 0377, 0377 };
425char oobdata[] = {TIOCPKT_WINDOW}; 418static char oobdata[] = {TIOCPKT_WINDOW};
426 419
427/* 420/*
428 * Handle a "control" request (signaled by magic being present) 421 * Handle a "control" request (signaled by magic being present)
429 * in the data stream. For now, we are only willing to handle 422 * in the data stream. For now, we are only willing to handle
430 * window size changes. 423 * window size changes.
431 */ 424 */
432int 425static int
433control(pty, cp, n) 426control(int pty, char *cp, int n)
434 int pty; 
435 char *cp; 
436 int n; 
437{ 427{
438 struct winsize w; 428 struct winsize w;
439 429
440 if (n < (int)(4+sizeof (w)) || cp[2] != 's' || cp[3] != 's') 430 if (n < (int)(4+sizeof (w)) || cp[2] != 's' || cp[3] != 's')
441 return (0); 431 return (0);
442 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 432 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */
443 memmove(&w, cp+4, sizeof(w)); 433 memmove(&w, cp+4, sizeof(w));
444 w.ws_row = ntohs(w.ws_row); 434 w.ws_row = ntohs(w.ws_row);
445 w.ws_col = ntohs(w.ws_col); 435 w.ws_col = ntohs(w.ws_col);
446 w.ws_xpixel = ntohs(w.ws_xpixel); 436 w.ws_xpixel = ntohs(w.ws_xpixel);
447 w.ws_ypixel = ntohs(w.ws_ypixel); 437 w.ws_ypixel = ntohs(w.ws_ypixel);
448 (void)ioctl(pty, TIOCSWINSZ, &w); 438 (void)ioctl(pty, TIOCSWINSZ, &w);
449 return (4+sizeof (w)); 439 return (4+sizeof (w));
450} 440}
451 441
452/* 442/*
453 * rlogin "protocol" machine. 443 * rlogin "protocol" machine.
454 */ 444 */
455void 445static void
456protocol(f, p) 446protocol(int f, int p)
457 int f, p; 
458{ 447{
459 char pibuf[1024+1], fibuf[1024], *pbp = NULL, *fbp = NULL; 448 char pibuf[1024+1], fibuf[1024], *pbp = NULL, *fbp = NULL;
460 /* XXX gcc above */ 449 /* XXX gcc above */
461 int pcc = 0, fcc = 0; 450 int pcc = 0, fcc = 0;
462 int cc, nfd; 451 int cc, nfd;
463 char cntl; 452 char cntl;
464 struct pollfd set[2]; 453 struct pollfd set[2];
465 454
466 /* 455 /*
467 * Must ignore SIGTTOU, otherwise we'll stop 456 * Must ignore SIGTTOU, otherwise we'll stop
468 * when we try and set slave pty's window shape 457 * when we try and set slave pty's window shape
469 * (our controlling tty is the master pty). 458 * (our controlling tty is the master pty).
470 */ 459 */
@@ -561,84 +550,78 @@ protocol(f, p) @@ -561,84 +550,78 @@ protocol(f, p)
561 pcc = 0; 550 pcc = 0;
562 } 551 }
563 } 552 }
564 if (set[1].revents & POLLOUT && pcc > 0) { 553 if (set[1].revents & POLLOUT && pcc > 0) {
565 cc = write(f, pbp, pcc); 554 cc = write(f, pbp, pcc);
566 if (cc > 0) { 555 if (cc > 0) {
567 pcc -= cc; 556 pcc -= cc;
568 pbp += cc; 557 pbp += cc;
569 } 558 }
570 } 559 }
571 } 560 }
572} 561}
573 562
574void 563static void
575cleanup(signo) 564cleanup(int signo)
576 int signo; 
577{ 565{
578 char *p, c; 566 char *p, c;
579 567
580 p = line + sizeof(_PATH_DEV) - 1; 568 p = line + sizeof(_PATH_DEV) - 1;
581#ifdef SUPPORT_UTMP 569#ifdef SUPPORT_UTMP
582 if (logout(p)) 570 if (logout(p))
583 logwtmp(p, "", ""); 571 logwtmp(p, "", "");
584#endif 572#endif
585#ifdef SUPPORT_UTMPX 573#ifdef SUPPORT_UTMPX
586 if (logoutx(p, 0, DEAD_PROCESS)) 574 if (logoutx(p, 0, DEAD_PROCESS))
587 logwtmpx(p, "", "", 0, DEAD_PROCESS); 575 logwtmpx(p, "", "", 0, DEAD_PROCESS);
588#endif 576#endif
589 (void)chmod(line, 0666); 577 (void)chmod(line, 0666);
590 (void)chown(line, 0, 0); 578 (void)chown(line, 0, 0);
591 c = *p; *p = 'p'; 579 c = *p; *p = 'p';
592 (void)chmod(line, 0666); 580 (void)chmod(line, 0666);
593 (void)chown(line, 0, 0); 581 (void)chown(line, 0, 0);
594 *p = c; 582 *p = c;
595 if (ttyaction(line, "rlogind", "root")) 583 if (ttyaction(line, "rlogind", "root"))
596 syslog(LOG_ERR, "%s: ttyaction failed", line); 584 syslog(LOG_ERR, "%s: ttyaction failed", line);
597 shutdown(netf, 2); 585 shutdown(netf, 2);
598 exit(1); 586 exit(1);
599} 587}
600 588
601void 589static void
602fatal(f, msg, syserr) 590fatal(int f, const char *msg, int syserr)
603 int f; 
604 const char *msg; 
605 int syserr; 
606{ 591{
607 int len; 592 int len;
608 char buf[BUFSIZ], *bp, *ep; 593 char buf[BUFSIZ], *bp, *ep;
609 594
610 bp = buf; 595 bp = buf;
611 ep = buf + sizeof(buf); 596 ep = buf + sizeof(buf);
612 597
613 /* 598 /*
614 * Prepend binary one to message if we haven't sent 599 * Prepend binary one to message if we haven't sent
615 * the magic null as confirmation. 600 * the magic null as confirmation.
616 */ 601 */
617 if (!confirmed) 602 if (!confirmed)
618 *bp++ = '\001'; /* error indicator */ 603 *bp++ = '\001'; /* error indicator */
619 if (syserr) 604 if (syserr)
620 len = snprintf(bp, ep - bp, "rlogind: %s: %s.\r\n", 605 len = snprintf(bp, ep - bp, "rlogind: %s: %s.\r\n",
621 msg, strerror(errno)); 606 msg, strerror(errno));
622 else 607 else
623 len = snprintf(bp, ep - bp, "rlogind: %s.\r\n", msg); 608 len = snprintf(bp, ep - bp, "rlogind: %s.\r\n", msg);
624 (void) write(f, buf, bp + len - buf); 609 (void) write(f, buf, bp + len - buf);
625 exit(1); 610 exit(1);
626} 611}
627 612
628int 613static int
629do_rlogin(dest, host) 614do_rlogin(struct sockaddr *dest, char *host)
630 struct sockaddr *dest; 
631 char *host; 
632{ 615{
633 int retval; 616 int retval;
634 617
635 getstr(rusername, sizeof(rusername), "remuser too long"); 618 getstr(rusername, sizeof(rusername), "remuser too long");
636 getstr(lusername, sizeof(lusername), "locuser too long"); 619 getstr(lusername, sizeof(lusername), "locuser too long");
637 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 620 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long");
638 621
639 pwd = getpwnam(lusername); 622 pwd = getpwnam(lusername);
640 if (pwd == NULL) { 623 if (pwd == NULL) {
641 syslog(LOG_INFO, 624 syslog(LOG_INFO,
642 "%s@%s as %s: unknown login.", rusername, host, lusername); 625 "%s@%s as %s: unknown login.", rusername, host, lusername);
643 return (-1); 626 return (-1);
644 } 627 }
@@ -651,47 +634,43 @@ do_rlogin(dest, host) @@ -651,47 +634,43 @@ do_rlogin(dest, host)
651 syslog(LOG_INFO, "%s@%s as %s: iruserok succeeded", 634 syslog(LOG_INFO, "%s@%s as %s: iruserok succeeded",
652 rusername, host, lusername); 635 rusername, host, lusername);
653 } else { 636 } else {
654 if (__rcmd_errstr) 637 if (__rcmd_errstr)
655 syslog(LOG_INFO, "%s@%s as %s: iruserok failed (%s)", 638 syslog(LOG_INFO, "%s@%s as %s: iruserok failed (%s)",
656 rusername, host, lusername, __rcmd_errstr); 639 rusername, host, lusername, __rcmd_errstr);
657 else 640 else
658 syslog(LOG_INFO, "%s@%s as %s: iruserok failed", 641 syslog(LOG_INFO, "%s@%s as %s: iruserok failed",
659 rusername, host, lusername); 642 rusername, host, lusername);
660 } 643 }
661 return(retval); 644 return(retval);
662} 645}
663 646
664void 647static void
665getstr(buf, cnt, errmsg) 648getstr(char *buf, int cnt, const char *errmsg)
666 char *buf; 
667 int cnt; 
668 const char *errmsg; 
669{ 649{
670 char c; 650 char c;
671 651
672 do { 652 do {
673 if (read(0, &c, 1) != 1) 653 if (read(0, &c, 1) != 1)
674 exit(1); 654 exit(1);
675 if (--cnt < 0) 655 if (--cnt < 0)
676 fatal(STDOUT_FILENO, errmsg, 0); 656 fatal(STDOUT_FILENO, errmsg, 0);
677 *buf++ = c; 657 *buf++ = c;
678 } while (c != 0); 658 } while (c != 0);
679} 659}
680 660
681 661
682void 662static void
683setup_term(fd) 663setup_term(int fd)
684 int fd; 
685{ 664{
686 char *cp = index(term+ENVSIZE, '/'); 665 char *cp = index(term+ENVSIZE, '/');
687 char *speed; 666 char *speed;
688 struct termios tt; 667 struct termios tt;
689 668
690#ifndef notyet 669#ifndef notyet
691 tcgetattr(fd, &tt); 670 tcgetattr(fd, &tt);
692 if (cp) { 671 if (cp) {
693 *cp++ = '\0'; 672 *cp++ = '\0';
694 speed = cp; 673 speed = cp;
695 cp = index(speed, '/'); 674 cp = index(speed, '/');
696 if (cp) 675 if (cp)
697 *cp++ = '\0'; 676 *cp++ = '\0';
@@ -711,60 +690,59 @@ setup_term(fd) @@ -711,60 +690,59 @@ setup_term(fd)
711 *cp++ = '\0'; 690 *cp++ = '\0';
712 tcgetattr(fd, &tt); 691 tcgetattr(fd, &tt);
713 cfsetspeed(&tt, atoi(speed)); 692 cfsetspeed(&tt, atoi(speed));
714 tcsetattr(fd, TCSAFLUSH, &tt); 693 tcsetattr(fd, TCSAFLUSH, &tt);
715 } 694 }
716#endif 695#endif
717 696
718 env[0] = term; 697 env[0] = term;
719 env[1] = 0; 698 env[1] = 0;
720 environ = env; 699 environ = env;
721} 700}
722 701
723 702
724void 703static void
725usage() 704usage(void)
726{ 705{
727 syslog(LOG_ERR, "usage: rlogind [-alnL]"); 706 syslog(LOG_ERR, "usage: rlogind [-alnL]");
 707 exit(1);
728} 708}
729 709
730/* 710/*
731 * Check whether host h is in our local domain, 711 * Check whether host h is in our local domain,
732 * defined as sharing the last two components of the domain part, 712 * defined as sharing the last two components of the domain part,
733 * or the entire domain part if the local domain has only one component. 713 * or the entire domain part if the local domain has only one component.
734 * If either name is unqualified (contains no '.'), 714 * If either name is unqualified (contains no '.'),
735 * assume that the host is local, as it will be 715 * assume that the host is local, as it will be
736 * interpreted as such. 716 * interpreted as such.
737 */ 717 */
738int 718static int
739local_domain(h) 719local_domain(char *h)
740 char *h; 
741{ 720{
742 char localhost[MAXHOSTNAMELEN + 1]; 721 char localhost[MAXHOSTNAMELEN + 1];
743 char *p1, *p2; 722 char *p1, *p2;
744 723
745 localhost[0] = 0; 724 localhost[0] = 0;
746 (void) gethostname(localhost, sizeof(localhost)); 725 (void) gethostname(localhost, sizeof(localhost));
747 localhost[sizeof(localhost) - 1] = '\0'; 726 localhost[sizeof(localhost) - 1] = '\0';
748 p1 = topdomain(localhost); 727 p1 = topdomain(localhost);
749 p2 = topdomain(h); 728 p2 = topdomain(h);
750 if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 729 if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
751 return (1); 730 return (1);
752 return (0); 731 return (0);
753} 732}
754 733
755char * 734static char *
756topdomain(h) 735topdomain(char *h)
757 char *h; 
758{ 736{
759 char *p; 737 char *p;
760 char *maybe = NULL; 738 char *maybe = NULL;
761 int dots = 0; 739 int dots = 0;
762 740
763 for (p = h + strlen(h); p >= h; p--) { 741 for (p = h + strlen(h); p >= h; p--) {
764 if (*p == '.') { 742 if (*p == '.') {
765 if (++dots == 2) 743 if (++dots == 2)
766 return (p); 744 return (p);
767 maybe = p; 745 maybe = p;
768 } 746 }
769 } 747 }
770 return (maybe); 748 return (maybe);