1 /* $NetBSD: cu.c,v 1.18 2006/04/05 23:30:57 yamt 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.18 2006/04/05 23:30:57 yamt 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:heot0123456789", 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 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 case 'o': 149 if (parity != 0) 150 errx(3, "more than one parity specified"); 151 parity = 1; /* odd */ 152 break; 153 case 't': 154 HW = 1, DU = -1, DC = 1; 155 break; 156 case '0': case '1': case '2': case '3': case '4': 157 case '5': case '6': case '7': case '8': case '9': 158 snprintf(brbuf, sizeof(brbuf) -1, "%s%c", 159 brbuf, c); 160 BR = atoi(brbuf); 161 break; 162 default: 163 if (nostop == 0) 164 cuusage(); 165 break; 166 } 167 } 168 169 argc -= optind; 170 argv += optind; 171 172 switch (argc) { 173 case 1: 174 if (phonearg) 175 errx(3, "more than one phone number specified"); 176 else 177 PN = argv[0]; 178 break; 179 case 0: 180 /* 181 * No system or number to call. We're "direct", so use 182 * the tty as local. 183 */ 184 HW = 1; DU = -1; DC = 1; 185 break; 186 default: 187 cuusage(); 188 break; 189 } 190 191 signal(SIGINT, cleanup); 192 signal(SIGQUIT, cleanup); 193 signal(SIGHUP, cleanup); 194 signal(SIGTERM, cleanup); 195 /* signal(SIGCHLD, SIG_DFL) */ /* XXX seems wrong */ 196 197 /* 198 * The "cu" host name is used to define the 199 * attributes of the generic dialer. 200 */ 201 (void)snprintf(sbuf, sizeof sbuf, "cu%d", (int)BR); 202 if ((i = hunt(sbuf)) == 0) { 203 errx(3,"all ports busy"); 204 } 205 if (i == -1) { 206 errx(3, "link down"); 207 } 208 setbuf(stdout, NULL); 209 vinit(); 210 switch (parity) { 211 case -1: 212 setparity("even"); 213 break; 214 case 1: 215 setparity("odd"); 216 break; 217 case 0: 218 setparity("none"); 219 break; 220 default: 221 setparity("none"); 222 break; 223 } 224 225 switch (flow) { 226 case -1: 227 if(nostop) { 228 setboolean(value(TAND), FALSE); 229 setboolean(value(HARDWAREFLOW), FALSE); 230 } 231 else { 232 setboolean(value(TAND), TRUE); 233 setboolean(value(HARDWAREFLOW), FALSE); 234 } 235 break; 236 case 1: 237 setboolean(value(TAND), FALSE); 238 setboolean(value(HARDWAREFLOW), TRUE); 239 break; 240 case 0: 241 default: 242 setboolean(value(TAND), FALSE); 243 setboolean(value(HARDWAREFLOW), FALSE); 244 break; 245 } 246 setcharacter(value(ESCAPE), useresc); 247 setboolean(value(VERBOSE), FALSE); 248 if (HD) 249 setboolean(value(LECHO), TRUE); 250 if (HW) { 251 if (ttysetup((speed_t)BR) != 0) { 252 errx(3, "unsupported speed %ld", BR); 253 } 254 } 255 if (connect()) { 256 errx(1, "Connect failed"); 257 } 258 if (!HW) { 259 if (ttysetup((speed_t)BR) != 0) { 260 errx(3, "unsupported speed %ld", BR); 261 } 262 } 263 } 264 265 static void 266 cuusage(void) 267 { 268 fprintf(stderr, "Usage: cu [options] [phone-number]\n" 269 "Use cu --help for help\n"); 270 exit(8); 271 } 272 273 static void 274 cuhelp(void) 275 { 276 fprintf(stderr, 277 "BSD tip/cu\n" 278 "Usage: cu [options] [phone-number]\n" 279 " -E,--escape char: Use this escape character\n" 280 " -F,--flow {hard,soft,none}: Use RTS/CTS, ^S/^Q, no flow control\n" 281 " --nostop: Do not use software flow control\n" 282 " -a, -p,--port port: Use this port as ACU/Dialer\n" 283 " -c,--phone number: Call this number\n" 284 " -h,--halfduplex: Echo characters locally (use \"half duplex\")\n" 285 " -e: Use even parity\n" 286 " -o: Use odd parity\n" 287 " -P,--parity {even,odd,none}: use even, odd, no parity\n" 288 " -l,--line line: Use this device (ttyXX)\n" 289 " -s,--speed,--baud speed,-#: Use this speed\n" 290 " -t: Connect via hard-wired connection\n"); 291 exit(0); 292 } 293