diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-09-21 17:42:40 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-09-21 17:42:40 +0000 |
commit | 707669501f59208c00d447d5a5314aa6942341fb (patch) | |
tree | 3f5dc1d8806b793fbfaa54a04f18ae2ff37de77e /util-linux | |
parent | efd3f38f8cc823af30ce2a19d7f4eb55c3866cad (diff) | |
download | busybox-w32-707669501f59208c00d447d5a5314aa6942341fb.tar.gz busybox-w32-707669501f59208c00d447d5a5314aa6942341fb.tar.bz2 busybox-w32-707669501f59208c00d447d5a5314aa6942341fb.zip |
microcom: add new applet, this time for real
Diffstat (limited to 'util-linux')
-rw-r--r-- | util-linux/microcom.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/util-linux/microcom.c b/util-linux/microcom.c new file mode 100644 index 000000000..f6f8e07f6 --- /dev/null +++ b/util-linux/microcom.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* microcom.c | ||
2 | * | ||
3 | * bare bones 'talk to modem' program - similar to 'cu -l $device' | ||
4 | * inspired by mgetty's microcom | ||
5 | * | ||
6 | */ | ||
7 | #include "busybox.h" | ||
8 | |||
9 | int microcom_main(int argc, char **argv); | ||
10 | int microcom_main(int argc, char **argv) | ||
11 | { | ||
12 | struct pollfd pfd[2]; | ||
13 | #define sfd (pfd[1].fd) | ||
14 | char *device_lock_file = NULL; | ||
15 | const char *s; | ||
16 | const char *opt_s = "9600"; | ||
17 | unsigned speed; | ||
18 | int len; | ||
19 | int exitcode = 1; | ||
20 | struct termios tio0, tiosfd, tio; | ||
21 | |||
22 | getopt32(argv, "s:", &opt_s); | ||
23 | argc -= optind; | ||
24 | argv += optind; | ||
25 | if (!argv[0]) | ||
26 | bb_show_usage(); | ||
27 | speed = xatou(opt_s); | ||
28 | |||
29 | // try to create lock file in /var/lock | ||
30 | s = bb_basename(argv[0]); | ||
31 | if (!s[0]) { | ||
32 | errno = ENODEV; | ||
33 | bb_perror_msg_and_die("can't lock device"); | ||
34 | } | ||
35 | device_lock_file = xasprintf("/var/lock/LCK..%s", s); | ||
36 | sfd = open(device_lock_file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644); | ||
37 | if (sfd < 0) { | ||
38 | if (ENABLE_FEATURE_CLEAN_UP) | ||
39 | free(device_lock_file); | ||
40 | device_lock_file = NULL; | ||
41 | if (errno == EEXIST) | ||
42 | bb_perror_msg_and_die("can't lock device"); | ||
43 | // We don't abort on other errors: /var/lock can be | ||
44 | // non-writable or non-existent | ||
45 | } else { | ||
46 | // %4d to make mgetty happy. It treats 4-bytes lock files as binary, | ||
47 | // not text, PID. Making 5+ char file. Brrr... | ||
48 | s = xasprintf("%4d\n", getpid()); | ||
49 | write(sfd, s, strlen(s)); | ||
50 | if (ENABLE_FEATURE_CLEAN_UP) | ||
51 | free((char*)s); | ||
52 | close(sfd); | ||
53 | } | ||
54 | |||
55 | // open device | ||
56 | sfd = open(argv[0], O_RDWR | O_NDELAY); | ||
57 | if (sfd < 0) { | ||
58 | bb_perror_msg("can't open device"); | ||
59 | goto unlock_and_exit; | ||
60 | } | ||
61 | fcntl(sfd, F_SETFL, O_RDWR); // why? | ||
62 | |||
63 | // put stdin to "raw mode", handle one character at a time | ||
64 | tcgetattr(STDIN_FILENO, &tio0); | ||
65 | tio = tio0; | ||
66 | tio.c_lflag &= ~(ICANON|ECHO); | ||
67 | tio.c_iflag &= ~(IXON|ICRNL); | ||
68 | tio.c_oflag &= ~(ONLCR); | ||
69 | tio.c_cc[VMIN] = 1; | ||
70 | tio.c_cc[VTIME] = 0; | ||
71 | if (tcsetattr(STDIN_FILENO, TCSANOW, &tio)) { | ||
72 | bb_perror_msg("can't tcsetattr for %s", "stdin"); | ||
73 | goto unlock_and_exit; | ||
74 | } | ||
75 | |||
76 | /* same thing for modem (plus: set baud rate) - TODO: make CLI option */ | ||
77 | tcgetattr(sfd, &tiosfd); | ||
78 | tio = tiosfd; | ||
79 | tio.c_lflag &= ~(ICANON|ECHO); | ||
80 | tio.c_iflag &= ~(IXON|ICRNL); | ||
81 | tio.c_oflag &= ~(ONLCR); | ||
82 | tio.c_cc[VMIN] = 1; | ||
83 | tio.c_cc[VTIME] = 0; | ||
84 | cfsetispeed(&tio, tty_value_to_baud(speed)); | ||
85 | cfsetospeed(&tio, tty_value_to_baud(speed)); | ||
86 | if (tcsetattr(sfd, TCSANOW, &tio)) { | ||
87 | bb_perror_msg("can't tcsetattr for %s", "device"); | ||
88 | goto unlock_and_exit; | ||
89 | } | ||
90 | |||
91 | // disable SIGINT | ||
92 | signal(SIGINT, SIG_IGN); | ||
93 | |||
94 | // drain stdin | ||
95 | tcflush(STDIN_FILENO, TCIFLUSH); | ||
96 | printf("connected to '%s' (%d bps), exit with ctrl-X...\r\n", argv[0], speed); | ||
97 | |||
98 | // main loop: check with poll(), then read/write bytes across | ||
99 | pfd[0].fd = STDIN_FILENO; | ||
100 | pfd[0].events = POLLIN; | ||
101 | /*pfd[1].fd = sfd;*/ | ||
102 | pfd[1].events = POLLIN; | ||
103 | while (1) { | ||
104 | int i; | ||
105 | while (-1 == poll(pfd, 2, -1) && EINTR == errno) | ||
106 | continue; | ||
107 | for (i = 0; i < 2; ++i) { | ||
108 | if (pfd[i].revents & POLLIN) { | ||
109 | len = read(pfd[i].fd, bb_common_bufsiz1, COMMON_BUFSIZE); | ||
110 | if (len > 0) { | ||
111 | if (!i && 24 == bb_common_bufsiz1[0]) | ||
112 | goto done; // ^X exits | ||
113 | write(pfd[1-i].fd, bb_common_bufsiz1, len); | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | done: | ||
119 | tcsetattr(sfd, TCSANOW, &tiosfd); | ||
120 | tcsetattr(STDIN_FILENO, TCSANOW, &tio0); | ||
121 | tcflush(STDIN_FILENO, TCIFLUSH); | ||
122 | |||
123 | if (ENABLE_FEATURE_CLEAN_UP) | ||
124 | close(sfd); | ||
125 | exitcode = 0; | ||
126 | |||
127 | unlock_and_exit: | ||
128 | // delete lock file | ||
129 | if (device_lock_file) { | ||
130 | unlink(device_lock_file); | ||
131 | if (ENABLE_FEATURE_CLEAN_UP) | ||
132 | free(device_lock_file); | ||
133 | } | ||
134 | return exitcode; | ||
135 | } | ||