source: trunk/minix/commands/simple/modem.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.8 KB
RevLine 
[9]1/* modem - Put modem into DIALIN or DIALOUT mode. Author: F. van Kempen */
2
3/* Exit: 0 OK, suspended/restarted GETTY
4 * 1 UNIX error
5 * 2 Process busy
6 * Version: 1.3 12/30/89
7 *
8 * Author: F. van Kempen, MicroWalt Corporation
9 *
10 * All fancy stuff removed, see getty.c. Kees J. Bot.
11 *
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <sys/wait.h>
19#include <fcntl.h>
20#include <signal.h>
21#include <string.h>
22#include <unistd.h>
23#include <utmp.h>
24#include <errno.h>
25
26#include <minix/paths.h>
27
28char PATH_UTMP[] = _PATH_UTMP; /* current logins */
29
30_PROTOTYPE(void usage , (void));
31_PROTOTYPE(int main , (int argc , char *argv []));
32_PROTOTYPE(void sendcodes , (char *tty, char *codes));
33
34
35void usage()
36{
37 fprintf(stderr,
38"Usage: modem [-sio] [-I in-codes] [-O out-codes] line [command args ...]\n");
39 exit(1);
40}
41
42
43main(argc, argv)
44int argc;
45char *argv[];
46{
47 struct utmp entry;
48 char devtty[1024], *tty;
49 char **command;
50 int ex_code = 0;
51 int fd, i, slot, getty;
52 struct stat st;
53 enum { TOGGLE, DIALIN, DIALOUT } mode= TOGGLE;
54 int silent = 0;
55 _PROTOTYPE(void (*hsig), (int));
56 _PROTOTYPE(void (*isig), (int));
57 _PROTOTYPE(void (*qsig), (int));
58 _PROTOTYPE(void (*tsig), (int));
59 pid_t pid;
60 int r, status;
61 uid_t uid = getuid();
62 gid_t gid = getgid();
63 char *in_codes, *out_codes;
64
65 i = 1;
66 while (i < argc && argv[i][0] == '-') {
67 char *opt = argv[i++] + 1;
68
69 if (opt[0] == '-' && opt[1] == 0) break;
70
71 while (*opt != 0) {
72 switch (*opt++) {
73 case 's': /* silent mode */
74 silent = 1;
75 break;
76 case 'i': /* DIAL-IN mode: suspend GETTY */
77 mode = DIALIN;
78 break;
79 case 'o': /* DIAL-OUT mode: restart GETTY */
80 mode = DIALOUT;
81 break;
82 case 'I': /* code to switch modem to dial-in */
83 if (*opt == 0) {
84 if (i == argc) usage();
85 opt = argv[i++];
86 }
87 in_codes = opt;
88 opt = "";
89 break;
90 case 'O': /* code to switch modem to dial-out */
91 if (*opt == 0) {
92 if (i == argc) usage();
93 opt = argv[i++];
94 }
95 out_codes = opt;
96 opt = "";
97 break;
98 default:
99 usage();
100 }
101 }
102 }
103
104 if (i == argc) usage();
105 tty = argv[i++]; /* Modem line */
106
107 if (mode != TOGGLE && i != argc) usage();
108 command = argv + i; /* Command to execute (if any). */
109
110 if (strchr(tty, '/') == NULL) {
111 strcpy(devtty, "/dev/");
112 strncat(devtty, tty, 1024 - 6);
113 tty = devtty;
114 }
115
116 if (stat(tty, &st) < 0) {
117 fprintf(stderr, "modem: %s: %s\n", tty, strerror(errno));
118 exit(1);
119 }
120
121 if (!S_ISCHR(st.st_mode)) {
122 fprintf(stderr, "%s is not a tty\n", tty);
123 exit(1);
124 }
125
126 /* Find the utmp slot number for the line. */
127 if ((fd= open(tty, O_RDONLY)) < 0 || (slot= fttyslot(fd)) == 0) {
128 fprintf(stderr, "modem: %s: %s\n", tty, strerror(errno));
129 exit(1);
130 }
131 close(fd);
132
133 /* Read the UTMP file to find out the PID and STATUS of the GETTY. */
134 entry.ut_type= 0;
135 if ((fd = open(PATH_UTMP, O_RDONLY)) < 0
136 || lseek(fd, (off_t) slot * sizeof(entry), SEEK_SET) < 0
137 || read(fd, &entry, sizeof(entry)) < 0
138 ) {
139 fprintf(stderr, "modem: cannot read UTMP !\n");
140 exit(1);
141 }
142 close(fd);
143
144 hsig= signal(SIGHUP, SIG_IGN);
145 isig= signal(SIGINT, SIG_IGN);
146 qsig= signal(SIGQUIT, SIG_IGN);
147 tsig= signal(SIGTERM, SIG_IGN);
148
149 /* Process the terminal entry if we got one. */
150 switch (entry.ut_type) {
151 case LOGIN_PROCESS: /* getty waiting for a call */
152 getty = 1;
153 break;
154 case USER_PROCESS: /* login or user-shell */
155 if (!silent) fprintf(stderr, "modem: line is busy.\n");
156 exit(2);
157 break;
158 default:
159 getty = 0;
160 }
161
162 for (i = (mode == TOGGLE) ? 0 : 1; i < 2; i++) {
163 /* Now perform the desired action (DIALIN or DIALOUT). */
164 switch (mode) {
165 case DIALOUT:
166 case TOGGLE:
167 if (getty) kill(entry.ut_pid, SIGUSR1); /* suspend getty */
168 chown(tty, uid, st.st_gid); /* give line to user */
169 chmod(tty, 0600);
170 if (out_codes != NULL) sendcodes(tty, out_codes);
171 if (!silent) printf("modem on %s set for dialout.\n", tty);
172 break;
173 case DIALIN:
174 if (in_codes != NULL) sendcodes(tty, in_codes);
175 chown(tty, 0, st.st_gid); /* revoke access */
176 chmod(tty, 0600);
177 if (getty) kill(entry.ut_pid, SIGUSR2); /* restart getty */
178 if (!silent) printf("modem on %s set for dialin.\n", tty);
179 }
180 if (mode == TOGGLE) {
181 /* Start the command to run */
182 pid_t pid;
183 int status;
184
185 switch ((pid = fork())) {
186 case -1:
187 fprintf(stderr, "modem: fork(): %s\n", strerror(errno));
188 ex_code= 1;
189 break;
190 case 0:
191 setgid(gid);
192 setuid(uid);
193 (void) signal(SIGHUP, hsig);
194 (void) signal(SIGINT, isig);
195 (void) signal(SIGQUIT, qsig);
196 (void) signal(SIGTERM, tsig);
197 execvp(command[0], command);
198 fprintf(stderr, "modem: %s: %s\n",
199 command[0], strerror(errno));
200 _exit(127);
201 default:
202 while ((r= wait(&status)) != pid) {
203 if (r == -1 && errno != EINTR) break;
204 }
205 if (r == -1 || status != 0) ex_code = 1;
206 }
207 mode = DIALIN;
208 }
209 }
210 exit(ex_code);
211}
212
213void sendcodes(tty, codes)
214char *tty, *codes;
215{
216 int fd;
217 int c;
218 char buf[1024], *bp = buf;
219
220 if ((fd = open(tty, O_RDWR|O_NONBLOCK)) < 0) {
221 fprintf(stderr, "modem: can't send codes to %s: %s\n",
222 tty, strerror(errno));
223 return;
224 }
225 while ((c = *codes++) != 0) {
226fprintf(stderr, "%d\n", __LINE__);
227 if (c == '\\') {
228 if ((c = *codes++) == 0) break;
229 if (c == 'r') c= '\r';
230 if (c == 'n') c= '\n';
231 }
232 *bp++ = c;
233 if (bp == buf + sizeof(buf) || c == '\r' || c == '\n') {
234fprintf(stderr, "%d\n", __LINE__);
235 write(fd, buf, bp - buf);
236fprintf(stderr, "%d\n", __LINE__);
237 do {sleep(1);
238fprintf(stderr, "%d\n", __LINE__);
239 fprintf(stderr, "%d\n", read(fd, buf, sizeof(buf)));
240 }while (read(fd, buf, sizeof(buf)) > 0);
241fprintf(stderr, "%d\n", __LINE__);
242 bp = buf;
243 }
244 }
245 if (bp > buf) {
246fprintf(stderr, "%d\n", __LINE__);
247 write(fd, buf, bp - buf);
248fprintf(stderr, "%d\n", __LINE__);
249 do sleep(1); while (read(fd, buf, sizeof(buf)) > 0);
250fprintf(stderr, "%d\n", __LINE__);
251 }
252 close(fd);
253}
Note: See TracBrowser for help on using the repository browser.