[AMG]: '''execline''' [http://www.skarnet.org/software/execline/] is a non-interactive scripting language. It is designed to be secure and embeddable. The '''execline''' and '''execlineb''' languages are extremely minimal, and all runtime functionality is provided by external programs. One highly unusual yet important aspect of '''execline''' is that while the script is running, ''the interpreter is not resident.'' In a manner of speaking, the script runs itself! This is accomplished through massive amounts of Bernstein chaining: every program does its thing then execs into the next program. '''execline''' comes with a suite of commands for providing the basics. See the '''execline''' page for the full list and links to manuals. It is important to note that some of the section headings on the '''execline''' page are themselves links. ---- To show a little bit about how this language works, here's my '''/service/clockspeed_adjust/run''' script. This script periodically gets the time from an NTP server so that '''clockspeed''' [http://cr.yp.to/clockspeed.html] can gauge the actual speed of the hardware clock. #!/command/execlineb # Redirect stderr to stdout. fdmove -c 2 1 # Switch to clockspeed_adjust's UID and GID. envuidgid Gclockspeed_adjust # Limit the the size of the data segment. softlimit -d 131072 # Get the IP address of the NTP server. backtick -n SERVER { head -1 cfg/SERVER } # Loop forever. loopwhile { # Obtain timing mark for calibrating clockspeed adjustment. foreground { echo "Obtaining new calibration mark from ${SERVER}:" } foreground { pipeline { sntpclock ${SERVER} } pipeline { tee /package/misc/spf/clockspeed/adjust } clockview } # Read the current "attoseconds" value into the log. foreground { echo "Viewing current attoseconds in hardware tick:" } foreground { redirfd -r 0 /package/misc/spf/clockspeed/etc/atto clockview } # Grab the current values of WAIT and WAIT_MAX. multisubstitute { backtick -n WAIT { head -1 cfg/WAIT } backtick -n WAIT_MAX { head -1 cfg/WAIT_MAX } } # Wait. foreground { echo "Waiting ${WAIT} seconds until next adjustment..." } foreground { sleep ${WAIT} } # Compute the new value for $WAIT. backtick -n WAIT_NEW { expr ${WAIT} * 3 } redirfd -w 1 cfg/WAIT ifthenelse { test ${WAIT_NEW} -lt ${WAIT_MAX} } { echo ${WAIT_NEW} } { echo ${WAIT_MAX} } } # vim: set ts=4 sts=4 sw=4 tw=80 et: '''execlineb''' reads in this script, strips comments, converts the brace notation to the tilde notation used by '''execline''' and friends, then execs into the resulting "script". In this case that means running '''fdmove -c 2 1 envuidgid Gclockspeed_adjust softlimit -d 131072 backtick -n SERVER ~head ~-1 ~cfg/SERVER ; loopwhile ...'''. If you want to see the full shebang, get execline, put the above script in a file, add '''echo''' as the first command, then run it. (Do it! This will give you an important insight into how '''execline''' really works.) Anyway, '''fdmove''' starts, redirects its stderr to its stdout, then execs into '''envuidgid'''. And so on. '''backtick''' forks and execs into '''head''', collects its stdout, substitutes it for every occurrence of '''${SERVER}''' in the remainder of its argv, and execs into '''loopwhile''' with the modified argv. '''loopwhile''' repeatedly fork/execs into its "first" argument (everything up until the ''';''' which corresponds to the closing brace). I think you get the picture. Even though there's no resident interpreter, the above script manages to maintain state. It does so through the filesystem. At the end of the loop, it computes a value and writes it into the file '''cfg/WAIT'''. At the beginning of the loop, it reads a value from '''cfg/WAIT''' and substitutes it for '''${WAIT}'''. Kinda neat, I think. A language simpler than [lisp], hehehe. <> Language