/* $NetBSD: cu.c,v 1.25 2024/11/03 10:43:27 rillig Exp $ */ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #ifndef lint #if 0 static char sccsid[] = "@(#)cu.c 8.1 (Berkeley) 6/6/93"; #endif __RCSID("$NetBSD: cu.c,v 1.25 2024/11/03 10:43:27 rillig Exp $"); #endif /* not lint */ #include "tip.h" __dead static void cuhelp(void); __dead static void cuusage(void); /* * Botch the interface to look like cu's */ void cumain(int argc, char *argv[]) { int c, i, phonearg = 0, e; int parity = 0; /* 0 is no parity */ int flow = -1; /* -1 is "tandem" ^S/^Q */ static int helpme = 0, nostop = 0; int useresc = '~'; static char sbuf[12]; int cmdlineBR; static struct option longopts[] = { { "help", no_argument, &helpme, 1 }, { "escape", required_argument, NULL, 'E' }, { "flow", required_argument, NULL, 'F' }, { "parity", required_argument, NULL, 'P' }, { "phone", required_argument, NULL, 'c' }, { "port", required_argument, NULL, 'a' }, { "line", required_argument, NULL, 'l' }, { "speed", required_argument, NULL, 's' }, { "halfduplex", no_argument, NULL, 'h' }, { "nostop", no_argument, &nostop, 1 }, { NULL, 0, NULL, 0 } }; if (argc < 2) cuusage(); CU = NULL; DV = NULL; BR = DEFBR; cmdlineBR = 0; while((c = getopt_long(argc, argv, "E:F:P:a:p:c:l:ns:hefot0123456789", longopts, NULL)) != -1) { if (helpme == 1) cuhelp(); switch(c) { case 'E': if(strlen(optarg) > 1) errx(3, "only one escape character allowed"); useresc = optarg[0]; break; case 'F': if (strncmp(optarg, "hard", sizeof("hard") - 1 ) == 0) flow = 1; else if (strncmp(optarg, "soft", sizeof("soft") - 1 ) == 0) flow = -1; else if(strcmp(optarg, "none") != 0) errx(3, "bad flow setting"); else flow = 0; break; case 'P': if(strcmp(optarg, "even") == 0) parity = -1; else if(strcmp(optarg, "odd") == 0) parity = 1; else if(strcmp(optarg, "none") != 0) errx(3, "bad parity setting"); else parity = 0; break; case 'a': case 'p': CU = optarg; break; case 'c': phonearg = 1; PN = optarg; break; case 'l': if (DV != NULL) errx(3,"more than one line specified"); if(strchr(optarg, '/')) DV = optarg; else (void)asprintf(&DV, "/dev/%s", optarg); break; case 'n': useresc = -1; break; case 's': BR = (long)strtoi(optarg, NULL, 0, 1, LONG_MAX, &e); if (e) warnc(e, "Conversion of `%s' to a baud rate " "failed, using %ld", optarg, BR); break; case 'h': HD = TRUE; break; case 'e': if (parity != 0) errx(3, "more than one parity specified"); parity = -1; /* even */ break; /* Compatibility with Taylor cu */ case 'f': flow = 0; break; case 'o': if (parity != 0) errx(3, "more than one parity specified"); parity = 1; /* odd */ break; case 't': HW = 1, DU = -1, DC = 1; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': cmdlineBR = cmdlineBR * 10 + (c - '0'); BR = cmdlineBR; break; default: if (nostop == 0) cuusage(); break; } } argc -= optind; argv += optind; switch (argc) { case 1: if (phonearg) errx(3, "more than one phone number specified"); else /* Compatibility with Taylor cu */ if(!strcmp(argv[0], "dir")) { HW = 1; DU = -1; DC = 1; } else PN = argv[0]; break; case 0: /* * No system or number to call. We're "direct", so use * the tty as local. */ HW = 1; DU = -1; DC = 1; break; default: cuusage(); break; } (void)signal(SIGINT, cleanup); (void)signal(SIGQUIT, cleanup); (void)signal(SIGHUP, cleanup); (void)signal(SIGTERM, cleanup); /* (void)signal(SIGCHLD, SIG_DFL) */ /* XXX seems wrong */ /* * The "cu" host name is used to define the * attributes of the generic dialer. */ (void)snprintf(sbuf, sizeof sbuf, "cu%d", (int)BR); if ((i = hunt(sbuf)) == 0) { errx(3,"all ports busy"); } if (i == -1) { errx(3, "link down"); } setbuf(stdout, NULL); vinit(); switch (parity) { case -1: setparity("even"); break; case 1: setparity("odd"); break; case 0: setparity("none"); break; default: setparity("none"); break; } switch (flow) { case -1: if(nostop) { setboolean(value(TAND), FALSE); setboolean(value(HARDWAREFLOW), FALSE); } else { setboolean(value(TAND), TRUE); setboolean(value(HARDWAREFLOW), FALSE); } break; case 1: setboolean(value(TAND), FALSE); setboolean(value(HARDWAREFLOW), TRUE); break; case 0: default: setboolean(value(TAND), FALSE); setboolean(value(HARDWAREFLOW), FALSE); break; } setcharacter(value(ESCAPE), useresc); setboolean(value(VERBOSE), FALSE); if (HD) setboolean(value(LECHO), TRUE); if (HW) { if (ttysetup((speed_t)BR) != 0) { errx(3, "unsupported speed %ld", BR); } } if (tip_connect()) { errx(1, "Connect failed"); } if (!HW) { if (ttysetup((speed_t)BR) != 0) { errx(3, "unsupported speed %ld", BR); } } } static void cuusage(void) { (void)fprintf(stderr, "Usage: cu [options] [phone-number|\"dir\"]\n" "Use cu --help for help\n"); exit(8); } static void cuhelp(void) { (void)fprintf(stderr, "BSD tip/cu\n" "Usage: cu [options] [phone-number|\"dir\"]\n" " -E,--escape char: Use this escape character\n" " -F,--flow {hard,soft,none}: Use RTS/CTS, ^S/^Q, no flow control\n" " -f: Use no flow control\n" " --nostop: Do not use software flow control\n" " -a, -p,--port port: Use this port as ACU/Dialer\n" " -c,--phone number: Call this number\n" " -h,--halfduplex: Echo characters locally (use \"half duplex\")\n" " -e: Use even parity\n" " -o: Use odd parity\n" " -P,--parity {even,odd,none}: use even, odd, no parity\n" " -l,--line line: Use this device (ttyXX)\n" " -n: Disable escape character processing\n" " -s,--speed,--baud speed,-#: Use this speed\n" " -t: Connect via hard-wired connection\n"); exit(0); }