xref: /netbsd-src/usr.bin/tip/cu.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
1 /*	$NetBSD: cu.c,v 1.24 2019/08/18 14:16:02 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1983, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #include <getopt.h>
34 #include <inttypes.h>
35 
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)cu.c	8.1 (Berkeley) 6/6/93";
39 #endif
40 __RCSID("$NetBSD: cu.c,v 1.24 2019/08/18 14:16:02 christos Exp $");
41 #endif /* not lint */
42 
43 #include "tip.h"
44 
45 __dead static void cuhelp(void);
46 __dead static void cuusage(void);
47 
48 /*
49  * Botch the interface to look like cu's
50  */
51 void
52 cumain(int argc, char *argv[])
53 {
54 	int c, i, phonearg = 0, e;
55 	int parity = 0;		/* 0 is no parity */
56 	int flow = -1;		/* -1 is "tandem" ^S/^Q */
57 	static int helpme = 0, nostop = 0;
58 	int useresc = '~';
59 	static char sbuf[12];
60 	int cmdlineBR;
61 	extern char *optarg;
62 	extern int optind;
63 
64 	static struct option longopts[] = {
65 		{ "help",	no_argument,		&helpme,	1 },
66 		{ "escape",	required_argument,	NULL,		'E' },
67 		{ "flow",	required_argument,	NULL,		'F' },
68 		{ "parity",	required_argument,	NULL,		'P' },
69 		{ "phone", 	required_argument,	NULL,		'c' },
70 		{ "port",	required_argument,	NULL,		'a' },
71 		{ "line",	required_argument,	NULL,		'l' },
72 		{ "speed",	required_argument,	NULL,		's' },
73 		{ "halfduplex",	no_argument,		NULL,		'h' },
74 		{ "nostop",	no_argument,		&nostop,	1  },
75 		{ NULL,		0,			NULL,		0 }
76 	};
77 
78 
79 	if (argc < 2)
80 		cuusage();
81 
82 	CU = NULL;
83 	DV = NULL;
84 	BR = DEFBR;
85 	cmdlineBR = 0;
86 
87 	while((c = getopt_long(argc, argv,
88 	    "E:F:P:a:p:c:l:ns:hefot0123456789", longopts, NULL)) != -1) {
89 
90 		if (helpme == 1) cuhelp();
91 
92 		switch(c) {
93 
94 		case 'E':
95 			if(strlen(optarg) > 1)
96 				errx(3, "only one escape character allowed");
97 			useresc = optarg[0];
98 			break;
99 		case 'F':
100 			if (strncmp(optarg, "hard", sizeof("hard") - 1 ) == 0)
101 				flow = 1;
102 			else
103 				if (strncmp(optarg, "soft",
104 				    sizeof("soft") - 1 ) == 0)
105 					flow = -1;
106 				else
107 					if(strcmp(optarg, "none") != 0)
108 						errx(3, "bad flow setting");
109 					else
110 						flow = 0;
111 			break;
112 		case 'P':
113 			if(strcmp(optarg, "even") == 0)
114 				parity = -1;
115 			else
116 				if(strcmp(optarg, "odd") == 0)
117 					parity = 1;
118 				else
119 					if(strcmp(optarg, "none") != 0)
120 						errx(3, "bad parity setting");
121 					else
122 						parity = 0;
123 			break;
124 		case 'a':
125 		case 'p':
126 			CU = optarg;
127 			break;
128 		case 'c':
129 			phonearg = 1;
130 			PN = optarg;
131 			break;
132 		case 'l':
133 			if (DV != NULL)
134 				errx(3,"more than one line specified");
135 			if(strchr(optarg, '/'))
136 				DV = optarg;
137 			else
138 				(void)asprintf(&DV, "/dev/%s", optarg);
139 			break;
140 		case 'n':
141 			useresc = -1;
142 			break;
143 		case 's':
144 			BR = (long)strtoi(optarg, NULL, 0, 1, LONG_MAX, &e);
145 			if (e)
146 				warnc(e, "Conversion of `%s' to a baud rate "
147 				    "failed, using %ld", optarg, BR);
148 			break;
149 		case 'h':
150 			HD = TRUE;
151 			break;
152 		case 'e':
153 			if (parity != 0)
154 				errx(3, "more than one parity specified");
155 			parity = -1; /* even */
156 			break;
157 			/* Compatibility with Taylor cu */
158 		case 'f':
159 			flow = 0;
160 			break;
161 		case 'o':
162 			if (parity != 0)
163 				errx(3, "more than one parity specified");
164 			parity = 1; /* odd */
165 			break;
166 		case 't':
167 			HW = 1, DU = -1, DC = 1;
168 			break;
169 		case '0': case '1': case '2': case '3': case '4':
170 		case '5': case '6': case '7': case '8': case '9':
171 			cmdlineBR = cmdlineBR * 10 + (c - '0');
172 			BR = cmdlineBR;
173 			break;
174 		default:
175 			if (nostop == 0)
176 				cuusage();
177 			break;
178 		}
179 	}
180 
181 	argc -= optind;
182 	argv += optind;
183 
184 	switch (argc) {
185 	case 1:
186 		if (phonearg)
187 			errx(3, "more than one phone number specified");
188 		else
189 			/* Compatibility with Taylor cu */
190 			if(!strcmp(argv[0], "dir")) {
191 				HW = 1; DU = -1; DC = 1;
192 			} else
193 				PN = argv[0];
194 		break;
195 	case 0:
196 		/*
197 		 * No system or number to call.  We're "direct", so use
198 		 * the tty as local.
199 		 */
200 		HW = 1; DU = -1; DC = 1;
201 		break;
202 	default:
203 		cuusage();
204 		break;
205 	}
206 
207 	(void)signal(SIGINT, cleanup);
208 	(void)signal(SIGQUIT, cleanup);
209 	(void)signal(SIGHUP, cleanup);
210 	(void)signal(SIGTERM, cleanup);
211 	/* (void)signal(SIGCHLD, SIG_DFL) */	/* XXX seems wrong */
212 
213 	/*
214 	 * The "cu" host name is used to define the
215 	 * attributes of the generic dialer.
216 	 */
217 	(void)snprintf(sbuf, sizeof sbuf, "cu%d", (int)BR);
218 	if ((i = hunt(sbuf)) == 0) {
219 		errx(3,"all ports busy");
220 	}
221 	if (i == -1) {
222 		errx(3, "link down");
223 	}
224 	setbuf(stdout, NULL);
225 	vinit();
226 	switch (parity) {
227 	case -1:
228 		setparity("even");
229 		break;
230 	case 1:
231 		setparity("odd");
232 		break;
233 	case 0:
234 		setparity("none");
235 		break;
236 	default:
237 		setparity("none");
238 		break;
239 	}
240 
241 	switch (flow) {
242 	case -1:
243 		if(nostop) {
244 			setboolean(value(TAND), FALSE);
245 			setboolean(value(HARDWAREFLOW), FALSE);
246 		}
247 		else {
248 			setboolean(value(TAND), TRUE);
249 			setboolean(value(HARDWAREFLOW), FALSE);
250 		}
251 		break;
252 	case 1:
253 		setboolean(value(TAND), FALSE);
254 		setboolean(value(HARDWAREFLOW), TRUE);
255 		break;
256 	case 0:
257 	default:
258 		setboolean(value(TAND), FALSE);
259 		setboolean(value(HARDWAREFLOW), FALSE);
260 		break;
261 	}
262 	setcharacter(value(ESCAPE), useresc);
263 	setboolean(value(VERBOSE), FALSE);
264 	if (HD)
265 		setboolean(value(LECHO), TRUE);
266 	if (HW) {
267 		if (ttysetup((speed_t)BR) != 0) {
268 			errx(3, "unsupported speed %ld", BR);
269 		}
270 	}
271 	if (tip_connect()) {
272 		errx(1, "Connect failed");
273 	}
274 	if (!HW) {
275 		if (ttysetup((speed_t)BR) != 0) {
276 			errx(3, "unsupported speed %ld", BR);
277 		}
278 	}
279 }
280 
281 static void
282 cuusage(void)
283 {
284 	(void)fprintf(stderr, "Usage: cu [options] [phone-number|\"dir\"]\n"
285 	    "Use cu --help for help\n");
286 	exit(8);
287 }
288 
289 static void
290 cuhelp(void)
291 {
292 	(void)fprintf(stderr,
293 	    "BSD tip/cu\n"
294 	    "Usage: cu [options] [phone-number|\"dir\"]\n"
295 	    " -E,--escape char: Use this escape character\n"
296 	    " -F,--flow {hard,soft,none}: Use RTS/CTS, ^S/^Q, no flow control\n"
297 	    " -f: Use no flow control\n"
298 	    " --nostop: Do not use software flow control\n"
299 	    " -a, -p,--port port: Use this port as ACU/Dialer\n"
300 	    " -c,--phone number: Call this number\n"
301 	    " -h,--halfduplex: Echo characters locally (use \"half duplex\")\n"
302 	    " -e: Use even parity\n"
303 	    " -o: Use odd parity\n"
304 	    " -P,--parity {even,odd,none}: use even, odd, no parity\n"
305 	    " -l,--line line: Use this device (ttyXX)\n"
306 	    " -n: Disable escape character processing\n"
307 	    " -s,--speed,--baud speed,-#: Use this speed\n"
308 	    " -t: Connect via hard-wired connection\n");
309 	exit(0);
310 }
311