/* * Command processor, command table, and a lot of commands * Sometimes a command only exists to exercise a particular * subroutine. To aid in distinguishing, all command names * begin with Z. */ #include "stdio.h" #include "signal.h" #include "errno.h" #ifdef BBN_VAX_UNIX # define VFORK vfork # define VEXIT _exit #endif #ifndef BBN_VAX_UNIX # define VFORK fork # define VEXIT exit #endif #include "tnio.h" #include "telnet.h" #ifdef NCP #include "ncpopen.h" #endif #include "globdefs.h" #include "ttyctl.h" #ifdef TCP #include "netlib.h" #include "con.h" #endif TCP extern int termfd; extern int errno; struct ComEntry { char *ComName; int (*ComFunc)(); int ComInt; char *ComStr; }; /* * Each ComEntry is called with four arguments. Normally, they are: * * A parameter: either an integer or a character string. The structure * must have both because there is no way to statically initialize a * union. It is assumed that the command takes a character string * if ComStr is non-NULL; if it is NULL, the ComInt is supplied * instead. * * The number of arguments that appeared on the command line -- as with * UNIX main programs, this is at least 1; * A pointer to an array of pointers to arguments, as with UNIX main programs. * * Each function may also be called upon to explain what it does. In this call, * the second argument will be 0 and the third argument will be the name * of the entry. * The command table itself is at the end of the program to avoid the need * to declare all the entries. */ /* -------------------------- C A L L C M D ------------------------- */ /* * Splits the line up into words separated by tabs or blanks. Looks up * the first word on the line in the command table (above), and calls the * indicated function as explained above. If the word is not found, it is * an error. */ callcmd(line) char *line; { register char *linep, *eol; int linelen; char **argp; struct ComEntry *comp; int outside_arg; static char *arglst[100]; extern struct ComEntry ComTab[]; extern struct ComEntry * getcom(); linelen = strlen(line); eol = &line[linelen-1]; /* Point to end */ /* Clear MSB of each byte, in case binary mode is on. */ for (linep = line; linep <= eol; linep++) *linep &= 0177; /* Make arg array point to beginning of each argument. */ /* Null-terminate it. */ argp = arglst; outside_arg = 1; for (linep = line; linep <= eol; linep++) switch(*linep) { case ' ': case '\t': outside_arg++; *linep = 0; break; default: if(outside_arg) { *argp++ = linep; outside_arg = 0; } break; } /* Execute it */ if (argp >= &arglst[sizeof(arglst) - 1]) fprintf(stderr, "con: too many args. Max is %d.\r\n", sizeof(arglst) / sizeof(arglst[0])); else if (argp > arglst) /* At least a command name */ { *argp = 0; /* To indicate last arg */ if ((comp = getcom(arglst[0], ComTab))) { arglst[0] = comp->ComName; /* Give full name */ if (comp->ComStr != NULL) (*(comp->ComFunc))(comp->ComStr, argp - arglst, arglst); else (*(comp->ComFunc))(comp->ComInt, argp - arglst, arglst); } else cmderr(0, "Unrecognized command: %s\n", arglst[0]); } } /* -------------------------- G E T C O M --------------------------- */ /* * getcom(strp, comtab) takes a pointer to a command name and looks it up * in comtab, returning a pointer to its entry there. */ struct ComEntry *getcom(strp, comtabp) char *strp; struct ComEntry comtabp[]; { struct ComEntry *cp; /* pointer to com table entry */ struct ComEntry *candidate; /* ptr to candidate command */ register int nmatch; /* num chrs matched on this try */ register int bestmatch; /* best match found yet */ if (strp == 0) return(0); /* can't match null string */ candidate = 0; bestmatch = 0; for (cp = comtabp; cp->ComFunc; cp++) /* linear srch */ { if((nmatch = compar(strp, cp->ComName)) != 0) if (nmatch == -1) return(cp); /* take exact match */ else if (nmatch > bestmatch) { candidate = cp; bestmatch = nmatch; } else { /* had two candidates that matched same */ fprintf(stderr, "Not unique\r\n"); return(0); } } return(candidate); } /* -------------------------- C O M P A R --------------------------- */ /* * compar(s1, s2) compares s1 against s2. Returns -1 if they are equal. * Otherwise, if s1 is a prefix of s2, returns # chars in common. * Otherwise returns 0. */ compar(s1, s2) char *s1; char *s2; { register char *sp1 ,*sp2; sp1 = s1; sp2 = s2; while (*sp1++ == *sp2++) if (*(sp1-1) == 0) return(-1); /* Exact match */ /* Strings differ. If first one ran out, return # chars matched. */ if (*(sp1-1) == 0) return(sp1-s1-1); /* Not a match at all... */ return(0); } /* -------------------------- Z N E T O P E N ----------------------- */ /* * Open a TELNET connection. Set NetConP to the connection pointer if * successful. */ znetopen(arg, argc, argv) int arg; int argc; char * argv[]; { NETCONN * connp = NULL; TTYMODE *modec = NULL; TTYMODE *modep = NULL; struct tchars *tp; int fd; #ifdef NCP struct ncpopen ncpopen; #endif #ifdef TCP struct con tcpopen; #endif extern int debug; extern int needprompt; extern NETCONN * NetConP; extern TTYMODE *NetModeP; extern NETCONN * telopen(); extern NETCONN * telinit(); extern TTYMODE * AllocMode(); extern int telfd(); extern int sendint(); extern int from_net(); extern int net2user(); extern myecf(), myelf(), myaof(), mybreakf(), mygaf(), mysynchf(); if (setexit()) { if (modep != NULL) FreeMode(modep); if (connp != NULL) telfinish(connp); return; } if (argc == 0) { fprintf(stderr, "Open a connection to the specified host.\r\n"); return; } if (NetConP != NULL) rcmderr(0, "Connection already open.\n"); if (ArgFlag("-debug", argv)) debug = 1; argc = ArgCount(argv); fprintf(stderr, "Trying...\r\n"); # ifdef NCP argparse(argc, argv, &ncpopen); fd = open("/dev/net/ncp", &ncpopen); if (debug) { printf(" Host is 0x%X:", ncpopen.o_host); printf("\nNCP structure:\n o_op = %d\n o_type = 0%o\n", ncpopen.o__op, ncpopen.o__type); printf(" o__id = %d\n o_lskt = 0%o\n o_fskt = 0%O\n", ncpopen.o__id, ncpopen.o_lskt, ncpopen.o_fskt); printf(" o__ohost = %d\n o_bysize = %d\n o_nmal = %d\n", ncpopen.o__frnhost, ncpopen.o_bsize, ncpopen.o_nomall); printf(" o__timo = %d\n o_relid = %d\n o_host = 0%O\n", ncpopen.o_timeo, ncpopen.o_relid, ncpopen.o_host); } # endif NCP # ifdef TCP argparse(argc, argv, &tcpopen); if ((fd = open("/dev/net/tcp",&tcpopen)) >= 0) ioctl(fd, NETSETE, NULL); /* urgent assumed off, eols on. */ # endif TCP if (fd == -1) rcmderr(-1, "Cannot connect to foreign host.\r\n"); fprintf(stderr, "Open\r\n"); connp = telinit(fd); if (connp == NULL) rcmderr(-1, "Cannot get connection block.\n"); modec = AllocMode(); if (modec == NULL) rcmderr(-1, "Cannot get mode block.\n"); NetConP = connp; NetModeP = modec; ChgMode(modec); SetFlags(modec, CRMOD, 0); modep = AllocMode(); tp = &(modep->tm_tchars); tp->t_brkc = '\r'; modep->tm_local = modec->tm_local&(~LCTLECH); ChgMode(modep); if (debug) { extern int verbose; telfunc(connp, EC, myecf); telfunc(connp, EL, myelf); telfunc(connp, AO, myaof); telfunc(connp, BREAK, mybreakf); telfunc(connp, GA, mygaf); telfunc(connp, SYNCH, mysynchf); verbose = 1; } #ifdef AWAIT IoEnter(telfd(connp), from_net, 0, connp); IoxEnter(net2user, connp); #endif #ifndef AWAIT { extern int other_pid; extern int par_uid; other_pid = fork(); if (other_pid == 0) { signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); other_pid = par_uid; from_net(1, connp); /* Does not return */ abort(); /* If it returns, I want to know why */ } } #endif needprompt = 0; signal(SIGINT, sendint); } /* -------------------------- A R G P A R S E ----------------------- */ /* * Parse open command arguments. Put result in ncpopen structure. */ argparse(argc, argv, op) int argc; char * argv[]; # ifdef NCP register struct ncpopen * op; # endif NCP # ifdef TCP register struct con * op; # endif TCP { extern int debug; int host_arg_index; int i; extern int fsocket; char *logfile; extern int telwtlog, telrdlog; extern int ArgInt(), ArgFlag(), ArgCount(); extern long ArgLong(); extern char * ArgStr(); if (argc == 1) rcmderr(0, "Usage: %s [-ls #] [-fs #] [-t #] [-server] [-direct] [-init] [-specific] [host]\n", argv[0]); /* Defaults */ #ifdef NCP op->o_type = 0; op->o_nomall = 0; op->o_host = 0L; if (ArgFlag("-server", argv)) { op->o_type |= SERVER; op->o_lskt = SERVER_SOCKET; } op->o_lskt = ArgInt("-ls", 0, argv); op->o_fskt = ArgLong("-fs", (long)fsocket, argv); op->o_timeo = ArgInt("-t", 0, argv); op->o_relid = ArgInt("-fd", 0, argv); /* Useless right now */ logfile = ArgStr("-log", NULL, argv); if (logfile) { telrdlog = telwtlog = creat(logfile, fmodes(logfile)); if (telrdlog == -1) cmderr(-1, "Log file \"%s\" cannot be created.\n", logfile); } if (ArgFlag("-direct", argv)) op->o_type |= DIRECT; if (ArgFlag("-init", argv)) op->o_type |= INIT; if (ArgFlag("-specific", argv)) op->o_type |= SPECIFIC; if (ArgFlag("-duplex", argv)) op->o_type |= DUPLEX; if (ArgFlag("-relative", argv)) /* Useless right now */ op->o_type |= RELATIVE; #endif NCP #ifdef TCP op->c_mode = CONTCP | CONACT | ((debug)?CONDEBUG:0); op->c_sbufs = op->c_rbufs = 2; op->c_lo = op->c_hi = 0; if (ArgFlag("-server", argv)) { op->c_mode &= ~CONACT; op->c_lport = SERVER_SOCKET; op->c_rbufs = 1; } else op->c_sbufs = 1; op->c_lport = ArgInt("-lp", 0, argv); op->c_fport = ArgInt("-fp", fsocket, argv); op->c_timeo = ArgInt("-t", 30, argv); logfile = ArgStr("-log", NULL, argv); if (logfile) { telrdlog = telwtlog = creat(logfile, fmodes(logfile)); if (telrdlog == -1) cmderr(-1, "Log file \"%s\" cannot be created.\n", logfile); } /* if (ArgFlag("-direct", argv)) /* what is all this stuff anyway??? op->c_type |= DIRECT; if (ArgFlag("-init", argv)) op->c_type |= INIT; if (ArgFlag("-specific", argv)) op->c_type |= SPECIFIC; if (ArgFlag("-duplex", argv)) op->c_type |= DUPLEX;*/ /* if (ArgFlag("-relative", argv)) /* Useless right now */ /* op->c_type |= RELATIVE; */ #endif TCP argc = ArgCount(argv); host_arg_index = 0; for (i = 1; i < argc; i++) if (argv[i][0] == '-') rcmderr(0, "Unknown option: \"%s\".\n", argv[i]); else if (host_arg_index == 0) host_arg_index = i; else rcmderr(0, "Superfluous argument: \"%s\".\n", argv[i]); if (host_arg_index != 0) { # ifdef NCP op->o_host = gethost(argv[host_arg_index]); if (op->o_host == -1L) # endif # ifdef TCP op->c_fcon = gethost(argv[host_arg_index]); mkanyhost(op->c_lcon); if (isbadhost(op->c_fcon)) # endif rcmderr(0, "Unknown host specifier: \"%s\".\n", argv[host_arg_index]); } # ifdef NCP if (op->o_type == 0 && op->o_host == 0L) # endif NCP # ifdef TCP if (isanyhost(op->c_fcon)) # endif TCP rcmderr(0, "No host specified.\n"); return; } /* -------------------------- Z V E R B O S E ------------------------- */ /* * Turns the verbose flag on or off. */ zverbose(val, argc, argv) char val; int argc; char *argv[]; { extern int verbose; if (argc == 0) { if (val == 'v') fprintf(stderr, "Announce all subsequent option negotiation\r\n"); else fprintf(stderr, "Announce only important option negotiations (e.g. 'Remote echo')\r\n"); return; } else if (argc != 1) { fprintf(stderr, "I take no arguments\r\n"); return; } switch(val) { case 'v': verbose = 1; fprintf(stderr, "Verbose mode\r\n"); break; case 'b': verbose = 0; fprintf(stderr, "Brief mode\r\r\n"); break; default: fprintf(stderr, "vswitch(%c)?\r\n", val); break; } return; } /* -------------------------- Z S E N D C T L ----------------------- */ zsendctl(arg, argc, argv) int arg; int argc; char *argv[]; { extern NETCONN *NetConP; if (argc > 1) { fprintf(stderr, "I take no arguments\r\n"); return; } if (argc == 0) switch(arg) { case AO: fprintf(stderr, "Abort output (send an Abort-Output and Synch)\r\n"); return; case BREAK: fprintf(stderr, "Break; that is, send a Break and Synch\r\n"); return; case IP: fprintf(stderr, "Interrupt process (send IP and Synch)\r\n"); return; case AYT: fprintf(stderr, "Ask foreign host if it is still alive (send AYT)\r\n"); return; case EC: fprintf(stderr, "Erase last character (send EC)\r\n"); return; case EL: fprintf(stderr, "Erase to beginning of line (send EL)\r\n"); return; case SYNCH: fprintf(stderr, "Send a Synch\r\n"); return; case GA: fprintf(stderr, "Send a Go-Ahead\r\n"); return; } if (NetConP == 0) { fprintf(stderr, "No active connection\r\n"); return; } sendctl(NetConP, arg); } /* -------------------------- Z H E L P ----------------------------- */ zhelp(arg, argc, argv) int arg; int argc; char *argv[]; { int i; extern struct ComEntry ComTab[]; if (argc == 1) /* Give each command and have it show-and-tell */ { fprintf(stderr, "TELNET Commands\r\n"); fprintf(stderr, "Only enough of each command name to uniquely identify it need be typed.\r\n\n"); for (i = 0; ComTab[i].ComFunc; i++) { fprintf(stderr, "%-11s", ComTab[i].ComName); if (ComTab[i].ComStr != NULL) (*(ComTab[i].ComFunc))(ComTab[i].ComStr, 0, &ComTab[i].ComName); else (*(ComTab[i].ComFunc))(ComTab[i].ComInt, 0, &ComTab[i].ComName); } } else if (argc == 0) fprintf(stderr, "Briefly explain each command.\r\n"); else { fprintf(stderr, "Sorry, individual explanations not implemented yet\r\n"); fprintf(stderr, "Type 'help' for a list of all commands and their purposes\r\n"); } return; } /* -------------------------- Z S H E L L --------------------------- */ /* * Execute the rest of the line as a shell command. * If there were no arguments, invoke a subshell. */ zshell(arg, argc, argv) int arg; int argc; char *argv[]; { int (*oldint)(); int (*oldquit)(); int junk; register char *p; char *shellcmd; TTYMODE *oldmode; int subsh; extern int errno; extern int escape; extern int inputfd; extern TTYMODE *ChgMode(); extern TTYMODE *OrigMode(); extern char *getenv(); int (*signal())(); /* * The arguments to this command (argv[1] on) are joined back together * and fed to the shell. Joining back together is, of course, klugy... */ if (argc <= 0) fprintf(stderr, "Pass the rest of the line to the shell for execution\r\n"); else { if (argc == 1) subsh = 1; else subsh = 0; argc--; /* Now it equals the number of args */ for (p = argv[1]; --argc > 0;) /* Loop (argc minus 1) times */ { while(*++p) /* Get to the null... */ ; *p = ' '; /* Replace with blank */ } oldmode = ChgMode(OrigMode()); if ((shellcmd = getenv("SHELL")) == NULL) shellcmd = "/bin/sh"; switch(VFORK()) { case -1: fprintf(stderr, "No processes!\r\n"); break; case 0: oldint = signal(SIGINT, SIG_DFL); oldquit = signal(SIGQUIT, SIG_DFL); if (inputfd != 0) { close(0); dup(inputfd); } if (termfd != 1) { close(1); dup(termfd); } close(2); dup(1); if (subsh) execl(shellcmd, SHELL_0, 0); else execl(shellcmd, SHELL_0, "-c", argv[1], 0); cmderr(errno, "Attempting to execute %s", shellcmd); VEXIT(0); /* Child process */ default: oldint = signal(SIGINT, SIG_IGN); oldquit = signal(SIGQUIT, SIG_IGN); wait(&junk); signal(SIGINT, oldint); signal(SIGQUIT, oldquit); fprintf(stderr, "%c\n", escape); ChgMode(oldmode); break; } } } /* -------------------------- Z E X E C ----------------------------- */ /* * Invoke the command whose name is "arg". This direct execution * does not change the tty modes to "local". Hence any program * invoked by this command must put out "\r\n" to end each line, * rather than just "\n", so that if CRMOD has been cleared the command's * output will still print properly. (The change of "\n"s to "\r\n"s is * all that distinguishes /etc/nettty from /bin/stty.) */ zexec(arg, argc, argv) char *arg; int argc; char *argv[]; { int junk; extern int errno; extern char *errmsg(); extern int escape; if (argc == 0) fprintf(stderr, "Invoke the UNIX %s command\r\n", argv[0]); else { switch(VFORK()) { case -1: fprintf(stderr, "No processes!\r\n"); break; case 0: if (termfd != 1) { close(1); dup(termfd); } close(2); dup(1); execvp(arg, argv); cmderr(errno, "Cannot execute %s\r\n", arg); VEXIT(0); default: wait(&junk); fprintf(stderr, "%c\r\n", escape); break; } } } /* -------------------------- Z N E T C L O S E --------------------- */ /* * Close a network connection. */ znetclose(arg, argc, argv) int arg; int argc; char *argv[]; { extern NETCONN *NetConP; extern int udone; if (argc == 0) fprintf(stderr, "Close the current network connection\r\n"); else if (argc != 1) fprintf(stderr, "%s takes no arguments\r\n", argv[0]); else if (NetConP == 0) /* Connection we're supposed to close doesn't exist */ return; else udone++; } /* -------------------------- Z S E N D O P T ----------------------- */ /* * Start the negotiation process for the requested option. */ zsendopt(arg, argc, argv) int arg; int argc; char *argv[]; { int optno; extern NETCONN *NetConP; if (argc == 0) { fprintf(stderr, "Try to negotiate the specified option.\r\n"); return; } if (setexit()) return; if (argc != 2) { int i, nopts; fprintf(stderr, "Usage: %s option\r\n", argv[0]); fprintf(stderr, "Available options are:"); nopts = 0; for (i = 0; i < 255; i++) /* All possible option numbers */ { extern char *optname(); char * name = optname(i); if (name != NULL) { if (nopts % 3 == 0) fprintf(stderr, "\r\n\t "); fprintf(stderr, "%-20s", name); nopts++; } } fprintf(stderr, "\r\n"); return; } if (NetConP == NULL) { fprintf(stderr, "No active connection\r\n"); return; } optno = optnum(argv[1]); if (optno == -1) rcmderr(0, "\"%s\" ambiguous.\r\n", argv[1]); if (optno == -2) rcmderr(0, "\"%s\" not recognized.\r\n", argv[1]); if (sendopt(NetConP, arg, optno)) rcmderr(0, "Could not request option \"%s\".\r\n", argv[1]); return; } /* -------------------------- Z O P T I O N ------------------------- */ /* * Accept or refuse the given option. */ zoption(arg, argc, argv) int arg; /* 0 refuse, nonzero accept */ int argc; char * argv[]; { int optno; extern int optnum(), option(); if (argc == 0) { if (arg) fprintf(stderr, "Accept the specified option.\r\n"); else fprintf(stderr, "Refuse the specified option.\r\n"); return; } if (setexit()) return; if (argc == 2) { optno = optnum(argv[1]); if (optno == -2) rcmderr(0, "Option \"%s\" not recognized.\r\n", argv[1]); if (optno == -1) rcmderr(0, "Option \"%s\" ambiguous.\r\n", argv[1]); if (option(arg, optno)) rcmderr(0, "Cannot enter option.\r\n"); } else rcmderr(0, "Usage: %s option\r\n", argv[0]); return; } /* -------------------------- Z S E N D S U B ----------------------- */ /* * Send a subnegotiation. */ zsendsub(arg, argc, argv) int arg; int argc; char * argv[]; { int i; char buffer[64]; int optno; extern char * atoiv(); extern NETCONN * NetConP; if (argc == 0) { fprintf(stderr, "Send the specified subnegotiation sequence.\n"); return; } if (argc == 1) { fprintf(stderr, "Usage: %s optnum [ byte ] ...\n", argv[0]); return; } if (setexit()) return; optno = optnum(argv[1]); if (optno == -1) rcmderr(0, "\"%s\" ambiguous.\r\n", argv[1]); if (optno == -2) rcmderr(0, "\"%s\" not recognized.\r\n", argv[1]); for (i = 2; i < argc; i++) { int value; if (*atoiv(argv[i], &value) != '\0') rcmderr(0, "\"%s\" is not numeric.\r\n", argv[i]); buffer[i-2] = value; } sendsub(NetConP, optno, buffer, i-2); } /* -------------------------- Z E X I T ----------------------------- */ /* * Exit from telnet without waiting for connection to stabilize. */ zexit(arg, argc, argv) int arg; int argc; char * argv[]; { extern int xdone; if (argc == 0) { fprintf(stderr, "Exit from TELNET immediately.\r\n"); return; } xdone = 1; check_done(); } /* -------------------------- Z S E T ------------------------------- */ /* * Sets the variable to the character described. */ zset(arg, argc, argv) int arg; int argc; char *argv[]; { register char * ap; register int * charp; extern int escape; if (argc == 0) { fprintf(stderr, "Set special characters.\r\n"); return; } if (argc != 3) { fprintf(stderr, "Usage: %s <function> { <char> | off }\r\n", argv[0]); fprintf(stderr, " where <function> is currently only 'escape' ('esc')\r\n"); return; } ap = argv[1]; if ((strcmp(ap, "escape") == 0) || (strcmp(ap, "esc") == 0)) charp = &escape; else { fprintf(stderr, "No such function: \"%s\".\r\n", ap); return; } ap = argv[2]; if (ap[1] == '\0') *charp = ap[0] & 0377; else if (strcmp(ap, "off") == 0) *charp = -1; else { fprintf(stderr, "Sorry, only a literal character or 'off' may be specified.\r\n"); return; } } /* -------------------------- C O M T A B --------------------------- */ extern zinput(); struct ComEntry ComTab[] = { "help", zhelp, 0, NULL, "?", zhelp, 0, NULL, "verbose", zverbose, 'v', NULL, "brief", zverbose, 'b', NULL, "ip", zsendctl, IP, NULL, "ao", zsendctl, AO, NULL, "break", zsendctl, BREAK, NULL, "ec", zsendctl, EC, NULL, "el", zsendctl, EL, NULL, "ayt", zsendctl, AYT, NULL, "synch", zsendctl, SYNCH, NULL, "ga", zsendctl, GA, NULL, "stty", zexec, 0, "/bin/stty", #ifdef MODTTY "modtty", zexec, 0, "/bin/modtty", #endif MODTTY "set", zset, 0, NULL, "open", znetopen, 0, NULL, "connect", znetopen, 0, NULL, #ifdef AWAIT "do", zsendopt, TN_DO, NULL, "dont", zsendopt, TN_DONT,NULL, "will", zsendopt, TN_WILL,NULL, "wont", zsendopt, TN_WONT,NULL, "sub", zsendsub, 0, NULL, "accept", zoption, 1, NULL, "refuse", zoption, 0, NULL, #endif "close", znetclose, 0, NULL, /* Clean close */ "x", zshell, 0, NULL, "quit", zexit, 0, NULL, #ifdef NOT_YET_IMPLEMENTED "input", zinput, 0, NULL, #endif 0, 0, 0, NULL, }; /* -------------------------- A N N O U N C E ----------------------- */ /* * Announce being called with given argument. */ announce(arg) char * arg; { fprintf(stderr, "%s", arg); } /* -------------------------- M Y E C F ----------------------------- */ myecf() { announce("<EC>"); } /* -------------------------- M Y E L F ----------------------------- */ myelf() { announce("<EL>"); } /* -------------------------- M Y A O F ----------------------------- */ myaof() { announce("<AO>"); } /* -------------------------- M Y I P F ----------------------------- */ mygaf() { announce("<GA>"); } /* -------------------------- M Y B R E A K F ----------------------- */ mybreakf() { announce("<BREAK>"); } /* -------------------------- M Y S Y N C H ------------------------- */ mysynchf() { announce("<SYNCH>"); } /* ------------------------------------------------------------------ */