Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / ttyw.c
1 #ifndef BSD42
2 #undef  TTYD
3 #endif
4
5 #ifdef  TTYD
6 /* ttyw.c - the writer */
7
8 #include <errno.h>
9 #include <stdio.h>
10 #include <strings.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <netdb.h>
15 #ifndef hpux
16 #include <arpa/inet.h>
17 #endif
18 #include "ttyd.h"
19 #include "ttym.c"
20
21 /* \f */
22
23 ttyw (command, host, line, user)
24 char   *command,
25        *host,
26        *line,
27        *user;
28 {
29     int     privd,
30             sd;
31     unsigned    times;
32     char        buffer[BUFSIZ];
33     struct      hostent *hp;
34     struct      servent *sp;
35     struct sockaddr_in  tty_socket,
36                        *tsock = &tty_socket;
37
38     if (command == NULL) {
39         errno = EINVAL;
40         return NOTOK;
41     }
42
43     if ((sp = getservbyname ("ttyserver", "tcp")) == NULL) {
44         errno = ENETDOWN;
45         return NOTOK;
46     }
47     if (host == NULL)
48         (void) gethostname (host = buffer, sizeof buffer);
49     if ((hp = gethostbyname (host))==NULL) {
50         errno = ENETDOWN;
51         return NOTOK;
52     }
53
54     if (line && strncmp (line, "/dev/", strlen ("/dev/")) == 0)
55         line += strlen ("/dev/");
56
57     privd = *command >= 'A' && *command <= 'Z';/* crude */
58
59 /* \f */
60
61     for (times = 1; times <= 16; times *= 2) {
62         if ((sd = getport (0, privd)) == NOTOK)
63             return NOTOK;
64
65         bzero ((char *) tsock, sizeof *tsock);
66         tsock -> sin_family = hp -> h_addrtype;
67         tsock -> sin_port = sp -> s_port;
68         bcopy (hp -> h_addr, (char *) &tsock -> sin_addr, hp -> h_length);
69
70         if (connect (sd, (struct sockaddr *) tsock, sizeof *tsock) == NOTOK) {
71             (void) close (sd);
72             if (errno == ECONNREFUSED || errno == EINTR) {
73                 sleep (times);
74                 continue;
75             }
76             break;
77         }
78
79         ttym (sd, command, line, user, NULL);
80         if (ttyv (sd) == NOTOK || ttyv (sd) == NOTOK) {
81             (void) close (sd);
82             errno = EPERM;      /* what else??? */
83             return NOTOK;
84         }
85         else
86             return sd;
87     }
88
89     return NOTOK;
90 }
91
92 /* \f */
93
94 static int  getport (options, privd)
95 unsigned    options;
96 int     privd;
97 {
98     int     sd,
99             port;
100     struct sockaddr_in  unx_socket,
101                        *usock = &unx_socket;
102
103     if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK)
104         return sd;
105
106     if (options & SO_DEBUG)
107         (void) setsockopt (sd, SOL_SOCKET, SO_DEBUG, NULL, 0);
108     (void) setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, NULL, 0);
109
110     if (!privd)
111         return sd;
112
113     usock -> sin_family = AF_INET;
114     usock -> sin_addr.s_addr = INADDR_ANY;
115
116     for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
117         usock -> sin_port = htons (port);
118
119         switch (bind (sd, (struct sockaddr *) usock, sizeof *usock)) {
120             case NOTOK: 
121                 if (errno != EADDRINUSE && errno != EADDRNOTAVAIL)
122                     return NOTOK;
123                 continue;
124
125             default: 
126                 return sd;
127         }
128     }
129
130     return NOTOK;
131 }
132 #endif  TTYD