--- /dev/null
+Change log
+==========
+Changes to gcom
+===============
+Tues Jan 03 2006 Paul Hardwick
+ - Updated gcom for GT EDGE support and added many new built-in scripts
+ - Re-wrote the header file to make it easier to maintain
+ - Updated man-pages
+ - Put it under version control since this utility will now be maintained.
+ - http://peck.gotdns.com/svn/gcom
+
+Mon Jan 24 2005 Martin Gregorie
+ - changed option handler to avoid reporting a NULL option when no
+ arguments were supplied or when an invalid option was given.
+ - changed the help display to fit neatly on a 25 x 80 telnet or
+ ssh screen.
+ - created the man page from dcon and previous gcom documentation.
+ - created the COMPILING, CHANGELOG, MANIFEST and TODO files from
+ pre-existing documentation.
+
+October 2003 Paul Hardwick
+ 0 Minor changes to make dcon compile with current gcc without
+ errors or warnings.
+ 1 Added gcom.h which provides "built-in" scripts and a support
+ routine of specific use to (Option) gsm type modems.
+ 2 Modified script loading so that by default every script is
+ pre-pended with an internal "default" script that opens the
+ serial port correctly, checks if a PIN is required (prompting
+ the user if needed) then checks registration status and signal
+ strength. If you call the other built-in scripts then this
+ default is not executed.
+ 3 Added "-s" option to skip the internal default script. If this
+ option is used then the user must manually open the serial port
+ with the right baud rate.
+
+Changes to dcon, all done by Daniel.Chouinard
+---------------
+Wed Jan 1 15:32:04 EST 1997
+ - Made it case independent.
+ - Happy new year!
+ - Indexed labels, major speed improvement.
+
+Mon Dec 30 21:10:46 EST 1996 not distributed
+ - Fixed select() on comfd so that `pppd connect 'dcon script'` works again.
+
+
+Mon Dec 23 16:10:24 EST 1996 not distributed
+ 22 hour session!
+ - Added $right(), $left(), $dirname(), $basename(), $hex(), $hexu(), $oct(),
+ $script(), $tolower(), $toupper(), and verbose() functions.
+ - Added abort, flash, and dump commands.
+ - Fixed #!/usr/local/bin/dcon support.
+ - Fixed re-entrant getstring() bug.
+ - Normalized gettoken() and getstring()
+ - Used getopt() instead of if...else if...else if...
+ - Added 0xffff (hex), 07777 (octal), 0%1111 (binary) notations.
+ - Added [$]a0-z9 variable ranges and managed (Woohee!) to keep it
+ compatible with old syntax.
+ - Only allocate strings as needed.
+ - Much better error reporting and exit code handling.
+ - Pulled a groin muscle while sitting crooked. Go figure.
+ - Created makescript.
+ - Added automatic xterm call in ppp-ex.scr when in X.
+ - Doc: Contents, syntax, error reporting, added new functions, etc...
+
+Wed Dec 11 18:30:42 EST 1996
+ - Changed my E-mail address in doc.
+ - Added a fix to dogoto() so that the label gets printed in log
+ (less confusing to see if a goto or gosub in test executed or not.)
+ - Had lasagna for supper.
+
+Sometime a while ago before I moved (August 1996, I think)
+ - Ansified code and Makefile, contributed by John Gotts.
+ (You guys out there are such purists! :)
+
+Sat Jul 20 08:19:13 EDT 1996 V: 0.96
+ - Better error reporting.
+
+Fri Jul 19 22:29:37 EDT 1996
+ - Got a bug report from Glen Thigpen that dcon-0.91 reports "Token too long"
+ errors. Found that dcon didn't deal with non-terminated last lines
+ properly. Fixed.
+
+Mon Apr 29 21:38:04 EDT 1996 V: 0.95
+ - Got a bug report from J. Van Koll reporting that the included
+ ppp-ex.scr had two lines that were truncated. Modified ppp-ex.scr
+
+
--- /dev/null
+Building gcom
+=============
+Switch to the directory where files from gcom.tgz were unpacked. Run:
+
+ make all
+
+You can run gcom immediately if your datacard is plugged in and the
+USB devices used by it have the appropriate permissions.
+
+To install gcom, sigmon and their documentation, become root,
+make sure you're in the directory where gcom was compiled and run:
+
+ make install
+
+This will install gcom and sigmon in /usr/local/bin and their manpages
+in /usr/local/man/man1. If this doesn't match your installation or you
+want to install the executables and manpages somewhere else, simply
+edit the EXE and MAN macro definitions on lines 3 and 4 of Makefile.
+
+To remove the executables and manpages, become root, make sure you're
+in the directory where gcom was compiled and run:
+
+ make uninstall
+
+To tidy to after installing gcom, make sure you're logged in as the
+used who compiled gcom and in the directory where gcom was compiled.
+Then run:
+
+ make clean
+
+The example scripts included in the distribution are left in the
+build directory.
+
--- /dev/null
+#Set GPRS only mode
+set com 115200n81
+set senddelay 0.05
+waitquiet 1 0.2
+send "AT_OPSYS=0^m"
+print "Setting GPRS only mode\n"
+ get 2 "^m" $s
+ get 2 "^m" $s
+print $s
+
--- /dev/null
+The following files should have been installed when you unarchived
+the tarball. If your file set does not match this list then you
+have an invalidly tarball and should delete the files and obtain
+a valid download.
+
+CHANGELOG
+COMPILING
+gcom.1
+gcom.c
+gcom.h
+gpl.txt
+GPRS.txt
+Makefile
+MANIFEST
+operator
+sigmon
+sigmon.1
+TODO
+UMTS.txt
--- /dev/null
+#
+# Makefile - build and install the gmon package
+# Copyright (C) 2005 Martin Gregorie
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# martin@gregorie.org
+#
+# $Id$
+#
+LIB = -L/usr/local/lib
+INC = -I/usr/local/include
+EXE = /usr/local/bin
+MAN = /usr/share/man/man1
+CPROG = gcom
+SCRIPT = sigmon
+BIN = $(CPROG) $(SCRIPT)
+MANP = gcom.1 sigmon.1
+
+CFLAGS = -c
+LDFLAGS =
+
+all: $(BIN)
+
+install:
+ chmod a-w $(BIN)
+ chmod u+rw $(BIN)
+ chmod a+x $(BIN)
+ cp $(BIN) $(EXE)
+ chmod a-wx $(MANP)
+ chmod u+rw $(MANP)
+ chmod a+r $(MANP)
+ cp $(MANP) $(MAN)
+
+uninstall:
+ cd $(EXE); rm $(BIN)
+ cd $(MAN); rm $(MANP)
+
+clean:
+ rm *.o $(CPROG)
+
+
+gcom: gcom.o
+ cc gcom.o $(LDFLAGS) -o gcom
+
+gcom.o: gcom.c gcom.h
+ cc gcom.c $(CFLAGS)
+
--- /dev/null
+To Do
+=====
+Better error handling for built-in scripts. (non-existent at the moment)
+
+Old - unlikely to be addressed:
+Option: locking (uucp? What's the standard?) (Who cares?)
+
+Better testkey (Change stdin mode to raw, update input, system, exec & exit)
+
+getcomchar() (Get one byte from com so a dumb term could be written in a
+ script. Should be done only after testkey)
+
+Polling sucks. Could this be (major) changed to be interrupt-driven?
+(Do people still use non-16550s out there?)
+
+Error reporting doesn't display the line containing the error.
+
--- /dev/null
+#Set UMTS only mode
+set com 115200n81
+set senddelay 0.05
+waitquiet 1 0.2
+send "AT_OPSYS=1^m"
+print "Setting UMTS only mode\n"
+
--- /dev/null
+.\" Paul Hardwick
+.\" paul@peck.org.uk
+.TH gcom 1 "04 January, 2006"
+.LO 1
+.SH NAME
+gcom \- Option GlobeTrotter GPRS/EDGE/3G/HSDPA and Vodafone 3G/GPRS datacard control tool
+.SH SYNOPSIS
+.B gcom
+.RB \-d
+.I "device"
+.RB -ehstvx
+.I "script"
+.SH OPTIONS
+.in +5
+.B \-d
+.I device
+.in +10
+set the device to be used to communicate with the data-card.
+Defaults to
+.I /dev/modem
+.PP
+.in +5
+.B \-e
+.in +10
+turn on serial communications echo.
+.PP
+.in +5
+.B \-h
+.in +10
+display summary help and exit.
+.PP
+.in +5
+.B \-s
+.in +10
+don\'t run the internal
+.I default
+script before an external script.
+.PP
+.in +5
+.B \-t
+.in +10
+change to an alternate line terminator (default "\n").
+.PP
+.in +5
+.B \-v
+.in +10
+run in verbose mode. This traces scripts as they are executed.
+It is intended to help in debugging scripts.
+.PP
+.in +5
+.B \-x
+.in +10
+for internal and external scripts, any reference to 115200 baud is converted to 57600.
+This is useful for data cards that don't like 115200 baud such as the GlobeTrotter EDGE.
+.PP
+.in -10
+.SH DESCRIPTION
+.B gcom
+is a scripting language interpreter useful for establishing
+communications on serial lines and through PCMCIA modems
+as well as GPRS and 3G datacards.
+.PP
+.B gcom
+has some features that are rarely found in other utilities of the same type.
+.in 5
+.SS Features
+.nf
+- Pre-defined built-in scripts for 2G/3G datacard control
+- Simple, BASIC-like script language.
+- Command-line and file sourcing of script.
+- Multi-response waitfor.
+- waitquiet permits line stabilization.
+- In-line text capture.
+- Multi-process support: fork, wait, kill, exit.
+- Debugging verbose and log output.
+- logging to file.
+- Flow control: goto, gosub, return, if, else.
+- Low-impact on system resources.
+- Time commands and functions.
+- String manipulations.
+- Environment manipulation: env(), putenv.
+- External utilities system calls: system, exec.
+.PP
+.SS Supported GPRS and 3G datacards
+.B gcom
+has been tested against GlobeTrotter GPRS,EDGE, Combo EDGE, 3G, 3G EDGE, HSDPA
+and GlobeTrotter Fusion as well as Vodafone 3G.
+It can set the PIN and display information about datacards before a PPP
+connection is started.
+Additionally, because the GlobeTrotter and Vodafone 3G/GPRS datacard have
+a secondary serial interface, these datacards can be monitored while a PPP
+connection is in existence and transferring data.
+.PP
+.B gcom
+is primarily designed to work with the GlobeTrotter range of datacards but
+should be compatible with any other GPRS or 3G datacard provided its
+interface is implemented as one or more serial or USB serial devices
+and it is controlled and queried by an implementation of the Hayes
+command interface with the same AT command extensions used by the listed
+datacards.
+.
+.SS Using gcom
+.B gcom
+has only one function: to run a script. This may be one of a number
+of "standard" internal scripts or an external script. Both types of script are
+invoked in the same way. The "standard" scripts are built into
+.B gcom
+and will work for serially connected modems, built-in modems, PCMCIA modems
+as well as the GlobeTrotter GPRS and the Vodafone 3G/GPRS datacards.
+.PP
+.SS Built-in scripts
+
+.in -5
+.I gcom
+.in +5
+This runs the default internal script. Running
+.B gcom
+without any script specified, e.g.,
+.I gcom -d /dev/ttyS1
+it will check for a PIN and
+prompt you if it is required. The next thing it does is wait for the
+device to register, it then reports the signal strength.
+If you don\'t specify a port with the
+.B -d
+option then
+.I /dev/modem
+is assumed.
+If the -s switch is not used then this default script is run before any external script.
+
+.in -5
+.I gcom help
+.in +5
+Lists these and the other options available.
+.PP
+.in -5
+.I gcom info
+.in +5
+Lists the datacard configuration.
+
+.in -5
+.I gcom sig
+.in +5
+Prints the signal strength.
+
+.in -5
+.I gcom reg
+.in +5
+Prints the registration state.
+
+.in -5
+.I gcom 3G
+.in +5
+Puts a GlobeTrotter 3G/Fusion and Vodafone 3G into 3G network only
+mode (UMTS/HSDPA).
+
+.in -5
+.I gcom 2G
+.in +5
+Puts a GlobeTrotter 3G/Fusion and Vodafone 3G into 2G network only
+mode (GSM/GPRS/EDGE).
+
+.in -5
+.I gcom 3G2G
+.in +5
+Puts a GlobeTrotter 3G/Fusion and Vodafone 3G into 3G preferred
+mode (UMTS/HSDPA and GSM/GPRS/EDGE).
+
+.in -5
+.I gcom GTEDGE
+.in +5
+Use this command to initialise GlobeTrotter EDGE and GlobeTrotter
+Combo EDGE cards before doing anything else. (It switches on the radio).
+
+.in -5
+.I gcom USA
+.in +5
+Switch to 900/1900 MHz band for USA operation. GlobeTrotter GPRS datacards only.
+
+.in -5
+.I gcom EUROPE
+.in +5
+Switch to 900/1800 MHz band for European operation. GlobeTrotter GPRS datacards only.
+
+.PP
+.SS Custom Scripts
+
+As well as built in scripts you can make your own. The following
+script sets a Vodafone 3G datacard or Option Fusion card\'s UMTS mode to GPRS:
+.PP
+.in +5
+#Set GPRS only mode
+.br
+set com 115200n81
+.br
+set senddelay 0.05
+.br
+waitquiet 1 0.2
+.br
+send "AT_OPSYS=0^m"
+.br
+print "Setting GPRS only mode"
+.PP
+If you saved the above script as GPRS you would call it like this:
+.PP
+.in +5
+.I gcom GPRS
+.in -5
+.PP
+If you needed to specify the port as well then do this:
+.PP
+.in +5
+.I gcom -d /dev/ttyS1 GPRS
+.in -5
+.PP
+You can also pass environment parameters to a
+.B gcom
+script via
+.I $env().
+.
+
+.SS Replacing chat
+.B chat
+is a utility that comes with the ppp package (for Linux, anyway) that,
+with a set of expect-send string couples, does enough to connect most people
+to ISPs and such. While chat\'s use is very simple, it isn\'t very flexible.
+That\'s where
+.B gcom
+takes over.
+.PP
+.B gcom
+can be used in place of
+.B chat
+using the same strategy.
+For example, a pppd
+line reading:
+.PP
+.in +5
+.nf
+pppd connect \\
+ \'chat -v "" ATDT5551212 CONNECT "" ogin: ppp \\
+ word: whitewater\' \\
+ /dev/cua1 38400 debug crtscts modem defaultroute
+.fi
+.in -5
+.PP
+Would, using
+.B gcom,
+read:
+.PP
+.in +5
+.nf
+pppd connect \'gcom /root/scripts/isp.scr\' /dev/cua1 38400 \\
+ debug crtscts modem defaultroute
+.fi
+.in -5
+.PP
+And the isp.scr script would read:
+.PP
+.nf
+ send "ATDT5551212^m"
+ waitfor 60 "ogin:"
+ send "ppp^m"
+ waitfor 60 "word:"
+ send "whitewater^m"
+.fi
+.PP
+Of course it then becomes trivial to make this script a whole lot more
+functional by adding code for busy detect, re-dialing, etc...
+.
+.SS Verbose output
+
+When the verbose option is turned on,
+.B gcom
+reports everthing on
+the standard error channel.
+If turned on from the command line (-v), the output contains 4 sections.
+.PP
+- Command line argument actions
+.in +2
+These are actions taken because they were specified from the command
+line, such as opening a communication device (-d), etc...
+For these to be output, you must specify -v as the first argument.
+.in -2
+.PP
+- List of arguments
+.in +2
+The number and list of arguments passed. This is useful in case
+you have a bunch of environment variables or quotes, back-quotes,
+backslashes on the command line and you\'re not sure what the
+script really sees.
+.in -2
+.PP
+- Script list
+.in +2
+A list of the script to execute. This may be a concatenation of
+the default internal script, unless this is suppressed by the -s
+option, and a script file. Every line is listed with its
+line number and character position.
+.in -2
+.PP
+- Execution output
+.in +2
+List of commands as they are executed. The parser prints the
+line its currently on, starting from the exact point where its
+at to the end of the line. Multiple command groups on a single
+line produce multiple output lines. Verbose output may be mixed
+with script output (print, eprint or lprint.)
+.in -2
+.PP
+Here\'s an example:
+.PP
+.in +2
+.nf
+$ gcom -v -d/dev/cua1 -s blah.scr
+gcom 00:18:46 -> Verbose output enabled
+gcom 00:18:46 -> Script file: blah.scr
+gcom 00:18:46 -> argc:5
+gcom 00:18:46 -> argv[0]=gcom
+gcom 00:18:46 -> argv[1]=-v
+gcom 00:18:46 -> argv[2]=-d/dev/cua1
+gcom 00:18:46 -> argv[3]=-s
+gcom 00:18:46 -> argv[4]=blah.scr
+gcom 00:18:46 -> ---Script---
+.in +3
+1@0000 set com 38400n81 let a=2
+2@0025 print "9x",a,"=",9*a,"\\n"
+3@0051 sleep 5
+4@0059 exit 0
+.in -3
+gcom 00:18:46 -> ---End of script---
+gcom 00:18:46 -> @0000 set com 38400n81 let a=2
+gcom 00:18:46 -> @0017 let a=2
+gcom 00:18:46 -> @0025 print "9x",a,"=",9*a,"\\n"
+9x2=18
+gcom 00:18:46 -> @0051 sleep 5
+gcom 00:18:51 -> @0059 exit 0
+.in -2
+.fi
+.
+.SH Programming manual
+.SS Syntax
+The syntax used for
+.B gcom
+scripts is rather simple, somewhat BASIC-like.
+A script is a non-tokenized, pure ASCII text file containing lines terminated
+by newline characters (Unix standard.) Scripts can be created and/or modified
+using any standard text editor (vi, vim, joe, pico, emacs, ed, microEmacs)
+Lines in a
+.B gcom
+script read like so:
+.nf
+
+ - Empty line
+ - [indent]rem remark
+ - [indent][[:|label] LABEL] [command [arguments]] rem remark
+ - [indent][[:|label] LABEL] [command [arguments]] [command [arguments]]...
+.PP
+Characters used for indentation are the space and tabulation characters.
+The rem command makes the script parser skip the rest of the line.
+The rem command can also be written as "#" or "//".
+.PP
+Labels consist of lowercase and uppercase letters and digits.
+Case is ignored in labels.
+.PP
+Commands and their arguments are separated by spaces and/or tabs.
+Command groups are separated by spaces, tabs, or newlines.
+.PP
+Expressions must not contain spaces or tabs.
+.nf
+This is ok : let n=x+76
+This is not: let n= x + 76
+ Because this space ^ would terminate the let command group.
+.fi
+.
+.SS Error reporting
+
+When
+.B gcom
+detects a script error, it immediately turns on verbose mode,
+generates a dump (see the dump command), reports the error in three lines
+and stops the execution. The first line reported is the command group
+being executed, the second one shows where the parser got and the third
+line reports the character position of the program counter, the error and
+the exit code.
+
+Here\'s an example:
+.PP
+.in +5
+.nf
+$ gcom -vs blar2.scr
+.fi
+.in -5
+.PP
+Where the blar2.scr script is:
+.PP
+.nf
+.in +5
+inc n
+dec d3
+let a=58/3
+let $d="fod"
+let c=1/0
+let $y4="sdfgsdfgsdfg"
+.in -5
+.fi
+.PP
+The trace and error report looks like this:
+.PP
+.in +5
+.nf
+gcom 11:20:15 -> Verbose output enabled
+gcom 11:20:15 -> Script file: blar2.scr
+gcom 11:20:15 -> argc:3
+gcom 11:20:15 -> argv[0]=gcom
+gcom 11:20:15 -> argv[1]=-vs
+gcom 11:20:15 -> argv[2]=blar2.scr
+gcom 11:20:15 -> ---Script---
+.in +3
+1@0000 inc n
+2@0007 dec d3
+3@0015 let a=58/3
+4@0027 let $d="fod"
+5@0041 let c=1/0
+6@0052 let $y4="sdfgsdfgsdfg"
+.in -3
+gcom 11:20:15 -> ---End of script---
+gcom 11:20:15 -> @0000 inc n
+gcom 11:20:15 -> @0007 dec d3
+gcom 11:20:15 -> @0015 let a=58/3
+gcom 11:20:15 -> @0027 let $d="fod"
+gcom 11:20:15 -> @0041 let c=1/0
+gcom 11:20:15 -> -- Error Report --
+gcom 11:20:15 -> ----> ^
+gcom 11:20:15 -> Error @49, line 5, Division by zero. (6)
+.fi
+.in -5
+.
+.SS Exit codes
+When
+.B gcom
+terminates, it does so with an "exit code". That is a number passed
+back to the calling process to signify success or failures. In every-day
+Unix, 0 (zero) means success and everything else means whatever the author
+of the program wants it to mean. In a shell script, or directly on the command
+line, you may look at the content of
+.I $?
+after having called
+.B gcom
+to examine its exit code.
+.PP
+Example:
+.PP
+.in +5
+.nf
+#!/bin/sh
+gcom /root/bin/call-isp
+if [ $? != 0 ]; then
+ echo "Oops! Something went wrong."
+fi
+.fi
+.in -5
+.PP
+Internal
+.B gcom
+error codes are as follows:
+.PP
+.in +5
+.nf
+0 : No problems whatsoever. Apparently.
+1 : Communication device problems.
+2 : Console (tty) device problems.
+3 : Memory problems.
+4 : File or pipe problems.
+5 : Syntax errors.
+6 : Division by zero.
+7 : Variable mis-management.
+8 : System problems. (Couldn\'t call /bin/sh or some such)
+.fi
+.in -5
+.
+.SS Commands
+.PP
+.nf
+Command : : Alias: label
+Description : Notes an anchor point for goto or gosub to branch to.
+Syntax : Keyword must not contain any special characters.
+Note : Must be first statement in a line.
+See Also : goto, gosub, return.
+Example:
+ :loop
+ gosub bravo
+ print "The time is ",$time(),"\\n"
+ sleep 1
+ goto loop
+ label bravo
+ print "Twonk!\\n"
+ return
+
+Command : abort
+Description : Causes gcom to call abort() and produce a core dump.
+Syntax : abort
+See Also : dump, exit.
+
+
+Command : cd
+Description : Change directory.
+Syntax : cd directory
+Notes : -1 is returned in % if the change could not be made.
+Notes : directory is a string and thus could be a variable.
+See Also : $cwd().
+Example:
+ cd "duh"
+ if % != 0 print "Could not cd into duh.\\n"
+
+
+Command : close
+Description : closes file previously opened with open.
+Syntax : close file
+See Also : open.
+
+
+Command : dec
+Description : Decrements the content of an integer variable by 1.
+Syntax : dec x
+Notes : x is from a to z or a0 to z9.
+Notes : Note that "let x=x-1" also works.
+See Also : let, inc.
+
+
+Command : dump
+Description : Lists all non-zero integer variables and modified string
+Description : variables as log entries (standard error channel.)
+Syntax : dump
+See Also : abort, exit
+
+
+Command : else
+Description : Alternatively execute commands if last "if" tested false.
+Syntax : else commands...
+See Also : if
+Example:
+ if w<350 print "Wow! Imagine that.\\n"
+ else print "Rush Limbaugh is a big fat bastard.\\n"
+
+
+Command : eprint
+Description : print a comma-separated list of arguments on stderr.
+Syntax : eprint var,stringvar,"text",...
+Notes : Like print but on the standard error file descriptor.
+Notes : The error output can be re-directed with "2>file" on
+Notes : the command line.
+See Also : print.
+
+
+Command : exec
+Description : Replaces current gcom process with another process.
+Syntax : exec "command -args..."
+See Also : system, fork.
+Example:
+ #Finished script, call cu.
+ exec "cu -l "+$dev()+" -s "+$baud()
+
+
+Command : exit
+Description : terminates script execution with exit code.
+Syntax : exit exit_code
+See Also : abort, dump.
+Example:
+ :error
+ exit 1
+ :smeggit
+ exit 0
+
+
+Command : flash
+Description : Toggles DTR on communication device for a specified time.
+Syntax : flash float_constant
+Notes : float_constant is precise down to 1/100th sec.
+Notes : Causes modem to drop carrier or go to command mode,
+Notes : depending on modem settings. Setting the baud rate to 0
+Notes : for a time has the same effect.
+See Also : sleep, set com.
+Example:
+ :disconnect
+ flash 0.5
+ exit 0
+
+
+Command : fprint
+Description : print a comma-separated list of arguments in a file.
+Syntax : fprint var,stringvar,"text",...
+Notes : Like print but appended to a file previously opened
+Notes : by open.
+See Also : print.
+
+
+Command : fork
+Description : forks gcom process in two. Both processes continue
+Description : executing the script.
+Syntax : fork
+Notes : % returns 0 for child process, new process ID for
+Notes : parent or -1 for error.
+See Also : wait, kill, pid(), ppid().
+Example:
+ fork
+ if % = -1 goto error
+ if % = 0 goto child
+ :parent
+ ...
+
+Command : get
+Description : get string from communication device.
+Syntax : get timeout "terminators" $string
+Notes : timeout is a float constant, terminators is a
+Notes : list of characters that, when received, terminate
+Notes : get. Terminators are ignored when received first.
+See Also : waitfor.
+Example:
+ waitfor 60 "connect"
+ if % != 0 goto error
+ get 2 " ^m" $s
+ print "Connection parameters: ",$s,"\\n"
+
+
+Command : gosub
+Description : calls a subroutine.
+Syntax : gosub label
+Notes : Currently, gcom only supports 128 levels of gosub
+Notes : calls (enough!)
+See Also : :, goto, return.
+Example:
+ gosub routine
+ sleep 1
+ gosub routine
+ goto end
+ :routine
+ print "Flim-flam!\\n"
+ return
+
+
+Command : goto
+Description : Sends execution somewhere else in the script.
+Syntax : goto label
+See Also : :, gosub, return.
+Example:
+ :win95
+ print "Today I want to go and use Linux, thank you.\\n"
+ goto win95
+
+
+Command : hset
+Description : Set the hundreds timer.
+Syntax : hset value
+Notes : This command resets the hundreds of seconds timer to
+Notes : a value for htime to start from.
+See Also : htime().
+Example:
+ hset 0
+ :loop
+ print "Time in 1/100 of a sec.: ",htime(),"\\n"
+ sleep 0.01
+ goto loop
+
+
+Command : if
+Description : tests a condition
+Syntax : if test_condition commands...
+Notes : Conditionnaly executes commands if test condition is true.
+Notes : Test operators are = (equal), != (not equal),
+Notes : <> (not equal to) < (less than), > (greater than),
+Notes : <= (less or equal), >= (greater or equal).
+Notes : All operators can be used with integers and strings.
+Notes : If test_condition is false, if skips to
+Notes : the next line.
+See Also : else.
+Example:
+ if n>30 print "Oh-ho! too many sheep!\\n" goto error
+ if n=17 print "Hurray! we\'ve enough sheep\\n" goto party
+ if n<17 print "Murray, get more sheep.\\n" goto getmore
+ if $z < "Marmaluke" goto ...
+ if 3*a>5+b goto ...
+
+
+Command : inc
+Description : increments the content of an integer variable by 1.
+Syntax : inc x
+Notes : x is a-z or a0-z9.
+See Also : dec, let.
+
+
+Command : input
+Description : input string from keyboard into string variable.
+Syntax : input $x
+Notes : input terminates entry only with the ENTER key.
+Notes : Spaces, tabs and other funny characters are all
+Notes : stored in the variable.
+See Also : set echo.
+Example:
+ print "Enter your full name :"
+ input $n4
+
+
+Command : kill
+Description : Sends a signal to a process.
+Syntax : kill signal processID
+Notes : Both signal and processID are integer values. Same as
+Notes : standard unix kill except that signal aliases are not
+Notes : accepted and signal is not optional.
+Notes : 0 is returned in % if the signal could be sent, -1
+Notes : otherwise.
+Notes : Signal 0 can be used to detect process existance.
+See Also : wait, pid(), ppid().
+Example:
+ fork
+ let p=%
+ if p = 0 goto child
+ sleep 300
+ kill 15 p
+ sleep 1
+ kill 0 p
+ if % != 0 print "Child terminated\\n" goto ok
+ print "Could not terminate child!\\n"
+ kill 9 p
+ sleep 1
+ kill 0 p
+ if % = 0 print "Could not kill child!\\n" goto error
+ print "Child killed.\\n"
+ :ok
+ ...
+
+
+Command : let
+Description : Does a variable assignment.
+Syntax : let x=content
+Notes : x is [$]a0-z9.
+See Also : inc, dec.
+Example:
+ let a=5
+ let b=(time()-a)+5
+ let y7=6809
+ let z=0%11010111 #Binary
+ let z=077324 #octal
+ let z=0xf5b8 #hexadecimal
+ let $c="Daniel "
+ let $d=$c+" Chouinard"
+ let $s5="Frimpin\' Jeosaphat!"
+
+
+Command : lprint
+Description : Print a comma-separated list of arguments to the log.
+Syntax : fprint var,stringvar,"text",...
+Notes : Like print but printed like a log entry if verbose is on.
+Notes : logging is sent to stderr.
+See Also : print, eprint, fprint.
+
+
+Command : open
+Description : Opens a file or a communication device.
+Syntax : open com device, open com (stdin), open file FILE
+See Also : close.
+Example:
+ open com /dev/cua1
+ set com 38400n81
+ open file "/tmp/log"
+ fprintf "This is a log\\n"
+ close file
+
+
+Command : print
+Description : print a comma-separated list of arguments.
+Syntax : print var,stringvar,"text",...
+Notes : Spaces and newlines are not automatically added.
+See Also : eprint, fprint, lprint.
+Example:
+ let b=26
+ let $c="text variables"
+ print "Contstant text ",b," ",$c," time: ",$time(),"\\n"
+
+
+Command : putenv
+Description : Sets an environment variable.
+Syntax : putenv "var=content"
+Notes : Environment variables are automatically exported,
+Notes : never returned. Children processes inherit the
+Notes : environment.
+See Also : $env().
+Example:
+ putenv "SCRIPTDIR=/usr/lib/gcom/scripts"
+ system "dothat" # dothat reads env. var. SCRIPTDIR...
+
+
+Command : rem Aliases: #, //
+Description : Remark. Rest of line is ignored.
+Syntax : Note that a space must follow "rem".
+Example:
+ #This is a remark
+ // So is this
+ rem This ain\'t no disco.
+
+
+Command : return
+Description : Returns from subroutine.
+Syntax : return
+See Also : gosub.
+
+
+Command : send
+Description : sends a string to the communication line (modem usually).
+Syntax : send string
+Notes : Carriage return (ENTER) is not sent automatically
+Notes : (use ^m).
+Example:
+ send "atdt555-1212^m"
+ send $g+"^m"
+ send "The time is "+$time()+"^m^j"
+
+
+Command : set
+Description : sets working parameters.
+Syntax : set parameter value
+Notes :
+
+Command Description
+----------------------------- -------------------------------------------------
+set echo on|off Keyboard echo on-screen.
+set comecho on|off Received characters echoed on-screen.
+set senddelay time_constant In-between character delay for "send"
+set ignorecase on|off Case sensitivity for "waitfor".
+ Default=on.
+set clocal on|off clocal on = ignore modem signals
+set umask mode file mode creation defaults.
+ See man umask.
+set verbose on|off verbose on = debug output enabled.
+set com com_params communication parameters.
+ ex.: 19200n81, 300e71
+ baud |||
+ Parity |
+ Data bits |
+ Stop bits |
+
+Example:
+ set echo off
+ print "Password :"
+ input $p
+ print "\\n"
+ set echo on
+ set comecho on
+ set clocal on
+ set senddelay 0.1
+ set ignorecase on
+ set com 38400n81
+ set umask 022 # Must be octal (leading zero)
+ ...
+
+Note on clocal:
+ If want your script to keep working after the carrier detect
+ signal has dropped, set clocal on, otherwise, a CD drop causes
+ the device line to close (hang up). This could happen if,
+ let\'s say, your script calls and connects, then disconnects or
+ drops dtr (flash), then tries to re-connect again.
+
+
+Command : sleep
+Description : Pauses execution.
+Syntax : sleep float_constant
+Notes : Float_constant is precise down to 1/100th sec, unless
+Notes : more than 100 seconds, in which case the precision
+Notes : falls down to 1 sec.
+
+Example:
+ sleep 0.06
+ sleep 3
+ sleep 86400 /* A whole day */
+
+
+Command : system
+Description : Calls a system (unix) command
+Syntax : system "command"
+See Also : exec.
+Example:
+ :dir
+ print "listing of directory ",$cwd(),\\n"
+ system "ls -l |more"
+
+
+Command : testkey
+Description : Tests keyboard for keystroke, returns 1 in % if present.
+Syntax : testkey
+Notes : Can only test for ENTER key. Future versions of gcom
+Notes : will test for more and return keycodes in %.
+See Also : input.
+Example:
+ let n=1
+ :loop
+ print n," sheep... ZZZzzz...\\n"
+ sleep n
+ inc n
+ testkey
+ if % = 0 goto loop
+
+
+Command : wait
+Description : Wait for a child process to terminate.
+Syntax : wait
+Notes : Process ID of terminated child is returned in %
+See Also : fork, kill.
+Example:
+ fork
+ let p=%
+ if p=0 goto child
+ if p=-1 goto error
+ print "Waiting for child to finish..."
+ wait
+ print "\\n"
+ if %!=p print "Wait got wrong PID!\\n" goto error
+ print "Child is done.\\n"
+
+
+Command : waitfor
+Description : Waits until one of a list of strings is received
+Syntax : waitfor timeout "string1","string2","string3"...
+Notes : Timeout is a floating time constant. waitquiet returns
+Notes : 0 for the first string received, 1 for the second, etc...
+Notes : and -1 for a timeout. Case is ignored by default unless
+Notes : ignorecase is set to off.
+See Also : get.
+Example:
+ :dial
+ send "atdt555-4411^m"
+ waitfor 60 "no carrier","busy","no dial tone","connect"
+ if % = -1 goto timedout
+ if % = 0 goto nocd
+ if % = 1 goto redial
+ if % = 2 goto error
+ if % = 3 goto connected
+
+
+Command : waitquiet
+Description : Waits until communication line stops receiving for a time.
+Syntax : waitquiet timeout quiettime
+Notes : Both timeout and quiettime are floating time constants
+Notes : with 1/100th sec. accuracy. Usefull for "swallowing"
+Notes : incoming characters for a while or waiting for an
+Notes : unknown prompt.
+Example:
+ :closecon
+ send "logoff^m"
+ waitquiet 10 0.5
+ send "yes^m"
+.fi
+.
+.SS Integer functions
+.PP
+.nf
+I-Function : Access
+Description : Verifies access rights to a file
+Syntax : let x=access("/tmp/file","frwx")
+Notes : The second string contains one or more of
+Notes : \'f\',\'r\',\'w\',\'x\' to repectively check
+Notes : existence, read, write and execute permissions.
+Notes : Under root id, the only useful check is \'f\', as
+Notes : all others will return true.
+Return Value: 0 if the file exists, is readable, writable,
+Return Value: executable, or -1 if not.
+See Also : man access(2)
+
+I-Function : baud
+Description : Returns current baudrate of communication line.
+Syntax : let x=baud()
+Notes : Does not necessarily match the modem connection speed.
+See Also : $baud().
+
+I-Function : len
+Description : Returns the length of a string.
+Syntax : let x=len($s)
+Notes : "" is zero. Strings currently have a maximum length of
+Notes : 1024 characters. gcom doesn\'t handle string overflow
+Notes : at all.
+
+I-Function : htime
+Description : Returns hundreds of seconds since start of script.
+Syntax : let x=htime()
+Notes : Set to a specific value with hset.
+See Also : hset.
+
+I-Function : pid
+Description : Returns process ID number of current process (gcom)
+Syntax : let x=pid()
+See Also : ppid(), fork
+
+I-Function : ppid
+Description : Returns process ID number of parent process.
+Syntax : let x=ppid()
+Notes : Can be used by forked child to detect parent
+Notes : process.
+
+I-Function : time
+Description : Returns time in seconds since Jan 1, 00:00:00 1970 GMT.
+Syntax : let x=time()
+Notes : Used to calculate time differences.
+See Also : $time()
+
+
+I-Function : val
+Description : Returns value of string.
+Syntax : let x=val($x)
+Notes : String is not an expression; must only contain [0-9]
+Notes : characters. Future versions of gcom will be able to
+Notes : evaluate expressions. (Maybe) (This was written 6
+Notes : years ago.)
+
+
+I-Function : verbose
+Description : Returns value of verbose setting.
+Syntax : let x=verbose()
+Notes : 0=off, 1=on.
+.nf
+.
+.SS String functions
+.PP
+.nf
+S-Function : basename
+Description : Returns basename part of path.
+Syntax : let $x=$basename($p)
+Notes : $basename("/usr/bin/more")="more"
+See Also : $dirname().
+
+S-Function : baud
+Description : Returns string representation of current baud rate.
+Syntax : let $x=$baud()
+Notes : Defined by "set com"
+See Also : baud(), set com.
+
+S-Function : cwd
+Description : Returns current working directory pathname.
+Syntax : let $x=$cwd()
+See Also : cd.
+
+S-Function : dev
+Description : Returns current communication device pathname.
+Syntax : let $x=$dev()
+Notes : defined by "-d" command line argument or "open com"
+See Also : open com.
+
+S-Function : dirname
+Description : Returns directory name part of path.
+Syntax : let $x=$dirname($p)
+Notes : $dirname("/usr/bin/more")="/usr/bin"
+See Also : $basename().
+
+S-Function : env
+Description : Returns content of an environment variable
+Syntax : let $x=$env("HOME")
+Notes : Non-existant variables return an empty string.
+See Also : putenv.
+
+S-Function : hex
+Description : Converts value to hexadecimal representation
+Syntax : let $x=$hex(x)
+Notes : Letters a-f in lowercase, no preceding "0x"
+See Also : $hexu(), $oct().
+
+S-Function : hexu
+Description : Converts value to hexadecimal representation
+Syntax : let $x=$hex(x)
+Notes : Letters A-F in uppercase, no preceding "0x"
+See Also : $hex(), $oct().
+
+S-Function : hms
+Description : Converts number of seconds into time string
+Syntax : let $x=$hms(x)
+Notes : Format is "HH:MM:SS". Useful for chronometer displays
+Notes : Use with "time()", do not try to increment a variable
+Notes : every second using "sleep 1". (See ISP script example)
+Notes : Format becomes "HHH:MM:SS" after 99 hours, 59 minutes,
+Notes : 59s...
+See Also : time().
+
+S-Function : left
+Description : Returns left portion of a string
+Syntax : let $x=$left($s,l)
+Notes : $s=Source string, l=length
+Notes : l must be less than the length of the string.
+See Also : $right(), $mid().
+
+S-Function : mid
+Description : Returns midsection of a string.
+Syntax : let $x=$mid($s,s,l)
+Notes : $s=Source string, s=start, l=length
+Notes : s must be less than the length of the string, l can be
+Notes : some huge number (9999) to return the right side of a
+Notes : string to the end. the first character of a string is
+Notes : position 0, not 1.
+See Also : $right(), $left().
+
+S-Function : oct
+Description : Converts value to octal representation.
+Syntax : let $x=$oct(x)
+See Also : $hex(), $hexu().
+
+S-Function : right
+Description : Returns right portion of a string.
+Syntax : let $x=$right($s,l)
+Notes : $s=Source string, l=length
+Notes : l must be less than the length of the string.
+See Also : $left(), $mid().
+
+S-Function : rpipe
+Description : Returns the first line from a system piped command
+Syntax : let $x=$rpipe("/bin/ls |grep myfile")
+Notes : Not very useful unless used with head, tail, grep,
+Notes : etc...
+See Also : system.
+
+S-Function : time
+Description : Returns 24 character local time string
+Syntax : let $x=$time()
+See Also : time().
+Notes : Time is in this format: Mon Apr 8 14:21:22 1996
+ 012345678901234567890123
+ 1 2
+
+S-Function : tolower
+Description : Returns lowercase\'d string.
+Syntax : let $x=$tolower($y)
+
+S-Function : toupper
+Description : Returns uppercase\'d string.
+Syntax : let $x=$toupper($y)
+.fi
+.
+.SS Test operators
+.PP
+.nf
+Operator Description Example Result
+= equal if 1+2=3 yes
+!= not equal if 1+2!=3 no
+<> not equal if 1+2<>3 no
+> Greater than if 1+3>3 yes
+< Less than if 1+3<3 no
+>= Greater or equal if 3>=3 yes
+<= Greater or equal if 2<=3 yes
+.nf
+.PP
+Strings can be compared using the same operators.
+.PP
+.nf
+"aaa" < "aab", "aaaa" > "aaa", "Test" != "test", "One" = "One",
+"A" > "a", "Fumble" <= "Fumigate", "Farsical" <> "Comedic"
+.fi
+.PP
+.B Note
+that "set ignorecase on" does NOT apply to string comparisons.
+.
+.SS Expression operators
+.PP
+.nf
+Operator Description Example Result
++ Addition let a=2+2 4
++ Concatenation let $b="aa"+"bb" "aabb"
+- Substraction let e=2-5 -3
+* Multiplication let f=11*2 22
+/ Division let g=34/11 3
+& Bit-Wise AND let h=42&7 2
+| Bit-Wise OR let a=42|5 47
+^ Bit-Wise XOR let a=42^7 45
+.fi
+.PP
+Mixed expression examples:
+.PP
+.nf
+#Returns number of seconds since 00:00:00
+let $t=$time() #Take a snapshot.
+let a=(val(mid$($t,11,2))*3600)+(val(mid$($t,14,2))*60)+val(mid$($t,17,2))
+#Notice the extra sets of parenthesis because gcom\'s expression
+#evaluator is brain-dead.
+#For example, 5-2+1 should give you 4, right? Well, according to
+#getvalue(), it actually gives 2, because it does it somewhat from
+#right to left.
+#So to evaluate 5-2+1 correctly, use (5-2)+1. If you\'re using
+#simple, two-element calculations, don\'t worry about it.
+#5-2 will give you 3.
+.PP
+#Concatenation (Calls cu)
+exec "cu -l "+$dev()+" -s "+$baud()"
+.PP
+#In a test condition
+if a+c > strlen($c) goto toomuch
+.PP
+#String comparison
+let $t=$mid($time(),11,8)
+if $t > "19:59:59" print "Too late for that!\\n" goto toolate
+if $t < "08:00:00" print "Too early!\\n" goto tooearly
+if $t = "00:00:00" print "Oh god! It\'s Twinkee time!\\n"
+.fi
+.
+.SH KNOWN "FEATURES"
+The getvalue() parser. It makes me laugh so I think I\'ll leave it that way.
+- Daniel.Chouinard@pwc.utc.com
+.
+.SH AUTHORS
+.PP
+Daniel.Chouinard <Daniel.Chouinard@pwc.utc.com> wrote the original
+.B dcon
+utility.
+.PP
+Paul Hardwick <paul@peck.org.uk> updated it for the latest compilers,
+provided the built-in script functionality and tested it against
+GPRS and 3G datacards.
+.PP
+Martin Gregorie <martin@gregorie.org> wrote the original manpage for
+.B gcom
+from the
+.B dcon
+documentation and packaged
+.B gcom
+for distribution.
+.
+.SS History
+Daniel
+Chouinard wrote most (90%) of
+.B dcon
+back in 1989 when he started doing Unix Apps tech support mostly
+by modem to customer
+systems. He was tired of typing all those passwords and funny call-charging
+codes everytime he used cu. Also, the company he worked for needed a system
+that would log call times and estimated costs. Thus
+.B dcon
+was born.
+Six or seven years later (1996) and he was using pppd to connect to
+his ISP site. He was more or less happy with
+.B chat
+but found it lacked flow control and multiple response checks
+from "atdt...".
+He wanted it to do different things for "no carrier", "no dial tone",
+and "busy".
+Although he thought that
+.B chat
+would probably be enhanced someday, when he found dcon.c on one of his
+old 45M tapes he
+tried compiling it on his Linux box and, lo and behold, it did.
+In the end, he added a few things to it (kill, fork, wait, 1/100 sec. times)
+and left it at that.
+.PP
+A couple of years ago Paul Hardwick found the
+program,
+.B dcon 0.97,
+last modified in 1996. The purpose of this
+program was to run scripts that would control Linux serial ports. The
+implementation was very similar to something he had written for
+Windows. Anyway, rather than reinvent he contacted the author, Daniel
+Chouinard, and asked his permission to reuse the code.
+Happily he gave permission and a basic but useful utility
+called
+.B gcom
+was created. Paul takes no credit for the engine,
+apart from making it compatible with todays compilers.
+It is basically
+.B dcon
+repackaged.
+
+
--- /dev/null
+/*
+ * gcom version 0.3 - 3G/GPRS datacard management utility
+ *
+ * Copyright (C) 2003 Paul Hardwick <paul@peck.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * See gcom.doc for more configuration and usage information.
+ *
+ */
+
+ /***************************************************************************
+* $Id: gcom.c 10 2006-01-04 12:40:44Z paul $
+* $HeadURL: http://10.0.0.4/svn/gcom/gcom.c $
+ ****************************************************************************/
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <termio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include "gcom.h"
+
+#define MAXLABELS 3000 /* Maximum number of labels */
+#define MAXGOSUBS 128 /* Max depth */
+#define STRINGL 1024 /* String lengths. Also, max script line length */
+#define MAXPATH 1024 /* Max filename length (less or equal to STRINGL) */
+#define MAXTOKEN 20 /* Maximum token or label length */
+#define GTDEVICE "/dev/modem"
+
+#define BOOL unsigned char
+#define NVARS 286 /* a-z, a0-z9 == 26*11 */
+
+extern char *optarg;
+extern int optind, opterr;
+FILE *filep;
+char *script;
+int scriptspace;
+BOOL ifres;
+int lastpc,pc; /* program "counters" */
+long resultcode=0; /* result code */
+int ignorecase=1; /* no case sensitivity */
+BOOL comecho=0; /* echo what's comin' in */
+BOOL high_speed=0;
+long senddelay=0; /* 0/100th second character delay for sending */
+long number; /* For getonearg() returning an long */
+char **label; /* Index of labels for goto and gosub */
+int *labelpc; /* Positions of said labels in script */
+int labels; /* Number of labels found in script */
+long intvars[NVARS]; /* [a-z][0-9] integer variables */
+char string[STRINGL]; /* For getstring() returns and misc. use (misuse) */
+char *stringvars[NVARS]; /* $[a-z][0-9] string variables */
+char cspeed[10]; /* Ascii representation of baudrate */
+int speed=B0; /* Set to B110, B150, B300,..., B38400 */
+char device[MAXPATH]; /* Comm device. May be "-" */
+char token[MAXTOKEN]; /* For gettoken() returns */
+char scriptfile[MAXPATH]; /* Script file name */
+BOOL verbose=0; /* Log actions */
+struct termio cons, stbuf, svbuf; /* termios: svbuf=before, stbuf=while */
+int comfd=0; /* Communication file descriptor. Defaults to stdin. */
+char msg[STRINGL]; /* Massage messages here */
+int preturn,returns[MAXGOSUBS];
+int clocal=0;
+int parity=0, bits=CS8, stopbits=0;
+unsigned long hstart,hset;
+char NullString[]={ "" };
+BOOL lastcharnl=1; /* Indicate that last char printed from getonebyte
+ was a nl, so no new one is needed */
+
+
+//"open com \"/dev/modem\"\nset com 38400n81\nset senddelay 0.05\nsend \"ATi^m\"\nget 2 \" ^m\" $s\nprint \"Response : \",$s,\"\\n\"\nget 2 \" ^m\" $s\nprint \"Response :\",$s,\"\\n\"\nget 2 \" ^m\" $s\nprint \"Response : \",$s,\"\\n\"\n\n";
+/* Prototypes. */
+unsigned long htime(void);
+void dormir(unsigned long microsecs);
+void dotestkey(void);
+void ext(long xtc);
+void vmsg(char *text);
+void skipline(void);
+void printwhere(void);
+void writecom(char *text);
+int getonebyte(void);
+void dodump(void);
+void serror(char *text, int exitcode);
+void skipspaces(void);
+void getopen(void);
+void getclose(void);
+int gettoken(void);
+void skiptoken(void);
+long getvalue(void);
+void getcomma(void);
+void gethardstring(void);
+void getstring(void);
+unsigned long getdvalue(void);
+void dolet(void);
+int dowaitquiet(void);
+int dowaitfor(void);
+BOOL getonoroff(void);
+void setcom(void);
+void doset(void);
+void dogoto(void);
+void dogosub(void);
+unsigned char getonearg(void);
+void doif(void);
+int getindex(void);
+int getintindex(void);
+int getstringindex(void);
+void doget(void);
+void doprint(int channel);
+void doclose(void);
+void opendevice(void);
+void doopen(void);
+int doscript(void);
+
+/* Returns hundreds of seconds */
+unsigned long htime(void) {
+ struct timeval timenow;
+ gettimeofday(&timenow,NULL);
+ return(100L*(timenow.tv_sec-hstart)+(timenow.tv_usec)/10000L-hset);
+}
+
+/* I use select() 'cause CX/UX 6.2 doesn't have usleep().
+ On Linux, usleep() uses select() anyway.
+*/
+void dormir(unsigned long microsecs) {
+ struct timeval timeout;
+ timeout.tv_sec=microsecs/1000000L;
+ timeout.tv_usec=microsecs-(timeout.tv_sec*1000000L);
+ select(1,0,0,0,&timeout);
+}
+
+/* Tests for ENTER key */
+void dotestkey(void) {
+ fd_set fds;
+ struct timeval timeout;
+ timeout.tv_sec=0L;
+ timeout.tv_usec=10000L;
+ FD_ZERO(&fds);
+ FD_SET(0,&fds); /* Prepare to select() from stdin */
+ resultcode=select(1,&fds,0,0,&timeout);
+ if(resultcode) getchar();
+}
+
+/* Exit after resetting terminal settings */
+void ext(long xtc) {
+ ioctl(1, TCSETA, &cons);
+ exit(xtc);
+}
+
+/* Log message if verbose is on */
+void vmsg(char *text) {
+ time_t t;
+ char *ct;
+ if(verbose) {
+ if(lastcharnl==0) {
+ fprintf(stderr,"\n");
+ lastcharnl=1;
+ }
+ t=time(0);
+ ct=ctime(&t);
+ fprintf(stderr,"gcom %c%c:%c%c:%c%c -> %s\n",
+ ct[11],ct[12],ct[14],ct[15],ct[17],ct[18],
+ text);
+ }
+}
+
+/* Skip to next statement */
+void skipline(void) {
+ while(script[pc]!='\n' && script[pc]!=0) pc++;
+ if(script[pc]) pc++;
+}
+
+void printwhere(void) {
+ int a,b,c;
+ sprintf(msg,"@%04d ",pc);
+ a=pc;
+ skipline();
+ b=pc-1;
+ pc=a;
+ c=strlen(msg);
+ for(;a<b;a++) msg[c++]=script[a];
+ msg[c]=0;
+ vmsg(msg);
+}
+
+/* Write a null-terminated string to communication device */
+void writecom(char *text) {
+ int res;
+ unsigned int a;
+ char ch;
+ for(a=0;a<strlen(text);a++) {
+ ch=text[a];
+ res=write(comfd,&ch,1);
+ if(senddelay) dormir(senddelay);
+ if(res!=1) {
+ serror("Could not write to COM device",1);
+ }
+ }
+}
+
+/* Gets a single byte from comm. device. Return -1 if none avail. */
+int getonebyte(void) {
+ fd_set rfds;
+ int res;
+ char ch;
+ comecho = 1;
+ struct timeval timeout;
+ timeout.tv_sec=0L;
+ timeout.tv_usec=10000;
+ FD_ZERO(&rfds);
+ FD_SET(comfd, &rfds);
+ res=select(comfd+1,&rfds,NULL,NULL,&timeout);
+ if(res) {
+ res=read(comfd,&ch,1);
+ if(res==1) {
+ if(comecho) {
+ if(ch=='\n') lastcharnl=1;
+ else {
+ if(ch!='\r') lastcharnl=0;
+ }
+ /*fputc(ch,stderr);*/
+ }
+ return(ch);
+ }
+ }
+ else {
+ return(-1); /* Nada. */
+ }
+ return(0);
+}
+
+void dodump(void) {
+ char lmsg[STRINGL];
+ int a,b,c;
+ c=verbose;
+ verbose=1;
+ sprintf(lmsg,"-- Integer variables --"); vmsg(lmsg);
+ for(a=0;a<26;a++) {
+ for(b=0;b<11;b++) {
+ if(intvars[b*26+a]) {
+ sprintf(lmsg," = %ld",intvars[b*26+a]);
+ lmsg[1]='a'+a;
+ lmsg[2]=' ';
+ if(b) lmsg[2]='0'+b-1;
+ vmsg(lmsg);
+ }
+ }
+ }
+ sprintf(lmsg,"-- String variables --"); vmsg(lmsg);
+ for(a=0;a<26;a++) {
+ for(b=0;b<11;b++) {
+ if(stringvars[b*26+a]!=NullString) {
+ sprintf(lmsg,"$ = \"%s\"",stringvars[b*26+a]);
+ lmsg[1]='a'+a;
+ lmsg[2]=' ';
+ if(b) lmsg[2]='0'+b-1;
+ vmsg(lmsg);
+ }
+ }
+ }
+ verbose=c;
+}
+
+/* Report script errors and quit */
+void serror(char *text, int exitcode) {
+ int a,line;
+ char lmsg[STRINGL];
+ verbose=1;
+ //dodump();
+ vmsg("-- Error Report --");
+ a=pc;
+ pc=lastpc;
+ //printwhere();
+ pc=a;
+ while(pc!=0 && (script[pc]==' ' || script[pc]=='\t')) pc--;
+ strcpy(lmsg,"----> ");
+ for(a=6;a<STRINGL;a++) lmsg[a]=' ';
+ for(a=0;a<pc-lastpc;a++) {
+ if(script[a+lastpc]=='\t') lmsg[a+8]='\t';
+ }
+ a+=6;
+ lmsg[a++]='^';
+ lmsg[a]=0;
+ vmsg(lmsg);
+ a=0; line=1;
+ while(a<pc) {
+ if(script[a++]=='\n') {
+ if(a<pc) line++;
+ }
+ }
+ sprintf(lmsg,"Error @%d, line %d, %s. (%d)\n",pc,line,text,exitcode);
+ vmsg(lmsg);
+ ext(exitcode);
+}
+
+void skipspaces(void) {
+ while(script[pc]==' ' || script[pc]=='\t' ) pc++;
+}
+
+void getopen(void) {
+ int a;
+ a=pc;
+ skipspaces();
+ if(script[pc++]!='(') {
+ pc=a;
+ serror("Function requires open parenthesis",5);
+ }
+}
+
+void getclose(void) {
+ int a;
+ a=pc;
+ skipspaces();
+ if(script[pc++]!=')') {
+ pc=a;
+ serror("Function requires close parenthesis",5);
+ }
+}
+
+void skiptoken(void) {
+ skipspaces();
+ while(script[pc]!=' ' && script[pc]!='\t' && script[pc]!='\n' ) pc++;
+ skipspaces();
+}
+
+/* Parse script[pc] to get next statement. Resolve comments and labels... */
+int gettoken(void) {
+ int tokenp=0;
+ skipspaces();
+ if(script[pc]=='=' || script[pc]=='<' || script[pc]=='>' || script[pc]=='!') {
+ token[0]=0;
+ while(script[pc]=='=' || script[pc]=='<' || script[pc]=='>' || script[pc]=='!') {
+ token[tokenp++]=script[pc++];
+ }
+ token[tokenp]=0;
+ return(0);
+ }
+ if(script[pc]=='#') {
+ strcpy(token,"rem");
+ pc++;
+ return(0);
+ }
+ if(script[pc]=='/' && script[pc+1]=='/') {
+ strcpy(token,"rem");
+ pc+=2;
+ return(0);
+ }
+ if(script[pc]==':') {
+ strcpy(token,"label");
+ pc++;
+ return(0);
+ }
+ while(script[pc]!=' ' && script[pc]!='\n' &&
+ script[pc]!='\t' && script[pc]!='(') {
+ token[tokenp]=script[pc++];
+ if(token[tokenp]>='A' && token[tokenp]<='Z') {
+ token[tokenp]=token[tokenp]-'A'+'a';
+ }
+ if(tokenp++==MAXTOKEN-1) serror("Token too long",5);
+ }
+ token[tokenp]=0;
+ if(strcmp(token,"then")==0) return(gettoken()); /* Ignore then for if */
+ return(0);
+}
+
+/* shitfaced recursive value parser. must write better one */
+long getvalue(void) {
+ unsigned long p=0;
+ int goone=1;
+ unsigned int a;
+ int base,amode;
+ skipspaces();
+ if(script[pc]=='(') {
+ pc++;
+ p=getvalue();
+ getclose();
+ }
+ else if(script[pc]==')') {
+ return(p);
+ }
+ else if(script[pc]=='"' || script[pc]=='\'' || script[pc]=='$' ) {
+ serror("Did not expect a string",7);
+ }
+ else if( (script[pc]>='a' && script[pc]<='z' &&
+ script[pc+1]>='a' && script[pc+1]<='z') ||
+ (script[pc]>='A' && script[pc]<='Z' &&
+ script[pc+1]>='A' && script[pc+1]<='Z') ) {
+ gettoken();
+ getopen();
+ if(strcmp(token,"len")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ p=strlen(string);
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"htime")==0) {
+ p=htime();
+ }
+ else if(strcmp(token,"time")==0) {
+ p=time(0);
+ }
+ else if(strcmp(token,"pid")==0) {
+ p=getpid();
+ }
+ else if(strcmp(token,"ppid")==0) {
+ p=getppid();
+ }
+ else if(strcmp(token,"verbose")==0) {
+ p=verbose;
+ }
+ else if(strcmp(token,"isatty")==0) {
+ p=isatty(getvalue());
+ }
+ else if(strcmp(token,"baud")==0) {
+ p=atol(cspeed);
+ }
+ else if(strcmp(token,"access")==0) {
+ char toto[STRINGL];
+ char afile[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ strcpy(afile,string);
+ getcomma();
+ getstring();
+ if(string[0]==0) serror("Missing access mode[s]",5);
+ amode=0;
+ for(a=0;a<strlen(string);a++) {
+ switch(string[a]) {
+ case 'R' :
+ case 'r' : amode|=R_OK; break;
+ case 'W' :
+ case 'w' : amode|=W_OK; break;
+ case 'X' :
+ case 'x' : amode|=X_OK; break;
+ case 'F' :
+ case 'f' : amode|=F_OK; break;
+ default : serror("Access modes are r,w,x, and f",5);
+ }
+ }
+ p=access(afile,amode);
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"val")==0 || strcmp(token,"atol")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ p=atol(string);
+ strcpy(string,toto);
+ }
+ else serror("Unknown Integer function",5);
+ getclose();
+ }
+ if(script[pc]=='%') {
+ pc++;
+ skipspaces();
+ p=resultcode;
+ }
+ while(goone) {
+ if(script[pc]=='+') {
+ pc++;
+ p+=getvalue();
+ }
+ else if(script[pc]=='-') {
+ pc++;
+ p-=getvalue();
+ }
+ else if(script[pc]=='^') {
+ pc++;
+ p^=getvalue();
+ }
+ else if(script[pc]=='&') {
+ pc++;
+ p&=getvalue();
+ }
+ else if(script[pc]=='|') {
+ pc++;
+ p|=getvalue();
+ }
+ else if(script[pc]=='*') {
+ pc++;
+ p*=getvalue();
+ }
+ else if(script[pc]=='/') {
+ pc++;
+ a=getvalue();
+ if(a==0) serror("Division by zero",6);
+ p/=a;
+ }
+ else if((script[pc]>='a' && script[pc]<='z') ||
+ (script[pc]>='A' && script[pc]<='Z') ) {
+ p=intvars[getintindex()];
+ }
+ else if(script[pc]>='0' && script[pc]<='9') {
+ base=10;
+ if(script[pc]=='0') {
+ base=8;
+ pc++;
+ if(script[pc]=='x' || script[pc]=='X') {
+ base=16;
+ pc++;
+ }
+ if(script[pc]=='%') {
+ base=2;
+ pc++;
+ }
+ }
+ while((script[pc]>='0' && script[pc]<='9') ||
+ (script[pc]>='a' && script[pc]<='f') ||
+ (script[pc]>='A' && script[pc]<='F')) {
+ if(script[pc]>='a' && script[pc]<='f') {
+ p=p*base+script[pc++]-'a'+10;
+ }
+ else if(script[pc]>='A' && script[pc]<='F') {
+ p=p*base+script[pc++]-'A'+10;
+ }
+ else {
+ p=p*base+script[pc++]-'0';
+ }
+ }
+ }
+ else {
+ goone=0;
+ }
+ }
+ return(p);
+}
+
+void getcomma(void) {
+ skipspaces();
+ if(script[pc++]!=',') serror("Comma expected",5);
+}
+
+void gethardstring(void) {
+ int a=0;
+ skipspaces();
+ while(script[pc]!=0 && script[pc]!=' ' && script[pc]!='\t' &&
+ script[pc]!='\n') {
+ string[a++]=script[pc++];
+ }
+ string[a]=0;
+}
+
+/* Parse a string from script[pc] */
+void getstring(void) {
+ FILE *fp;
+ time_t t;
+ unsigned int a,b;
+ int c,p=0;
+ unsigned char ch,match;
+ string[0]=0;
+ skipspaces();
+ if(script[pc]!='"' && script[pc]!='\'' && script[pc]!='$' ) {
+ serror("Expected a string",7);
+ }
+ while(script[pc]!=' ' && script[pc]!='\t' && script[pc]!='\n' && script[pc]!=',' && script[pc]!=')' && script[pc]!='=' && script[pc]!='<' && script[pc]!='>' && script[pc]!='!' ) {
+ if(script[pc]=='+') pc++;
+ skipspaces();
+ if( (script[pc]=='$' && script[pc+1]>='a' && script[pc+1]<='z' &&
+ script[pc+2]>='a' && script[pc+2]<='z') ||
+ (script[pc]=='$' && script[pc+1]>='A' && script[pc+1]<='Z' &&
+ script[pc+2]>='A' && script[pc+2]<='Z') ) {
+ pc++;
+ gettoken();
+ getopen();
+ if(strcmp(token,"time")==0) {
+ t=time(0);
+ strcat(string,ctime(&t));
+ string[strlen(string)-1]=0;
+ }
+ else if(strcmp(token,"rpipe")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ if((fp=popen(string,"r"))==NULL) serror("Could not popen!",4);
+ fgets(string,STRINGL-1,fp);
+ string[strlen(string)-1]=0;
+ pclose(fp);
+ strcat(toto,string);
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"env")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ if(getenv(string)) strcat(toto,(char *)getenv(string));
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"hms")==0) {
+ long sec,min,hour;
+ sec=getvalue();
+ min=sec/60L;
+ sec-=min*60L;
+ hour=min/60L;
+ min-=hour*60L;
+ sprintf(string,"%s%02ld:%02ld:%02ld",string,hour,min,sec);
+ }
+ else if(strcmp(token,"dev")==0) {
+ strcat(string,device);
+ }
+ else if(strcmp(token,"cwd")==0) {
+ getcwd(string,STRINGL);
+ }
+ else if(strcmp(token,"baud")==0) {
+ strcat(string,cspeed);
+ }
+ else if(strcmp(token,"str")==0 || strcmp(token,"ltoa")==0) {
+ sprintf(string,"%s%ld",string,getvalue());
+ }
+ else if(strcmp(token,"hexu")==0) {
+ sprintf(string,"%s%lX",string,getvalue());
+ }
+ else if(strcmp(token,"hex")==0) {
+ sprintf(string,"%s%lx",string,getvalue());
+ }
+ else if(strcmp(token,"oct")==0) {
+ sprintf(string,"%s%lo",string,getvalue());
+ }
+ else if(strcmp(token,"dirname")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ b=0;
+ for(a=0;a<strlen(string);a++) {
+ if(string[a]=='/' || string[a]=='\\') b=a;
+ }
+ string[b]=0;
+ strcat(toto,string);
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"tolower")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ for(a=0;a<strlen(string);a++) {
+ if(string[a]>='A' && string[a]<='Z' ) string[a]=string[a]-'A'+'a';
+ }
+ strcat(toto,string);
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"toupper")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ for(a=0;a<strlen(string);a++) {
+ if(string[a]>='a' && string[a]<='z' ) string[a]=string[a]-'a'+'A';
+ }
+ strcat(toto,string);
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"basename")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ b=0;
+ for(a=0;a<strlen(string);a++) {
+ if(string[a]=='/' || string[a]=='\\') b=a+1;
+ }
+ a=strlen(toto);
+ while(string[b]) toto[a++]=string[b++];
+ toto[a]=0;
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"script")==0) {
+ strcat(string,scriptfile);
+ }
+ else if(strcmp(token,"right")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ getcomma();
+ b=getvalue();
+ if(b>strlen(string)) serror("String is shorter than second argument",7);
+ c=strlen(toto);
+ a=strlen(string)-b;
+ while(b!=0 && string[a]!=0) {
+ toto[c++]=string[a++];
+ b--;
+ }
+ toto[c]=0;
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"left")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ getcomma();
+ b=getvalue();
+ if(b>strlen(string)) serror("String is shorter than second argument",7);
+ c=strlen(toto);
+ a=0;
+ while(b!=0 && string[a]!=0) {
+ toto[c++]=string[a++];
+ b--;
+ }
+ toto[c]=0;
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"mid")==0) {
+ char toto[STRINGL];
+ strcpy(toto,string);
+ getstring();
+ getcomma();
+ a=getvalue();
+ getcomma();
+ b=getvalue();
+ if(a>strlen(string)) serror("String is shorter than second argument",7);
+ c=strlen(toto);
+ while(b!=0 && string[a]!=0) {
+ toto[c++]=string[a++];
+ b--;
+ }
+ toto[c]=0;
+ strcpy(string,toto);
+ }
+ else if(strcmp(token,"sex")==0) {
+ strcat(string,"You're a naughty boy, you!");
+ }
+ else serror("Invalid string funtion",5);
+ getclose();
+ }
+ else if(script[pc]=='$') {
+ strcat(string,stringvars[getstringindex()]);
+ }
+ else if(script[pc]=='"' || script[pc]=='\'') {
+ match=script[pc++];
+ while(script[pc]!=match) {
+ ch=script[pc++];
+ if(ch==0) serror("Umatched quote.",5);
+ if(ch=='\\') {
+ if(script[pc]<='7' && script[pc]>='0' &&
+ script[pc+1]<='7' && script[pc+1]>='0' ) {
+ ch=0;
+ while(script[pc]>='0' && script[pc]<='7') {
+ ch=8*ch+script[pc++]-'0';
+ }
+ }
+ else {
+ switch(script[pc]) {
+ case 'T' :
+ case 't' : ch=9; break;
+ case 'R' :
+ case 'r' : ch=13; break;
+ case 'N' :
+ case 'n' : ch=10; break;
+ case 'B' :
+ case 'b' : ch=8; break;
+ case 'F' :
+ case 'f' : ch=12; break;
+ case '"' :
+ case '^' :
+ case '\'' :
+ case '\\' : ch=script[pc]; break;
+ default : serror("Malformed escaped character",5);
+ }
+ pc++;
+ }
+ }
+ else if(ch=='^') {
+ ch=script[pc];
+ if(ch!='^' && ch!='"' && ch!='\'' && ch!='\\' ) {
+ ch=ch&31; /* Control char */
+ }
+ pc++;
+ }
+ p=strlen(string);
+ string[p++]=ch;
+ string[p]=0;
+ }
+ pc++; /* Space over quote */
+ }
+ else {
+ p=strlen(string);
+ string[p++]=script[pc++];
+ string[p]=0;
+ }
+ }
+}
+
+/* Get a value, multiply by a hundred (for time values) */
+unsigned long getdvalue(void) {
+ float f;
+ gettoken();
+ skipspaces();
+ sscanf(token,"%f",&f);
+ f+=0.00001; /* Rounding errors */
+ return(100.0*f);
+}
+
+void dolet(void) {
+ int index;
+ BOOL svar=0;
+ skipspaces();
+ if(script[pc]=='$') {
+ svar=1;
+ index=getstringindex();
+ }
+ else index=getintindex();
+ skipspaces();
+ gettoken();
+ if(strcmp(token,"=")!=0) serror("Bad LET assignment, '=' missing",5);
+ skipspaces();
+ if(svar) {
+ getstring();
+ strcpy(stringvars[index],string);
+ }
+ else {
+ intvars[index]=getvalue();
+ }
+}
+
+/* See documentation for doXXX() functions */
+int dowaitquiet(void) {
+ unsigned long timeout,timequiet,quiet,now;
+ int c,quit;
+ timeout=htime()+getdvalue();
+ quiet=getdvalue();
+ timequiet=htime()+quiet;
+ quit=1;
+ while(quit==1) {
+ now=htime();
+ c=getonebyte();
+ if(c!= -1) timequiet=now+quiet;
+ if(now>=timequiet) quit=0;
+ if(now>=timeout) quit=255;
+ }
+ return(quit);
+}
+
+int dowaitfor(void) {
+ char strings[20][80];
+ char buffer[128];
+ unsigned long timeout;
+ unsigned int a;
+ int b,c;
+ b=0;
+ buffer[127]=0;
+ skipspaces();
+ timeout=htime()+getdvalue();
+ while(script[pc]==',' || script[pc]=='$' || script[pc]=='"' ||
+ script[pc]=='\'' ) {
+ if(script[pc]==',') pc++;
+ getstring();
+ skipspaces();
+ strcpy(strings[b],string);
+ if(ignorecase) {
+ for(a=0;a<strlen(strings[b]);a++) {
+ if(strings[b][a]>='A' && strings[b][a]<='Z') {
+ strings[b][a]=strings[b][a]-'A'+'a';
+ }
+ }
+ }
+ b++;
+ }
+ strings[b][0]=0;
+ while(htime()<timeout) {
+ c=getonebyte();
+ //printf("Byte \"%c\" ",c);
+ if(c!= -1) {
+ if(ignorecase) {
+ if(c>='A' && c<='Z') c=c-'A'+'a';
+ }
+ for(a=0;a<127;a++) buffer[a]=buffer[a+1]; //shuffle down
+ buffer[126]=c;
+ b=0;
+ while(strings[b][0]) {
+ c=strlen(strings[b]);
+ if (strcmp(strings[b],&buffer[127-c]) == 0){
+ return(b);
+ }
+ b++;
+ }
+ }
+ }
+ return(-1);
+}
+
+/* Parse script for "on" or "off" wich are tokens, not strings */
+BOOL getonoroff(void) {
+ int a,b;
+ b=pc;
+ gettoken();
+ if(strcmp(token,"on")==0) return(1);
+ if(strcmp(token,"off")==0) return(0);
+ pc=b;
+ a=getvalue();
+ if(a!=0 && a!=1) serror("Bad value (should be on or off, 1 or 0.)",5);
+ return(a);
+}
+
+void setcom(void) {
+ stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB);
+ stbuf.c_cflag |= (speed | bits | CREAD | clocal | parity | stopbits );
+ if (ioctl(comfd, TCSETA, &stbuf) < 0) {
+ serror("Can't ioctl set device",1);
+ }
+}
+
+void doset(void) {
+ struct termio console;
+ int a,b;
+ gettoken();
+ if(strcmp(token,"echo")==0) {
+ a=0;
+ if(getonoroff()) a=ECHO|ECHOE;
+ if(ioctl(0, TCGETA, &console)<0) {
+ serror("Can't ioctl FD zero!\n",2);
+ }
+ console.c_lflag &= ~(ECHO | ECHOE);
+ console.c_lflag |= a;
+ ioctl(0, TCSETA, &console);
+ }
+ else if(strcmp(token,"senddelay")==0) {
+ senddelay=10000L*getdvalue();
+ }
+ else if(strcmp(token,"clocal")==0) {
+ clocal=0;
+ if(getonoroff()) clocal=CLOCAL;
+ setcom();
+ }
+ else if(strcmp(token,"umask")==0) {
+ umask(getvalue()&0777);
+ }
+ else if(strcmp(token,"verbose")==0) {
+ verbose=getonoroff();
+ }
+ else if(strcmp(token,"comecho")==0) {
+ comecho=getonoroff();
+ }
+ else if(strcmp(token,"ignorecase")==0) {
+ ignorecase=getonoroff();
+ }
+ else if(strcmp(token,"com")==0) {
+ skipspaces();
+ if(script[pc]=='$' || script[pc]=='\'' || script[pc]=='"') {
+ getstring();
+ strcpy(token,string);
+ }
+ else gettoken();
+ a=0;
+ b=0;
+ while(token[b]>='0' && token[b]<='9') {
+ a=10*a+token[b++]-'0';
+ }
+ if(token[b]) {
+ switch(token[b]) {
+ case 'n': parity=0; break;
+ case 'e': parity=PARENB; break;
+ case 'o': parity=PARENB|PARODD; break;
+ default : serror("Parity can only ben E, N, or O",5);
+ }
+ b++;
+ if(token[b]) {
+ switch(token[b]) {
+ case '5' : bits=CS5; break;
+ case '6' : bits=CS6; break;
+ case '7' : bits=CS7; break;
+ case '8' : bits=CS8; break;
+ default : serror("Bits can only be 5, 6, 7, or 8",5);
+ }
+ b++;
+ if(token[b]) {
+ switch(token[b]) {
+ case '1': stopbits=0; break;
+ case '2': stopbits=CSTOPB; break;
+ default : serror("Stop bits can only be 1 or 2",5);
+ }
+ }
+ }
+ }
+ sprintf(cspeed,"%d",a);
+ switch(a) {
+ case 0: speed = B0;break;
+ case 50: speed = B50;break;
+ case 75: speed = B75;break;
+ case 110: speed = B110;break;
+ case 150: speed = B150;break;
+ case 300: speed = B300;break;
+ case 600: speed = B600;break;
+ case 1200: speed = B1200;break;
+ case 2400: speed = B2400;break;
+ case 4800: speed = B4800;break;
+ case 9600: speed = B9600;break;
+ case 19200: speed = B19200;break;
+ case 38400: speed = B38400;break;
+ case 57600: speed = B57600;break;
+ case 115200: {
+ if(high_speed == 0) speed = B115200;
+ else speed = B57600;
+ break;
+ }
+ case 460800: speed = B460800; break;
+ default: serror("Invalid baudrate",1);
+ }
+ setcom();
+ }
+}
+
+void dogoto(void) {
+ int a,originalpos;
+ originalpos=pc;
+ gettoken();
+ for(a=0;a<labels;a++) {
+ if(strcmp(token,label[a])==0) break;
+ }
+ if(a>=labels) {
+ pc=originalpos;
+ sprintf(msg,"Label \"%s\" not found",token);
+ serror(msg,5);
+ }
+ else {
+ pc=labelpc[a];
+ }
+}
+
+void dogosub(void) {
+ int a;
+ if(preturn==MAXGOSUBS) serror("Reached maximum GOSUB depth",3);
+ a=pc;
+ gettoken();
+ returns[preturn++]=pc;
+ pc=a;
+ dogoto();
+}
+
+/* Gets arguments and returns 0 for a string, 1 for an int. Used with if */
+BOOL getonearg(void) {
+ if(script[pc]=='"' || script[pc]=='\'' || script[pc]=='$' ) {
+ getstring();
+ return(0);
+ }
+ else {
+ number=getvalue();
+ return(1);
+ }
+}
+
+void doif(void) {
+ char stringarg[STRINGL];
+ char tokencopy[MAXTOKEN];
+ int intarg;
+ skipspaces();
+ ifres=0;
+ if(getonearg()) {
+ intarg=number;
+ gettoken();
+ skipspaces();
+ if(getonearg()!=1) serror("Comparison mis-match",7);
+ if(strcmp(token,"<")==0) {
+ if(intarg<number) ifres=1;
+ }
+ if(strcmp(token,"<=")==0) {
+ if(intarg<=number) ifres=1;
+ }
+ else if(strcmp(token,"=")==0) {
+ if(intarg==number) ifres=1;
+ }
+ else if(strcmp(token,">")==0) {
+ if(intarg>number) ifres=1;
+ }
+ else if(strcmp(token,">=")==0) {
+ if(intarg>=number) ifres=1;
+ }
+ else if(strcmp(token,"<>")==0) {
+ if(intarg!=number) ifres=1;
+ }
+ else if(strcmp(token,"!=")==0 || strcmp(token,"<>")==0) {
+ if(intarg!=number) ifres=1;
+ }
+ }
+ else {
+ strcpy(stringarg,string);
+ gettoken();
+ strcpy(tokencopy,token);
+ skipspaces();
+ if(getonearg()!=0) serror("Comparison mis-match",7);
+ if(strcmp(tokencopy,"<")==0) {
+ if(strcmp(stringarg,string)<0) ifres=1;
+ }
+ if(strcmp(tokencopy,"<=")==0) {
+ if(strcmp(stringarg,string)<=0) ifres=1;
+ }
+ else if(strcmp(tokencopy,"=")==0) {
+ if(strcmp(stringarg,string)==0) ifres=1;
+ }
+ else if(strcmp(tokencopy,">")==0) {
+ if(strcmp(stringarg,string)>0) ifres=1;
+ }
+ else if(strcmp(tokencopy,">=")==0) {
+ if(strcmp(stringarg,string)>=0) ifres=1;
+ }
+ else if(strcmp(tokencopy,"!=")==0 || strcmp(tokencopy,"<>")==0) {
+ if(strcmp(stringarg,string)!=0) ifres=1;
+ }
+ }
+ if(!ifres) skipline();
+}
+
+int getindex(void) {
+ int index;
+ index=script[pc++];
+ if(index>='A' && index<='Z') index=index-'A'+'a';
+ if(index>'z' || index<'a') serror("Malformed variable name",7);
+ index=index-'a';
+ if(script[pc]>='0' && script[pc]<='9') {
+ index=index+(1+script[pc++]-'0')*26;
+ }
+ return(index);
+}
+
+/* Parse script to find integer variable index */
+int getintindex(void) {
+ skipspaces();
+ if(script[pc]=='$') serror("Integer variable expected",7);
+ return(getindex());
+}
+
+/* Parse script to find string variable index and allocate memory for storage
+ as needed. */
+int getstringindex(void) {
+ int index;
+ skipspaces();
+ if(script[pc++]!='$') serror("String variable expected",7);
+ index=getindex();
+ if(stringvars[index]==NullString) {
+ stringvars[index]=(char *)malloc(STRINGL);
+ if(stringvars[index]==NULL) serror("Could not malloc",3);
+ stringvars[index][0]=0;
+ }
+ return(index);
+}
+
+void doget(void) {
+ char terminators[STRINGL];
+ unsigned int a;
+ int b,c,index;
+ int goahead=1;
+ unsigned long timeout;
+ timeout=htime()+getdvalue();
+ getstring();
+ strcpy(terminators,string);
+ index=getstringindex();
+ string[0]=0;
+ b=0;
+ resultcode=0;
+ while(goahead && htime()<timeout) {
+ c=getonebyte();
+ if(c!= -1) {
+ for(a=0;a<strlen(terminators);a++) {
+ if(c==terminators[a]) goahead=0;
+ }
+ if(goahead==0 && b==0) goahead=1; /* Ignore terminators if nothing yet */
+ else if(goahead) {
+ string[b++]=c;
+ string[b]=0;
+ }
+ }
+ }
+ if(goahead) resultcode= -1;
+ strcpy(stringvars[index],string);
+}
+
+void doprint(int channel) {
+ skipspaces();
+ msg[0]=0;
+ while(script[pc]!=' ' && script[pc]!='\t' && script[pc]!='\n') {
+ if(script[pc]==',') pc++;
+ else {
+ if(script[pc]=='"' || script[pc]=='\'' || script[pc]=='$' ) {
+ getstring();
+ strcat(msg,string);
+ }
+ else {
+ sprintf(string,"%ld",getvalue());
+ strcat(msg,string);
+ }
+ }
+ }
+ switch(channel) {
+ case 1: printf("%s",msg); fflush(stdout); break;
+ case 2: fputs(msg,stderr); break;
+ case 3:
+ if(msg[strlen(msg)-1]=='\n') msg[strlen(msg)-1]=0;
+ vmsg(msg);
+ break;
+ case 4:
+ if(filep==NULL) serror("File not opened",4);
+ fputs(msg,filep);
+ break;
+ }
+}
+
+void doclose(void) {
+ gettoken();
+ if(strcmp(token,"hardcom")==0) {
+ if(comfd== -1) serror("Com device not open",1);
+ vmsg("Closing device");
+ if (ioctl(comfd, TCSETA, &svbuf) < 0) {
+ sprintf(msg,"Can't ioctl set device %s.\n",device);
+ serror(msg,1);
+ }
+ close(comfd);
+ comfd= -1;
+ }
+ else if(strcmp(token,"com")==0) {
+ if(comfd== -1) serror("Com device not open",1);
+ vmsg("Closing com fd");
+ close(comfd);
+ comfd= -1;
+ }
+ else if(strcmp(token,"file")==0) {
+ if(filep==NULL) serror("Log file not open",4);
+ fclose(filep);
+ filep=NULL;
+ }
+}
+
+void opengt(void) {
+ if(strcmp(device,"-")!=0) {
+ if ((comfd = open(device, O_RDWR|O_EXCL|O_NONBLOCK|O_NOCTTY)) <0) { //O_NONBLOCK|O_NOCTTY)) <0) {//
+ sprintf(msg,"Can't open GlobeTrotter %s.\n",device);
+ printf(msg);
+ ext(1);
+ }
+ }
+ else comfd=0;
+ if (ioctl (comfd, TCGETA, &svbuf) < 0) {
+ sprintf(msg,"Can't control %s, please try again.\n",device);
+ serror(msg,1);
+ }
+ ioctl(comfd, TCGETA, &stbuf);
+ speed=stbuf.c_cflag & CBAUD;
+ if (high_speed == 0) strcpy(cspeed,"115200");
+ else strcpy(cspeed,"57600");
+ bits=stbuf.c_cflag & CSIZE;
+ clocal=stbuf.c_cflag & CLOCAL;
+ stopbits=stbuf.c_cflag & CSTOPB;
+ parity=stbuf.c_cflag & (PARENB | PARODD);
+ stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR );
+ stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET);
+ stbuf.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL);
+ stbuf.c_lflag &= ~(ECHO | ECHOE);
+ stbuf.c_cc[VMIN] = 1;
+ stbuf.c_cc[VTIME] = 0;
+ stbuf.c_cc[VEOF] = 1;
+ setcom();
+ dormir(200000); /* Wait a bit (DTR raise) */
+ sprintf(msg,"Opened %s as FD %d",device,comfd);
+ vmsg(msg);
+}
+
+void opendevice(void) {
+ if(strcmp(device,"-")!=0) {
+ if ((comfd = open(device, O_RDWR|O_EXCL|O_NONBLOCK|O_NOCTTY)) <0) { //O_NONBLOCK|O_NOCTTY)) <0) {//
+ sprintf(msg,"Can't open device %s.\n",device);
+ printf(msg);
+ ext(1);
+ }
+ }
+ else comfd=0;
+ if (ioctl (comfd, TCGETA, &svbuf) < 0) {
+ sprintf(msg,"Can't ioctl get device %s.\n",device);
+ serror(msg,1);
+ }
+ ioctl(comfd, TCGETA, &stbuf);
+ speed=stbuf.c_cflag & CBAUD;
+ switch(speed) {
+ case B0: strcpy(cspeed,"0");break;
+ case B50: strcpy(cspeed,"50");break;
+ case B75: strcpy(cspeed,"75");break;
+ case B110: strcpy(cspeed,"110");break;
+ case B300: strcpy(cspeed,"300");break;
+ case B600: strcpy(cspeed,"600");break;
+ case B1200: strcpy(cspeed,"1200");break;
+ case B2400: strcpy(cspeed,"2400");break;
+ case B4800: strcpy(cspeed,"4800");break;
+ case B9600: strcpy(cspeed,"9600");break;
+ case B19200: strcpy(cspeed,"19200");break;
+ case B38400: strcpy(cspeed,"38400");break;
+ case B115200:
+ {
+ if (high_speed == 0) strcpy(cspeed,"115200");
+ else strcpy(cspeed,"57600");
+ break;
+ }
+ case B460800: strcpy(cspeed, "460800");break;
+ }
+ bits=stbuf.c_cflag & CSIZE;
+ clocal=stbuf.c_cflag & CLOCAL;
+ stopbits=stbuf.c_cflag & CSTOPB;
+ parity=stbuf.c_cflag & (PARENB | PARODD);
+ stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR );
+ stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET);
+ stbuf.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL);
+ stbuf.c_lflag &= ~(ECHO | ECHOE);
+ stbuf.c_cc[VMIN] = 1;
+ stbuf.c_cc[VTIME] = 0;
+ stbuf.c_cc[VEOF] = 1;
+ setcom();
+ dormir(200000); /* Wait a bit (DTR raise) */
+ sprintf(msg,"Opened %s as FD %d",device,comfd);
+ vmsg(msg);
+}
+
+void doopen(void) {
+ gettoken();
+ if(strcmp(token,"com")==0) {
+ skipspaces();
+ if(script[pc]=='$' || script[pc]=='\'' || script[pc]=='"') {
+ getstring();
+ }
+ else gethardstring();
+ strcpy(device,string);
+ opendevice();
+ }
+ else if (strcmp(token,"file")==0) {
+ if(filep!=NULL) serror("File already open",4);
+ getstring();
+ if((filep=fopen(string,"a"))==NULL) serror("Could not open file",4);
+ }
+ else serror("OPEN only takes com or file argument",5);
+}
+
+int doscript(void) {
+ int a,b;
+ int exitcode=0;
+ char line[STRINGL];
+ pc=0;
+ while(script[pc]) {
+ if(script[pc]=='\n') pc++;
+ lastpc=pc;
+ skipspaces();
+ if(verbose) printwhere();
+ if(gettoken()) serror("Could not gettoken()",5);
+ if(strcmp(token,"rem")==0) {
+ skipline();
+ }
+ else if (strcmp(token,"label")==0) {
+ skiptoken(); /* Get rid of keyword */
+ }
+ else if(strcmp(token,"open")==0) {
+ doopen();
+ }
+ else if(strcmp(token,"opengt")==0) {
+ opengt();
+ }
+ else if(strcmp(token,"close")==0) {
+ doclose();
+ }
+ else if(strcmp(token,"exec")==0) {
+ getstring();
+ strcpy(msg,"exec ");
+ strcat(msg,string); /* Let sh do all the command line work! */
+ execl("/bin/sh","sh","-c",msg,(char *)0);
+ serror("Could not execl /bin/sh!",8);
+ }
+ else if(strcmp(token,"exit")==0) {
+ ext(getvalue());
+ }
+ else if(strcmp(token,"testkey")==0) {
+ dotestkey();
+ }
+ else if(strcmp(token,"kill")==0) {
+ a=getvalue();
+ resultcode=kill(getvalue(),a);
+ }
+ else if(strcmp(token,"fork")==0) {
+ resultcode=fork();
+ }
+ else if(strcmp(token,"hset")==0) {
+ hset=0;
+ hstart=time(0);
+ hset=htime()-getvalue();
+ }
+ else if(strcmp(token,"cd")==0) {
+ getstring();
+ resultcode=chdir(string);
+ }
+ else if(strcmp(token,"putenv")==0) {
+ getstring();
+ strcpy(line,string);
+ resultcode=putenv(line); /* putenv can't read from global string[] */
+ }
+ else if(strcmp(token,"wait")==0) {
+ resultcode=wait(0);
+ }
+ else if(strcmp(token,"system")==0) {
+ getstring();
+ system(string);
+ }
+ else if(strcmp(token,"input")==0) {
+ FILE *infd = fdopen(0,"r");
+ fgets(stringvars[getstringindex()],1024,infd);
+ //fclose(infd);
+ }
+ else if(strcmp(token,"get")==0) {
+ doget();
+ }
+ else if(strcmp(token,"print")==0) {
+ doprint(1);
+ }
+ else if(strcmp(token,"eprint")==0) {
+ doprint(2);
+ }
+ else if(strcmp(token,"lprint")==0) {
+ doprint(3);
+ }
+ else if(strcmp(token,"fprint")==0) {
+ doprint(4);
+ }
+ else if(strcmp(token,"if")==0) {
+ doif();
+ }
+ else if(strcmp(token,"else")==0) {
+ if(ifres) skipline();
+ }
+ else if(strcmp(token,"gosub")==0) {
+ dogosub();
+ }
+ else if(strcmp(token,"return")==0) {
+ if(preturn==0) serror("RETURN without gosub",5);
+ pc=returns[--preturn];
+ }
+ else if(strcmp(token,"goto")==0) {
+ dogoto();
+ }
+ else if(strcmp(token,"waitfor")==0) {
+ resultcode=dowaitfor();
+ }
+ else if(strcmp(token,"waitquiet")==0) {
+ resultcode=dowaitquiet();
+ }
+ else if(strcmp(token,"set")==0) {
+ doset();
+ }
+ else if(strcmp(token,"dec")==0) {
+ intvars[getintindex()]--;
+ }
+ else if(strcmp(token,"inc")==0) {
+ intvars[getintindex()]++;
+ }
+ else if(strcmp(token,"let")==0) {
+ dolet();
+ }
+ else if(strcmp(token,"dump")==0) {
+ dodump();
+ }
+ else if(strcmp(token,"abort")==0) {
+ vmsg("Aborting");
+ abort();
+ }
+ else if(strcmp(token,"send")==0) {
+ getstring();
+ writecom(string);
+ }
+ else if(strcmp(token,"flash")==0) {
+ b=speed;
+ speed=0;
+ setcom();
+ a=getdvalue();
+ dormir(10000L*a);
+ speed=b;
+ setcom();
+ }
+ else if(strcmp(token,"sleep")==0) {
+ a=getdvalue();
+ if(a<10000) dormir(10000L*a);
+ else sleep(a/100); /* I guess it's the same. Oh well, past 100 secs,
+ use sleep instead. */
+ }
+ else {
+ /* Humour is the spice of life. */
+ switch(time(0)&7) {
+ case 0 : serror("That's human mumbo-jumbo to me",5); break;
+ case 1 : serror("Lovely but incomprehensible",5); break;
+ case 2 : serror("What's that, governor?",5); break;
+ case 3 : serror("Very funny. I don't get it",5); break;
+ case 4 : serror("Huh?",5); break;
+ case 5 : serror("gcom doesn't speak spanish",5); break;
+ case 6 : serror("Mais, qu'est-ce que vous dites?",5); break;
+ default: serror("%E-6837-% : Corrupted human data detected",5); break;
+ }
+ }
+ skipspaces();
+ while(script[pc]=='\n') pc++;
+ }
+ return(exitcode);
+}
+
+int main(int argc,char **argv) {
+ unsigned int a;
+ int aa,b,i,skip_default;
+ unsigned char ch;
+ unsigned char terminator='\n';
+ char line[STRINGL];
+
+ strcpy(device,GTDEVICE);
+ FILE *fp;
+ hstart=time(0);
+ hset=htime();
+ preturn=0;
+ skip_default=0;
+ filep=NULL;
+ scriptspace=4096;
+ ioctl(1, TCGETA, &cons);
+ if((script=( char *)malloc(scriptspace))==NULL) {
+ serror("Could not malloc()",3);
+ }
+ for(a=0;a<NVARS;a++) {
+ intvars[a]=0;
+ stringvars[a]=NullString;
+ }
+ strcpy(cspeed,"0");
+ scriptfile[0]=0;
+ b=0; a=0;
+ for(a=0;a<strlen(argv[0]);a++) {
+ if(argv[0][a]=='/') b=a+1;
+ }
+ while((aa=getopt(argc,argv,"xhevd:t:sb:"))!= -1) {
+ switch(aa) {
+ case 0:
+ ext(0);
+ break;
+ case 't':
+ terminator=optarg[0];
+ sprintf(msg,"Alternate line terminator set to \"%c\"",terminator);
+ vmsg(msg);
+ break;
+ case 'd':
+ strcpy(device,optarg);
+ //opendevice();
+ break;
+ case 'e':
+ comecho=1;
+ vmsg("Communication echo turned on");
+ break;
+ case 'v':
+ verbose=1;
+ vmsg("Verbose output enabled");
+ break;
+ case 's':
+ skip_default=1;
+ break;
+ case 'h':
+ printf("gcom version 0.3 Copyright Paul Hardwick (c) 2005 \n");
+ printf("\nType 'gcom help' for more information\n");
+ ext(1);
+ break;
+ case 'x':
+ printf("High speed overide (115200 is now 57600).\n");
+ high_speed =1;
+ break;
+ default:
+ ext(1);
+ }
+ }
+ if(optind<argc) {
+ strcpy(scriptfile,argv[optind++]);
+ sprintf(msg,"Script file: %s",scriptfile);
+ vmsg(msg);
+ }
+
+ char * code;
+ code = get_code(scriptfile);
+ if (code != NULL){
+ scriptspace=strlen(code)+2;
+ if((script=( char *)realloc(script,scriptspace))==0) {
+ serror("Could not malloc()",3);
+ }
+ strcpy(script,code);
+ for(aa=0;aa<scriptspace;aa++) {
+ if(script[aa]==terminator) script[aa]='\n';
+ }
+ //scriptfile[0] = '\0';
+ }
+ else if (scriptfile[0]) {
+ code = get_code("default");
+ if (code != NULL && !skip_default){
+ scriptspace=strlen(code)+2;
+ if((script=( char *)realloc(script,scriptspace))==0) {
+ serror("Could not malloc()",3);
+ }
+ strcpy(script,code);
+ for(aa=0;aa<scriptspace;aa++) {
+ if(script[aa]==terminator) script[aa]='\n';
+ }
+ //scriptfile[0] = '\0';
+ }
+ if((fp=fopen(scriptfile,"r"))==NULL) {
+ sprintf(msg,"Could not open scriptfile \"%s\".\n",scriptfile);
+ serror(msg,1);
+ }
+ i=strlen(script);
+ if(i) {
+ script[i++]='\n'; script[i]=0;
+ }
+ while((fgets(line,STRINGL-1,fp))!=NULL) {
+ b=strlen(line);
+ if((scriptspace-i)<STRINGL) {
+ scriptspace+=STRINGL+STRINGL;
+ if((script=(char *)realloc(script,scriptspace))==NULL) {
+ serror("Could not realloc()",3);
+ }
+ }
+ for(aa=0;aa<b;aa++) {
+ script[i]=line[aa];
+ if(script[i]==terminator) script[i]='\n';
+ i++;
+ }
+ }
+ script[i]=0;
+ fclose(fp);
+ }
+
+ if(script[0]) {
+ i=strlen(script)-1;
+ while((script[i]=='\n' || script[i]==' ' || script[i]=='\t') && i!=0) i--;
+ script[++i]='\n';
+ script[++i]=0;
+ }
+ i=strlen(script); /* Script is one huge string */
+ /* Indexing labels */
+ label=(char **)malloc(sizeof(char *)*MAXLABELS);
+ labelpc=(int *)malloc(sizeof(int *)*MAXLABELS);
+ if(label==NULL || labelpc==NULL) {
+ serror("Can't malloc",3);
+ }
+ labels=0;
+ pc=0;
+ while(script[pc]) {
+ lastpc=pc;
+ gettoken();
+ if(strcmp(token,"label")==0) {
+ gettoken();
+ for(aa=0;aa<labels;aa++) {
+ if(strcmp(token,label[aa])==0) {
+ pc=lastpc;
+ serror("Duplicate label",5);
+ }
+ }
+ if(labels==MAXLABELS) serror("Maximum number of labels reached",3);
+ labelpc[labels]=lastpc;
+ label[labels]=(char *)malloc(strlen(token)+1);
+ if(label[labels]==NULL) serror("Can't malloc one label",3);
+ strcpy(label[labels],token);
+ labels++;
+ }
+ skipline();
+ }
+ //printf(script);
+ if(verbose) {
+ sprintf(msg,"argc:%d",argc);
+ vmsg(msg);
+ for(aa=0;aa<argc;aa++) {
+ sprintf(msg,"argv[%d]=%s",aa,argv[aa]);
+ vmsg(msg);
+ }
+ vmsg(" ---Script---");
+ aa=0; b=0; ch='\n';
+ while(aa<i) {
+ if(ch=='\n' && script[aa]!=0) {
+ fprintf(stderr,"%4d@%04d ",++b,aa);
+ }
+ ch=script[aa++];
+ fputc(ch,stderr);
+ }
+ vmsg(" ---End of script---");
+ }
+
+ if(script[0]==0) {
+ fprintf(stderr,"No script!\n");
+ ext(1);
+ }
+
+ a=doscript();
+ dormir(200000);
+ if(comfd!= -1) close(comfd);
+ sprintf(msg,"Exit with code %d.\n",a);
+ vmsg(msg);
+ ext(a);
+}
--- /dev/null
+/***************************************************************************
+ * gcom.h - 3G/GPRS datacard management utility header file
+ *
+ * Copyright (C) 2003 Paul Hardwick <paul@peck.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ***************************************************************************/
+
+/***************************************************************************
+* $Id: gcom.h 10 2006-01-04 12:40:44Z paul $
+* $HeadURL: http://10.0.0.4/svn/gcom/gcom.h $
+****************************************************************************/
+
+
+char _default_code[] =
+ "opengt\n\
+ set com 115200n81\n\
+ set senddelay 0.05\n\
+ send \"AT+CFUN=1^m\"\n\
+ waitquiet 1 0.2\n\
+ :start\n\
+ flash 0.1\n\
+ send \"AT+CPIN?^m\"\n\
+ waitfor 30 \"SIM PUK\",\"SIM PIN\",\"READY\",\"ERROR\",\"ERR\"\n\
+ if % = -1 goto error\n\
+ if % = 0 goto ready\n\
+ if % = 1 goto getpin\n\
+ if % = 2 goto ready\n\
+ if % = 3 goto error\n\
+ if % = 4 goto error\n\
+ :error\n\
+ print $s,\" ***SIM ERROR***\n\"\n\
+ print \"Check device port configuration.\nCheck SIM is inserted\nTest SIM in a mobile phone?\n\"\n\
+ exit 1\n\
+ :getpin\n\
+ #handle case where Vodafone 3 generates wrong response\n\
+ waitfor 1 \"2\"\n\
+ if % = 0 goto ready\n\
+ print \"\nEnter PIN number: \"\n\
+ input $x\n\
+ let a=len($x)\n\
+ if a<>5 goto getpin\n\
+ let c=0\n\
+ :test\n\
+ let $c=$mid($x,c,1)\n\
+ if $c<\"0\" goto getpin\n\
+ if $c>\"9\" goto getpin\n\
+ inc c\n\
+ if c<4 goto test\n\
+ let a=val($x)\n\
+ if a<0 goto getpin\n\
+ if a>9999 goto getpin\n\
+ let $c=$left($x,4)\n\
+ :enterpin\n\
+ send \"AT+CPIN=\\\"\"\n\
+ send $c\n\
+ send \"\\\"^m\"\n\
+ waitfor 20 \"OK\",\"ERR\"\n\
+ if % = -1 goto timeerror\n\
+ if % = 0 goto cont\n\
+ if % = 1 goto pinerror\n\
+ :pinerror\n\
+ :timeerror\n\
+ print \"ERROR entering PIN code\n\"\n\
+ print \"Caution! - entering the wrong PIN code three times will lock the SIM\n\"\n\
+ exit 1\n\
+ :ready\n\
+ print \"SIM ready\n\"\n\
+ :cont\n\
+ print \"Waiting for Registration..(120 sec max)\"\n\
+ let c = 0\n\
+ :waitreg\n\
+ send \"AT+CREG?^m\"\n\
+ waitfor 2 \"+CREG: 0,1\",\"+CREG: 0,5\"\n\
+ if % = -1 goto regagain\n\
+ if % = 0 goto homereg\n\
+ if % = 1 goto roamreg\n\
+ :regagain\n\
+ if c > 120 goto regtimeout\n\
+ let c=c+2\n\
+ print \".\"\n\
+ goto waitreg\n\
+ :regtimeout\n\
+ print \"\nFailed to register\n\"\n\
+ exit 1\n\
+ :homereg\n\
+ print \"\nRegistered on Home network: \"\n\
+ goto registered\n\
+ :roamreg\n\
+ print \"\nRegistered on Roaming network: \"\n\
+ goto registered\n\
+ :registered\n\
+ waitquiet 1 0.1\n\
+ send \"AT+COPS?^m\"\n\
+ get 2 \"^m\" $s\n\
+ get 2 \"^m\" $s\n\
+ let a=len($s)\n\
+ let b=a-12\n\
+ if b < 1 goto regtimeout\n\
+ let $c=$right($s,b)\n\
+ print $c,\"\n\"\n\
+ let c=0\n\
+ :signal\n\
+ waitquiet 1 0.1\n\
+ send \"AT+CSQ^m\"\n\
+ get 2 \"^m\" $s\n\
+ get 2 \"^m\" $s\n\
+ let a=len($s)\n\
+ let a=a-6\n\
+ let $s=$right($s,a)\n\
+ if $s <> \"0,0\" goto sigcont\n\
+ if c > 3 goto sigexit\n\
+ let c=c+1\n\
+ pause 1\n\
+ goto signal\n\
+ :sigexit\n\
+ print \"Signal strength measure 0,0 too low!\"\n\
+ exit 1\n\
+ :sigcont\n\
+ print \"Signal Quality:\",$s,\"\\n\"\n\
+ waitquiet 1 0.1\n";
+
+char _info_code[] =
+ "print \"##### GlobeTrotter Configuration #####\\n\"\n\
+ opengt\n\
+ set com 115200n81\n\
+ set senddelay 0.05\n\
+ waitquiet 2 0.5\n\
+ :manf\n\
+ print \"Manufacturer Text: \"\n\
+ send \"AT+cgmi^m\"\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ let x=len($s)\n\
+ dec x\n\
+ let $s=$right($s,x)\n\
+ print $s,\"\\n\"\n\
+ :imei_serial\n\
+ waitquiet 5 0.1\n\
+ print \"IMEI and Serial Number: \"\n\
+ send \"AT+GSN^m\"\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ let x=len($s)\n\
+ dec x\n\
+ let $s=$right($s,x)\n\
+ print ,$s,\"\\n\"\n\
+ :firmware\n\
+ waitquiet 5 0.1\n\
+ print \"Manufacturer\'s Revision: \"\n\
+ send \"AT+GMR^m\"\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \"^m\" $s\n\
+ print $s,\"\\n\"\n\
+ :hardware\n\
+ waitquiet 5 0.1\n\
+ print \"Hardware Revision: \"\n\
+ send \"AT_OHWV^m\"\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ print $s,\"\\n\"\n\
+ :networklock\n\
+ waitquiet 5 0.1\n\
+ print \"Network Locked: \"\n\
+ send \"AT+clck=\\\"PN\\\",2^m\"\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ print $s,\"\\n\"\n\
+ waitquiet 5 0.1\n\
+ :customized\n\
+ print \"Customisation: \"\n\
+ send \"AT_ocst^m\"\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \",^m\" $s\n\
+ print $s,\"\\n\"\n\
+ :bandsettings\n\
+ waitquiet 5 0.1\n\
+ print \"Band settings: \"\n\
+ send \"AT_OSBM?^m\"\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ if $s=\"4\" print \"Europe 900/1800MHz \"\n\
+ if $s=\"5\" print \"USA 900/1900MHz \"\n\
+ print \"(\",$s,\")\\n\" \n\
+ :autoattach\n\
+ waitquiet 5 0.1\n\
+ print \"Auto Attach: \"\n\
+ send \"AT_OCGAA?^m\"\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ get 2 \" ^m\" $s\n\
+ print $s,\"\\n\" \n\
+ waitquiet 5 0.1 \n\
+ print \"##### END #####\\n\"" ;
+
+
+char _USA_code[]=
+ "print \"##### Band Change to USA operation #####\\n\"\n\
+ opengt\n\
+ set com 115200n81\n\
+ set senddelay 0.05\n\
+ waitquiet 2 0.5\n\
+ send \"AT_OSBM=5^m\"\n\
+ waitfor 10 \"OK\",\"ERR\"\n\
+ if % = -1 goto timeout\n\
+ if % = 0 goto cont\n\
+ if % = 1 goto error\n\
+ :timeout\n\
+ print \"Timeout Error communicating with device.\n\"\n\
+ exit 1\n\
+ :error\n\
+ print \"Error response from device.\n\"\n\
+ exit 1\n\
+ :cont\n\
+ print \"Complete\\n\"\n";
+
+char _Europe_code[] =
+ "print \"##### Band Change to European operation #####\\n\"\n\
+ opengt\n\
+ set com 115200n81\n\
+ set senddelay 0.05\n\
+ waitquiet 2 0.5\n\
+ send \"AT_OSBM=4^m\"\n\
+ waitfor 10 \"OK\",\"ERR\"\n\
+ if % = -1 goto timeout\n\
+ if % = 0 goto cont\n\
+ if % = 1 goto error\n\
+ :timeout\n\
+ print \"Timeout Error communicating with device.\n\"\n\
+ exit 1\n\
+ :error\n\
+ print \"Error response from device.\n\"\n\
+ exit 1\n\
+ :cont\n\
+ print \"Complete\\n\"\n";
+
+char _sig_code[] =
+ "opengt\n\
+ set com 115200n81\n\
+ set senddelay 0.05\n\
+ waitquiet 2 0.5\n\
+ let c=0\n\
+ :signal\n\
+ waitquiet 1 0.1\n\
+ send \"AT+CSQ^m\"\n\
+ get 2 \"^m\" $s\n\
+ get 2 \"^m\" $s\n\
+ let a=len($s)\n\
+ let a=a-6\n\
+ let $s=$right($s,a)\n\
+ if $s <> \"0,0\" goto sigcont\n\
+ if c > 3 goto sigexit\n\
+ let c=c+1\n\
+ pause 1\n\
+ goto signal\n\
+ :sigexit\n\
+ print \"Signal strength measure 0,0 too low!\"\n\
+ exit 1\n\
+ :sigcont\n\
+ print \"Signal Quality:\",$s,\"\\n\"\n\
+ waitquiet 1 0.1\n\
+ exit 0\n";
+
+char _reg_code[] =
+ "opengt\n\
+ set com 115200n81\n\
+ set senddelay 0.05\n\
+ waitquiet 2 0.5\n\
+ print \"Waiting for Registration\"\n\
+ let c = 0\n\
+ :waitreg\n\
+ send \"AT+CREG?^m\"\n\
+ waitfor 2 \"+CREG: 0,1\",\"+CREG: 0,5\"\n\
+ if % = -1 goto regagain\n\
+ if % = 0 goto homereg\n\
+ if % = 1 goto roamreg\n\
+ :regagain\n\
+ if c > 120 goto regtimeout\n\
+ let c=c+2\n\
+ print \".\"\n\
+ goto waitreg\n\
+ :regtimeout\n\
+ print \"\nFailed to register\n\"\n\
+ exit 1\n\
+ :homereg\n\
+ print \"\nRegistered on Home network: \"\n\
+ goto registered\n\
+ :roamreg\n\
+ print \"\nRegistered on Roaming network: \"\n\
+ goto registered\n\
+ :registered\n\
+ waitquiet 1 0.1\n\
+ send \"AT+COPS?^m\"\n\
+ get 2 \"^m\" $s\n\
+ get 2 \"^m\" $s\n\
+ let a=len($s)\n\
+ let b=a-12\n\
+ if b < 1 goto regtimeout\n\
+ let $c=$right($s,b)\n\
+ print $c,\"\n\"\n";
+
+char _3G2G_mode_code[] =
+ "opengt\n\
+ set com 115200n81\n\
+ set senddelay 0.05\n\
+ waitquiet 1 0.2\n\
+ send \"AT_OPSYS=3^m\"\n\
+ waitfor 10 \"OK\",\"ERR\"\n\
+ if % = -1 goto timeout\n\
+ if % = 0 goto cont\n\
+ if % = 1 goto error\n\
+ :timeout\n\
+ print \"Timeout Error communicating with device.\n\"\n\
+ exit 1\n\
+ :error\n\
+ print \"Error response from device.\n\"\n\
+ exit 1\n\
+ :cont\n\
+ print \"Set 3G preferred mode\\n\"\n";
+
+
+char _3G_mode_code[] =
+ "opengt\n\
+ set com 115200n81\n\
+ set senddelay 0.05\n\
+ waitquiet 1 0.2\n\
+ send \"AT_OPSYS=1^m\"\n\
+ waitfor 10 \"OK\",\"ERR\"\n\
+ if % = -1 goto timeout\n\
+ if % = 0 goto cont\n\
+ if % = 1 goto error\n\
+ :timeout\n\
+ print \"Timeout Error communicating with device.\n\"\n\
+ exit 1\n\
+ :error\n\
+ print \"Error response from device.\n\"\n\
+ exit 1\n\
+ :cont\n\
+ print \"Set 3G only mode\\n\"\n";
+
+char _2G_mode_code[] =
+ "opengt\n\
+ set com 115200n81\n\
+ set senddelay 0.05\n\
+ waitquiet 1 0.2\n\
+ send \"AT_OPSYS=0^m\"\n\
+ waitfor 10 \"OK\",\"ERR\"\n\
+ if % = -1 goto timeout\n\
+ if % = 0 goto cont\n\
+ if % = 1 goto error\n\
+ :timeout\n\
+ print \"Timeout Error communicating with device.\n\"\n\
+ exit 1\n\
+ :error\n\
+ print \"Error response from device.\n\"\n\
+ exit 1\n\
+ :cont\n\
+ print \"Set 2G only mode\\n\"\n";
+
+char _GTEDGE_code[] =
+ "opengt\n\
+ set com 57600n81\n\
+ send \"AT+CFUN=1^m\"\n\
+ waitquiet 5 0.2";
+
+char _help_code[] =
+ "print \"gcom Version 0.3\n Usage: \"\n\
+ print \"gcom [options] [built in script]'|[external script]\n\n\"\n\
+ print \"Built in scripts -\n\"\n\
+ print \" gcom [default] Checks SIM status (requests PIN if required),\n\"\n\
+ print \" registration and signal strength reported by\n\"\n\
+ print \" datacard.\n\"\n\
+ print \" gcom info Display configuration of datacard.\n\"\n\
+ print \" gcom sig Report Signal strength.\n\"\n\
+ print \" gcom reg Report Registration status.\n\"\n\
+ print \"\n Valid for GlobeTrotter GPRS only:\n\"\n\
+ print \" gcom USA Switch to 900/1900 MHz band for USA operation.\n\"\n\
+ print \" gcom Europe Switch to 900/1800 MHz band for Europen operation.\n\"\n\
+ print \"\n Valid for GlobeTrotter EDGE and Combo EDGE only:\n\"\n\
+ print \" gcom GTEDGE Switch on radio interface.\n\"\n\
+ print \"\n Valid for Vodafone 3G, GlobeTrotter Fusion :\n\"\n\
+ print \" gcom 2G 2G networks only.\n\"\n\
+ print \" gcom 3G 3G networks only\n\"\n\
+ print \" gcom 3G2G 3G network preferred\n\"\n\
+ print \"\nCommand line options (must be before script name) - \\n\"\n\
+ print \" -d device Use alternative device. e.g -d /dev/ttyUSB0\n\"\n\
+ print \" -e Turn on communication echo.\n\"\n\
+ print \" -h Help.\n\"\n\
+ print \" -s Don't run internal 'default' script before running\n\"\n\
+ print \" external script.\n\"\n\
+ print \" -t=\"\\n\" Set alternative line terminator (default=\"\\n\").\n\"\n\
+ print \" -v Verbose mode. Print lots of trace info.\n\"\n\
+ print \" -x Speed exchange. 115200 replaced by 57600.\n\"\n\
+ print \" ***used for GlobeTrotter EDGE and Combo EDGE***\n\"\n\
+ print \"NOTES:\ngcom assumes that the GlobeTrotter device is /dev/modem (create a logical link\n\"\n\
+ print \"to actual device or use -d switch). Unless you use the '-s' switch gcom will\n\"\n\
+ print \"run the internal 'default' script first before running an external script file.\n\"\n" ;
+
+char *get_code(char* name){
+ if(strlen(name)==0) return(_default_code);
+ if (strcmp(name,"default")==0) return (_default_code);
+ if (strcmp(name,"help")==0) return (_help_code);
+ if (strcmp(name,"info")==0) return (_info_code);
+ if (strcmp(name,"USA")==0) return (_USA_code);
+ if (strcmp(name,"Europe")==0) return (_Europe_code);
+ if (strcmp(name,"sig")==0) return (_sig_code);
+ if (strcmp(name,"reg")==0) return (_reg_code);
+ if (strcmp(name,"GTEDGE")==0) return (_GTEDGE_code);
+ if (strcmp(name,"2G")==0) return (_2G_mode_code);
+ if (strcmp(name,"3G")==0) return (_3G_mode_code);
+ if (strcmp(name,"3G2G")==0) return (_3G2G_mode_code);
+ return(NULL);
+}
+
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+############################################################################
+# operator - a gcom script for viewing and selecting networks
+#
+# An example of how you might do operator selection when travelling
+# in a foreign country.
+# Big ToDo - improve the interface!!!
+#
+# Copyright (C) 2003 Paul Hardwick <paul@peck.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+###########################################################################
+
+############################################################################
+# $Id: gcom.h 10 2006-01-04 12:40:44Z paul $
+# $HeadURL: http://10.0.0.4/svn/gcom/gcom.h $
+############################################################################
+opengt
+set com 115200n81
+set senddelay 0.05
+waitquiet 2 0.5
+ :operator
+ send "AT+COPS=?^m"
+ waitfor 20 "+COPS=?","Error"
+ if % = -1 goto timeout
+ if % = 0 goto getlist
+ print "Error response from device\n"
+ exit 1
+ :getlist
+ let c=0
+ print "Getting Operator list: "
+ :waiting
+ print "."
+ get 2 "^m" $s
+ if % = -1 goto stillwaiting
+ waitquiet 1 0.2
+ print "\n"
+ print $s,"\n\n==============================================================\n"
+ print "Format: (Access,Long Name, Short Name, Network ID [,Technology])\n"
+ print "Access: 2 - Registered, 1 - Available, 3 - Forbidden\n"
+ print "Technology: 0 - GSM/GPRS, 2 - UMTS (Not available on all cards)\n"
+ print "\nEnter the Network ID to attempt manual registration\n [blank = automatic selection]:"
+ input $a
+ let a=len($a)
+ dec a
+ let $a=$left($a,a)
+ if $a = "" goto automatic
+ let $b="AT+COPS=1,2,\""+$a
+ let $b=$b+"\"^m"
+ send $b
+ goto waitresult
+ :automatic
+ let $b="AT+COPS=0^m"
+ send $b
+ :waitresult
+ waitfor 60 "OK","ERR"
+ if % = -1 goto timeout
+ if % = 2 goto failedreg
+ print "Registration request accepted\n"
+ print "Command was: ",$b,"\n"
+ exit 0
+ :failedreg
+ print "Registration request refused\n"
+ print "Command was: ",$b,"\n"
+ exit 1
+ :stillwaiting
+ if c > 60 goto timeout
+ let c=c+1
+ goto waiting
+ :timeout
+ print "Network Search Timeout\n"
+ exit 1
--- /dev/null
+#
+# sigmon - 3G/GPRS datacard signal strength monitor
+#
+if [ $# -eq 1 ]
+then
+ if [ "$1" == '-?' ]
+ then
+ echo "Syntax: sigmon"
+ echo "Function: 3G/GPRS datacard signal strength monitor"
+ echo "Options: none"
+ else
+ echo "Invalid option - $1"
+ fi
+ exit 1
+else
+ if [ $# -gt 1 ]
+ then
+ echo "Error: only one option permitted"
+ exit 1
+ fi
+fi
+
+echo "Use Ctrl/C to terminate monitoring"
+
+while true
+do
+ gcom -d /dev/ttyUSB2 sig
+ sleep 5
+done
+#
+# sigmon - use gmon to continuously monitor signal strength
+# Copyright (C) 2005 Martin Gregorie
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# martin@gregorie.org
+#
+
--- /dev/null
+.\" Paul Hardwick
+.\" paul@peck.org.uk
+.TH sigmon 1 "22 January, 2005"
+.LO 1
+.SH NAME
+sigmon \- Vodafone 3G/GPRS datacard signal strength monitor
+.SH SYNOPSIS
+.B sigmon -?
+
+.SH OPTIONS
+.in +5
+.B \-?
+.in +10
+gives brief usage details
+.in -10
+
+.SH DESCRIPTION
+.B sigmon
+is a command line tool for monitoring the signal strength seen by a Vodafone
+3G/GPRS datacard. Once started, it queries the datacard for the signal
+strength and displays it every 5 seconds. Use
+.I Ctrl/C
+to stop the signal strength display and exit from
+.B sigmon
+
+.SH BUGS
+.B sigmon
+is a simple script that assumes that the third port of the datacard is
+/dev/ttyUSB2. If the datacard is not the first USB device registered the
+script must be modified to correct the port name. Read /var/log/messages
+to find the correct port name.
+
+.SH DEPENDENCIES
+.B sigmon
+requires
+.I gcom
+to be installed so that it appears in the current search path when
+.B sigmon
+is run.
+