sti.c revision 1.8 1 1.8 christos /* $NetBSD: sti.c,v 1.8 2009/08/27 19:40:06 christos Exp $ */
2 1.1 christos
3 1.1 christos /*-
4 1.1 christos * Copyright (c) 2005 The NetBSD Foundation, Inc.
5 1.1 christos * All rights reserved.
6 1.1 christos *
7 1.1 christos * This code is derived from software contributed to The NetBSD Foundation
8 1.1 christos * by Christos Zoulas.
9 1.1 christos *
10 1.1 christos * Redistribution and use in source and binary forms, with or without
11 1.1 christos * modification, are permitted provided that the following conditions
12 1.1 christos * are met:
13 1.1 christos * 1. Redistributions of source code must retain the above copyright
14 1.1 christos * notice, this list of conditions and the following disclaimer.
15 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 christos * notice, this list of conditions and the following disclaimer in the
17 1.1 christos * documentation and/or other materials provided with the distribution.
18 1.1 christos *
19 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 christos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 christos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 christos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 christos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 christos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 christos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 christos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 christos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 christos * POSSIBILITY OF SUCH DAMAGE.
30 1.1 christos */
31 1.1 christos #include <sys/cdefs.h>
32 1.8 christos #ifdef __RCSID
33 1.8 christos __RCSID("$NetBSD: sti.c,v 1.8 2009/08/27 19:40:06 christos Exp $");
34 1.8 christos #endif
35 1.1 christos
36 1.1 christos #include <sys/param.h>
37 1.1 christos #include <sys/ioctl.h>
38 1.1 christos #include <ctype.h>
39 1.1 christos #include <stdio.h>
40 1.1 christos #include <string.h>
41 1.1 christos #include <stdlib.h>
42 1.1 christos #include <unistd.h>
43 1.1 christos #include <fcntl.h>
44 1.1 christos #include <err.h>
45 1.8 christos #include <errno.h>
46 1.8 christos #ifdef __RCSID
47 1.2 christos #include <vis.h>
48 1.8 christos #else
49 1.8 christos #define setprogname(a)
50 1.8 christos extern const char *__progname;
51 1.8 christos #define getprogname() __progname
52 1.8 christos #endif
53 1.1 christos
54 1.1 christos static int
55 1.2 christos unescape(const char **pp, int *state)
56 1.1 christos {
57 1.2 christos char ch, out;
58 1.1 christos
59 1.8 christos #ifdef __RCSID
60 1.2 christos while ((ch = *(*pp)++) != '\0') {
61 1.2 christos switch(unvis(&out, ch, state, 0)) {
62 1.2 christos case 0:
63 1.2 christos case UNVIS_NOCHAR:
64 1.2 christos break;
65 1.2 christos case UNVIS_VALID:
66 1.2 christos return out;
67 1.2 christos case UNVIS_VALIDPUSH:
68 1.2 christos (*pp)--;
69 1.2 christos return out;
70 1.2 christos case UNVIS_SYNBAD:
71 1.2 christos errno = EILSEQ;
72 1.2 christos return -1;
73 1.1 christos }
74 1.1 christos }
75 1.2 christos if (unvis(&out, '\0', state, UNVIS_END) == UNVIS_VALID)
76 1.2 christos return out;
77 1.8 christos #else
78 1.8 christos switch ((ch = *(*pp)++)) {
79 1.8 christos case '\0':
80 1.8 christos goto out;
81 1.8 christos case '^':
82 1.8 christos ch = *(*pp)++;
83 1.8 christos return CTRL(ch);
84 1.8 christos case '\\':
85 1.8 christos switch (ch = *(*pp)++) {
86 1.8 christos case 'a': return '\a';
87 1.8 christos case 'b': return '\b';
88 1.8 christos case 'e': return '\e';
89 1.8 christos case 'f': return '\f';
90 1.8 christos case 't': return '\t';
91 1.8 christos case 'n': return '\n';
92 1.8 christos case 'r': return '\r';
93 1.8 christos case 'v': return '\v';
94 1.8 christos case '\\': return '\\';
95 1.8 christos
96 1.8 christos case '0': case '1': case '2': case '3':
97 1.8 christos case '4': case '5': case '6': case '7':
98 1.8 christos out = 0;
99 1.8 christos if (ch >= '0' && ch < '8') {
100 1.8 christos out = out * 8 + ch - '0';
101 1.8 christos ch = *(*pp)++;
102 1.8 christos if (ch >= '0' && ch < '8') {
103 1.8 christos out = out * 8 + ch - '0';
104 1.8 christos ch = *(*pp)++;
105 1.8 christos if (ch >= '0' && ch < '8')
106 1.8 christos out = out * 8 + ch - '0';
107 1.8 christos }
108 1.8 christos }
109 1.8 christos return out;
110 1.8 christos default:
111 1.8 christos break;
112 1.8 christos }
113 1.8 christos break;
114 1.8 christos default:
115 1.8 christos return ch;
116 1.8 christos }
117 1.8 christos out:
118 1.8 christos #endif
119 1.2 christos errno = ENODATA;
120 1.2 christos return -1;
121 1.1 christos }
122 1.1 christos
123 1.1 christos static void
124 1.1 christos sti(int fd, int c)
125 1.1 christos {
126 1.1 christos char ch = c;
127 1.1 christos
128 1.1 christos if (ioctl(fd, TIOCSTI, &ch) == -1)
129 1.1 christos err(1, "Cannot simulate terminal input");
130 1.1 christos }
131 1.1 christos
132 1.5 christos static void
133 1.5 christos sendstr(int fd, const char *str)
134 1.5 christos {
135 1.5 christos int c, state = 0;
136 1.5 christos const char *ptr = str;
137 1.5 christos
138 1.5 christos while ((c = unescape(&ptr, &state)) != -1)
139 1.5 christos sti(fd, c);
140 1.5 christos
141 1.5 christos if (c == -1 && errno != ENODATA)
142 1.5 christos warn("Cannot decode `%s'", str);
143 1.5 christos }
144 1.5 christos
145 1.1 christos int
146 1.1 christos main(int argc, char *argv[])
147 1.1 christos {
148 1.5 christos const char *tty;
149 1.1 christos char ttydev[MAXPATHLEN];
150 1.5 christos int fd;
151 1.1 christos
152 1.1 christos setprogname(*argv);
153 1.1 christos
154 1.6 peter if (argc < 2) {
155 1.4 christos (void)fprintf(stderr, "Usage: %s <tty> [arg ...]\n",
156 1.4 christos getprogname());
157 1.1 christos return 1;
158 1.1 christos }
159 1.1 christos
160 1.1 christos argc--;
161 1.1 christos argv++;
162 1.1 christos
163 1.1 christos tty = *argv++;
164 1.1 christos argc--;
165 1.1 christos
166 1.1 christos if (strncmp(tty, "/dev/", 5) == 0)
167 1.1 christos (void)snprintf(ttydev, sizeof(ttydev), "%s", tty);
168 1.1 christos else if (strncmp(tty, "tty", 3) == 0 || strncmp(tty, "pty", 3) == 0 ||
169 1.1 christos strncmp(tty, "pts/", 4) == 0)
170 1.1 christos (void)snprintf(ttydev, sizeof(ttydev), "/dev/%s", tty);
171 1.1 christos else if (isdigit((unsigned char)*tty))
172 1.1 christos (void)snprintf(ttydev, sizeof(ttydev), "/dev/pts/%s", tty);
173 1.1 christos else
174 1.1 christos (void)snprintf(ttydev, sizeof(ttydev), "/dev/tty%s", tty);
175 1.1 christos
176 1.1 christos if ((fd = open(ttydev, O_RDWR)) == -1)
177 1.1 christos err(1, "Cannot open `%s'", ttydev);
178 1.1 christos
179 1.4 christos if (argc == 0) {
180 1.4 christos char *line;
181 1.8 christos #ifndef __RCSID
182 1.8 christos line = malloc(10240);
183 1.8 christos while (fgets(line, 10240, stdin) != NULL) {
184 1.8 christos char *p;
185 1.8 christos if ((p = strrchr(line, '\n')) != NULL)
186 1.8 christos *p = '\0';
187 1.8 christos sendstr(fd, line);
188 1.8 christos }
189 1.8 christos free(line);
190 1.8 christos #else
191 1.4 christos while ((line = fparseln(stdin, NULL, NULL, NULL, 0)) != NULL) {
192 1.5 christos sendstr(fd, line);
193 1.4 christos free(line);
194 1.4 christos }
195 1.8 christos #endif
196 1.5 christos } else {
197 1.5 christos for (; argc--; argv++) {
198 1.5 christos sendstr(fd, *argv);
199 1.5 christos if (argc != 0)
200 1.5 christos sti(fd, ' ');
201 1.5 christos }
202 1.1 christos }
203 1.1 christos
204 1.1 christos (void)close(fd);
205 1.1 christos return 0;
206 1.1 christos }
207