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