linuxcnc.in
1 #!/bin/bash 2 ################################################################################ 3 # usage: linuxcnc [options] [<ini-file>] 4 # 5 # options: 6 # -v = verbose - prints info as it works 7 # -d = echos script commands to screen for debugging 8 # 9 # this version calls pickconfig.tcl to pick an ini file if one 10 # is not specified on the command line 11 # 12 ################################################################################ 13 # Author: 14 # License: GPL Version 2 15 # System: Linux 16 # 17 # Copyright (c) 2004-2009 All rights reserved. 18 ################################################################################ 19 20 # -1. Get all rip-environment items if we are RIP 21 if test "xyes" = "x@RUN_IN_PLACE@"; then 22 if test "${EMC2_HOME:-}" != "@EMC2_HOME@"; then 23 exec @EMC2_HOME@/scripts/rip-environment linuxcnc "$@" 24 fi 25 fi 26 27 ################################################################################ 28 # 0. Values that come from configure 29 ################################################################################ 30 prefix=@prefix@ 31 exec_prefix=@exec_prefix@ 32 33 PIDOF="@PIDOF@ -x" 34 PS=@PS@ 35 AWK=@AWK@ 36 GREP=@GREP@ 37 IPCS=@IPCS@ 38 KILL=@KILL@ 39 40 LINUXCNC_HOME=@EMC2_HOME@; export LINUXCNC_HOME 41 42 LINUXCNC_BIN_DIR=@EMC2_BIN_DIR@ 43 LINUXCNC_TCL_DIR=@EMC2_TCL_DIR@ 44 LINUXCNC_HELP_DIR=@EMC2_HELP_DIR@ 45 LINUXCNC_RTLIB_DIR=@EMC2_RTLIB_DIR@ 46 LINUXCNC_CONFIG_PATH="@LINUXCNC_CONFIG_PATH@" 47 LINUXCNC_NCFILES_DIR=@EMC2_NCFILES_DIR@ 48 LINUXCNC_LANG_DIR=@EMC2_LANG_DIR@ 49 REALTIME=@REALTIME@ 50 LINUXCNC_IMAGEDIR=@EMC2_IMAGE_DIR@ 51 LINUXCNC_TCL_LIB_DIR=@EMC2_TCL_LIB_DIR@ 52 HALLIB_DIR=@HALLIB_DIR@; export HALLIB_DIR 53 HALLIB_PATH=.:$HALLIB_DIR; export HALLIB_PATH 54 55 # put ~.local/bin in PATH if missing. See: 56 # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=839155 57 if [ -d $HOME/.local/bin ]; then 58 if [[ "$PATH" != *".local/bin"* ]]; then 59 PATH=$HOME/.local/bin:$PATH 60 fi 61 fi 62 63 #put the LINUXCNC_BIN_DIR in PATH 64 PATH=$LINUXCNC_BIN_DIR:$PATH 65 #ditto scripts if not RIP 66 [ -d $LINUXCNC_HOME/scripts ] && PATH=$LINUXCNC_HOME/scripts:$PATH 67 68 if test "xyes" = "x@RUN_IN_PLACE@"; then 69 if [ -z "$LD_LIBRARY_PATH" ]; then 70 LD_LIBRARY_PATH=$LINUXCNC_HOME/lib 71 else 72 LD_LIBRARY_PATH=$LINUXCNC_HOME/lib:"$LD_LIBRARY_PATH" 73 fi 74 export LD_LIBRARY_PATH 75 fi 76 77 if [ -z "$PYTHONPATH" ]; then 78 PYTHONPATH=$LINUXCNC_HOME/lib/python 79 else 80 PYTHONPATH=$LINUXCNC_HOME/lib/python:"$PYTHONPATH" 81 fi 82 export PYTHONPATH 83 84 85 MODULE_EXT=@MODEXT@ # module extension, used when insmod'ing 86 87 DEBUG_FILE=$(mktemp /tmp/linuxcnc.debug.XXXXXX) 88 PRINT_FILE=$(mktemp /tmp/linuxcnc.print.XXXXXX) 89 90 program_available () { 91 type -path "$1" > /dev/null 2>&1 92 } 93 94 usage () { 95 P=${0##*/} 96 cat <<EOF 97 $P: Run LINUXCNC 98 99 Usage: 100 $P [-d] [-v] 101 Choose the configuration file graphically 102 103 $P [-k] [-d] [-v] path/to/your.ini 104 Name the configuration file using its path 105 106 $P [-k] [-d] [-v] -l 107 Use the previous configuration file 108 109 -d: Turn on "debug" mode 110 -v: Turn on "verbose" mode 111 -k: Continue in the presence of errors in .hal files 112 EOF 113 114 } 115 116 ################################################################################ 117 # 1.1. strip and process command line options 118 ################################################################################ 119 while getopts "dvlhkr" opt 120 do 121 case "$opt" in 122 d) 123 # enable echoing of script and command output 124 if tty -s; then 125 DEBUG_FILE=/dev/fd/2 126 echo "Debug mode on" >$DEBUG_FILE 127 fi 128 set -x;; 129 v) 130 # enable printing of verbose messages 131 if tty -s; then 132 PRINT_FILE=/dev/fd/1 133 echo "Verbose mode on" >$PRINT_FILE 134 fi;; 135 r) 136 RUNTESTS=yes 137 ;; 138 l) 139 USE_LAST_INIFILE=1;; 140 k) DASHK=-k;; 141 h) 142 usage 143 exit 0;; 144 *) 145 usage 146 exit 1 147 esac 148 done 149 shift $(($OPTIND-1)) 150 151 case "@KERNEL_VERS@" in 152 "") ;; 153 *) 154 if [ `uname -r` != "@KERNEL_VERS@" ]; then 155 if tty -s; then 156 echo "LinuxCNC requires the real-time kernel @KERNEL_VERS@ to run." 157 echo "Before running LinuxCNC, reboot and choose this kernel at the boot menu." 158 else 159 @WISH@ <<EOF 160 wm wi . 161 tk_messageBox -type ok \ 162 -title LinuxCNC -icon error -title "Realtime Kernel Required" \ 163 -message {LinuxCNC requires the real-time kernel @KERNEL_VERS@ to run. Before running LinuxCNC, reboot and choose this kernel at the boot menu.} 164 exit 165 EOF 166 fi 167 exit 168 fi 169 esac 170 171 if [ -z $RUNTESTS ]; then 172 if ! tty -s; then 173 exec 2>> $DEBUG_FILE 174 exec >> $PRINT_FILE 175 fi 176 fi 177 178 function ErrorCheck () { 179 result=$? 180 if [ ! -z "$DISPLAY" ]; then 181 echo "catch {send -async popimage destroy .}; destroy ." | @WISH@ 182 fi 183 184 if [ $result -ne 0 ]; then 185 if tty -s || [ -z "$DISPLAY" ] ; then 186 if [ -f $DEBUG_FILE ]; then 187 cp $DEBUG_FILE $HOME/linuxcnc_debug.txt 188 else 189 echo "(debug information was sent to stderr)" \ 190 > $HOME/linuxcnc_debug.txt 191 fi 192 193 if [ -f $PRINT_FILE ]; then 194 cp $PRINT_FILE $HOME/linuxcnc_print.txt 195 else 196 echo "(print information was sent to stdout)" \ 197 > $HOME/linuxcnc_print.txt 198 fi 199 200 echo "\ 201 LinuxCNC terminated with an error. You can find more information in the log: 202 $HOME/linuxcnc_debug.txt 203 and 204 $HOME/linuxcnc_print.txt 205 as well as in the output of the shell command 'dmesg' and in the terminal" 206 else 207 @WISH@ $LINUXCNC_TCL_DIR/show_errors.tcl $DEBUG_FILE $PRINT_FILE 208 fi 209 fi 210 rm -f $DEBUG_FILE $PRINT_FILE 2>/dev/null 211 exit $result 212 } 213 214 trap ErrorCheck EXIT 215 216 ################################################################################ 217 # 1.3. INIFILE find inifile to use # 218 ################################################################################ 219 220 if [ ! -z "$1" ]; then 221 case "$1" in 222 -) USE_LAST_INIFILE=1;; 223 /*) INIFILE="$1" ;; 224 *) INIFILE="`pwd`/$1";; 225 esac 226 shift 227 fi 228 EXTRA_ARGS="$@" 229 230 # 1.3.1. Determine if we have run-in place or installed system 231 RUN_IN_PLACE=@RUN_IN_PLACE@ 232 echo RUN_IN_PLACE=$RUN_IN_PLACE >>$PRINT_FILE 233 234 LINUXCNCVERSION="@EMC2VERSION@"; export LINUXCNCVERSION 235 236 # common from here.. 237 INIVAR=inivar 238 HALCMD="halcmd $DASHK" 239 PICKCONFIG="@WISH@ $LINUXCNC_TCL_DIR/bin/pickconfig.tcl" 240 LINUXCNC_EMCSH=@WISH@ 241 242 echo LINUXCNC_DIR=$LINUXCNC_DIR >>$PRINT_FILE 243 echo LINUXCNC_BIN_DIR=$LINUXCNC_BIN_DIR >>$PRINT_FILE 244 echo LINUXCNC_TCL_DIR=$LINUXCNC_TCL_DIR >>$PRINT_FILE 245 echo LINUXCNC_SCRIPT_DIR=$LINUXCNC_SCRIPT_DIR >>$PRINT_FILE 246 echo LINUXCNC_RTLIB_DIR=$LINUXCNC_RTLIB_DIR >>$PRINT_FILE 247 echo LINUXCNC_CONFIG_DIR=$LINUXCNC_CONFIG_DIR >>$PRINT_FILE 248 echo LINUXCNC_LANG_DIR=$LINUXCNC_LANG_DIR >>$PRINT_FILE 249 echo INIVAR=$INIVAR >>$PRINT_FILE 250 echo HALCMD=$HALCMD >>$PRINT_FILE 251 echo LINUXCNC_EMCSH=$LINUXCNC_EMCSH >>$PRINT_FILE 252 253 #export some common directories, used by some of the GUI's 254 export LINUXCNC_TCL_DIR 255 export LINUXCNC_EMCSH 256 export LINUXCNC_HELP_DIR 257 export LINUXCNC_LANG_DIR 258 export REALTIME 259 export HALCMD 260 export LINUXCNC_NCFILES_DIR 261 262 [ -z $RUNTESTS ] && echo "LINUXCNC - $LINUXCNCVERSION" 263 264 # was an inifile specified on the command line? 265 if [ ! -z "$USE_LAST_INIFILE" ]; then 266 INIFILE=$($INIVAR -ini ~/.linuxcncrc -var LAST_CONFIG -sec PICKCONFIG 2>>$DEBUG_FILE) 267 echo "Using previous inifile: $INIFILE" >> $PRINT_FILE 268 fi 269 270 if [ ! -n "$INIFILE" ] ; then 271 # nothing specified, get from the user 272 # it returns either a path, or nothing at all 273 INIFILE=$($PICKCONFIG) 274 # if name is xxxx.demo, then: 275 # execute xxxx.demo in background and exit 276 if [ "${INIFILE%%.demo}".demo = "${INIFILE}" ] ; then 277 "${INIFILE}" & 278 exit 0 279 fi 280 fi 281 282 if [ ! -n "$INIFILE" ] ; then 283 # still nothing specified, exit 284 exit 0 285 fi 286 287 function handle_includes () { 288 hdr="# handle_includes():" 289 inifile="$1" 290 cd "$(dirname $inifile)" ;# for the function() subprocess only 291 $GREP "^#INCLUDE" "$inifile" >/dev/null 292 status=$? 293 if [ $status -ne 0 ] ; then 294 echo "$inifile" ;# just use the input 295 return 0 ;# ok 296 fi 297 outfile="$(dirname $inifile)/$(basename $inifile).expanded" 298 >|"$outfile" 299 echo "#*** $outfile" >>"$outfile" 300 echo "#*** Created: $(date)" >>"$outfile" 301 echo "#*** Autogenerated file with expanded #INCLUDEs" >>"$outfile" 302 echo "" >>"$outfile" 303 line=0 304 while read a b ; do 305 line=$((line + 1)) 306 if [ "$a" = "#INCLUDE" ] ; then 307 if [ "X$b" = "X" ] ; then 308 msg="$hdr <$line> found #INCLUDE with no filename" >>"$outfile" 309 echo "$msg" >&2 310 echo "$msg" >>"$outfile" 311 else 312 # expand file name 313 breal=$(eval echo "$b") 314 # -r: readable 315 if [ -r "$breal" ] ; then 316 echo "" >>"$outfile" 317 echo "#*** Begin #INCLUDE file: $breal" >>"$outfile" 318 cat "$breal" >>"$outfile" 319 echo "#*** End #INCLUDE file: $breal" >>"$outfile" 320 else 321 msg="$hdr <$line> CANNOT READ $breal" 322 echo "$msg" >&2 323 echo "$msg" >>"$outfile" 324 fi 325 fi 326 else 327 echo "$a $b" >> "$outfile" 328 fi 329 done <"$inifile" 330 echo "$outfile" ;# use the expanded file 331 return 0 ;# ok 332 } 333 334 function split_app_items () { 335 app_name=$1 336 shift 337 app_args=$* 338 } 339 340 function run_applications () { 341 NUM=1 342 APPFILE=`$INIVAR -tildeexpand -ini "$INIFILE" -var APP -sec APPLICATIONS -num $NUM 2> /dev/null` 343 if [ -z "$APPFILE" ] ; then return ; fi 344 DEFAULT_APPLICATION_DELAY=0 345 GetFromIni DELAY APPLICATIONS 346 DELAY=${retval:-$DEFAULT_APPLICATION_DELAY} 347 while [ -n "$APPFILE" ] ; do 348 split_app_items $APPFILE # --> app_name app_args 349 # try all explicit specifications before trying PATH 350 case "$app_name" in 351 /*) # absolute pathname 352 exe_name=$app_name;; 353 \./*) # name relative to inifile directory 354 exe_name="$(pwd)/$app_name";; 355 *) # try local first then PATH 356 exe_name=$(pwd)/$app_name 357 if [ ! -x $exe_name ] ; then 358 exe_name=$(which $app_name) 359 fi 360 esac 361 if [ ! -f "$exe_name" ] ; then 362 echo "APP: Cannot find executable file for: <$app_name>" 363 else 364 if [ ! -x "$exe_name" ] ; then 365 echo "APP: File not executable: <$exe_name>" 366 else 367 echo "APP: $app_name found: <$exe_name>" 368 (sleep $DELAY; eval $exe_name $app_args) & 369 fi 370 fi 371 NUM=$(($NUM+1)) 372 APPFILE=`$INIVAR -tildeexpand -ini "$INIFILE" -var APP -sec APPLICATIONS -num $NUM 2> /dev/null` 373 done 374 } 375 376 INIFILE="$(handle_includes "$INIFILE")" 377 378 # delete directories from path, save name only 379 INI_NAME="${INIFILE##*/}" 380 INI_DIR="${INIFILE%/*}" 381 CONFIG_DIR="${INIFILE%/*}" 382 export CONFIG_DIR 383 export PATH=$CONFIG_DIR/bin:$PATH 384 385 [ -z $RUNTESTS ] && echo "Machine configuration directory is '$INI_DIR'" 386 echo "Machine configuration file is '$INI_NAME'" 387 388 # make sure ini file exists (the tcl script just did this, so we could 389 # eliminate this test, but it does no harm) 390 391 if [ ! -f "$INIFILE" ] ; then 392 echo "Could not find ini file '$INIFILE'" 393 trap '' EXIT 394 exit -1 395 fi 396 echo INIFILE="$INIFILE" >>$PRINT_FILE 397 398 ################################################################################ 399 # 2. extract info from the ini file that we will need later 400 ################################################################################ 401 retval= 402 403 # 2.1. define helper function 404 function GetFromIniQuiet { 405 #$1 var name $2 - section name 406 name=$1 407 retval=`$INIVAR -ini "$INIFILE" -var $1 -sec $2 2> /dev/null` 408 if [ ! -n "$1" ] ; then 409 exit -1 410 fi 411 echo "$name=$retval" >>$PRINT_FILE 412 } 413 414 function GetFromIni { 415 #$1 var name $2 - section name 416 name=$1 417 retval=`$INIVAR -ini "$INIFILE" -var $1 -sec $2 2>>$DEBUG_FILE` 418 if [ ! -n "$1" ] ; then 419 echo "Can't find variable $1 in section [$2] of file $INIFILE." 420 exit -1 421 fi 422 echo "$name=$retval" >>$PRINT_FILE 423 } 424 425 # Usage: 426 # GetFromIniEx VAR1 SEC1 [VAR2 SEC2...VARn SECn] [default] 427 function GetFromIniEx { 428 original_var="[$2]$1" 429 while [ $# -ge 2 ]; do 430 if retval=`$INIVAR -ini "$INIFILE" -var "$1" -sec "$2" 2>/dev/null`; then return; fi 431 shift 2 432 done 433 if [ $# -eq 0 ]; then 434 echo "Can't find $original_var in $INIFILE." 435 exit -1 436 fi 437 retval="$1" 438 } 439 440 # 2.1.5 check version 441 GetFromIni VERSION EMC 442 if [ "$retval" != "1.1" ]; then 443 if [ -z "$DISPLAY" ]; then 444 echo "ini file [EMC]VERSION indicates update is needed, but the update GUI can't run without an X display" 445 exit 1 446 fi 447 update_ini -d "$INIFILE" 448 exitval=$? 449 case "$exitval" in 450 0) ;; 451 42) echo "update_ini cancelled by user" ; exit 0;; 452 *) echo "update script failed in an unexpected way."; exit $exitval ;; 453 esac 454 fi 455 456 @TCLSH@ $HALLIB_DIR/check_config.tcl "$INIFILE" 457 exitval=$? 458 case "$exitval" in 459 0) ;; 460 1) echo "check_config validation failed"; exit $exitval ;; 461 *) echo "check_config validation failed in an unexpected way."; exit $exitval ;; 462 esac 463 # 2.2. get param file 464 465 GetFromIni PARAMETER_FILE RS274NGC 466 RS274NGC_PARAMFILE=$retval 467 468 # 2.3. get mot information 469 GetFromIniEx MOT MOT EMCMOT EMCMOT motmod 470 EMCMOT=$retval$MODULE_EXT # add module extension 471 472 # 2.4. get io information 473 GetFromIniEx IO IO EMCIO EMCIO io 474 EMCIO=$retval 475 476 # 2.5. get task information 477 GetFromIni TASK TASK 478 EMCTASK=$retval 479 480 if [ "$EMCTASK" = emctask ]; then EMCTASK=linuxcnctask; fi 481 482 # 2.6. we hardcode the server name, change if needed 483 # linuxcncsvr now holds/creates all the NML channels, 484 # so it needs to start by default, as the first process 485 EMCSERVER=linuxcncsvr 486 487 # 2.7. get halui information 488 GetFromIniQuiet HALUI HAL 489 HALUI=$retval 490 491 # 2.8. get display information 492 GetFromIni DISPLAY DISPLAY 493 EMCDISPLAY=`(set -- $retval ; echo $1 )` 494 EMCDISPLAYARGS=`(set -- $retval ; shift ; echo $* )` 495 496 case $EMCDISPLAY in 497 tkemc) EMCDISPLAY=tklinuxcnc ;; 498 esac 499 500 # 2.9. get NML config information 501 GetFromIniEx NML_FILE LINUXCNC NML_FILE EMC @DEFAULT_NMLFILE@ 502 NMLFILE=$retval 503 export NMLFILE 504 505 # 2.10. INI information that may be needed by other apps in process tree 506 GetFromIni COORDINATES TRAJ 507 TRAJ_COORDINATES=$retval 508 export TRAJ_COORDINATES 509 510 GetFromIni KINEMATICS KINS 511 KINS_KINEMATICS=$retval 512 export KINS_KINEMATICS 513 514 ################################################################################ 515 # 3. Done gathering information, define a few functions 516 # Execution resumes after function definitions... 517 ################################################################################ 518 519 KILL_TASK= 520 KILL_TIMEOUT=20 521 522 ################################################################################ 523 # 3.1. Kills a list of tasks with timeout 524 # if it doesn't work, kill -9 is used 525 ################################################################################ 526 function KillTaskWithTimeout() { 527 if [ ! -n "$KILL_PIDS" ] ; then 528 KILL_PIDS=`$PIDOF $KILL_TASK` 529 fi 530 if [ ! -n "$KILL_PIDS" ] ; then 531 echo "Could not find pid(s) for task $KILL_TASK" 532 return -1 533 fi 534 local NPROCS 535 for KILL_PID in $KILL_PIDS ; do 536 if $PS -o comm= $KILL_PID | $GREP -q '<defunct>'; then 537 echo "Skipping defunct task $KILL_TASK, PID=$KILL_PID" >>$PRINT_FILE 538 continue 539 fi 540 # first a "gentle" kill with signal TERM 541 $KILL $KILL_PID 542 WAIT=$KILL_TIMEOUT 543 # wait and see if it dissappears 544 while [ $WAIT -gt 1 ] ; do 545 # see if it's still alive 546 NPROCS=$($PS -o comm= $KILL_PID | $GREP -v '<defunct>' | wc -l) 547 if [ $NPROCS -gt 0 ]; then 548 WAIT=$(($WAIT-1)) 549 sleep .1 550 else 551 WAIT=0 552 fi 553 done 554 if [ $WAIT -gt 0 ] ; then 555 # gentle didn't work, get serious 556 echo "Timeout, trying kill -9" >>$PRINT_FILE 557 $KILL -9 $KILL_PID 558 WAIT=$KILL_TIMEOUT 559 # wait and see if it dissappears 560 while [ $WAIT -gt 1 ] ; do 561 # see if it's still alive 562 NPROCS=$($PS -o comm= $KILL_PID | $GREP -v '<defunct>' | wc -l) 563 if [ $NPROCS -gt 0 ]; then 564 WAIT=$(($WAIT-1)) 565 sleep .1 566 else 567 WAIT=0 568 fi 569 done 570 fi 571 if [ $WAIT -gt 0 ] ; then 572 echo "Could not kill task $KILL_TASK, PID=$KILL_PID" 573 fi 574 done 575 KILL_PIDS= 576 KILL_TASK= 577 } 578 579 580 ################################################################################ 581 # 3.2. define the cleanup function 582 # 583 # this cleanup function doesn't know or care what was actually 584 # loaded - it simply kills _any_ processes in its list of 585 # components 586 ################################################################################ 587 function Cleanup() { 588 589 echo "Shutting down and cleaning up LinuxCNC..." 590 # Kill displays first - that should cause an orderly 591 # shutdown of the rest of linuxcnc 592 for KILL_TASK in linuxcncpanel iosh linuxcncsh linuxcncrsh linuxcnctop mdi debuglevel gmoccapy gscreen; do 593 if $PIDOF $KILL_TASK >>$DEBUG_FILE ; then 594 KillTaskWithTimeout 595 fi 596 done 597 598 if program_available axis-remote ; then 599 if [ ! -z "$DISPLAY" ]; then 600 axis-remote --ping && axis-remote --quit 601 fi 602 fi 603 604 if [ "$1" = "other" ]; then 605 echo -n "Waiting for other session to finish exiting..." 606 WAIT=$KILL_TIMEOUT 607 while [ $WAIT -gt 1 ]; do 608 if ! [ -f $LOCKFILE ]; then 609 echo " Ok" 610 return 0 611 fi 612 WAIT=$(($WAIT-1)) 613 sleep .1 614 done 615 echo "lockfile still not removed" 616 fi 617 618 SHUTDOWN=`$INIVAR -ini "$INIFILE" -var SHUTDOWN -sec HAL 2> /dev/null` 619 if [ -n "$SHUTDOWN" ]; then 620 echo "Running HAL shutdown script" 621 $HALCMD -f $SHUTDOWN 622 fi 623 624 # now kill all the other user space components 625 for KILL_TASK in linuxcncsvr milltask; do 626 if $PIDOF $KILL_TASK >>$DEBUG_FILE ; then 627 KillTaskWithTimeout 628 fi 629 done 630 631 echo "Stopping realtime threads" >> $DEBUG_FILE 632 $HALCMD stop 633 echo "Unloading hal components" >> $DEBUG_FILE 634 $HALCMD unload all 635 636 for i in `seq 10`; do 637 # (the one component is the halcmd itself) 638 if [ `$HALCMD list comp | wc -w` = 1 ]; then break; fi 639 sleep .2 640 done 641 642 echo "Removing HAL_LIB, RTAPI, and Real Time OS modules" >>$PRINT_FILE 643 $REALTIME stop 644 645 echo "Removing NML shared memory segments" >> $PRINT_FILE 646 while read b x t x x x x x x m x; do 647 case $b$t in 648 BSHMEM) ipcrm -M $m 2>/dev/null;; 649 esac 650 done < $NMLFILE 651 652 653 # remove lock file 654 if [ -f $LOCKFILE ] ; then 655 rm $LOCKFILE 656 fi 657 } 658 659 660 661 ################################################################################ 662 # 4. done with function definitions, execution resumes here 663 ################################################################################ 664 665 # Name of lock file to check for that signifies that LinuxCNC is up, 666 # to prevent multiple copies of controller 667 LOCKFILE=/tmp/linuxcnc.lock 668 669 # Check for lock file 670 if [ -f $LOCKFILE ]; then 671 if tty -s; then 672 echo -n "LinuxCNC is still running. Restart it? [Y/n] " 673 read input; [ -z $input ] && input=y 674 else 675 input=$(@WISH@ <<EOF 676 wm wi . 677 puts [tk_messageBox -title LinuxCNC -message "LinuxCNC is still running. Restart it?" -type yesno] 678 exit 679 EOF 680 ) 681 fi 682 case $input in 683 y|Y|yes) 684 echo Cleaning up old LinuxCNC... 685 Cleanup other 686 ;; 687 *) 688 echo Not starting new LinuxCNC 689 exit 0 690 ;; 691 esac 692 fi 693 echo Starting LinuxCNC... 694 695 # trap ^C so that it's called if user interrupts script 696 trap 'Cleanup ; exit 0' SIGINT SIGTERM 697 698 # go to the dir where the ini file is 699 # either configs/<specific-config> when run-in-place, or 700 # /usr/local/share/linuxcnc/configs/<specific-config> (wherever it was installed) 701 cd "$INI_DIR" 702 703 # Create the lock file 704 touch $LOCKFILE 705 706 ################################################################################ 707 # 4.1. pop up intro graphic 708 ################################################################################ 709 img=`$INIVAR -ini "$INIFILE" -var INTRO_GRAPHIC -sec DISPLAY 2>>$DEBUG_FILE` 710 imgtime=`$INIVAR -ini "$INIFILE" -var INTRO_TIME -sec DISPLAY 2>>$DEBUG_FILE` 711 if [ "$imgtime" = "" ] ; then 712 imgtime=5 713 fi 714 if [ "$img" != "" ] ; then 715 if [ -e "$img" ]; then 716 true 717 elif [ -e "$INI_DIR/$img" ]; then 718 img="$INI_DIR/$img" 719 elif [ -e "$LINUXCNC_IMAGEDIR/$img" ]; then 720 img="$LINUXCNC_IMAGEDIR/$img" 721 else 722 img= 723 fi 724 fi 725 if [ "$img" != "" ] ; then 726 if [ -x $LINUXCNC_TCL_DIR/bin/popimage ] ; then 727 $LINUXCNC_TCL_DIR/bin/popimage $img $imgtime & 728 fi 729 fi 730 731 ################################################################################ 732 # 4.2. Now we can finally start loading LinuxCNC 733 ################################################################################ 734 735 # 4.3.1. Run linuxcncserver in background, always (it owns/creates the NML buffers) 736 echo "Starting LinuxCNC server program: $EMCSERVER" >>$PRINT_FILE 737 if ! program_available $EMCSERVER; then 738 echo "Can't execute server program $EMCSERVER" 739 Cleanup 740 exit 1 741 fi 742 export INI_FILE_NAME="$INIFILE" 743 $EMCSERVER -ini "$INIFILE" 744 745 # 4.3.2. Start REALTIME 746 echo "Loading Real Time OS, RTAPI, and HAL_LIB modules" >>$PRINT_FILE 747 if ! $REALTIME start ; then 748 echo "Realtime system did not load" 749 Cleanup 750 exit -1 751 fi 752 753 # 4.3.3. export the location of the HAL realtime modules so that 754 # "halcmd loadrt" can find them 755 export HAL_RTMOD_DIR=$LINUXCNC_RTLIB_DIR 756 757 # 4.3.4. Run io in background if so defined in INI 758 if [ "$EMCIO" != "" ] ; then 759 echo "Starting LinuxCNC IO program: $EMCIO" >>$PRINT_FILE 760 if ! program_available $EMCIO ; then 761 echo "Can't execute IO program $EMCIO" 762 Cleanup 763 exit 1 764 fi 765 $HALCMD loadusr -Wn iocontrol $EMCIO -ini "$INIFILE" 766 else 767 echo "Skipping LinuxCNC IO program >>$PRINT_FILE" 768 fi 769 770 # 4.3.5. Run halui in background, if necessary 771 if [ -n "$HALUI" ] ; then 772 echo "Starting HAL User Interface program: $HALUI" >>$PRINT_FILE 773 if ! program_available $HALUI ; then 774 echo "Can't execute halui program $HALUI" 775 Cleanup 776 exit 1 777 fi 778 $HALCMD loadusr -Wn halui $HALUI -ini "$INIFILE" 779 fi 780 781 # 4.3.6. execute HALCMD config files (if any) 782 783 TWOPASS=`$INIVAR -ini "$INIFILE" -var TWOPASS -sec HAL -num 1 2> /dev/null` 784 if [ -n "$TWOPASS" ] ; then 785 # 4.3.6.1. if [HAL]TWOPASS is defined, handle all [HAL]HALFILE entries here: 786 CFGFILE=@EMC2_TCL_LIB_DIR@/twopass.tcl 787 export PRINT_FILE # twopass can append to PRINT_FILE 788 if ! haltcl -i "$INIFILE" $CFGFILE && [ "$DASHK" = "" ]; then 789 Cleanup 790 exit -1 791 fi 792 else 793 # 4.3.6.2. conventional execution of HALCMD config files 794 # get first config file name from ini file 795 NUM=1 796 CFGFILE=`$INIVAR -tildeexpand -ini "$INIFILE" -var HALFILE -sec HAL -num $NUM 2> /dev/null` 797 while [ -n "$CFGFILE" ] ; do 798 IFS='\ ' read CFGFILE CFGFILE_ARGS <<< "$CFGFILE" # separate args 799 foundmsg="" 800 saveIFS=$IFS; IFS=: # colon (:) path separator for HALLIB_PATH 801 explicit_file_in_hallib=${CFGFILE#LIB:} # strip leading 'LIB:' 802 if [ -z "$explicit_file_in_hallib" ] ; then 803 echo "ILLFORMED LIB:file:<$CFGFILE>" 804 fi 805 if [ "$explicit_file_in_hallib" != "$CFGFILE" ] ; then 806 foundfile="$HALLIB_DIR/$explicit_file_in_hallib" 807 if [ ! -r $foundfile ] ; then 808 echo "CANNOT READ LIB:file:$foundfile" 809 fi 810 foundmsg="Found file(LIB): $foundfile" 811 else 812 if [ "${CFGFILE:0:1}" = "/" ] ; then 813 foundfile=$CFGFILE ;# absolute path specified 814 foundmsg="Found file(ABS): $foundfile" 815 else 816 for pathdir in $HALLIB_PATH ; do 817 foundfile=$pathdir/$CFGFILE 818 if [ -r $foundfile ] ; then 819 # use first file found in HALLIB_PATH 820 if [ "${pathdir:0:1}" = "." ] ; then 821 foundmsg="Found file(REL): $foundfile" 822 else 823 foundmsg="Found file(lib): $foundfile" 824 fi 825 break 826 fi 827 done 828 fi 829 fi 830 [ -d $foundfile ] && foundmsg="" 831 IFS=$saveIFS 832 if [ -z "$foundmsg" ] ; then 833 echo "CANNOT FIND FILE FOR:$CFGFILE" 834 Cleanup 835 exit -1 836 fi 837 echo "$foundmsg" 838 CFGFILE="$foundfile" 839 case $CFGFILE in 840 *.tcl) 841 if ! haltcl -i "$INIFILE" $CFGFILE $CFGFILE_ARGS \ 842 && [ "$DASHK" = "" ]; then 843 Cleanup 844 exit -1 845 fi 846 ;; 847 *) 848 if ! $HALCMD -i "$INIFILE" -f $CFGFILE && [ "$DASHK" = "" ]; then 849 Cleanup 850 exit -1 851 fi 852 esac 853 # get next config file name from ini file 854 NUM=$(($NUM+1)) 855 CFGFILE=`$INIVAR -tildeexpand -ini "$INIFILE" -var HALFILE -sec HAL -num $NUM 2> /dev/null` 856 done 857 fi 858 859 # 4.3.7. Run task in background 860 echo "Starting TASK program: $EMCTASK" >>$PRINT_FILE 861 if ! program_available $EMCTASK ; then 862 echo "Can't execute TASK program $EMCTASK" 863 Cleanup 864 exit 1 865 fi 866 867 halcmd loadusr -Wn inihal $EMCTASK -ini "$INIFILE" & 868 869 # 4.3.8. execute discrete HAL commands from ini file (if any) 870 # get first command from ini file 871 NUM=1 872 HALCOMMAND=`$INIVAR -ini "$INIFILE" -var HALCMD -sec HAL -num $NUM 2> /dev/null` 873 while [ -n "$HALCOMMAND" ] ; do 874 if [ -n "$HALCOMMAND" ] ; then 875 echo "Running HAL command: $HALCOMMAND" >>$PRINT_FILE 876 if ! $HALCMD $HALCOMMAND && [ "$DASHK" = "" ]; then 877 echo "ini file HAL command $HALCOMMAND failed." 878 Cleanup 879 exit -1 880 fi 881 fi 882 # get next command from ini file 883 NUM=$(($NUM+1)) 884 HALCOMMAND=`$INIVAR -ini "$INIFILE" -var HALCMD -sec HAL -num $NUM 2> /dev/null` 885 done 886 887 # 4.3.9. start the realtime stuff ticking 888 $HALCMD start 889 890 # 4.3.10. run other applications 891 run_applications 892 893 # 4.3.11. Run display in foreground 894 echo "Starting DISPLAY program: $EMCDISPLAY" >>$PRINT_FILE 895 result=0 896 case $EMCDISPLAY in 897 tklinuxcnc) 898 # tklinuxcnc is in the tcl directory, not the bin directory 899 if [ ! -x $LINUXCNC_TCL_DIR/$EMCDISPLAY.tcl ] ; then 900 echo "Can't execute DISPLAY program $LINUXCNC_TCL_DIR/$EMCDISPLAY.tcl $EMCDISPLAYARGS" 901 Cleanup 902 exit 1 903 fi 904 $LINUXCNC_TCL_DIR/$EMCDISPLAY.tcl -ini "$INIFILE" $EMCDISPLAYARGS 905 result=$? 906 ;; 907 dummy) 908 # dummy display just waits for <ENTER> 909 echo "DUMMY DISPLAY MODULE, press <ENTER> to continue." 910 read foo; 911 ;; 912 linuxcncrsh) 913 $EMCDISPLAY $EMCDISPLAYARGS $EXTRA_ARGS -- -ini "$INIFILE" 914 ;; 915 *) 916 # all other displays are assumed to be commands on the PATH 917 if ! program_available $EMCDISPLAY; then 918 echo "Can't execute DISPLAY program $EMCDISPLAY $EMCDISPLAYARGS $EXTRA_ARGS" 919 Cleanup 920 exit 1 921 fi 922 $EMCDISPLAY -ini "$INIFILE" $EMCDISPLAYARGS $EXTRA_ARGS 923 result=$? 924 ;; 925 esac 926 927 # the display won't return until you shut it down, 928 # so when you get here it's time to clean up 929 Cleanup 930 931 exit $result