Changeset 4507 for branches/1.3


Ignore:
Timestamp:
Jul 16, 2014, 1:54:18 PM (10 years ago)
Author:
gah
Message:

update nanoscale from trunk, update meshviewer (needs tests in bat)

Location:
branches/1.3
Files:
1 deleted
5 edited

Legend:

Unmodified
Added
Removed
  • branches/1.3/gui/scripts/vtkmeshviewer.tcl

    r4474 r4507  
    9292    private method PanCamera {}
    9393    private method SetObjectStyle { dataobj }
    94     private method SetOpacity { dataset }
    9594    private method SetOrientation { side }
    9695    private method SetPolydataOpacity {}
     
    114113    private variable _style;            # Array of current component styles.
    115114    private variable _initialStyle;     # Array of initial component styles.
    116     private variable _axis
    117115    private variable _reset 1;          # Indicates that server was reset and
    118116                                        # needs to be reinitialized.
    119117
    120     private variable _first ""     ;# This is the topmost dataset.
     118    private variable _first "";         # This is the topmost dataset.
    121119    private variable _start 0
    122120    private variable _title ""
    123121
    124     common _downloadPopup          ;# download options from popup
     122    common _downloadPopup;              # download options from popup
    125123    private common _hardcopy
    126124    private variable _width 0
     
    184182    set _limits(zmax) 1.0
    185183
    186     array set _axis [subst {
    187         xgrid           0
    188         ygrid           0
    189         zgrid           0
    190         xcutaway        0
    191         ycutaway        0
    192         zcutaway        0
    193         xposition       0
    194         yposition       0
    195         zposition       0
    196         xdirection      -1
    197         ydirection      -1
    198         zdirection      -1
    199         visible         1
    200         labels          1
    201     }]
    202     array set _settings [subst {
    203         outline                 0
    204         polydata-edges          0
    205         polydata-lighting       1
    206         polydata-opacity        100
    207         polydata-visible        1
    208         polydata-wireframe      0
    209     }]
     184    array set _settings {
     185        -axesvisible            1
     186        -axislabels             1
     187        -outline                0
     188        -polydataedges          0
     189        -polydatalighting       1
     190        -polydataopacity        100
     191        -polydatavisible        1
     192        -polydatawireframe      0
     193        -xcutaway               0
     194        -xdirection             -1
     195        -xgrid                  0
     196        -xposition              0
     197        -ycutaway               0
     198        -ydirection             -1
     199        -ygrid                  0
     200        -yposition              0
     201        -zcutaway               0
     202        -zdirection             -1
     203        -zgrid                  0
     204        -zposition              0
     205    }
    210206    itk_component add view {
    211207        canvas $itk_component(plotarea).view \
     
    407403itcl::body Rappture::VtkMeshViewer::SetPolydataOpacity {} {
    408404    set _polydataOpacityPending 0
    409     foreach dataset [CurrentDatasets -visible $_first] {
    410         SetOpacity $dataset
    411     }
    412 }
    413 
    414 itcl::body Rappture::VtkMeshViewer::EventuallySetPolydataOpacity { args } {
     405    set val $_settings(-polydataopacity)
     406    set sval [expr { 0.01 * double($val) }]
     407    SendCmd "polydata opacity $sval"
     408}
     409
     410itcl::body Rappture::VtkMeshViewer::EventuallySetPolydataOpacity { val } {
     411    set _settings(-polydataopacity) $val
    415412    if { !$_polydataOpacityPending } {
    416413        set _polydataOpacityPending 1
     
    478475        set _dlist [lreplace $_dlist $pos $pos]
    479476        array unset _obj2ovride $dataobj-*
    480         array unset _settings $dataobj-*
    481477        set changed 1
    482478    }
     
    832828        $_arcball resize $w $h
    833829        DoResize
    834         InitSettings axis-xgrid axis-ygrid axis-zgrid axis-mode \
    835             axis-visible axis-labels
    836  
     830        InitSettings -xgrid -ygrid -zgrid -axismode -axesvisible -axislabels
    837831        StopBufferingCommands
    838832        SendCmd "imgflush"
     
    874868        }
    875869        lappend _obj2datasets($dataobj) $tag
    876         if { [info exists _obj2ovride($dataobj-raise)] } {
     870        if { [info exists _obj2ovride($dataobj-raise)] &&
     871             $_obj2ovride($dataobj-raise) } {
    877872            SendCmd "dataset visible 1 $tag"
    878873            SetOpacity $tag
     
    896891        }
    897892    }
    898     InitSettings outline
     893    InitSettings -outline
    899894    if { $_reset } {
    900895        # These are settings that rely on a dataset being loaded.
    901         InitSettings polydata-edges polydata-lighting polydata-opacity \
    902             polydata-visible polydata-wireframe
     896        InitSettings -polydataedges -polydatalighting -polydataopacity \
     897            -polydatavisible -polydatawireframe
    903898 
    904899        set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
     
    11521147    }
    11531148    switch -- $what {
    1154         "outline" {
    1155             set bool $_settings(outline)
    1156             foreach dataset [CurrentDatasets -visible $_first] {
     1149        "-outline" {
     1150            set bool $_settings($what)
     1151            # Only display a outline for the currently visible sets.
     1152            SendCmd "outline visible 0"
     1153            foreach dataset [CurrentDatasets -visible] {
    11571154                SendCmd "outline visible $bool $dataset"
    11581155            }
    11591156        }
    1160         "polydata-opacity" {
    1161             foreach dataset [CurrentDatasets -visible $_first] {
    1162                 SetOpacity $dataset
    1163             }
    1164         }
    1165         "polydata-wireframe" {
    1166             set bool $_settings(polydata-wireframe)
    1167             foreach dataset [CurrentDatasets -visible $_first] {
    1168                 SendCmd "polydata wireframe $bool $dataset"
    1169             }
    1170         }
    1171         "polydata-visible" {
    1172             set bool $_settings(polydata-visible)
    1173             foreach dataset [CurrentDatasets -visible $_first] {
     1157        "-polydataopacity" {
     1158            EventuallySetPolydataOpacity
     1159        }
     1160        "-polydatawireframe" {
     1161            set bool $_settings($what)
     1162            SendCmd "polydata wireframe $bool"
     1163        }
     1164        "-polydatavisible" {
     1165            set bool $_settings($what)
     1166            # Only change visibility of data sets marked "visible".
     1167            foreach dataset [CurrentDatasets -visible] {
    11741168                SendCmd "polydata visible $bool $dataset"
    11751169            }
    11761170        }
    1177         "polydata-lighting" {
    1178             set bool $_settings(polydata-lighting)
    1179             foreach dataset [CurrentDatasets -visible $_first] {
    1180                 SendCmd "polydata lighting $bool $dataset"
    1181             }
    1182         }
    1183         "polydata-edges" {
    1184             set bool $_settings(polydata-edges)
    1185             foreach dataset [CurrentDatasets -visible $_first] {
    1186                 SendCmd "polydata edges $bool $dataset"
    1187             }
    1188         }
    1189         "axis-visible" {
    1190             set bool $_axis(visible)
     1171        "-polydatalighting" {
     1172            set bool $_settings($what)
     1173            SendCmd "polydata lighting $bool"
     1174        }
     1175        "-polydataedges" {
     1176            set bool $_settings($what)
     1177            SendCmd "polydata edges $bool"
     1178        }
     1179        "-axesvisible" {
     1180            set bool $_settings($what)
    11911181            SendCmd "axis visible all $bool"
    11921182        }
    1193         "axis-labels" {
    1194             set bool $_axis(labels)
     1183        "-axislabels" {
     1184            set bool $_settings($what)
    11951185            SendCmd "axis labels all $bool"
    11961186        }
    1197         "axis-xgrid" {
    1198             set bool $_axis(xgrid)
     1187        "-xgrid" {
     1188            set bool $_settings($what)
    11991189            SendCmd "axis grid x $bool"
    12001190        }
    1201         "axis-ygrid" {
    1202             set bool $_axis(ygrid)
     1191        "-ygrid" {
     1192            set bool $_settings($what)
    12031193            SendCmd "axis grid y $bool"
    12041194        }
    1205         "axis-zgrid" {
    1206             set bool $_axis(zgrid)
     1195        "-zgrid" {
     1196            set bool $_settings($what)
    12071197            SendCmd "axis grid z $bool"
    12081198        }
    1209         "axis-mode" {
     1199        "-axismode" {
    12101200            set mode [$itk_component(axismode) value]
    12111201            set mode [$itk_component(axismode) translate $mode]
    12121202            SendCmd "axis flymode $mode"
    12131203        }
    1214         "axis-xcutaway" - "axis-ycutaway" - "axis-zcutaway" {
    1215             set axis [string range $what 5 5]
    1216             set bool $_axis(${axis}cutaway)
     1204        "-xcutaway" - "-ycutaway" - "-zcutaway" {
     1205            set axis [string range $what 1 1]
     1206            set bool $_settings($what)
    12171207            if { $bool } {
    1218                 set pos [expr $_axis(${axis}position) * 0.01]
    1219                 set dir $_axis(${axis}direction)
     1208                set pos [expr $_settings(-${axis}position) * 0.01]
     1209                set dir $_settings(-${axis}direction)
    12201210                $itk_component(${axis}CutScale) configure -state normal \
    12211211                    -troughcolor white
     
    12271217            }
    12281218        }
    1229         "axis-xposition" - "axis-yposition" - "axis-zposition" -
    1230         "axis-xdirection" - "axis-ydirection" - "axis-zdirection" {
    1231             set axis [string range $what 5 5]
    1232             #set dir $_axis(${axis}direction)
    1233             set pos [expr $_axis(${axis}position) * 0.01]
     1219        "-xposition" - "-yposition" - "-zposition" {
     1220            set axis [string range $what 1 1]
     1221            set pos [expr $_settings($what) * 0.01]
    12341222            SendCmd "renderer clipplane ${axis} $pos -1"
     1223        }
     1224        "-xdirection" - "-ydirection" - "-zdirection" {
     1225            set axis [string range $what 1 1]
     1226            puts stderr "direction not implemented"
    12351227        }
    12361228        default {
     
    13171309    checkbutton $inner.mesh \
    13181310        -text "Show Mesh" \
    1319         -variable [itcl::scope _settings(polydata-visible)] \
    1320         -command [itcl::code $this AdjustSetting polydata-visible] \
     1311        -variable [itcl::scope _settings(-polydatavisible)] \
     1312        -command [itcl::code $this AdjustSetting -polydatavisible] \
    13211313        -font "Arial 9" -anchor w
    13221314
    13231315    checkbutton $inner.outline \
    13241316        -text "Show Outline" \
    1325         -variable [itcl::scope _settings(outline)] \
    1326         -command [itcl::code $this AdjustSetting outline] \
     1317        -variable [itcl::scope _settings(-outline)] \
     1318        -command [itcl::code $this AdjustSetting -outline] \
    13271319        -font "Arial 9" -anchor w
    13281320
    13291321    checkbutton $inner.wireframe \
    13301322        -text "Show Wireframe" \
    1331         -variable [itcl::scope _settings(polydata-wireframe)] \
    1332         -command [itcl::code $this AdjustSetting polydata-wireframe] \
     1323        -variable [itcl::scope _settings(-polydatawireframe)] \
     1324        -command [itcl::code $this AdjustSetting -polydatawireframe] \
    13331325        -font "Arial 9" -anchor w
    13341326
    13351327    checkbutton $inner.lighting \
    13361328        -text "Enable Lighting" \
    1337         -variable [itcl::scope _settings(polydata-lighting)] \
    1338         -command [itcl::code $this AdjustSetting polydata-lighting] \
     1329        -variable [itcl::scope _settings(-polydatalighting)] \
     1330        -command [itcl::code $this AdjustSetting -polydatalighting] \
    13391331        -font "Arial 9" -anchor w
    13401332
    13411333    checkbutton $inner.edges \
    13421334        -text "Show Edges" \
    1343         -variable [itcl::scope _settings(polydata-edges)] \
    1344         -command [itcl::code $this AdjustSetting polydata-edges] \
     1335        -variable [itcl::scope _settings(-polydataedges)] \
     1336        -command [itcl::code $this AdjustSetting -polydataedges] \
    13451337        -font "Arial 9" -anchor w
    13461338
     
    13541346    }
    13551347    bind $inner.field <<Value>> \
    1356         [itcl::code $this AdjustSetting field]
     1348        [itcl::code $this AdjustSetting -field]
    13571349
    13581350    label $inner.opacity_l -text "Opacity" -font "Arial 9" -anchor w
    13591351    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
    1360         -variable [itcl::scope _settings(polydata-opacity)] \
     1352        -variable [itcl::scope _settings(-polydataopacity)] \
    13611353        -width 10 \
    13621354        -showvalue off \
    1363         -command [itcl::code $this AdjustSetting polydata-opacity]
    1364     $inner.opacity set $_settings(polydata-opacity)
     1355        -command [itcl::code $this AdjustSetting -polydataopacity]
     1356    $inner.opacity set $_settings(-polydataopacity)
    13651357
    13661358    blt::table $inner \
     
    13891381    checkbutton $inner.visible \
    13901382        -text "Show Axes" \
    1391         -variable [itcl::scope _axis(visible)] \
    1392         -command [itcl::code $this AdjustSetting axis-visible] \
     1383        -variable [itcl::scope _settings(-axesvisible)] \
     1384        -command [itcl::code $this AdjustSetting -axesvisible] \
    13931385        -font "Arial 9"
    13941386
    13951387    checkbutton $inner.labels \
    13961388        -text "Show Axis Labels" \
    1397         -variable [itcl::scope _axis(labels)] \
    1398         -command [itcl::code $this AdjustSetting axis-labels] \
     1389        -variable [itcl::scope _settings(-axislabels)] \
     1390        -command [itcl::code $this AdjustSetting -axislabels] \
    13991391        -font "Arial 9"
    14001392
    14011393    checkbutton $inner.gridx \
    14021394        -text "Show X Grid" \
    1403         -variable [itcl::scope _axis(xgrid)] \
    1404         -command [itcl::code $this AdjustSetting axis-xgrid] \
     1395        -variable [itcl::scope _settings(-xgrid)] \
     1396        -command [itcl::code $this AdjustSetting -xgrid] \
    14051397        -font "Arial 9"
    14061398    checkbutton $inner.gridy \
    14071399        -text "Show Y Grid" \
    1408         -variable [itcl::scope _axis(ygrid)] \
    1409         -command [itcl::code $this AdjustSetting axis-ygrid] \
     1400        -variable [itcl::scope _settings(-ygrid)] \
     1401        -command [itcl::code $this AdjustSetting -ygrid] \
    14101402        -font "Arial 9"
    14111403    checkbutton $inner.gridz \
    14121404        -text "Show Z Grid" \
    1413         -variable [itcl::scope _axis(zgrid)] \
    1414         -command [itcl::code $this AdjustSetting axis-zgrid] \
     1405        -variable [itcl::scope _settings(-zgrid)] \
     1406        -command [itcl::code $this AdjustSetting -zgrid] \
    14151407        -font "Arial 9"
    14161408
     
    14261418        "outer_edges"     "outer"         
    14271419    $itk_component(axismode) value "static"
    1428     bind $inner.mode <<Value>> [itcl::code $this AdjustSetting axis-mode]
     1420    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting -axismode]
    14291421
    14301422    blt::table $inner \
     
    15041496            -onimage [Rappture::icon x-cutplane] \
    15051497            -offimage [Rappture::icon x-cutplane] \
    1506             -command [itcl::code $this AdjustSetting axis-xcutaway] \
    1507             -variable [itcl::scope _axis(xcutaway)]
     1498            -command [itcl::code $this AdjustSetting -xcutaway] \
     1499            -variable [itcl::scope _settings(-xcutaway)]
    15081500    }
    15091501    Rappture::Tooltip::for $itk_component(xCutButton) \
     
    15151507            -borderwidth 1 -highlightthickness 0 \
    15161508            -command [itcl::code $this Slice move x] \
    1517             -variable [itcl::scope _axis(xposition)]
     1509            -variable [itcl::scope _settings(-xposition)]
    15181510    } {
    15191511        usual
     
    15321524            -offimage [Rappture::icon arrow-up] \
    15331525            -offvalue 1 \
    1534             -command [itcl::code $this AdjustSetting axis-xdirection] \
    1535             -variable [itcl::scope _axis(xdirection)]
    1536     }
    1537     set _axis(xdirection) -1
     1526            -command [itcl::code $this AdjustSetting -xdirection] \
     1527            -variable [itcl::scope _settings(-xdirection)]
     1528    }
     1529    set _settings(-xdirection) -1
    15381530    Rappture::Tooltip::for $itk_component(xDirButton) \
    15391531        "Toggle the direction of the X-axis cutaway"
     
    15441536            -onimage [Rappture::icon y-cutplane] \
    15451537            -offimage [Rappture::icon y-cutplane] \
    1546             -command [itcl::code $this AdjustSetting axis-ycutaway] \
    1547             -variable [itcl::scope _axis(ycutaway)]
     1538            -command [itcl::code $this AdjustSetting -ycutaway] \
     1539            -variable [itcl::scope _settings(-ycutaway)]
    15481540    }
    15491541    Rappture::Tooltip::for $itk_component(yCutButton) \
     
    15551547            -borderwidth 1 -highlightthickness 0 \
    15561548            -command [itcl::code $this Slice move y] \
    1557             -variable [itcl::scope _axis(yposition)]
     1549            -variable [itcl::scope _settings(-yposition)]
    15581550    } {
    15591551        usual
     
    15721564            -offimage [Rappture::icon arrow-up] \
    15731565            -offvalue 1 \
    1574             -command [itcl::code $this AdjustSetting axis-ydirection] \
    1575             -variable [itcl::scope _axis(ydirection)]
     1566            -command [itcl::code $this AdjustSetting -ydirection] \
     1567            -variable [itcl::scope _settings(-ydirection)]
    15761568    }
    15771569    Rappture::Tooltip::for $itk_component(yDirButton) \
    15781570        "Toggle the direction of the Y-axis cutaway"
    1579     set _axis(ydirection) -1
     1571    set _settings(-ydirection) -1
    15801572
    15811573    # Z-value slicer...
     
    15841576            -onimage [Rappture::icon z-cutplane] \
    15851577            -offimage [Rappture::icon z-cutplane] \
    1586             -command [itcl::code $this AdjustSetting axis-zcutaway] \
    1587             -variable [itcl::scope _axis(zcutaway)]
     1578            -command [itcl::code $this AdjustSetting -zcutaway] \
     1579            -variable [itcl::scope _settings(-zcutaway)]
    15881580    }
    15891581    Rappture::Tooltip::for $itk_component(zCutButton) \
     
    15951587            -borderwidth 1 -highlightthickness 0 \
    15961588            -command [itcl::code $this Slice move z] \
    1597             -variable [itcl::scope _axis(zposition)]
     1589            -variable [itcl::scope _settings(-zposition)]
    15981590    } {
    15991591        usual
     
    16111603            -offimage [Rappture::icon arrow-up] \
    16121604            -offvalue 1 \
    1613             -command [itcl::code $this AdjustSetting axis-zdirection] \
    1614             -variable [itcl::scope _axis(zdirection)]
    1615     }
    1616     set _axis(zdirection) -1
     1605            -command [itcl::code $this AdjustSetting -zdirection] \
     1606            -variable [itcl::scope _settings(-zdirection)]
     1607    }
     1608    set _settings(-zdirection) -1
    16171609    Rappture::Tooltip::for $itk_component(zDirButton) \
    16181610        "Toggle the direction of the Z-axis cutaway"
     
    17361728    set style [$dataobj hints style]
    17371729    if { $dataobj != $_first } {
    1738         set settings(-wireframe) 1
     1730        set settings(-polydatawireframe) 1
    17391731    }
    17401732
     
    17431735        -color white
    17441736        -edgecolor black
    1745         -edges 1
    17461737        -lighting 1
    17471738        -linewidth 1.0
    1748         -opacity 1.0
    17491739        -outline 0
    1750         -visible 1
    1751         -wireframe 0
     1740        -polydataedges 1
     1741        -polydataopacity 1.0
     1742        -polydatavisible 1
     1743        -polydatawireframe 0
    17521744    }
    17531745    if {$type == "cloud"} {
    17541746        set settings(-cloudstyle) points
    1755         set settings(-edges) 0
     1747        set settings(-polydataedges) 0
    17561748        set settings(-edgecolor) white
    17571749    }
     
    17631755    SendCmd "outline color [Color2RGB $settings(-color)] $tag"
    17641756    SendCmd "outline visible $settings(-outline) $tag"
    1765     set _settings(outline) $settings(-outline)
     1757    set _settings(-outline) $settings(-outline)
    17661758
    17671759    SendCmd "polydata add $tag"
    1768     SendCmd "polydata visible $settings(-visible) $tag"
     1760    SendCmd "polydata visible $settings(-polydatavisible) $tag"
    17691761    SendCmd "polydata cloudstyle $settings(-cloudstyle) $tag"
    1770     set _settings(polydata-visible) $settings(-visible)
    1771     SendCmd "polydata edges $settings(-edges) $tag"
    1772     set _settings(polydata-edges) $settings(-edges)
     1762    set _settings(-polydatavisible) $settings(-polydatavisible)
     1763    SendCmd "polydata edges $settings(-polydataedges) $tag"
     1764    set _settings(-polydataedges) $settings(-polydataedges)
    17731765    SendCmd "polydata color [Color2RGB $settings(-color)] $tag"
    1774     #SendCmd "polydata colormode constant {} $tag"
    1775     SendCmd "polydata lighting $settings(-lighting) $tag"
    1776     set _settings(polydata-lighting) $settings(-lighting)
     1766
     1767    SendCmd "polydata lighting $settings(-polydatalighting) $tag"
     1768    set _settings(-polydatalighting) $settings(-polydatalighting)
    17771769    SendCmd "polydata linecolor [Color2RGB $settings(-edgecolor)] $tag"
    17781770    SendCmd "polydata linewidth $settings(-linewidth) $tag"
    1779     SendCmd "polydata opacity $settings(-opacity) $tag"
    1780     set _settings(polydata-opacity) [expr 100.0 * $settings(-opacity)]
    1781     SendCmd "polydata wireframe $settings(-wireframe) $tag"
    1782     set _settings(polydata-wireframe) $settings(-wireframe)
     1771    SendCmd "polydata opacity $settings(-polydataopacity) $tag"
     1772    set _settings(-polydataopacity) [expr 100.0 * $settings(-polydataopacity)]
     1773    SendCmd "polydata wireframe $settings(-polydatawireframe) $tag"
     1774    set _settings(-polydatawireframe) $settings(-polydatawireframe)
    17831775    set havePolyData 1
    17841776}
     
    18421834}
    18431835
    1844 itcl::body Rappture::VtkMeshViewer::SetOpacity { dataset } {
    1845     set val $_settings(polydata-opacity)
    1846     set sval [expr { 0.01 * double($val) }]
    1847     if { !$_obj2ovride($dataset-raise) } {
    1848         # This is wrong.  Need to figure out why raise isn't set with 1
    1849         #set sval [expr $sval * .6]
    1850     }
    1851     SendCmd "polydata opacity $sval $dataset"
    1852 }
  • branches/1.3/packages/vizservers/nanoscale/Makefile.in

    r4501 r4507  
    2424RM              = rm -f
    2525
    26 SERVER_OBJS     = server2.o
     26SERVER_OBJS     = server.o
    2727CLIENT_OBJS     = client.o clientlib.o
    2828
  • branches/1.3/packages/vizservers/nanoscale/config.h.in

    r2448 r4507  
    1010#undef HAVE_ARPA_INET_H
    1111
    12 /* Define to 1 if you have the `avformat_alloc_context' function. */
    13 #undef HAVE_AVFORMAT_ALLOC_CONTEXT
    14 
    15 /* Define to 1 if you have the <Cg/cgGL.h> header file. */
    16 #undef HAVE_CG_CGGL_H
    17 
    18 /* Define to 1 if you have the <ffmpeg/avcodec.h> header file. */
    19 #undef HAVE_FFMPEG_AVCODEC_H
    20 
    21 /* Define to 1 if you have the <ffmpeg/avformat.h> header file. */
    22 #undef HAVE_FFMPEG_AVFORMAT_H
    23 
    24 /* Define to 1 if you have the <ffmpeg/avutil.h> header file. */
    25 #undef HAVE_FFMPEG_AVUTIL_H
    26 
    27 /* Define to 1 if you have the `img_convert' function. */
    28 #undef HAVE_IMG_CONVERT
    29 
    3012/* Define to 1 if you have the <inttypes.h> header file. */
    3113#undef HAVE_INTTYPES_H
    3214
    33 /* Define to 1 if you have the `avcodec' library (-lavcodec). */
    34 #undef HAVE_LIBAVCODEC
    35 
    36 /* Define to 1 if you have the <libavcodec/avcodec.h> header file. */
    37 #undef HAVE_LIBAVCODEC_AVCODEC_H
    38 
    39 /* Define to 1 if you have the `avformat' library (-lavformat). */
    40 #undef HAVE_LIBAVFORMAT
    41 
    42 /* Define to 1 if you have the <libavformat/avformat.h> header file. */
    43 #undef HAVE_LIBAVFORMAT_AVFORMAT_H
    44 
    45 /* Define to 1 if you have the `avutil' library (-lavutil). */
    46 #undef HAVE_LIBAVUTIL
    47 
    48 /* Define to 1 if you have the <libavutil/avutil.h> header file. */
    49 #undef HAVE_LIBAVUTIL_AVUTIL_H
    50 
    51 /* Define to 1 if you have the `highgui' library (-lhighgui). */
    52 #undef HAVE_LIBHIGHGUI
    53 
    5415/* Define to 1 if you have the <memory.h> header file. */
    5516#undef HAVE_MEMORY_H
     17
     18/* Define to 1 if you have the `mkstemps' function. */
     19#undef HAVE_MKSTEMPS
    5620
    5721/* Define to 1 if you have the <netdb.h> header file. */
     
    6125#undef HAVE_NETINET_IN_H
    6226
    63 /* Define to 1 if you have the <opencv/cv.h> header file. */
    64 #undef HAVE_OPENCV_CV_H
    65 
    66 /* Define to 1 if you have the <opencv/highgui.h> header file. */
    67 #undef HAVE_OPENCV_HIGHGUI_H
     27/* Define to 1 if you have the <Python.h> header file. */
     28#undef HAVE_PYTHON_H
    6829
    6930/* Define to 1 if you have the <stdint.h> header file. */
     
    9758#undef HAVE_UNISTD_H
    9859
    99 /* Define to 1 if you have the <vtkSmartPointer.h> header file. */
    100 #undef HAVE_VTKSMARTPOINTER_H
    101 
    10260/* Define to the address where bug reports for this package should be sent. */
    10361#undef PACKAGE_BUGREPORT
     
    11270#undef PACKAGE_TARNAME
    11371
     72/* Define to the home page for this package. */
     73#undef PACKAGE_URL
     74
    11475/* Define to the version of this package. */
    11576#undef PACKAGE_VERSION
    116 
    117 /* The size of `float', as computed by sizeof. */
    118 #undef SIZEOF_FLOAT
    119 
    120 /* The size of `int', as computed by sizeof. */
    121 #undef SIZEOF_INT
    122 
    123 /* The size of `long', as computed by sizeof. */
    124 #undef SIZEOF_LONG
    125 
    126 /* The size of `long long', as computed by sizeof. */
    127 #undef SIZEOF_LONG_LONG
    128 
    129 /* The size of `void *', as computed by sizeof. */
    130 #undef SIZEOF_VOID_P
    13177
    13278/* Define to 1 if you have the ANSI C header files. */
  • branches/1.3/packages/vizservers/nanoscale/renderservers.tcl.in

    r4485 r4507  
     1#
     2# This file is read by nanoscale to determine which ports to listen
     3# to and the how to start the associated render server.
     4#
     5# Render servers
     6#
     7#       Server                  Port            Usage
     8#       ======                  ====            =====
     9#       nanovis                 2000            production
     10#       vtkvis                  2010            production
     11#       geovis                  2015            testing
     12#       vmdshow                 2018            testing
     13#       pymol                   2019            testing
     14#       pymol                   2020            production
     15#
     16# The syntax is
     17#       register_server <name> <port> ?<flags>? {
     18#           commands...
     19#       } {
     20#           variables...
     21#       }
     22#
     23# Registers a server by <name> at port <port>.
     24# When a connection is made to <port>, <command> is run.
     25# Environment variables will be set before executing command. 
     26#
     27# Note: Don't set DISPLAY here. nanoscale itself sets the DISPLAY
     28#       variable.
     29#
     30# Defaults:
     31#   o Server reads from file descriptor 0.
     32#   o Server writes to descriptor 1.
     33#   o Server stdout and stderr are redirected to a log file. 
     34#
    135
    236set exec_prefix "@exec_prefix@"
    337set bindir "@bindir@"
    438set libdir "@libdir@"
    5 set vtkdir "@VTK_LIB_DIR@"
    639
    7 # NanoVis server --
     40# GeoVis server (port 2015) --
     41#     Map renderer
     42#
     43register_server geovis 2015 \
     44    -output 3 -logstdout no -logstderr no \
     45{
     46    ${bindir}/geovis -o 3
     47} {
     48    LD_LIBRARY_PATH ${libdir}
     49    OSGEARTH_DEFAULT_FONT /usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf
     50}
     51
     52# NanoVis --
     53#       Server Type     Volume renderer
     54#       Port            2000
     55#       Threaded        yes
     56# Notes:
     57#       o Continue to use default options until we offically upgrade
     58#         nanovis to the latest release.  We are currently using a 1.2
     59#         version of nanovis.
     60#       o Requires change to 1.2 nanovis.  Can't redirect stderr to log
     61#         or X will complain about performing socket operation on non-socket
     62#         descriptor.
    863#
    964register_server nanovis 2000 \
     
    1570}
    1671
    17 # VtkVis server --
    18 #    3D drawings (scene graphs), Contour and surface graphs.
     72# VtkVis --
     73#       Server type     3D drawings (scene graphs). Contour and surface graphs.
     74#       Port            2010
     75#       Threaded        yes
     76# Notes:
     77#       o Removed ${vtkdir} from LD_LIRBRARY_PATH. Not needed with VTK 6.
     78#       o Using new features in nanoscale/vtkvis to use file descriptor 3
     79#         for server output.  No automatic logging of stdout and stderr.
    1980#
    2081register_server vtkvis 2010 \
    21     -logstdout no -logstderr no \
     82    -output 3 -logstdout no -logstderr no \
    2283{
    23     ${bindir}/vtkvis
     84    ${bindir}/vtkvis -o 3
    2485} {
    25     LD_LIBRARY_PATH ${libdir}:${vtkdir}
     86    LD_LIBRARY_PATH ${libdir}
    2687}
    2788
     89# PymolProxy --
     90#       Server type     Molecular layouts using Pymol viewer.
     91#       Port            2020
     92#       Threaded        yes
     93# Notes:
     94#       o Need PYMOL_SITE_PATH for parallelpiped box.py location.
     95#       o Makes no sense to log stdout and stderr of the proxy.
     96#       o Renamed to just pymolproxy and removed non-threaded entry.
    2897#
    29 # Pymol server (threaded version of proxy) --
    30 #    Molecular layouts from PDB description. 
    31 #    Need PYMOL_SITE_PATH only for parallelpiped box.py location.
    32 #   
    3398register_server pymolproxy 2020 \
    3499    -logstdout no -logstderr no \
  • branches/1.3/packages/vizservers/nanoscale/server.c

    r2403 r4507  
     1/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
     2/* ======================================================================
     3 *  Copyright (c) 2004-2014  HUBzero Foundation, LLC
     4 * ----------------------------------------------------------------------
     5 *  See the file "license.terms" for information on usage and
     6 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
     7 * ======================================================================
     8 */
     9#define _GNU_SOURCE
     10#include <sys/socket.h>
     11
    112#include <stdio.h>
     13#include <string.h>
     14#include <errno.h>
     15#include <arpa/inet.h>
     16#include <getopt.h>
     17#include <stdarg.h>
     18#include <stdlib.h>
     19#include <sys/wait.h>
     20#include <sys/stat.h>
     21#include <sys/file.h>
     22#include <syslog.h>
    223#include <unistd.h>
    3 #include <stdlib.h>
    4 #include <string.h>
    5 #include <signal.h>
    6 #include <sys/types.h>
    7 #include <sys/socket.h>
    8 #include <sys/wait.h>
    9 #include <sys/select.h>
    10 #include <sys/time.h>
    11 #include <arpa/inet.h>
    1224#include <fcntl.h>
    13 #include <netinet/in.h>
    14 #include <getopt.h>
    15 #include <errno.h>
    16 
    17 // The initial request load for a new renderer.
    18 #define INITIAL_LOAD 100000000.0
    19 
    20 // The factor that the load is divided by every second.
    21 #define LOAD_DROP_OFF 2.0
    22 
    23 // The broadcast interval (in seconds)
    24 #define BROADCAST_INTERVAL 5
    25 
    26 // The load of a remote machine must be less than this factor to
    27 // justify redirection.
    28 #define LOAD_REDIRECT_FACTOR 0.8
    29 
    30 // Maxium number of services we support
    31 #define MAX_SERVICES 100
    32 
    33 float load = 0;             // The present load average for this system.
    34 int memory_in_use = 0;      // Total memory in use by this system.
    35 int children = 0;           // Number of children running on this system.
    36 int send_fd;                // The file descriptor we broadcast through.
    37 struct sockaddr_in send_addr;  // The subnet address we broadcast to.
    38 fd_set saved_rfds;          // Descriptors we're reading from.
    39 fd_set pipe_rfds;           // Descriptors that are pipes to children.
    40 fd_set service_rfds[MAX_SERVICES];
    41 int maxCards = 1;
    42 int dispNum = -1;
    43 char displayVar[200];
    44 
    45 struct host_info {
    46     struct in_addr in_addr;
    47     float          load;
    48     int            children;
     25
     26#include <tcl.h>
     27
     28#include "config.h"
     29
     30#define TRUE    1
     31#define FALSE   0
     32
     33#ifndef SERVERSFILE
     34#define SERVERSFILE  "/opt/hubzero/rappture/render/lib/renderservers.tcl"
     35#endif
     36
     37#ifndef LOGDIR
     38#define LOGDIR          "/tmp"
     39#endif
     40
     41#define ERROR(...)      SysLog(LOG_ERR, __FILE__, __LINE__, __VA_ARGS__)
     42#define TRACE(...)      SysLog(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
     43#define WARN(...)       SysLog(LOG_WARNING, __FILE__, __LINE__, __VA_ARGS__)
     44#define INFO(...)       SysLog(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
     45
     46static const char *syslogLevels[] = {
     47    "emergency",                        /* System is unusable */
     48    "alert",                            /* Action must be taken immediately */
     49    "critical",                         /* Critical conditions */
     50    "error",                            /* Error conditions */
     51    "warning",                          /* Warning conditions */
     52    "notice",                           /* Normal but significant condition */
     53    "info",                             /* Informational */
     54    "debug",                            /* Debug-level messages */
    4955};
    5056
    51 struct child_info {
    52     int   memory;
    53     int   pipefd;
    54     float requests;
    55 };
    56 
    57 struct host_info host_array[100];
    58 struct child_info child_array[100];
    59 
    60 /*
    61  * min()/max() macros that also do
    62  * strict type-checking.. See the
    63  * "unnecessary" pointer comparison.
     57/* RenderServer --
     58 *
     59 *      Contains information to describe/execute a render server.
    6460 */
    65 #define min(x,y) ({                             \
    66             typeof(x) _x = (x);                 \
    67             typeof(y) _y = (y);                 \
    68             (void) (&_x == &_y);                \
    69             _x < _y ? _x : _y; })
    70 
    71 #define max(x,y) ({                             \
    72             typeof(x) _x = (x);                 \
    73             typeof(y) _y = (y);                 \
    74             (void) (&_x == &_y);                \
    75             _x > _y ? _x : _y; })
    76 
     61typedef struct {
     62    const char *name;                   /* Name of server. */
     63    int port;                           /* Port to listen to. */
     64    int numCmdArgs;                     /* # of args in command.  */
     65    int numEnvArgs;                     /* # of args in environment.  */
     66    char *const *cmdArgs;               /* Command to execute for
     67                                         * server. */
     68    char *const *envArgs;               /* Environment strings to set. */
     69    int listenerFd;                     /* Descriptor of the listener
     70                                           socket. */
     71    int inputFd;                        /* Descriptor to dup input side of
     72                                         * server socket. */
     73    int outputFd;                       /* Descriptor to dup output side of
     74                                         * server socket. */
     75    int logStdout;                      /* Redirect server stdout to a
     76                                           file. */
     77    int logStderr;                      /* Redirect server stderr to a
     78                                           file. */
     79    int combineLogs;                    /* Combine server stdout/stderr in
     80                                         * same file. */
     81} RenderServer;
     82
     83static Tcl_HashTable serverTable;       /* Table of render servers
     84                                         * representing services available to
     85                                         * clients.  A new instance is forked
     86                                         * and executed each time a new
     87                                         * request is accepted. */
     88static int debug = FALSE;
     89static pid_t serverPid;
    7790
    7891static void
    79 close_child(int pipe_fd)
     92SysLog(int priority, const char *path, int lineNum, const char* fmt, ...)
    8093{
    81     int i;
    82     for(i=0; i<sizeof(child_array)/sizeof(child_array[0]); i++) {
    83         if (child_array[i].pipefd == pipe_fd) {
    84             children--;
    85             memory_in_use -= child_array[i].memory;
    86             child_array[i].memory = 0;
    87             FD_CLR(child_array[i].pipefd, &saved_rfds);
    88             FD_CLR(child_array[i].pipefd, &pipe_rfds);
    89             close(child_array[i].pipefd);
    90             child_array[i].pipefd = 0;
    91             break;
    92         }
    93     }
    94  
    95     printf("processes=%d, memory=%d, load=%f\n",
    96            children, memory_in_use, load);
    97 
     94#define MSG_LEN (2047)
     95    char message[MSG_LEN+1];
     96    const char *s;
     97    int length;
     98    va_list lst;
     99
     100    va_start(lst, fmt);
     101    s = strrchr(path, '/');
     102    if (s == NULL) {
     103        s = path;
     104    } else {
     105        s++;
     106    }
     107    length = snprintf(message, MSG_LEN, "nanoscale (%d %d) %s: %s:%d ",
     108        serverPid, getpid(), syslogLevels[priority],  s, lineNum);
     109    length += vsnprintf(message + length, MSG_LEN - length, fmt, lst);
     110    message[MSG_LEN] = '\0';
     111    if (debug) {
     112        fprintf(stderr, "%s\n", message);
     113    } else {
     114        syslog(priority, message, length);
     115    }
    98116}
    99117
    100 void note_request(int fd, float value)
    101 {
    102     int c;
    103     for(c=0; c < sizeof(child_array)/sizeof(child_array[0]); c++) {
    104         if (child_array[c].pipefd == fd) {
    105             child_array[c].requests += value;
    106 #ifdef DEBUGGING
    107             printf("Updating requests from pipefd %d to %f\n",
    108                    child_array[c].pipefd,
    109                    child_array[c].requests);
    110 #endif
    111             return;
    112         }
    113     }
    114 }
    115 
    116 volatile int sigalarm_set;
    117 
    118 static void
    119 sigalarm_handler(int signum)
    120 {
    121     sigalarm_set = 1;
    122 }
    123 
    124 static void
    125 help(const char *argv0)
     118static void
     119Help(const char *program)
    126120{
    127121    fprintf(stderr,
    128             "Syntax: %s [-d] -b <broadcast port> -l <listen port> -s <subnet> -c 'command'\n",
    129             argv0);
     122        "Syntax: %s [-d] [-f serversFile] [-x numVideoCards]\n", program);
    130123    exit(1);
    131124}
    132125
    133 static void
    134 clear_service_fd(int fd)
     126static RenderServer *
     127NewServer(Tcl_Interp *interp, const char *name)
    135128{
    136     int n;
    137 
    138     for(n = 0; n < MAX_SERVICES; n++) {
    139         if (FD_ISSET(fd, &service_rfds[n]))
    140             FD_CLR(fd, &service_rfds[n]);
    141     }
     129    RenderServer *serverPtr;
     130
     131    serverPtr = malloc(sizeof(RenderServer));
     132    memset(serverPtr, 0, sizeof(RenderServer));
     133    if (serverPtr == NULL) {
     134        Tcl_AppendResult(interp, "can't allocate structure for \"",
     135                name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     136        return NULL;
     137    }
     138    serverPtr->name = strdup(name);
     139    serverPtr->outputFd = STDOUT_FILENO;
     140    serverPtr->inputFd = STDIN_FILENO;
     141    serverPtr->combineLogs = TRUE;
     142    serverPtr->logStdout = TRUE;
     143    serverPtr->logStderr = TRUE;
     144    return serverPtr;
    142145}
    143146
    144 int
    145 main(int argc, char *argv[])
     147static int
     148ParseSwitches(Tcl_Interp *interp, RenderServer *serverPtr, int *objcPtr,
     149              Tcl_Obj ***objvPtr)
    146150{
    147     char server_command[MAX_SERVICES][1000];
    148     int nservices = 0;
    149     int command_argc[MAX_SERVICES];
    150     char **command_argv[MAX_SERVICES];
    151     int val;
    152     int listen_fd[MAX_SERVICES];
    153     int status;
    154     struct sockaddr_in listen_addr;
    155     struct sockaddr_in recv_addr;
    156     int listen_port[MAX_SERVICES];
    157     int recv_port = -1;
    158     int debug_flag = 0;
    159     int n;
    160 
    161     listen_port[0] = -1;
    162     server_command[0][0] = 0;
    163 
    164     strcpy(displayVar, "DISPLAY=:0.0");
    165     if (putenv(displayVar) < 0) {
    166         perror("putenv");
    167     }
    168     while(1) {
    169         int c;
    170         int option_index = 0;
    171         struct option long_options[] = {
    172             // name, has_arg, flag, val
    173             { 0,0,0,0 },
    174         };
    175 
    176         c = getopt_long(argc, argv, "+b:c:l:s:x:d", long_options,
    177                         &option_index);
    178         if (c == -1)
    179             break;
    180 
    181         switch(c) {
    182         case 'x': /* Number of video cards */
    183             maxCards = strtoul(optarg, 0, 0);
    184             if ((maxCards < 1) || (maxCards > 10)) {
    185                 fprintf(stderr, "bad number of max videocards specified\n");
    186                 return 1;
    187             }
    188             break;
    189         case 'd':
    190             debug_flag = 1;
    191             break;
    192         case 'b':
    193             recv_port = strtoul(optarg, 0, 0);
    194             break;
    195         case 'c':
    196             strncpy(server_command[nservices], optarg, sizeof(server_command[0]));
    197 
    198             if (listen_port[nservices] == -1) {
    199                 fprintf(stderr,"Must specify -l port before each -c command.\n");
    200                 return 1;
    201             }
    202 
    203             nservices++;
    204             listen_port[nservices] = -1;
    205             break;
    206         case 'l':
    207             listen_port[nservices] = strtoul(optarg,0,0);
    208             break;
    209         case 's':
    210             send_addr.sin_addr.s_addr = htonl(inet_network(optarg));
    211             if (send_addr.sin_addr.s_addr == -1) {
    212                 fprintf(stderr,"Invalid subnet broadcast address");
    213                 return 1;
    214             }
    215             break;
    216         default:
    217             fprintf(stderr,"Don't know what option '%c'.\n", c);
    218             return 1;
    219         }
    220     }
    221     if (nservices == 0 ||
    222         recv_port == -1 ||
    223         server_command[0][0]=='\0') {
    224         int i;
    225         for (i = 0; i < argc; i++) {
    226             fprintf(stderr, "argv[%d]=(%s)\n", i, argv[i]);
    227         }
    228         help(argv[0]);
    229         return 1;
    230     }
    231 
    232     for(n = 0; n < nservices; n++) {
    233         // Parse the command arguments...
    234 
    235         command_argc[n]=0;
    236         command_argv[n] = malloc((command_argc[n]+2) * sizeof(char *));
    237         command_argv[n][command_argc[n]] = strtok(server_command[n], " \t");
    238         command_argc[n]++;
    239         while( (command_argv[n][command_argc[n]] = strtok(NULL, " \t"))) {
    240             command_argv[n] = realloc(command_argv[n], (command_argc[n]+2) * sizeof(char *));
    241             command_argc[n]++;
    242         }
    243 
    244         // Create a socket for listening.
    245         listen_fd[n] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    246         if (listen_fd[n] < 0) {
    247             perror("socket");
    248             exit(1);
    249         }
    250  
    251         // If program is killed, drop the socket address reservation immediately.
    252         val = 1;
    253         status = setsockopt(listen_fd[n], SOL_SOCKET, SO_REUSEADDR, &val,
    254                             sizeof(val));
    255         if (status < 0) {
    256             perror("setsockopt");
    257             // Not fatal.  Keep on going.
    258         }
    259 
    260         // Bind this address to the socket.
    261         listen_addr.sin_family = AF_INET;
    262         listen_addr.sin_port = htons(listen_port[n]);
    263         listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    264         status = bind(listen_fd[n], (struct sockaddr *)&listen_addr,
    265                       sizeof(listen_addr));
    266         if (status < 0) {
    267             perror("bind");
    268             exit(1);
    269         }
    270 
    271         // Listen on the specified port.
    272         status = listen(listen_fd[n],5);
    273         if (status < 0) {
    274             perror("listen");
    275         }
    276     }
    277 
    278     // Create a socket for broadcast.
    279     send_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    280     if (send_fd < 0) {
    281         perror("socket");
    282         exit(1);
    283     }
    284 
    285     // If program is killed, drop the socket address reservation immediately.
    286     val = 1;
    287     status = setsockopt(send_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
    288     if (status < 0) {
    289         perror("setsockopt");
    290         // Not fatal.  Keep on going.
    291     }
    292 
    293     // We're going to broadcast through this socket.
    294     val = 1;
    295     status = setsockopt(send_fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val));
    296     if (status < 0) {
    297         perror("setsockopt");
    298         // Not fatal.  Keep on going.
    299     }
    300 
    301     // Bind this address to the socket.
    302     recv_addr.sin_family = AF_INET;
    303     recv_addr.sin_port = htons(recv_port);
    304     recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    305     status = bind(send_fd, (struct sockaddr *)&recv_addr,
    306                   sizeof(recv_addr));
    307     if (status < 0) {
    308         perror("bind");
    309         exit(1);
    310     }
    311 
    312     // Set up the address that we broadcast to.
    313     send_addr.sin_family = AF_INET;
    314     send_addr.sin_port = htons(recv_port);
    315 
    316     // Set up a signal handler for the alarm interrupt.
    317     // It doesn't do anything other than interrupt select() below.
    318     if (signal(SIGALRM, sigalarm_handler) == SIG_ERR) {
    319         perror("signal SIGALRM");
    320     }
    321 
    322     struct itimerval itvalue = {
    323         {1, 0}, {1, 0}
    324     };
    325     status = setitimer(ITIMER_REAL, &itvalue, NULL);
    326     if (status != 0) {
    327         perror("setitimer");
    328     }
    329 
    330     // We're ready to go.  Before going into the main loop,
    331     // broadcast a load announcement to other machines.
    332     int maxfd = send_fd;
    333     FD_ZERO(&saved_rfds);
    334     FD_ZERO(&pipe_rfds);
    335 
    336     for(n = 0; n < nservices; n++) {
    337         FD_ZERO(&service_rfds[n]);
    338         FD_SET(listen_fd[n], &saved_rfds);
    339         if (listen_fd[n] > maxfd)
    340             maxfd = listen_fd[n];
    341     }
    342 
    343     FD_SET(send_fd, &saved_rfds);
    344 
    345     if (!debug_flag) {
    346         if ( daemon(0,0) != 0 ) {
    347             perror("daemon");
    348             exit(1);
    349         }
    350     }
    351 
    352     while(1) {
    353         fd_set rfds = saved_rfds;
    354      
    355         status = select(maxfd+1, &rfds, NULL, NULL, 0);
    356         if (status <= 0) {
    357             if (sigalarm_set) {
    358                 sigalarm_set = 0;
    359             }
    360             continue;
    361         }
    362      
    363         int accepted = 0;
    364         for(n = 0; n < nservices; n++) {
    365             if (FD_ISSET(listen_fd[n], &rfds)) {
    366                 // Accept a new connection.
    367                 struct sockaddr_in newaddr;
    368                 unsigned int addrlen = sizeof(newaddr);
    369                 int newfd = accept(listen_fd[n], (struct sockaddr *)&newaddr, &addrlen);
    370                 if (newfd < 0) {
    371                     perror("accept");
    372                     continue;
    373                 }
    374              
    375                 printf("New connection from %s\n", inet_ntoa(newaddr.sin_addr));
    376                 FD_SET(newfd, &saved_rfds);
    377                 maxfd = max(maxfd, newfd);
    378                 FD_SET(newfd, &service_rfds[n]);
    379                 accepted = 1;
    380             }
    381         }
    382      
    383         if (accepted)
    384             continue;
    385      
    386         if (FD_ISSET(send_fd, &rfds)) {
    387             int buffer[1000];
    388             struct sockaddr_in peer_addr;
    389             unsigned int len = sizeof(peer_addr);
    390             status = recvfrom(send_fd, buffer, sizeof(buffer), 0,
    391                               (struct sockaddr*)&peer_addr, &len);
    392             if (status < 0) {
    393                 perror("recvfrom");
    394                 continue;
    395             }
    396             if (status != 8) {
    397                 fprintf(stderr,"Bogus message from %s\n",
    398                         inet_ntoa(peer_addr.sin_addr));
    399                 continue;
    400             }
    401             float peer_load = ntohl(buffer[0]);
    402             int peer_procs = ntohl(buffer[1]);
    403             //printf("Load for %s is %f (%d processes).\n",
    404             //       inet_ntoa(peer_addr.sin_addr), peer_load, peer_procs);
    405             int h;
    406             int free_index=-1;
    407             int found = 0;
    408             for(h=0; h<sizeof(host_array)/sizeof(host_array[0]); h++) {
    409                 if (host_array[h].in_addr.s_addr == peer_addr.sin_addr.s_addr) {
    410                     if (host_array[h].children != peer_procs) {
    411                         printf("Load for %s is %f (%d processes).\n",
    412                                inet_ntoa(peer_addr.sin_addr), peer_load, peer_procs);
    413                     }
    414                     host_array[h].load = peer_load;
    415                     host_array[h].children = peer_procs;
    416                     found = 1;
    417                     break;
    418                 }
    419                 if (host_array[h].in_addr.s_addr == 0 && free_index == -1) {
    420                     free_index = h;
    421                 }
    422             }
    423             if (!found) {
    424                 host_array[free_index].in_addr.s_addr = peer_addr.sin_addr.s_addr;
    425                 host_array[free_index].load = peer_load;
    426             }
    427             continue;
    428         }
    429      
    430         int i;
    431         for(i=0; i< maxfd +1; i++) {
    432             if (FD_ISSET(i,&rfds)) {
    433              
    434                 // If this is a pipe, get the load.  Update.
    435                 if (FD_ISSET(i,&pipe_rfds)) {
    436                     float value;
    437                     status = read(i, &value, sizeof(value));
    438                     if (status != 4) {
    439                         //fprintf(stderr,"error reading pipe, child ended?\n");
    440                         close_child(i);
    441                         /*close(i);
    442                           FD_CLR(i, &saved_rfds);
    443                           FD_CLR(i, &pipe_rfds); */
    444                     } else {
    445                         note_request(i,value);
    446                     }
    447                     continue;
    448                 }
    449              
    450                 // This must be a descriptor that we're waiting to from for
    451                 // the memory footprint.  Get it.
    452                 int msg;
    453                 status = read(i, &msg, 4);
    454                 if (status != 4) {
    455                     fprintf(stderr,"Bad status on read (%d).", status);
    456                     FD_CLR(i, &saved_rfds);
    457                     clear_service_fd(i);
    458                     close(i);
    459                     continue;
    460                 }
    461              
    462                 // find the new memory increment
    463                 int newmemory = ntohl(msg);
    464              
    465                 memory_in_use += newmemory;
    466                 load += 2*INITIAL_LOAD;
    467                 printf("Accepted new job with memory %d\n", newmemory);
    468                 //printf("My load is now %f\n", load);
    469              
    470                 // accept the connection.
    471                 msg = 0;
    472                 if (write(i, &msg, 4) != 4) {
    473                     fprintf(stderr, "short write for hostname\n");
    474                 }
    475              
    476                 int pair[2];
    477                 status = pipe(pair);
    478                 if (status != 0) {
    479                     perror("pipe");
    480                 }
    481              
    482                 // Make the child side of the pipe non-blocking...
    483                 status = fcntl(pair[1], F_SETFL, O_NONBLOCK);
    484                 if (status < 0) {
    485                     perror("fcntl");
    486                 }
    487                 dispNum++;
    488                 if (dispNum >= maxCards) {
    489                     dispNum = 0;
    490                 }
    491                 // Fork the new process.  Connect i/o to the new socket.
    492                 status = fork();
    493                 if (status < 0) {
    494                     perror("fork");
    495                 } else if (status == 0) {
    496                  
    497                     for(n = 0; n < MAX_SERVICES; n++) {
    498                         if (FD_ISSET(i, &service_rfds[n])) {
    499                             int status = 0;
    500 
    501                             if (!debug_flag) {
    502                                 // disassociate
    503                                 status = daemon(0,1);
    504                             }
    505                            
    506                             if (status == 0) {
    507                                 int fd;
    508 
    509                                 dup2(i, 0);  // stdin
    510                                 dup2(i, 1);  // stdout
    511                                 dup2(i, 2);  // stderr
    512                                 dup2(pair[1],3);
    513                                 // read end of pipe moved, and left open to
    514                                 // prevent SIGPIPE
    515                                 dup2(pair[0],4);
    516                              
    517                                 for(fd=5; fd<FD_SETSIZE; fd++)
    518                                     close(fd);
    519                              
    520                                 if (maxCards > 1) {
    521                                     displayVar[11] = dispNum + '0';
    522                                 }
    523                                 execvp(command_argv[n][0], command_argv[n]);
    524                             }
    525                             _exit(errno);
    526                         }
    527                     }
    528                     _exit(EINVAL);
    529                  
    530                 } else {
    531                     int c;
    532                     // reap initial child which will exit immediately
    533                     // (grandchild continues)
    534                     waitpid(status, NULL, 0);
    535                     for(c=0; c<sizeof(child_array)/sizeof(child_array[0]); c++) {
    536                         if (child_array[c].pipefd == 0) {
    537                             child_array[c].memory = newmemory;
    538                             child_array[c].pipefd = pair[0];
    539                             child_array[c].requests = INITIAL_LOAD;
    540                             status = close(pair[1]);
    541                             if (status != 0) {
    542                                 perror("close pair[1]");
    543                             }
    544                             FD_SET(pair[0], &saved_rfds);
    545                             FD_SET(pair[0], &pipe_rfds);
    546                             maxfd = max(pair[0], maxfd);
    547                             break;
    548                         }
    549                     }
    550                  
    551                     children++;
    552                 }
    553              
    554              
    555                 FD_CLR(i, &saved_rfds);
    556                 clear_service_fd(i);
    557                 close(i);
    558                 break;
    559             }
    560          
    561         } // for all connected_fds
    562      
    563     } // while(1)
    564  
     151    int i, objc;
     152    Tcl_Obj **objv;
     153
     154    objc = *objcPtr;
     155    objv = *objvPtr;
     156    for (i = 3; i < objc; i += 2) {
     157        const char *string;
     158        char c;
     159
     160        string = Tcl_GetString(objv[i]);
     161        if (string[0] != '-') {
     162            break;
     163        }
     164        c = string[1];
     165        if ((c == 'i') && (strcmp(string, "-input") == 0)) {
     166            int f;
     167
     168            if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) {
     169                return TCL_ERROR;
     170            }
     171            serverPtr->inputFd = f;
     172        } else if ((c == 'o') && (strcmp(string, "-output") == 0)) {
     173            int f;
     174
     175            if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) {
     176                return TCL_ERROR;
     177            }
     178            serverPtr->outputFd = f;
     179        } else if ((c == 'l') && (strcmp(string, "-logstdout") == 0)) {
     180            int state;
     181
     182            if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
     183                return TCL_ERROR;
     184            }
     185            serverPtr->logStdout = state;
     186        } else if ((c == 'l') && (strcmp(string, "-logstderr") == 0)) {
     187            int state;
     188
     189            if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
     190                return TCL_ERROR;
     191            }
     192            serverPtr->logStderr = state;
     193        } else if ((c == 'c') && (strcmp(string, "-combinelogs") == 0)) {
     194            int state;
     195
     196            if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
     197                return TCL_ERROR;
     198            }
     199            serverPtr->combineLogs = state;
     200        } else {
     201            Tcl_AppendResult(interp, "unknown switch \"", string, "\"",
     202                             (char *)NULL);
     203            return TCL_ERROR;
     204        }
     205    }
     206    *objcPtr = objc - (i - 3);
     207    *objvPtr = objv + (i - 3);
     208    return TCL_OK;
    565209}
    566210
     211/*
     212 * RegisterServerCmd --
     213 *
     214 *      Registers a render server to be run when a client connects
     215 *      on the designated port. The form of the commands is
     216 *
     217 *          register_server <name> <port> <cmd> <environ>
     218 *
     219 *      where
     220 *
     221 *          name        Token for the render server.
     222 *          port        Port to listen to accept connections.
     223 *          cmd         Command to be run to start the render server.
     224 *          environ     Name-value pairs of representing environment
     225 *                      variables.
     226 *
     227 *      Note that "cmd" and "environ" are variable and backslash
     228 *      substituted.  A listener socket automatically is established on
     229 *      the given port to accept client requests.
     230 *
     231 *      Example:
     232 *
     233 *          register_server myServer 12345 ?switches? {
     234 *               /path/to/myserver arg arg
     235 *          } {
     236 *               LD_LIBRARY_PATH $libdir/myServer
     237 *          }
     238 *
     239 */
     240static int
     241RegisterServerCmd(ClientData clientData, Tcl_Interp *interp, int objc,
     242                  Tcl_Obj *const *objv)
     243{
     244    Tcl_Obj *objPtr;
     245    const char *serverName;
     246    int bool, isNew;
     247    int f;
     248    int port;
     249    int numCmdArgs, numEnvArgs;
     250    char *const *cmdArgs;
     251    char *const *envArgs;
     252    struct sockaddr_in addr;
     253    RenderServer *serverPtr;
     254    Tcl_HashEntry *hPtr;
     255
     256    if (objc < 4) {
     257        Tcl_AppendResult(interp, "wrong # args: should be \"",
     258                Tcl_GetString(objv[0]), " serverName port ?flags? cmd ?environ?",
     259                (char *)NULL);
     260        return TCL_ERROR;
     261    }
     262    serverName = Tcl_GetString(objv[1]);
     263    if (Tcl_GetIntFromObj(interp, objv[2], &port) != TCL_OK) {
     264        return TCL_ERROR;
     265    }
     266    hPtr = Tcl_CreateHashEntry(&serverTable, (char *)((long)port), &isNew);
     267    if (!isNew) {
     268        Tcl_AppendResult(interp, "a server is already listening on port ",
     269                Tcl_GetString(objv[2]), (char *)NULL);
     270        return TCL_ERROR;
     271    }
     272    serverPtr = NewServer(interp, serverName);
     273    if (serverPtr == NULL) {
     274        return TCL_ERROR;
     275    }
     276    Tcl_SetHashValue(hPtr, serverPtr);
     277    if (ParseSwitches(interp, serverPtr, &objc, (Tcl_Obj ***)&objv) != TCL_OK) {
     278        goto error;
     279    }
     280    objPtr = Tcl_SubstObj(interp, objv[3],
     281                          TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES);
     282    if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numCmdArgs,
     283        (const char ***)&cmdArgs) != TCL_OK) {
     284        goto error;
     285    }
     286    serverPtr->cmdArgs = cmdArgs;
     287    serverPtr->numCmdArgs = numCmdArgs;
     288
     289    numEnvArgs = 0;
     290    envArgs = NULL;
     291    if (objc == 5) {
     292        objPtr = Tcl_SubstObj(interp, objv[4],
     293                TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES);
     294        if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numEnvArgs,
     295                (const char ***)&envArgs) != TCL_OK) {
     296            goto error;
     297        }
     298        if (numEnvArgs & 0x1) {
     299            Tcl_AppendResult(interp, "odd # elements in enviroment list",
     300                             (char *)NULL);
     301            goto error;
     302        }
     303    }
     304    serverPtr->envArgs = envArgs;
     305    serverPtr->numEnvArgs = numEnvArgs;
     306
     307    /* Create a socket for listening. */
     308    f = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     309    if (f < 0) {
     310        Tcl_AppendResult(interp, "can't create listerner socket for \"",
     311                serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     312        goto error;
     313    }
     314
     315    /* If the render server instance should be killed, drop the socket address
     316     * reservation immediately, don't linger. */
     317    bool = TRUE;
     318    if (setsockopt(f, SOL_SOCKET, SO_REUSEADDR, &bool, sizeof(bool)) < 0) {
     319        Tcl_AppendResult(interp, "can't create set socket option for \"",
     320                serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     321        goto error;
     322    }
     323
     324    /* Bind this address to the socket. */
     325    addr.sin_family = AF_INET;
     326    addr.sin_port = htons(port);
     327    addr.sin_addr.s_addr = htonl(INADDR_ANY);
     328    if (bind(f, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
     329        Tcl_AppendResult(interp, "can't bind to socket for \"",
     330                serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     331        goto error;
     332    }
     333    /* Listen on the specified port. */
     334    if (listen(f, 5) < 0) {
     335        Tcl_AppendResult(interp, "can't listen to socket for \"",
     336                serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     337        return TCL_ERROR;
     338    }
     339    serverPtr->listenerFd = f;
     340
     341    return TCL_OK;
     342 error:
     343    free(serverPtr);
     344    return TCL_ERROR;
     345}
     346
     347static int
     348ParseServersFile(const char *fileName)
     349{
     350    Tcl_Interp *interp;
     351
     352    interp = Tcl_CreateInterp();
     353    Tcl_MakeSafe(interp);
     354    Tcl_CreateObjCommand(interp, "register_server", RegisterServerCmd, NULL,
     355                         NULL);
     356    if (Tcl_EvalFile(interp, fileName) != TCL_OK) {
     357        ERROR("Can't add server: %s", Tcl_GetString(Tcl_GetObjResult(interp)));
     358        return FALSE;
     359    }
     360    Tcl_DeleteInterp(interp);
     361    return TRUE;
     362}
     363
     364int
     365main(int argc, char **argv)
     366{
     367#ifdef SA_NOCLDWAIT
     368    struct sigaction action;
     369#endif
     370    fd_set serverFds;
     371    int maxFd;                          /* Highest file descriptor in use. */
     372    char display[200];                  /* String used to manage the X
     373                                         * DISPLAY variable for each render
     374                                         * server instance. */
     375    int maxCards;                       /* Maximum number of video cards, each
     376                                         * represented by a different X
     377                                         * screen.  */
     378    int screenNum;                      /* Current X screen number. */
     379    Tcl_HashEntry *hPtr;
     380    Tcl_HashSearch iter;
     381    const char *fileName;               /* Path to servers file. */
     382
     383    serverPid = getpid();
     384    screenNum = 0;
     385    maxCards = 1;
     386    fileName = SERVERSFILE;
     387    debug = FALSE;
     388
     389    strcpy(display, ":0.0");
     390    Tcl_InitHashTable(&serverTable, TCL_ONE_WORD_KEYS);
     391
     392    /* Process command line switches. */
     393    for (;;) {
     394        int c;
     395        int option_index = 0;
     396        struct option long_options[] = {
     397            // name, has_arg, flag, val
     398            { 0,0,0,0 },
     399        };
     400
     401        c = getopt_long(argc, argv, "x:f:d", long_options, &option_index);
     402        if (c == -1) {
     403            break;
     404        }
     405
     406        switch(c) {
     407        case 'x':                       /* Number of video cards */
     408            maxCards = strtoul(optarg, 0, 0);
     409            if ((maxCards < 1) || (maxCards > 10)) {
     410                fprintf(stderr, "Bad number of max videocards specified\n");
     411                return 1;
     412            }
     413            break;
     414        case 'd':                       /* Debug  */
     415            debug = TRUE;
     416            break;
     417
     418        case 'f':                       /* Server file path. */
     419            fileName = strdup(optarg);
     420            break;
     421
     422        default:
     423            fprintf(stderr,"Don't know what option '%c'.\n", c);
     424            Help(argv[0]);
     425            exit(1);
     426        }
     427    }
     428
     429    if (!debug) {
     430        /* Detach this process from the controlling terminal process. The
     431         * current directory becomes /tmp and redirect stdin/stdout/stderr to
     432         * /dev/null. */
     433        if (daemon(0,0) < 0) {
     434            ERROR("Can't daemonize nanoscale: %s", strerror(errno));
     435            exit(1);
     436        }
     437    }
     438    serverPid = getpid();
     439    if (!ParseServersFile(fileName)) {
     440        exit(1);
     441    }
     442
     443    if (serverTable.numEntries == 0) {
     444        ERROR("No servers designated.");
     445        exit(1);
     446    }
     447    signal(SIGPIPE, SIG_IGN);
     448#ifdef SA_NOCLDWAIT
     449    memset(&action, 0, sizeof(action));
     450    action.sa_flags = SA_NOCLDWAIT;
     451    sigaction(SIGCHLD, &action, 0);
     452#else
     453    signal(SIGCHLD, SIG_IGN);
     454#endif
     455
     456    /* Build the array of servers listener file descriptors. */
     457    FD_ZERO(&serverFds);
     458    maxFd = -1;
     459    for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL;
     460         hPtr = Tcl_NextHashEntry(&iter)) {
     461        RenderServer *serverPtr;
     462
     463        serverPtr = Tcl_GetHashValue(hPtr);
     464        FD_SET(serverPtr->listenerFd, &serverFds);
     465        if (serverPtr->listenerFd > maxFd) {
     466            maxFd = serverPtr->listenerFd;
     467        }
     468    }
     469
     470    for (;;) {
     471        fd_set readFds;
     472
     473        /* Reset using the array of server file descriptors. */
     474        memcpy(&readFds, &serverFds, sizeof(serverFds));
     475        if (select(maxFd+1, &readFds, NULL, NULL, 0) <= 0) {
     476            ERROR("Select failed: %s", strerror(errno));
     477            break;                      /* Error on select. */
     478        }
     479        for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL;
     480             hPtr = Tcl_NextHashEntry(&iter)) {
     481            RenderServer *serverPtr;
     482            pid_t child;
     483            int sock;
     484            socklen_t length;
     485            struct sockaddr_in newaddr;
     486
     487            serverPtr = Tcl_GetHashValue(hPtr);
     488            if (!FD_ISSET(serverPtr->listenerFd, &readFds)) {
     489                continue;
     490            }
     491            /* Rotate the display's screen number.  If we have multiple video
     492             * cards, try to spread the jobs out among them.  */
     493            screenNum++;
     494            if (screenNum >= maxCards) {
     495                screenNum = 0;
     496            }
     497            /* Accept the new connection. */
     498            length = sizeof(newaddr);
     499#ifdef HAVE_ACCEPT4
     500            sock = accept4(serverPtr->listenerFd, (struct sockaddr *)&newaddr,
     501                           &length, SOCK_CLOEXEC);
     502#else
     503            sock = accept(serverPtr->listenerFd, (struct sockaddr *)&newaddr,
     504                          &length);
     505#endif
     506            if (sock < 0) {
     507                ERROR("Can't accept server \"%s\": %s", serverPtr->name,
     508                      strerror(errno));
     509                exit(1);
     510            }
     511#ifndef HAVE_ACCEPT4
     512            int flags = fcntl(sock, F_GETFD);
     513            flags |= FD_CLOEXEC;
     514            if (fcntl(sock, F_SETFD, flags) < 0) {
     515                ERROR("Can't set FD_CLOEXEC on socket \"%s\": %s",
     516                        serverPtr->name, strerror(errno));
     517                exit(1);
     518            }
     519#endif
     520            INFO("Connecting \"%s\" to %s\n", serverPtr->name,
     521                 inet_ntoa(newaddr.sin_addr));
     522
     523            /* Fork the new process.  Connect I/O to the new socket. */
     524            child = fork();
     525            if (child < 0) {
     526                ERROR("Can't fork \"%s\": %s", serverPtr->name,
     527                      strerror(errno));
     528                continue;
     529            }
     530            if (child == 0) {           /* Child process. */
     531                int i;
     532
     533                if ((!debug) && (setsid() < 0)) {
     534                    ERROR("Can't setsid \"%s\": %s", serverPtr->name,
     535                          strerror(errno));
     536                    exit(1);
     537                }
     538                if ((!debug) && ((chdir("/")) < 0)) {
     539                    ERROR("Can't change to root directory for \"%s\": %s",
     540                          serverPtr->name, strerror(errno));
     541                    exit(1);
     542                }
     543                if (serverPtr->combineLogs) {
     544                    char path[BUFSIZ];
     545                    int newFd;
     546
     547                    sprintf(path, "%s/%s-%d.log", LOGDIR,
     548                        serverPtr->name, getpid());
     549                    if (serverPtr->logStdout) {
     550                        newFd = open(path, O_WRONLY | O_CREAT| O_TRUNC, 0600);
     551                    } else {
     552                        newFd = open("/dev/null", O_WRONLY, 0600);
     553                    }
     554                    if (newFd < 0) {
     555                        ERROR("%s: can't open \"%s\": %s", serverPtr->name,
     556                              path, strerror(errno));
     557                        exit(1);
     558                    }
     559                    if (dup2(newFd, 1) < 0) {
     560                        ERROR("%s: can't dup stdout to \"%s\": %s",
     561                              serverPtr->name, path, strerror(errno));
     562                        exit(1);
     563                    }
     564                    if (dup2(newFd, 2) < 0) {
     565                        ERROR("%s: can't dup stderr to \"%s\": %s",
     566                              serverPtr->name, path, strerror(errno));
     567                        exit(1);
     568                    }
     569                } else {
     570                    char path[BUFSIZ];
     571                    int newFd;
     572
     573                    sprintf(path, "%s/%s-%d.stdout", LOGDIR,
     574                        serverPtr->name, getpid());
     575                    if (serverPtr->logStdout) {
     576                        newFd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
     577                    } else {
     578                        newFd = open("/dev/null", O_WRONLY, 0600);
     579                    }
     580                    if (newFd < 0) {
     581                        ERROR("%s: can't open \"%s\": %s", serverPtr->name,
     582                              path, strerror(errno));
     583                        exit(1);
     584                    }
     585                    if (dup2(newFd, 1) < 0) {
     586                        ERROR("%s: can't dup stdout to \"%s\": %s",
     587                              serverPtr->name, path, strerror(errno));
     588                        exit(1);
     589                    }
     590                    sprintf(path, "%s/%s-%d.stderr", LOGDIR,
     591                        serverPtr->name, getpid());
     592                    if (serverPtr->logStderr) {
     593                        newFd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
     594                    } else {
     595                        newFd = open("/dev/null", O_WRONLY, 0600);
     596                    }
     597                    if (newFd < 0) {
     598                        ERROR("%s: can't open \"%s\": %s", serverPtr->name,
     599                              path, strerror(errno));
     600                        exit(1);
     601                    }
     602                    if (dup2(newFd, 2) < 0) {
     603                        ERROR("%s: can't dup stderr to \"%s\": %s",
     604                              serverPtr->name, path, strerror(errno));
     605                        exit(1);
     606                    }
     607                }
     608                /* Dup the socket to descriptors, e.g. 3 and 4 */
     609                if (dup2(sock, serverPtr->inputFd) < 0)  { /* input */
     610                    ERROR("%s: can't dup socket to fd %d: %s",
     611                          serverPtr->name, serverPtr->inputFd,
     612                          strerror(errno));
     613                    exit(1);
     614                }
     615                /* If using a single descriptor for input and output, we don't
     616                 * need to call dup2 again
     617                 */
     618                if (serverPtr->outputFd != serverPtr->inputFd) {
     619                    if (dup2(sock, serverPtr->outputFd) < 0) { /* output */
     620                        ERROR("%s: can't dup socket to fd %d: %s",
     621                              serverPtr->name, serverPtr->outputFd,
     622                              strerror(errno));
     623                        exit(1);
     624                    }
     625                }
     626                /* Close all the other descriptors. */
     627                for (i = 3; i <= FD_SETSIZE; i++) {
     628                    if (i != serverPtr->inputFd &&
     629                        i != serverPtr->outputFd) {
     630                        close(i);
     631                    }
     632                }
     633
     634                /* Set the screen number in the DISPLAY variable. */
     635                display[3] = screenNum + '0';
     636                setenv("DISPLAY", display, 1);
     637                /* Set the enviroment, if necessary. */
     638                for (i = 0; i < serverPtr->numEnvArgs; i += 2) {
     639                    setenv(serverPtr->envArgs[i], serverPtr->envArgs[i+1], 1);
     640                }
     641                {
     642                    char *cmd;
     643
     644                    cmd = Tcl_Merge(serverPtr->numCmdArgs,
     645                                    (const char *const *)serverPtr->cmdArgs);
     646                    INFO("Executing %s: client=%s, \"%s\" in=%d out=%d on DISPLAY=%s",
     647                         serverPtr->name, inet_ntoa(newaddr.sin_addr),
     648                         cmd, serverPtr->inputFd, serverPtr->outputFd, display);
     649                    /* Replace the current process with the render server. */
     650                    execvp(serverPtr->cmdArgs[0], serverPtr->cmdArgs);
     651                    ERROR("Can't execute \"%s\": %s", cmd, strerror(errno));
     652                    Tcl_Free(cmd);
     653                    exit(1);
     654                }
     655            } else {
     656                close(sock);
     657            }
     658        }
     659    }
     660    exit(1);
     661}
Note: See TracChangeset for help on using the changeset viewer.