/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\. \ Ax-Talk / / A UNIX Shell script chat program \ \ / / by: Axon \ .\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/. It's always been said that nessecity is the mother of invention. Since hackers always seem to come up with crazy little programs, toys, tools, and other stuff like that, you'd think they often find themselves in a position of nessecity. I am no different. When I need something, and need it fast, I make it myself. As I sit here, I'm once again going to type a whole article on my palmtop, because my laptop is (again) down, but this time I'm prepared. My favorite computer bit the dust for the 5th time just a few weeks ago, and I'm sure that I'll once again resurrect it, it's just a matter of when. (for those of you that care, the processor isn't getting any juice. It's not like I FDISK'd my hard drive.) Since I am in the process of loading up my palmtop with toys so that it can almost take the place of my laptop, I found that one major problem exists: the lack of a good terminal program with TRUE VT-100 emulation, file transfer, and other things. Well I finally got a program with Xmodem (barf). Nothing with a good vt-100 though. The only thing I really need vt100 for is talk in unix. it screws up my palmtop screen even when the built-in term program "supports" vt emulation. On top of that, unix talk only allows 2 people to chat head to head, and sometimes I want to talk to more people than that at once. Sounds like a combo between nessecity, boredom, and desire. A very stimulating mixture of situations for a hacker. Enter: Ax-Talk. In 2 days, Ax-Talk went from a 5-minute "read and regurgitate to these terminals" shell script to an advanced, menu-ized, fairly powerful program (for a shell script at least). In its first stages, you had to type the full path to your chat-buddy's terminal (/dev/pts/xxx, or similar), and there wasn't even an exit command. You just ^C to get out. That's not very efficient. There were eventually 5 slots, so you can talk to 5 other people at once, and if you ended up not using all 5 slots, you wound up having to type "/dev/null" in each of them you didn't use. Let's face it, it sucked. The first things I really noticed that I hated in it was having to look up the terminal that you would want to send messages to, and associating that with a user. Along with that, having to type /dev/null 3 times... Also, Originally, you couldn't add or cut off any connections without quitting and restarting. yuck. I fixed the "quitting and restarting" mess first. You could eventually add or cut connections (still using /dev/...) while in the program. Then I found out that I could write a huge long line of code that could parse out a username and come up with what terminal they were on, and put the terminal path into a vaiable. This was a giant step. The /dev/null thing was easy to get rid of after all that. My baby was growing from 11 lines to 175 or more. Commands. I must have commands. I added some cool commands to it. The first, which proves to be most useful, is the .quit command. It's nice to be able to quit without having to break out of it. I then made a .clear command, to clear the screen. Clearing the screen is important, after all. I threw in a .action (chat actions), .exec (run a command from within ax- talk), and .help to show novices all the commands. This was in addition to the first command, .users, which allows you to change who gets your messages. It's now quite bulky, but it works. Thanks to arrays, I was able to shrink it down even more. In the earlier revisions, I was repeating a lot of code. I eventually brought back the option of using the terminal path, because Ax-Talk didn't like it when a person was logged on more than once. I eventually fixed that problem, too. If a person is logged on more than once, it informs you of this condition, then asks which terminal to use. I figured I would throw a copy of my script in here (since that was kind of the whole point of the article anyways). I'll warn you that the script does NOT conform to HiR article format rules. Several lines in it had to go over 78 characters, so don't miss them! Ax-Talk has become very large for being a simple shell script, but at the same time, it's also had the chance to be refined and is now extremely powerful, if you consider that it's nothing more than a bunch of UNIX shell commands strung together end-to-end. Woven into its rather complex web of commands lies the ability to modify it. It even has a config file. Note: I have yet to get this to work in linux. I only have AIX and linux to play with. Works good on AIX. If you can modify it to run under bash on your linux, send me the code at h_i_r@hotmail.com if you don't mess with unix or the korn shell (or still don't want to read the code), At least read the Revision history at the beginning. <---------------------------CUT HERE---------------------------------> #!/bin/ksh # Ax-Talk # Version 3.0 # # Written by Axon # # Ax-Talk History Timeline # # .01 First edition. Simply piped input to other terminal. # # .1 Added support to pipe input to 5 other terminals. # # 1.0 User-definable terminals; List of who is accepting # messages. # # 2.0 Major changes. All-day coding resulted in an inter- # active shell script that allowed the user to use the # name of the person instead of their terminal path. # added .users, .exec, .action, .help, and .quit # commands # # 2.1 Added support for most any unix platform by using an # rc file. Added comminication between actual ax-talk # clients so that if a user quit ax-talk, the script # will automatically remove them from the other # chatters' conference list. # # 2.2 Added support for original terminal path. Still # unable to fix the bug with multiple instances of # a username. The multiple instance username problem # won't show its ugly face if the users are # careful and type the terminal path instead of their # username. I'll work on trying to sense multiple # instances so that the script can warn the user, then # ask which terminal path to use. Maybe in a later rev. # In order to use multiple unix setups, I had to make a # second shell script for configuration purposes. # Configuration options are held under each user's home # directory in .ax-talk.rc. Communication between Ax- # Talk programs takes place by a world readable file # called .ax-talk-status under each user's home dir... # # 2.3 Made the script manually check for the configuration # file. I scrubbed the configuration script, and put # the code in the main script so it will run automatic- # ally if the config file is not found. # # 2.31 Added --config command line switch to change config # info. Not extremely useful yet, but maybe when there # is more meat to the config. # # 2.311 Just a test phase. took out tons of code and made # attempts to use arrays to save code space. This may # eventually mean a nearly infinite amount of people # can chat on the same system. (up to 1025?) # # 2.4 Full array architecture. Now you can define how many # users, not just limited to 5. This is changed with # the --config command line switch. Note, Ax-Talk 2.4 # is no longer compatable with 2.311 and earlier, due to # an added field in .ax-talk.rc. # # 2.5 Additional feature. When entering usernames, if a # period (.) is entered, the script automatically fills # in the rest of the user slots with ".". This will # dramatically speed up the time to enter Ax-Talk. # Tons of bugs to work out. The array structure makes # this feature queasy. # # 2.8 I'm practically ready to let this thing out to the # public, which I'm planning on doing with version 3. # This is kind of a "bug run", because i've fixed most # of the annoying things that I've seen. I also # added the ability to look at the source. I'm really # happy with it right now, but there still could be a # plethora of releases between 2.8 and 3.0 if I have # any last-minute feature additions to toss in. # # 2.81 A new command, .adduser was created. This allows # people who set a ridiculously low number of maximum # chatters to redeem themselves. It temporarily ups # the number of max chatters (for the current session # only), and asks for a username or terminal path. # # 3.0 Finally added the great stuff. Senses if the user # is logged in more than once. Flawless. #######################[RELEASE NOTES]########################## # Some unixes do not like \n in the echo lines. This is # # true in slackware linux, and possibly many others. it's # # not the case in most of the unixes i've tested this on, # # but it can be easily fixed by changing any echo lines that # # contain a \n to echo -n. If that doesn't work, i guess # # you could remove all the \n things out of all the echo lines # # that contain them. Substitute with echo "" # # # # This script uses the cut command quite often. On some # # REALLY archaic BSD-derived unixes, this does not exist. # # Honestly, they could be replaced with AWK, but awk commands # # would take up even more space. Feel free to convert to awk. # # # # This script has been tested to run on ksh, bash. sh (bsh) # # all ya gotta do is change the first line of the script that # # has #! /bin/sh to #! /bin/. # ################################################################ # # Variables used in Ax-Talk # # $config determines whether or not the config runs. 1 = active. # $start config: starting byte of the terminal field. # $nding config: Ending byte of the terminal field. # $maxterm Maximum desired terminals, plus 1. Used for loops. # $maxtrm A "show" variable. Depicts actual number of maximum terms. # $termstart Starting byte of terminal field (Read from rc file.) # $termend Ending byte of terminal field (Read from rc file.) # $q Counter variable for loops/arrays. # $comand What the user types onto the chat line. # $actioncmd What the user types into the action line. # $shellcommand Read and executed with the .exec command. # $LOGNAME Unix standard environment variable that holds the username. # $blarf Temporary variable. Used for pauses. # $uzer Temporary Variable. Plays a role in determining length # of a cell in Array $User[x] # # Arrays used in Ax-Talk # # $user[x] Usernames of selected people to chat with. # $termpath[x] Terminal paths corresponding with usernames. # # # Check for nessecary files. If missing, run the install process. # if [[ ! -a ~/.ax-talk.rc ]] then config=1 fi if [ $1 = "--config" ] then config=1 fi if [ $config = 1 ] then start=13 # nding=18 # Defaults. These work on AIX 4.2 maxtrm=5 # clear echo "Welcome to Ax-Talk, an interactive shell-script-based unix chat program!" echo "It looks like you haven't fully installed Ax-Talk yet, or you" echo "have decided to change your ax-talk configuration." echo "" echo "If this is the first time you've run Ax-Talk, you should choose #1" echo "" echo "1) Configure both terminal fields and maximum # of chatters (recommended)." echo "2) Configure terminal fields." echo "3) Configure maximum # of chatters." read confchoice case $confchoice in 1 ) echo "" echo "Look for where the third field is on the chart below. The field should" echo "read something like 'pts/4' or 'tty1'. You will be asked where this" echo "field starts and ends. We recommend adding 1 to the end of the field" echo "for instance if the field ended on number 19, type 20. it won't hurt." echo "the numbers for each column are read from top to bottom. look closely" echo "at the ledger above the list of people on the system." echo "" echo " 111111111122222222223333333333" echo "123456789012345678901234567890123456789" who -w echo "Terminal field start:" read start echo "Terminal Field end:" read nding echo echo "Maximum number of chatters at once: Recommend 5" read maxtrm maxterm=$(( 1 + $maxtrm )) echo "$start:$nding:$maxterm" > ~/.ax-talk.rc echo "0" > ~/.ax-talk-status echo "Ax-Talk Has been configured" echo "Press to start Ax-Talk!" ;; 2) echo "" echo "Look for where the third field is on the chart below. The field should" echo "read something like 'pts/4' or 'tty1'. You will be asked where this" echo "field starts and ends. We recommend adding 1 to the end of the field" echo "for instance if the field ended on number 19, type 20. it won't hurt." echo "the numbers for each column are read from top to bottom. look closely" echo "at the ledger above the list of people on the system." echo "" echo " 111111111122222222223333333333" echo "123456789012345678901234567890123456789" who -w echo "Terminal field start:" read start echo "Terminal Field end:" read nding echo ;; 3) echo "Maximum number of chatters at once: Recommend 5" read maxtrm maxterm=$(( 1 + $maxtrm )) echo "$start:$nding:$maxterm" > ~/.ax-talk.rc echo "0" > ~/.ax-talk-status ;; esac fi # # Initialize # echo "1" > ~/.ax-talk-status #tells the other Ax-Talks that we're alive. chmod 655 ~/.ax-talk-status #make sure other Ax-Talks can read the file. termstart=$(cat ~/.ax-talk.rc | cut -f1 -d':') #\ termend=$(cat ~/.ax-talk.rc | cut -f2 -d':') # > Reads the 3 fields out maxterm=$(cat ~/.ax-talk.rc | cut -f3 -d':') #/ of the config file. maxtrm=$(( maxterm-1 )) maxtermlen=$(( 7 )) # # Introduction and get usernames # clear echo "Welcome To Ax-Talk, a Shell Script Based Chat Program" echo "Version 3.0 -- By Axon Axon@compfind.com" echo "" echo "Please take time to look at the comments in the source code." echo "" echo "Enter $maxtrm usernames of the users you wish to chat with" echo "and hit enter after each name. If you don't need all" echo "$maxtrm, enter a period (.)" echo "If the person you wish to talk with is logged on more than once," echo "you will be asked what terminal you wish to talk with. If you" echo "would rather use the terminal path rather than the username, type a" echo "colon (:) followed by their terminal path (which is shown in the" echo "list below.)" echo "Examples:" echo ":pts/5" echo ":ttyp3" echo ":ttyS1" echo ":tty8" echo "" echo "Users Who Are Accepting Messages:" who -w | grep "+" echo "" # # Get usernames or terminal paths. Convert usernames<-->Terminal Paths # q=$(( 1 )) while [ $q != $maxterm ] do echo "User $q" read user[$q] termpath[$q]="$(who -w | grep "+" | grep ${user[$q]} | cut -b$termstart-$termend | cut -f1 -d' ')" if [ $(echo ${user[$q]} | cut -b1) = ":" ] then termpath[$q]="$(echo ${user[$q]} | cut -b2-)" user[$q]="$(who -w | grep "+" | grep ${termpath[$q]} | cut -b-8 | cut -f1 -d' ')" fi uzer=${user[$q]} if [ ${#uzer} = 1 ] then while [ $q != $maxterm ] do user[$q]="." termpath[$q]="null" q=$(( 1+$q )) done q=$(( $maxtrm )) fi trmpath=${termpath[$q]} termlen=$(( ${#trmpath} )) # # Added in Ver 3.0. Code to sense if a person is logged on more than once. # if [ $termlen -gt $maxtermlen ] then echo "The user you have selected may be logged into the server" echo "more than once. Please select a terminal from the following" echo "list. Type the name of the terminal. (I.E. pts/5 ttyp1 etc)." echo who -w | grep "+" | grep ${user[$q]} echo "" echo "Terminal Path:" read termpath[$q] # # Code to make sure that the terminal they chose is associated with the # user they originally asked for. # blarf=$(who -w | grep ${termpath[$q]} | cut -b1-8 | cut -f1 -d' ') if [ $blarf != ${user[$q]} ] then echo "An error occured while checking the terminal." echo "You May be able to try again by typing .users" echo "After you have entered chat." user[$q]="." termpath[$q]="null" fi fi q=$(( 1+$q )) done q=$(( 1 )) while [ $q != $maxterm ] do echo "\n$LOGNAME is connected to you for an Ax-Talk\n" > /dev/${termpath[$q]} q=$(( 1+q )) done clear echo "Chat Connection Message sent. To be courteous, please wait to" echo "receive chat connection message from other party, before trans-" echo "mitting anything." echo "" echo "Type .action to perform an action message." echo "Type .exec to run a single shell command without exiting Ax-Talk." echo "Type .quit to end Ax-Talk Session." echo "Type .clear to clear your screen during chat." echo "Type .users to modify which users the messages go to." echo "Type .adduser to temporarily add one more user to your Ax-Talk" echo " session if all of your slots are filled." echo "Type .help to see this list of commands and other help messages." echo "Type .source to examine the script code for Ax-Talk." echo "" while [ 1=1 ] # Begins the main loop of the program do # read comand case $comand in .adduser ) #Adds users to chat list. See Revision Notes. clear maxtrm=$(( 1 + $maxtrm )) maxterm=$(( 1 + $maxterm )) q=$(( $maxtrm )) echo "Enter username of the user you wish to chat with, and hit " echo "If the person you wish to talk with is logged on more than once," echo "you will be asked what terminal you wish to talk with. If you want" echo "to use the terminal path instead of the username, type a colon (:)" echo "followed by their terminal path (which is shown in the list below.)" echo "Examples:" echo ":pts/5" echo ":ttyp3" echo ":ttyS1" echo ":tty8" echo "" echo "Users Who Are Accepting Messages:" who -w | grep "+" echo "" read user[$q] termpath[$q]="$(who -w | grep "+" | grep ${user[$q]} | cut -b$termstart-$termend | cut -f1 -d' ')" if [ $(echo ${user[$q]} | cut -b1) = ":" ] then termpath[$q]="$(echo ${user[$q]} | cut -b2-)" user[$q]="$(who -w | grep "+" | grep ${termpath[$q]} | cut -b-8 | cut -f1 -d' ')" fi uzer=${user[$q]} if [ ${#uzer} = 1 ] then user[$q]="." termpath[$q]="null" fi trmpath=${termpath[$q]} termlen=$(( ${#trmpath} )) # # Added in Ver 3.0. Code to sense if a person is logged on more than once. # if [ $termlen -gt $maxtermlen ] then echo "The user you have selected may be logged into the server" echo "more than once. Please select a terminal from the following" echo "list. Type the name of the terminal. (I.E. pts/5 ttyp1 etc)." echo who -w | grep "+" | grep ${user[$q]} echo "" echo "Terminal Path:" read termpath[$q] # # Code to make sure that the terminal they chose is associated with the # user they originally asked for. # blarf=$(who -w | grep ${termpath[$q]} | cut -b1-8 | cut -f1 -d' ') if [ $blarf != ${user[$q]} ] then echo "An error occured while checking the terminal." echo "You May be able to try again by typing .users" echo "After you have entered chat." user[$q]="." termpath[$q]="null" fi fi clear echo "Extra user (${user[$q]})was successfully added." echo "Back to chatting..." ;; .source ) # View the source code and comments...woo! clear echo "This is the script source for Ax-Talk. Hit at any time to" echo "quit viewing the source. Hit to scroll down." echo "Press Now to start viewing source." read blarf cat ax-talk | more echo "Press to continue chatting" read blarf ;; .action ) echo "-->The next line you type will show up as an action." read actioncmd echo "-->$LOGNAME $actioncmd" q=$(( 1 )) while [ $q != $maxterm ] do echo "$LOGNAME $actioncmd" > /dev/${termpath[$q]} q=$(( 1 + $q )) done echo " " ;; .help ) # Show users the commands and general help stuff. echo "" echo "Type .action to perform an action message." echo "Type .exec to run a single shell command without quitting Ax-Talk." echo "Type .quit to end Ax-Talk Session." echo "Type .clear to clear your screen during chat." echo "Type .users to modify which users the messages go to." echo "Type .adduser to temporarily add another user to your Ax-Talk session" echo " if all your slots are filled. " echo "Type .help to see this list of commands and other help messages." echo "" echo " .action When you type .action, you are prompted for an" echo " action message. This message is not much different than a normal" echo " message, other than the fact that it shows up to the users without" echo " the colon. Example: if you typed 'is waving to everyone!' at the" echo " action message prompt, it would show up like this:" echo " $LOGNAME is waving to everyone!" echo " " echo " .exec When you type .exec, you are prompted for a shell" echo " command. Typical uses are for 'who', 'finger', and 'w', although" echo " this works for many other commands. This is an advanced feature." ;; .exec ) # Execute a command without quitting or suspending Ax-Talk echo "-->Enter a shell command to execute." read shellcommand $shellcommand echo "Back to chatting..." ;; .clear ) # Clears your screen so no one can see that you're chatting. clear ;; .users ) # View and edit what users are in your conference list. clear who -w | grep "+" echo echo "User Assignments" echo q=$(( 1 )) while [ $q != $maxterm ] do echo "User $q: ${user[$q]}" q=$(( 1 + $q )) done echo echo "Edit which user? 1 - $maxtrm, RETURN for no change." read q while [ $q != "3210" ] do echo "Enter username for User $q. If you are cutting User$q out of the conference," echo "place a period '.' Optionaly, you can place a colon ':' followed by" echo "their terminal path. You must use this method if they are logged on" echo "more than once." read user[$q] termpath[$q]="$(who -w | grep "+" | grep ${user[$q]} | cut -b$termstart-$termend | cut -f1 -d' ')" if [ $(echo ${user[$q]}| cut -b1) = ":" ] then termpath[$q]="$(echo ${user[$q]} | cut -b2-)" user[$q]="$(who -w | grep "+" | grep ${termpath[$q]} | cut -b-8 | cut -f1 -d' ')" fi uzer=${user[$q]} if [ ${#uzer} = 1 ] then termpath[$q]="null" fi echo "user $q changed." q=$(( 3210 )) done clear echo "Back to chatting..." ;; .quit) # Quits Ax-Talk break ;; *) # Communicates with other Ax-Talks, and sends your chat # message out. q=$(( 1 )) while [ $q != $maxterm ] do uzer=${user[$q]} if [ ${#uzer} != 1 ] then if [ $(cat ~${user[$q]}/.ax-talk-status | cut -f1 -d' ') = "0" ] then user[$q]="." termpath[$q]="null" fi fi q=$(( 1+$q )) done q=$(( 1 )) while [ $q != $maxterm ] do echo "\n$LOGNAME: $comand" > /dev/${termpath[$q]} q=$(( 1+$q )) done ;; esac done # End of main program loop. echo "0" > ~/.ax-talk-status # Tells other Ax-Talks that you've quit. q=$(( 1 )) while [ $q != $maxterm ] # Oh, yah. The actual people might do # want to know you quit, too... echo "\n$LOGNAME: has closed Ax-Talk." > /dev/${termpath[$q]} q=$(( 1+$q )) done echo "Closing Ax-Talk." <-------------------------CUT HERE(END)------------------------------>