aboutsummaryrefslogtreecommitdiff
path: root/miscutils/microcom.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-02-08 17:30:39 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-02-08 17:30:39 +0000
commitdc1c45795b36c232fe781962c5fab1df6b8299d9 (patch)
tree6ca4edb7f27b9521bd70682eb18c6bbf68f3ce6b /miscutils/microcom.c
parent97bd0e05ccef27563b4403c24952f0abec8eb6cf (diff)
downloadbusybox-w32-dc1c45795b36c232fe781962c5fab1df6b8299d9.tar.gz
busybox-w32-dc1c45795b36c232fe781962c5fab1df6b8299d9.tar.bz2
busybox-w32-dc1c45795b36c232fe781962c5fab1df6b8299d9.zip
microcom: update from maintainer
Diffstat (limited to 'miscutils/microcom.c')
-rw-r--r--miscutils/microcom.c153
1 files changed, 71 insertions, 82 deletions
diff --git a/miscutils/microcom.c b/miscutils/microcom.c
index 00a49837e..fb5e9c868 100644
--- a/miscutils/microcom.c
+++ b/miscutils/microcom.c
@@ -17,7 +17,7 @@ static void signal_handler(int signo)
17 signalled = signo; 17 signalled = signo;
18} 18}
19 19
20// set canonical tty mode 20// set raw tty mode
21static void xget1(int fd, struct termios *t, struct termios *oldt) 21static void xget1(int fd, struct termios *t, struct termios *oldt)
22{ 22{
23 tcgetattr(fd, oldt); 23 tcgetattr(fd, oldt);
@@ -32,7 +32,7 @@ static void xget1(int fd, struct termios *t, struct termios *oldt)
32 32
33static int xset1(int fd, struct termios *tio, const char *device) 33static int xset1(int fd, struct termios *tio, const char *device)
34{ 34{
35 int ret = tcsetattr(fd, TCSANOW, tio); 35 int ret = tcsetattr(fd, TCSAFLUSH, tio);
36 36
37 if (ret) { 37 if (ret) {
38 bb_perror_msg("can't tcsetattr for %s", device); 38 bb_perror_msg("can't tcsetattr for %s", device);
@@ -43,41 +43,45 @@ static int xset1(int fd, struct termios *tio, const char *device)
43int microcom_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 43int microcom_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
44int microcom_main(int argc, char **argv) 44int microcom_main(int argc, char **argv)
45{ 45{
46 struct pollfd pfd[2];
47 int nfd;
48 int sfd; 46 int sfd;
49/* #define sfd (pfd[0].fd) - gcc 4.2.1 is still not smart enough */ 47 int nfd;
50 char *device_lock_file; 48 struct pollfd pfd[2];
51 const char *opt_s = "9600";
52 speed_t speed;
53 const char *opt_t = "100"; // 0.1 sec timeout
54 unsigned timeout;
55 struct termios tio0, tiosfd, tio; 49 struct termios tio0, tiosfd, tio;
56 bool istty; 50 char *device_lock_file;
51 enum {
52 OPT_X = 1 << 0, // do not respect Ctrl-X, Ctrl-@
53 OPT_s = 1 << 1, // baudrate
54 OPT_t = 1 << 2 // wait for device response, msecs
55 };
56 speed_t speed = 9600;
57 int timeout = 100; // 0.1 sec timeout
57 58
58 // fetch options 59 // fetch options
59 opt_complementary = "-1"; /* at least one arg should be there */ 60 char *opt_s;
60 getopt32(argv, "s:t:", &opt_s, &opt_t); 61 char *opt_t;
61 argc -= optind; 62 unsigned opts;
63 opt_complementary = "=1"; /* exactly one arg should be there */
64 opts = getopt32(argv, "Xs:t:", &opt_s, &opt_t);
65 // apply options
66 if (opts & OPT_s)
67 speed = xatoi_u(opt_s);
68 if (opts & OPT_t)
69 timeout = xatoi_u(opt_t);
70// argc -= optind;
62 argv += optind; 71 argv += optind;
63 72
64 // check sanity
65 speed = xatou(opt_s);
66 timeout = xatou(opt_t);
67 device_lock_file = (char *)bb_basename(argv[0]);
68
69 // try to create lock file in /var/lock 73 // try to create lock file in /var/lock
74 device_lock_file = (char *)bb_basename(argv[0]);
70 device_lock_file = xasprintf("/var/lock/LCK..%s", device_lock_file); 75 device_lock_file = xasprintf("/var/lock/LCK..%s", device_lock_file);
71 sfd = open(device_lock_file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644); 76 sfd = open(device_lock_file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644);
72 if (sfd < 0) { 77 if (sfd < 0) {
73 if (errno == EEXIST) 78 if (errno == EEXIST)
74 bb_perror_msg_and_die("can't lock device"); 79 bb_perror_msg_and_die("can't create %s", device_lock_file);
75 // We don't abort on other errors: /var/lock can be
76 // non-writable or non-existent
77 if (ENABLE_FEATURE_CLEAN_UP) 80 if (ENABLE_FEATURE_CLEAN_UP)
78 free(device_lock_file); 81 free(device_lock_file);
79 device_lock_file = NULL; 82 device_lock_file = NULL;
80 } else { 83 }
84 if (sfd > 0) {
81 // %4d to make mgetty happy. It treats 4-bytes lock files as binary, 85 // %4d to make mgetty happy. It treats 4-bytes lock files as binary,
82 // not text, PID. Making 5+ char file. Brrr... 86 // not text, PID. Making 5+ char file. Brrr...
83 char *s = xasprintf("%4d\n", getpid()); 87 char *s = xasprintf("%4d\n", getpid());
@@ -99,17 +103,15 @@ int microcom_main(int argc, char **argv)
99 // open device 103 // open device
100 sfd = open_or_warn(argv[0], O_RDWR | O_NOCTTY | O_NONBLOCK); 104 sfd = open_or_warn(argv[0], O_RDWR | O_NOCTTY | O_NONBLOCK);
101 if (sfd < 0) 105 if (sfd < 0)
102 goto unlock_and_exit; 106 goto done;
103 fcntl(sfd, F_SETFL, O_RDWR | O_NOCTTY); 107 fcntl(sfd, F_SETFL, O_RDWR | O_NOCTTY);
104 108
105 /* put stdin to "raw mode" (if stdin is a TTY), 109 /* put stdin to "raw mode" (if stdin is a TTY),
106 handle one character at a time */ 110 handle one character at a time */
107 istty = isatty(STDIN_FILENO); 111 if (isatty(STDIN_FILENO)) {
108 if (istty) {
109 xget1(STDIN_FILENO, &tio, &tio0); 112 xget1(STDIN_FILENO, &tio, &tio0);
110 if (xset1(STDIN_FILENO, &tio, "stdin")) 113 if (xset1(STDIN_FILENO, &tio, "stdin"))
111 goto close_unlock_and_exit; 114 goto done;
112// tcflush(STDIN_FILENO, TCIFLUSH);
113 timeout = -1; // tty input? -> set infinite timeout for poll() 115 timeout = -1; // tty input? -> set infinite timeout for poll()
114 } 116 }
115 117
@@ -117,10 +119,12 @@ int microcom_main(int argc, char **argv)
117 xget1(sfd, &tio, &tiosfd); 119 xget1(sfd, &tio, &tiosfd);
118 // order device to hang up at exit 120 // order device to hang up at exit
119 tio.c_cflag |= (CREAD|HUPCL); 121 tio.c_cflag |= (CREAD|HUPCL);
122// if (!istty)
123// tio.c_iflag |= (IGNCR);
120 // set device speed 124 // set device speed
121 cfsetspeed(&tio, tty_value_to_baud(speed)); 125 cfsetspeed(&tio, tty_value_to_baud(speed));
122 if (xset1(sfd, &tio, argv[0])) 126 if (xset1(sfd, &tio, argv[0]))
123 goto restore0_close_unlock_and_exit; 127 goto restore0_and_done;
124 128
125 // main loop: check with poll(), then read/write bytes across 129 // main loop: check with poll(), then read/write bytes across
126 pfd[0].fd = sfd; 130 pfd[0].fd = sfd;
@@ -128,69 +132,54 @@ int microcom_main(int argc, char **argv)
128 pfd[1].fd = STDIN_FILENO; 132 pfd[1].fd = STDIN_FILENO;
129 pfd[1].events = POLLIN; 133 pfd[1].events = POLLIN;
130 134
131 // TODO: on piped input should we treat NL as CRNL?!
132
133 signalled = 0; 135 signalled = 0;
134 // initially we have to poll() both stdin and device
135 nfd = 2; 136 nfd = 2;
136 while (!signalled && nfd && safe_poll(pfd, nfd, timeout) > 0) { 137 while (!signalled && safe_poll(pfd, nfd, timeout) > 0) {
137 int i; 138 char c;
138 139 if (pfd[0].revents & POLLIN) {
139 for (i = 0; i < nfd; ++i) { 140 // read from device -> write to stdout
140 if (pfd[i].revents & (POLLIN | POLLHUP)) { 141 if (safe_read(sfd, &c, 1) > 0)
141// int fd; 142 write(STDOUT_FILENO, &c, 1);
142 char c; 143 }
143 // read a byte 144 if (pfd[1].revents & POLLIN) {
144 if (safe_read(pfd[i].fd, &c, 1) < 1) { 145 // read from stdin -> write to device
145 // this can occur at the end of piped input 146 if (safe_read(STDIN_FILENO, &c, 1) < 1) {
146 // from now we only poll() for device 147 // skip polling stdin if we got EOF/error
147 nfd--; 148 pfd[1].revents = 0;
149 nfd--;
150 continue;
151 }
152 // do we need special processing?
153 if (!(opts & OPT_X)) {
154 // ^@ sends Break
155 if (VINTR == c) {
156 tcsendbreak(sfd, 0);
148 continue; 157 continue;
149 } 158 }
150// fd = STDOUT_FILENO; 159 // ^X exits
151 // stdin requires additional processing 160 if (24 == c)
152 // (TODO: must be controlled by command line switch) 161 break;
153 if (i) {
154 // ^@ sends Break
155 if (0 == c) {
156 tcsendbreak(sfd, 0);
157 continue;
158 }
159 // ^X exits
160 if (24 == c)
161 goto done;
162// fd = sfd;
163 }
164 // write the byte
165 write(i ? sfd : STDOUT_FILENO, &c, 1);
166// write(fd, &c, 1);
167 // give device a chance to get data
168 // wait 0.01 msec
169 // (TODO: seems to be arbitrary to me)
170 if (i)
171 usleep(10);
172 } 162 }
163 write(sfd, &c, 1);
164//// vda: this is suspicious!
165 // without this we never get POLLIN on sfd
166 // until piped stdin is drained
167 if (-1 != timeout)
168 safe_poll(pfd, 1, 1 /* 1 ms */);
173 } 169 }
174 } 170 }
175done: 171 /* usleep(10000); - let last chars leave serial line */
176 tcsetattr(sfd, TCSANOW, &tiosfd);
177 172
178restore0_close_unlock_and_exit: 173 tcsetattr(sfd, TCSAFLUSH, &tiosfd);
179 if (istty) {
180// tcflush(STDIN_FILENO, TCIFLUSH);
181 tcsetattr(STDIN_FILENO, TCSANOW, &tio0);
182 }
183 174
184close_unlock_and_exit: 175restore0_and_done:
185 if (ENABLE_FEATURE_CLEAN_UP) 176 // timeout == -1 -- stdin is a tty
186 close(sfd); 177 if (-1 == timeout)
178 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);
187 179
188unlock_and_exit: 180done:
189 // delete lock file 181 if (device_lock_file)
190 if (device_lock_file) {
191 unlink(device_lock_file); 182 unlink(device_lock_file);
192 if (ENABLE_FEATURE_CLEAN_UP) 183
193 free(device_lock_file);
194 }
195 return signalled; 184 return signalled;
196} 185}