1 /* $NetBSD: cu.c,v 1.23 2016/01/03 15:38:29 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 35 #ifndef lint 36 #if 0 37 static char sccsid[] = "@(#)cu.c 8.1 (Berkeley) 6/6/93"; 38 #endif 39 __RCSID("$NetBSD: cu.c,v 1.23 2016/01/03 15:38:29 christos Exp $"); 40 #endif /* not lint */ 41 42 #include "tip.h" 43 44 __dead static void cuhelp(void); 45 __dead static void cuusage(void); 46 47 /* 48 * Botch the interface to look like cu's 49 */ 50 void 51 cumain(int argc, char *argv[]) 52 { 53 int c, i, phonearg = 0; 54 int parity = 0; /* 0 is no parity */ 55 int flow = -1; /* -1 is "tandem" ^S/^Q */ 56 static int helpme = 0, nostop = 0; 57 int useresc = '~'; 58 static char sbuf[12]; 59 int cmdlineBR; 60 extern char *optarg; 61 extern int optind; 62 63 static struct option longopts[] = { 64 { "help", no_argument, &helpme, 1 }, 65 { "escape", required_argument, NULL, 'E' }, 66 { "flow", required_argument, NULL, 'F' }, 67 { "parity", required_argument, NULL, 'P' }, 68 { "phone", required_argument, NULL, 'c' }, 69 { "port", required_argument, NULL, 'a' }, 70 { "line", required_argument, NULL, 'l' }, 71 { "speed", required_argument, NULL, 's' }, 72 { "halfduplex", no_argument, NULL, 'h' }, 73 { "nostop", no_argument, &nostop, 1 }, 74 { NULL, 0, NULL, 0 } 75 }; 76 77 78 if (argc < 2) 79 cuusage(); 80 81 CU = NULL; 82 DV = NULL; 83 BR = DEFBR; 84 cmdlineBR = 0; 85 86 while((c = getopt_long(argc, argv, 87 "E:F:P:a:p:c:l:ns:hefot0123456789", longopts, NULL)) != -1) { 88 89 if (helpme == 1) cuhelp(); 90 91 switch(c) { 92 93 case 'E': 94 if(strlen(optarg) > 1) 95 errx(3, "only one escape character allowed"); 96 useresc = optarg[0]; 97 break; 98 case 'F': 99 if (strncmp(optarg, "hard", sizeof("hard") - 1 ) == 0) 100 flow = 1; 101 else 102 if (strncmp(optarg, "soft", 103 sizeof("soft") - 1 ) == 0) 104 flow = -1; 105 else 106 if(strcmp(optarg, "none") != 0) 107 errx(3, "bad flow setting"); 108 else 109 flow = 0; 110 break; 111 case 'P': 112 if(strcmp(optarg, "even") == 0) 113 parity = -1; 114 else 115 if(strcmp(optarg, "odd") == 0) 116 parity = 1; 117 else 118 if(strcmp(optarg, "none") != 0) 119 errx(3, "bad parity setting"); 120 else 121 parity = 0; 122 break; 123 case 'a': 124 case 'p': 125 CU = optarg; 126 break; 127 case 'c': 128 phonearg = 1; 129 PN = optarg; 130 break; 131 case 'l': 132 if (DV != NULL) 133 errx(3,"more than one line specified"); 134 if(strchr(optarg, '/')) 135 DV = optarg; 136 else 137 (void)asprintf(&DV, "/dev/%s", optarg); 138 break; 139 case 'n': 140 useresc = -1; 141 break; 142 case 's': 143 BR = atoi(optarg); 144 break; 145 case 'h': 146 HD = TRUE; 147 break; 148 case 'e': 149 if (parity != 0) 150 errx(3, "more than one parity specified"); 151 parity = -1; /* even */ 152 break; 153 /* Compatibility with Taylor cu */ 154 case 'f': 155 flow = 0; 156 break; 157 case 'o': 158 if (parity != 0) 159 errx(3, "more than one parity specified"); 160 parity = 1; /* odd */ 161 break; 162 case 't': 163 HW = 1, DU = -1, DC = 1; 164 break; 165 case '0': case '1': case '2': case '3': case '4': 166 case '5': case '6': case '7': case '8': case '9': 167 cmdlineBR = cmdlineBR * 10 + (c - '0'); 168 BR = cmdlineBR; 169 break; 170 default: 171 if (nostop == 0) 172 cuusage(); 173 break; 174 } 175 } 176 177 argc -= optind; 178 argv += optind; 179 180 switch (argc) { 181 case 1: 182 if (phonearg) 183 errx(3, "more than one phone number specified"); 184 else 185 /* Compatibility with Taylor cu */ 186 if(!strcmp(argv[0], "dir")) { 187 HW = 1; DU = -1; DC = 1; 188 } else 189 PN = argv[0]; 190 break; 191 case 0: 192 /* 193 * No system or number to call. We're "direct", so use 194 * the tty as local. 195 */ 196 HW = 1; DU = -1; DC = 1; 197 break; 198 default: 199 cuusage(); 200 break; 201 } 202 203 (void)signal(SIGINT, cleanup); 204 (void)signal(SIGQUIT, cleanup); 205 (void)signal(SIGHUP, cleanup); 206 (void)signal(SIGTERM, cleanup); 207 /* (void)signal(SIGCHLD, SIG_DFL) */ /* XXX seems wrong */ 208 209 /* 210 * The "cu" host name is used to define the 211 * attributes of the generic dialer. 212 */ 213 (void)snprintf(sbuf, sizeof sbuf, "cu%d", (int)BR); 214 if ((i = hunt(sbuf)) == 0) { 215 errx(3,"all ports busy"); 216 } 217 if (i == -1) { 218 errx(3, "link down"); 219 } 220 setbuf(stdout, NULL); 221 vinit(); 222 switch (parity) { 223 case -1: 224 setparity("even"); 225 break; 226 case 1: 227 setparity("odd"); 228 break; 229 case 0: 230 setparity("none"); 231 break; 232 default: 233 setparity("none"); 234 break; 235 } 236 237 switch (flow) { 238 case -1: 239 if(nostop) { 240 setboolean(value(TAND), FALSE); 241 setboolean(value(HARDWAREFLOW), FALSE); 242 } 243 else { 244 setboolean(value(TAND), TRUE); 245 setboolean(value(HARDWAREFLOW), FALSE); 246 } 247 break; 248 case 1: 249 setboolean(value(TAND), FALSE); 250 setboolean(value(HARDWAREFLOW), TRUE); 251 break; 252 case 0: 253 default: 254 setboolean(value(TAND), FALSE); 255 setboolean(value(HARDWAREFLOW), FALSE); 256 break; 257 } 258 setcharacter(value(ESCAPE), useresc); 259 setboolean(value(VERBOSE), FALSE); 260 if (HD) 261 setboolean(value(LECHO), TRUE); 262 if (HW) { 263 if (ttysetup((speed_t)BR) != 0) { 264 errx(3, "unsupported speed %ld", BR); 265 } 266 } 267 if (tip_connect()) { 268 errx(1, "Connect failed"); 269 } 270 if (!HW) { 271 if (ttysetup((speed_t)BR) != 0) { 272 errx(3, "unsupported speed %ld", BR); 273 } 274 } 275 } 276 277 static void 278 cuusage(void) 279 { 280 (void)fprintf(stderr, "Usage: cu [options] [phone-number|\"dir\"]\n" 281 "Use cu --help for help\n"); 282 exit(8); 283 } 284 285 static void 286 cuhelp(void) 287 { 288 (void)fprintf(stderr, 289 "BSD tip/cu\n" 290 "Usage: cu [options] [phone-number|\"dir\"]\n" 291 " -E,--escape char: Use this escape character\n" 292 " -F,--flow {hard,soft,none}: Use RTS/CTS, ^S/^Q, no flow control\n" 293 " -f: Use no flow control\n" 294 " --nostop: Do not use software flow control\n" 295 " -a, -p,--port port: Use this port as ACU/Dialer\n" 296 " -c,--phone number: Call this number\n" 297 " -h,--halfduplex: Echo characters locally (use \"half duplex\")\n" 298 " -e: Use even parity\n" 299 " -o: Use odd parity\n" 300 " -P,--parity {even,odd,none}: use even, odd, no parity\n" 301 " -l,--line line: Use this device (ttyXX)\n" 302 " -n: Disable escape character processing\n" 303 " -s,--speed,--baud speed,-#: Use this speed\n" 304 " -t: Connect via hard-wired connection\n"); 305 exit(0); 306 } 307