<commit_before>// Copyright (c) 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "opt/build_module.h"
#include "opt/cfg.h"
#include "opt/ir_context.h"
#include "opt/pass.h"
#include "opt/propagator.h"

namespace {

using namespace spvtools;

using ::testing::UnorderedElementsAre;

class PropagatorTest : public testing::Test {
 protected:
  virtual void TearDown() {
    ctx_.reset(nullptr);
    cfg_.reset(nullptr);
    values_.clear();
    values_vec_.clear();
  }

  void Assemble(const std::string& input) {
    ctx_ = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, input);
    ASSERT_NE(nullptr, ctx_) << "Assembling failed for shader:\n"
                             << input << "\n";
    cfg_.reset(new ir::CFG(ctx_->module()));
  }

  bool Propagate(const opt::SSAPropagator::VisitFunction& visit_fn) {
    opt::SSAPropagator propagator(ctx_.get(), cfg_.get(), visit_fn);
    bool retval = false;
    for (auto& fn : *ctx_->module()) {
      retval |= propagator.Run(&fn);
    }
    return retval;
  }

  const std::vector<uint32_t>& GetValues() {
    values_vec_.clear();
    for (const auto& it : values_) {
      values_vec_.push_back(it.second);
    }
    return values_vec_;
  }

  std::unique_ptr<ir::IRContext> ctx_;
  std::unique_ptr<ir::CFG> cfg_;
  std::map<uint32_t, uint32_t> values_;
  std::vector<uint32_t> values_vec_;
};

TEST_F(PropagatorTest, LocalPropagate) {
  const std::string spv_asm = R"(
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %main "main" %outparm
               OpExecutionMode %main OriginUpperLeft
               OpSource GLSL 450
               OpName %main "main"
               OpName %x "x"
               OpName %y "y"
               OpName %z "z"
               OpName %outparm "outparm"
               OpDecorate %outparm Location 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
        %int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
      %int_4 = OpConstant %int 4
      %int_3 = OpConstant %int 3
      %int_1 = OpConstant %int 1
%_ptr_Output_int = OpTypePointer Output %int
    %outparm = OpVariable %_ptr_Output_int Output
       %main = OpFunction %void None %3
          %5 = OpLabel
          %x = OpVariable %_ptr_Function_int Function
          %y = OpVariable %_ptr_Function_int Function
          %z = OpVariable %_ptr_Function_int Function
               OpStore %x %int_4
               OpStore %y %int_3
               OpStore %z %int_1
         %20 = OpLoad %int %z
               OpStore %outparm %20
               OpReturn
               OpFunctionEnd
               )";
  Assemble(spv_asm);

  const auto visit_fn = [this](ir::Instruction* instr,
                               ir::BasicBlock** dest_bb) {
    *dest_bb = nullptr;
    if (instr->opcode() == SpvOpStore) {
      uint32_t lhs_id = instr->GetSingleWordOperand(0);
      uint32_t rhs_id = instr->GetSingleWordOperand(1);
      ir::Instruction* rhs_def = ctx_->get_def_use_mgr()->GetDef(rhs_id);
      if (rhs_def->opcode() == SpvOpConstant) {
        uint32_t val = rhs_def->GetSingleWordOperand(2);
        values_[lhs_id] = val;
        return opt::SSAPropagator::kInteresting;
      }
    }
    return opt::SSAPropagator::kVarying;
  };

  EXPECT_TRUE(Propagate(visit_fn));
  EXPECT_THAT(GetValues(), UnorderedElementsAre(4, 3, 1));
}

TEST_F(PropagatorTest, PropagateThroughPhis) {
  const std::string spv_asm = R"(
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %main "main" %x %outparm
               OpExecutionMode %main OriginUpperLeft
               OpSource GLSL 450
               OpName %main "main"
               OpName %x "x"
               OpName %outparm "outparm"
               OpDecorate %x Flat
               OpDecorate %x Location 0
               OpDecorate %outparm Location 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
        %int = OpTypeInt 32 1
       %bool = OpTypeBool
%_ptr_Function_int = OpTypePointer Function %int
      %int_4 = OpConstant %int 4
      %int_3 = OpConstant %int 3
      %int_1 = OpConstant %int 1
%_ptr_Input_int = OpTypePointer Input %int
          %x = OpVariable %_ptr_Input_int Input
%_ptr_Output_int = OpTypePointer Output %int
    %outparm = OpVariable %_ptr_Output_int Output
       %main = OpFunction %void None %3
          %4 = OpLabel
          %5 = OpLoad %int %x
          %6 = OpSGreaterThan %bool %5 %int_3
               OpSelectionMerge %25 None
               OpBranchConditional %6 %22 %23
         %22 = OpLabel
          %7 = OpLoad %int %int_4
               OpBranch %25
         %23 = OpLabel
          %8 = OpLoad %int %int_4
               OpBranch %25
         %25 = OpLabel
         %35 = OpPhi %int %7 %22 %8 %23
               OpStore %outparm %35
               OpReturn
               OpFunctionEnd
               )";

  Assemble(spv_asm);

  ir::Instruction *phi_instr = nullptr;
  const auto visit_fn = [this, &phi_instr](ir::Instruction* instr,
                                           ir::BasicBlock** dest_bb) {
    *dest_bb = nullptr;
    if (instr->opcode() == SpvOpLoad) {
      uint32_t rhs_id = instr->GetSingleWordOperand(2);
      ir::Instruction* rhs_def = ctx_->get_def_use_mgr()->GetDef(rhs_id);
      if (rhs_def->opcode() == SpvOpConstant) {
        uint32_t val = rhs_def->GetSingleWordOperand(2);
        values_[instr->result_id()] = val;
        return opt::SSAPropagator::kInteresting;
      }
    } else if (instr->opcode() == SpvOpPhi) {
      phi_instr = instr;
      opt::SSAPropagator::PropStatus retval;
      for (uint32_t i = 2; i < instr->NumOperands(); i += 2) {
        uint32_t phi_arg_id = instr->GetSingleWordOperand(i);
        auto it = values_.find(phi_arg_id);
        if (it != values_.end()) {
          EXPECT_EQ(it->second, 4);
          retval = opt::SSAPropagator::kInteresting;
          values_[instr->result_id()] = it->second;
        } else {
          retval = opt::SSAPropagator::kNotInteresting;
          break;
        }
      }
      return retval;
    }

    return opt::SSAPropagator::kVarying;
  };

  EXPECT_TRUE(Propagate(visit_fn));

  // The propagator should've concluded that the Phi instruction has a constant
  // value of 4.
  EXPECT_NE(phi_instr, nullptr);
  EXPECT_EQ(values_[phi_instr->result_id()], 4);

  EXPECT_THAT(GetValues(), UnorderedElementsAre(4, 4, 4));
}

}  // namespace
<commit_msg>Fix windows build. unsigned vs signed comparison in EXPECT_EQ.<commit_after>// Copyright (c) 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "opt/build_module.h"
#include "opt/cfg.h"
#include "opt/ir_context.h"
#include "opt/pass.h"
#include "opt/propagator.h"

namespace {

using namespace spvtools;

using ::testing::UnorderedElementsAre;

class PropagatorTest : public testing::Test {
 protected:
  virtual void TearDown() {
    ctx_.reset(nullptr);
    cfg_.reset(nullptr);
    values_.clear();
    values_vec_.clear();
  }

  void Assemble(const std::string& input) {
    ctx_ = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, input);
    ASSERT_NE(nullptr, ctx_) << "Assembling failed for shader:\n"
                             << input << "\n";
    cfg_.reset(new ir::CFG(ctx_->module()));
  }

  bool Propagate(const opt::SSAPropagator::VisitFunction& visit_fn) {
    opt::SSAPropagator propagator(ctx_.get(), cfg_.get(), visit_fn);
    bool retval = false;
    for (auto& fn : *ctx_->module()) {
      retval |= propagator.Run(&fn);
    }
    return retval;
  }

  const std::vector<uint32_t>& GetValues() {
    values_vec_.clear();
    for (const auto& it : values_) {
      values_vec_.push_back(it.second);
    }
    return values_vec_;
  }

  std::unique_ptr<ir::IRContext> ctx_;
  std::unique_ptr<ir::CFG> cfg_;
  std::map<uint32_t, uint32_t> values_;
  std::vector<uint32_t> values_vec_;
};

TEST_F(PropagatorTest, LocalPropagate) {
  const std::string spv_asm = R"(
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %main "main" %outparm
               OpExecutionMode %main OriginUpperLeft
               OpSource GLSL 450
               OpName %main "main"
               OpName %x "x"
               OpName %y "y"
               OpName %z "z"
               OpName %outparm "outparm"
               OpDecorate %outparm Location 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
        %int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
      %int_4 = OpConstant %int 4
      %int_3 = OpConstant %int 3
      %int_1 = OpConstant %int 1
%_ptr_Output_int = OpTypePointer Output %int
    %outparm = OpVariable %_ptr_Output_int Output
       %main = OpFunction %void None %3
          %5 = OpLabel
          %x = OpVariable %_ptr_Function_int Function
          %y = OpVariable %_ptr_Function_int Function
          %z = OpVariable %_ptr_Function_int Function
               OpStore %x %int_4
               OpStore %y %int_3
               OpStore %z %int_1
         %20 = OpLoad %int %z
               OpStore %outparm %20
               OpReturn
               OpFunctionEnd
               )";
  Assemble(spv_asm);

  const auto visit_fn = [this](ir::Instruction* instr,
                               ir::BasicBlock** dest_bb) {
    *dest_bb = nullptr;
    if (instr->opcode() == SpvOpStore) {
      uint32_t lhs_id = instr->GetSingleWordOperand(0);
      uint32_t rhs_id = instr->GetSingleWordOperand(1);
      ir::Instruction* rhs_def = ctx_->get_def_use_mgr()->GetDef(rhs_id);
      if (rhs_def->opcode() == SpvOpConstant) {
        uint32_t val = rhs_def->GetSingleWordOperand(2);
        values_[lhs_id] = val;
        return opt::SSAPropagator::kInteresting;
      }
    }
    return opt::SSAPropagator::kVarying;
  };

  EXPECT_TRUE(Propagate(visit_fn));
  EXPECT_THAT(GetValues(), UnorderedElementsAre(4, 3, 1));
}

TEST_F(PropagatorTest, PropagateThroughPhis) {
  const std::string spv_asm = R"(
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %main "main" %x %outparm
               OpExecutionMode %main OriginUpperLeft
               OpSource GLSL 450
               OpName %main "main"
               OpName %x "x"
               OpName %outparm "outparm"
               OpDecorate %x Flat
               OpDecorate %x Location 0
               OpDecorate %outparm Location 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
        %int = OpTypeInt 32 1
       %bool = OpTypeBool
%_ptr_Function_int = OpTypePointer Function %int
      %int_4 = OpConstant %int 4
      %int_3 = OpConstant %int 3
      %int_1 = OpConstant %int 1
%_ptr_Input_int = OpTypePointer Input %int
          %x = OpVariable %_ptr_Input_int Input
%_ptr_Output_int = OpTypePointer Output %int
    %outparm = OpVariable %_ptr_Output_int Output
       %main = OpFunction %void None %3
          %4 = OpLabel
          %5 = OpLoad %int %x
          %6 = OpSGreaterThan %bool %5 %int_3
               OpSelectionMerge %25 None
               OpBranchConditional %6 %22 %23
         %22 = OpLabel
          %7 = OpLoad %int %int_4
               OpBranch %25
         %23 = OpLabel
          %8 = OpLoad %int %int_4
               OpBranch %25
         %25 = OpLabel
         %35 = OpPhi %int %7 %22 %8 %23
               OpStore %outparm %35
               OpReturn
               OpFunctionEnd
               )";

  Assemble(spv_asm);

  ir::Instruction *phi_instr = nullptr;
  const auto visit_fn = [this, &phi_instr](ir::Instruction* instr,
                                           ir::BasicBlock** dest_bb) {
    *dest_bb = nullptr;
    if (instr->opcode() == SpvOpLoad) {
      uint32_t rhs_id = instr->GetSingleWordOperand(2);
      ir::Instruction* rhs_def = ctx_->get_def_use_mgr()->GetDef(rhs_id);
      if (rhs_def->opcode() == SpvOpConstant) {
        uint32_t val = rhs_def->GetSingleWordOperand(2);
        values_[instr->result_id()] = val;
        return opt::SSAPropagator::kInteresting;
      }
    } else if (instr->opcode() == SpvOpPhi) {
      phi_instr = instr;
      opt::SSAPropagator::PropStatus retval;
      for (uint32_t i = 2; i < instr->NumOperands(); i += 2) {
        uint32_t phi_arg_id = instr->GetSingleWordOperand(i);
        auto it = values_.find(phi_arg_id);
        if (it != values_.end()) {
          EXPECT_EQ(it->second, 4u);
          retval = opt::SSAPropagator::kInteresting;
          values_[instr->result_id()] = it->second;
        } else {
          retval = opt::SSAPropagator::kNotInteresting;
          break;
        }
      }
      return retval;
    }

    return opt::SSAPropagator::kVarying;
  };

  EXPECT_TRUE(Propagate(visit_fn));

  // The propagator should've concluded that the Phi instruction has a constant
  // value of 4.
  EXPECT_NE(phi_instr, nullptr);
  EXPECT_EQ(values_[phi_instr->result_id()], 4u);

  EXPECT_THAT(GetValues(), UnorderedElementsAre(4u, 4u, 4u));
}

}  // namespace
<|endoftext|>


<commit_before>/*
 * This file is part of signon
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include "pluginproxy.h"

#include <sys/types.h>
#include <pwd.h>

#include <QStringList>
#include <QThreadStorage>
#include <QThread>

#include "SignOn/uisessiondata_priv.h"
#include "SignOn/signonplugincommon.h"

/*
 *   TODO: remove the "SignOn/authpluginif.h" include below after the removal
 *         of the deprecated error handling (needed here only for the deprecated
 *         AuthPluginError::PLUGIN_ERROR_GENERAL).
 */
#include "SignOn/authpluginif.h"

using namespace SignOn;

//TODO get this from config
#define REMOTEPLUGIN_BIN_PATH QLatin1String("/usr/bin/signonpluginprocess")
#define PLUGINPROCESS_TIMEOUT 5000

namespace SignonDaemonNS {

    PluginProcess::PluginProcess(QObject *parent) : QProcess(parent)
    {
    }

    PluginProcess::~PluginProcess()
    {
        if (state() != QProcess::NotRunning)
            terminate();

        waitForFinished();
    }

    void PluginProcess::setupChildProcess()
    {
        // Drop all root privileges in the child process and switch to signon user
#ifndef NO_SIGNON_USER
        //get uid and gid
        struct passwd *passwdRecord = getpwnam("signon");
        if ( !passwdRecord ){
            fprintf(stderr, "failed to get user: signon\n");
            emit QProcess::finished(2, QProcess::NormalExit);
            exit(2);
        }
#ifdef SIGNOND_TRACE
        //this is run in remote plugin process, so trace should go to stderr
        fprintf(stderr, "got user: %s with uid: %d\n", passwdRecord->pw_name, passwdRecord->pw_uid);
#endif
        if (( ::setgid(passwdRecord->pw_gid))
                || (::setuid(passwdRecord->pw_uid))
                || (::getuid() != passwdRecord->pw_uid)
                ) {
            fprintf(stderr, "failed to set user: %s with uid: %d", passwdRecord->pw_name, passwdRecord->pw_uid);
            emit QProcess::finished(2, QProcess::NormalExit);
            exit(2);
        }
 #endif
    }

    PluginProxy::PluginProxy(QString type, QObject *parent)
            : QObject(parent)
    {
        TRACE();

        m_type = type;
        m_isProcessing = false;
        m_process = new PluginProcess(this);

        connect(m_process, SIGNAL(readyReadStandardError()), this, SLOT(onReadStandardError()));

        /*
         * TODO: some error handling should be added here, at least remove of current
         * request data from the top of the queue and reply an error code
         * */
        connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onExit(int, QProcess::ExitStatus)));
        connect(m_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(onError(QProcess::ProcessError)));
    }

    PluginProxy::~PluginProxy()
    {
    }

    PluginProxy* PluginProxy::createNewPluginProxy(const QString &type)
    {
        PluginProxy *pp = new PluginProxy(type);

        QStringList args = QStringList() << pp->m_type;
        pp->m_process->start(REMOTEPLUGIN_BIN_PATH, args);

        QByteArray tmp;

        if (!pp->waitForStarted(PLUGINPROCESS_TIMEOUT)) {
            TRACE() << "The process cannot be started";
            delete pp;
            return NULL;
        }

        if (!pp->readOnReady(tmp, PLUGINPROCESS_TIMEOUT)) {
            TRACE() << "The process cannot load plugin";
            delete pp;
            return NULL;
        }

        pp->m_type = pp->queryType();
        pp->m_mechanisms = pp->queryMechanisms();

        connect(pp->m_process, SIGNAL(readyReadStandardOutput()), pp, SLOT(onReadStandardOutput()));

        TRACE() << "The process is started";
        return pp;
    }

   bool PluginProxy::process(const QString &cancelKey, const QVariantMap &inData, const QString &mechanism)
   {
        TRACE();
        if (!restartIfRequired())
            return false;

        m_cancelKey = cancelKey;
        QVariant value = inData.value(SSOUI_KEY_UIPOLICY);
        m_uiPolicy = value.toInt();
        //TODO check if this part can be done in SignonSessionCore::startProcess()
        QVariantMap inDataTmp = inData;
        if (m_uiPolicy == RequestPasswordPolicy)
            inDataTmp.remove(SSOUI_KEY_PASSWORD);
        QDataStream in(m_process);

        in << (quint32)PLUGIN_OP_PROCESS;
        in << QVariant(inDataTmp);
        in << QVariant(mechanism);

        m_isProcessing = true;

        return true;
    }

   bool PluginProxy::processUi(const QString &cancelKey, const QVariantMap &inData)
   {
        TRACE() << inData;

        if (!restartIfRequired())
            return false;

        m_cancelKey = cancelKey;

        QDataStream in(m_process);

        in << (quint32)PLUGIN_OP_PROCESS_UI;
        in << QVariant(inData);

        m_isProcessing = true;

        return true;
    }

   bool PluginProxy::processRefresh(const QString &cancelKey, const QVariantMap &inData)
   {
        TRACE() << inData;

        if (!restartIfRequired())
            return false;

        m_cancelKey = cancelKey;

        QDataStream in(m_process);

        in << (quint32)PLUGIN_OP_REFRESH;
        in << QVariant(inData);

        m_isProcessing = true;

        return true;
    }

   void PluginProxy::cancel()
   {
       TRACE();
       QDataStream in(m_process);
       in << (quint32)PLUGIN_OP_CANCEL;
    }

   void PluginProxy::stop()
   {
       TRACE();
       QDataStream in(m_process);
       in << (quint32)PLUGIN_OP_STOP;
    }

    bool PluginProxy::readOnReady(QByteArray &buffer, int timeout)
    {
        bool ready = m_process->waitForReadyRead(timeout);

        if (ready) {
            if (!m_process->bytesAvailable())
                return false;

            while (m_process->bytesAvailable())
                buffer += m_process->readAllStandardOutput();
        }

        return ready;
    }

    bool PluginProxy::isProcessing()
    {
        return m_isProcessing;
    }

    void PluginProxy::onReadStandardOutput()
    {
        disconnect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(onReadStandardOutput()));

        QByteArray token;

        QVariant infoVa;
        QVariantMap info;

        if (!m_process->bytesAvailable()) {
            qCritical() << "No information available on process";
            m_isProcessing = false;
            emit processError(m_cancelKey, Error::InternalServer, QString());
            return;
        }

        QByteArray buffer;

        while (m_process->bytesAvailable())
            buffer += m_process->readAllStandardOutput();

        /*
         * we need to analyze the whole buffer
         * and if it contains error then emit only error
         * otherwise process/emit the incoming information
         * one by one
         * */
        QDataStream out(buffer);
        bool isResultObtained = false;

        while (out.status() == QDataStream::Ok) {
            quint32 opres;
            out >> opres; //result of operation: error code

            TRACE() << opres;

            if (opres == PLUGIN_RESPONSE_RESULT) {
                TRACE() << "PLUGIN_RESPONSE_RESULT";
                out >> infoVa; //SessionData in QVariant
                info = infoVa.toMap();
                m_isProcessing = false;

                if (!isResultObtained)
                    emit processResultReply(m_cancelKey, info);
                else
                    BLAME() << "Unexpected plugin response: " << info;

                isResultObtained = true;
            } else if (opres == PLUGIN_RESPONSE_STORE) {
                TRACE() << "PLUGIN_RESPONSE_STORE";
                out >> infoVa; //SessionData in QVariant
                info = infoVa.toMap();

                if (!isResultObtained)
                    emit processStore(m_cancelKey, info);
                else
                    BLAME() << "Unexpected plugin store: " << info;

            } else if (opres == PLUGIN_RESPONSE_UI) {
                TRACE() << "PLUGIN_RESPONSE_UI";
                out >> infoVa; //UiSessionData in QVariant
                info = infoVa.toMap();

                if (!isResultObtained) {
                    bool allowed = true;

                    if (m_uiPolicy == NoUserInteractionPolicy)
                        allowed = false;

                    if (m_uiPolicy == ValidationPolicy &&
                        (info.contains(SSOUI_KEY_QUERYUSERNAME)
                        || info.contains(SSOUI_KEY_QUERYPASSWORD)))
                        allowed = false;

                    if (!allowed) {
                        //set error and return;
                        TRACE() << "ui policy prevented ui launch";
                        info.insert(SSOUI_KEY_ERROR, QUERY_ERROR_FORBIDDEN);
                        processUi(m_cancelKey, info);
                    } else {
                        TRACE() << "open ui";
                        emit processUiRequest(m_cancelKey, info);
                    }
                } else {
                    BLAME() << "Unexpected plugin ui response: " << info;
                }
            } else if (opres == PLUGIN_RESPONSE_REFRESHED) {
                TRACE() << "PLUGIN_RESPONSE_REFRESHED";
                out >> infoVa; //UiSessionData in QVariant
                info = infoVa.toMap();

                if (!isResultObtained)
                    emit processRefreshRequest(m_cancelKey, info);
                else
                    BLAME() << "Unexpected plugin ui response: " << info;
            } else if (opres == PLUGIN_RESPONSE_ERROR) {
                TRACE() << "PLUGIN_RESPONSE_ERROR";
                quint32 err;
                QString errorMessage;
                out >> err;
                out >> errorMessage;
                m_isProcessing = false;

                if (!isResultObtained)
                    emit processError(m_cancelKey, (int)err, errorMessage);
                else
                    BLAME() << "Unexpected plugin error: " << errorMessage;

                isResultObtained = true;
            } else if (opres == PLUGIN_RESPONSE_SIGNAL) {
                TRACE() << "PLUGIN_RESPONSE_SIGNAL";
                quint32 state;
                QString message;

                out >> state;
                out >> message;

                if (!isResultObtained)
                    emit stateChanged(m_cancelKey, (int)state, message);
                else
                    BLAME() << "Unexpected plugin signal: " << state << " " << message;
            }
        }

        connect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(onReadStandardOutput()));
    }

    void PluginProxy::onReadStandardError()
    {
        QString ba = QString::fromLatin1(m_process->readAllStandardError());
        TRACE() << ba;
    }

    void PluginProxy::onExit(int exitCode, QProcess::ExitStatus exitStatus)
    {
        TRACE() << "Plugin process exit with code " << exitCode << " : " << exitStatus;

        if (m_isProcessing || exitStatus == QProcess::CrashExit) {
            qCritical() << "Challenge produces CRASH!";
            emit processError(m_cancelKey, Error::InternalServer, QLatin1String("plugin processed crashed"));
        }
        if (exitCode == 2) {
            TRACE() << "plugin process terminated because cannot change user";
        }

        m_isProcessing = false;
    }

    void PluginProxy::onError(QProcess::ProcessError err)
    {
        TRACE() << "Error: " << err;
    }

    QString PluginProxy::queryType()
    {
        TRACE();

        if (!restartIfRequired())
            return QString();

        QDataStream ds(m_process);
        ds << (quint32)PLUGIN_OP_TYPE;

        QByteArray typeBa, buffer;
        bool result;

        if ((result = readOnReady(buffer, PLUGINPROCESS_TIMEOUT))) {
            QDataStream out(buffer);
            out >> typeBa;
        } else
            qCritical("PluginProxy returned NULL result");

        return QString::fromLatin1(typeBa);
    }

    QStringList PluginProxy::queryMechanisms()
    {
        TRACE();

        if (!restartIfRequired())
            return QStringList();

        QDataStream in(m_process);
        in << (quint32)PLUGIN_OP_MECHANISMS;

        QByteArray buffer;
        QStringList strList;
        bool result;

        if ((result = readOnReady(buffer, PLUGINPROCESS_TIMEOUT))) {
            QVariant mechanismsVar;
            QDataStream out(buffer);

            out >> mechanismsVar;
            QVariantList varList = mechanismsVar.toList();

            for (int i = 0; i < varList.count(); i++)
                    strList << varList.at(i).toString();

            TRACE() << strList;
        } else
            qCritical("PluginProxy returned NULL result");

        return strList;
    }

    bool PluginProxy::waitForStarted(int timeout)
    {
        return m_process->waitForStarted(timeout);
    }

    bool PluginProxy::waitForFinished(int timeout)
    {
        return m_process->waitForFinished(timeout);
    }

    bool PluginProxy::restartIfRequired()
    {
        if (m_process->state() == QProcess::NotRunning) {
            TRACE() << "RESTART REQUIRED";
            m_process->start(REMOTEPLUGIN_BIN_PATH, QStringList(m_type));

            QByteArray tmp;
            if (!waitForStarted(PLUGINPROCESS_TIMEOUT) || !readOnReady(tmp, PLUGINPROCESS_TIMEOUT))
                return false;
        }
        return true;
    }

} //namespace SignonDaemonNS
<commit_msg>Reconsider bug fixing of NB#185401.<commit_after>/*
 * This file is part of signon
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include "pluginproxy.h"

#include <sys/types.h>
#include <pwd.h>

#include <QStringList>
#include <QThreadStorage>
#include <QThread>

#include "SignOn/uisessiondata_priv.h"
#include "SignOn/signonplugincommon.h"

/*
 *   TODO: remove the "SignOn/authpluginif.h" include below after the removal
 *         of the deprecated error handling (needed here only for the deprecated
 *         AuthPluginError::PLUGIN_ERROR_GENERAL).
 */
#include "SignOn/authpluginif.h"

using namespace SignOn;

//TODO get this from config
#define REMOTEPLUGIN_BIN_PATH QLatin1String("/usr/bin/signonpluginprocess")
#define PLUGINPROCESS_TIMEOUT 5000

namespace SignonDaemonNS {

    PluginProcess::PluginProcess(QObject *parent) : QProcess(parent)
    {
    }

    PluginProcess::~PluginProcess()
    {
        if (state() != QProcess::NotRunning)
            terminate();

        waitForFinished();
    }

    void PluginProcess::setupChildProcess()
    {
        // Drop all root privileges in the child process and switch to signon user
#ifndef NO_SIGNON_USER
        //get uid and gid
        struct passwd *passwdRecord = getpwnam("signon");
        if ( !passwdRecord ){
            fprintf(stderr, "failed to get user: signon\n");
            emit QProcess::finished(2, QProcess::NormalExit);
            exit(2);
        }
#ifdef SIGNOND_TRACE
        //this is run in remote plugin process, so trace should go to stderr
        fprintf(stderr, "got user: %s with uid: %d\n", passwdRecord->pw_name, passwdRecord->pw_uid);
#endif
        if (( ::setgid(passwdRecord->pw_gid))
                || (::setuid(passwdRecord->pw_uid))
                || (::getuid() != passwdRecord->pw_uid)
                ) {
            fprintf(stderr, "failed to set user: %s with uid: %d", passwdRecord->pw_name, passwdRecord->pw_uid);
            emit QProcess::finished(2, QProcess::NormalExit);
            exit(2);
        }
 #endif
    }

    PluginProxy::PluginProxy(QString type, QObject *parent)
            : QObject(parent)
    {
        TRACE();

        m_type = type;
        m_isProcessing = false;
        m_process = new PluginProcess(this);

        connect(m_process, SIGNAL(readyReadStandardError()), this, SLOT(onReadStandardError()));

        /*
         * TODO: some error handling should be added here, at least remove of current
         * request data from the top of the queue and reply an error code
         * */
        connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onExit(int, QProcess::ExitStatus)));
        connect(m_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(onError(QProcess::ProcessError)));
    }

    PluginProxy::~PluginProxy()
    {
    }

    PluginProxy* PluginProxy::createNewPluginProxy(const QString &type)
    {
        PluginProxy *pp = new PluginProxy(type);

        QStringList args = QStringList() << pp->m_type;
        pp->m_process->start(REMOTEPLUGIN_BIN_PATH, args);

        QByteArray tmp;

        if (!pp->waitForStarted(PLUGINPROCESS_TIMEOUT)) {
            TRACE() << "The process cannot be started";
            delete pp;
            return NULL;
        }

        if (!pp->readOnReady(tmp, PLUGINPROCESS_TIMEOUT)) {
            TRACE() << "The process cannot load plugin";
            delete pp;
            return NULL;
        }

        pp->m_type = pp->queryType();
        pp->m_mechanisms = pp->queryMechanisms();

        connect(pp->m_process, SIGNAL(readyReadStandardOutput()), pp, SLOT(onReadStandardOutput()));

        TRACE() << "The process is started";
        return pp;
    }

   bool PluginProxy::process(const QString &cancelKey, const QVariantMap &inData, const QString &mechanism)
   {
        TRACE();
        if (!restartIfRequired())
            return false;

        m_cancelKey = cancelKey;
        QVariant value = inData.value(SSOUI_KEY_UIPOLICY);
        m_uiPolicy = value.toInt();
        //TODO check if this part can be done in SignonSessionCore::startProcess()
        QVariantMap inDataTmp = inData;
        if (m_uiPolicy == RequestPasswordPolicy)
            inDataTmp.remove(SSOUI_KEY_PASSWORD);
        QDataStream in(m_process);

        in << (quint32)PLUGIN_OP_PROCESS;
        in << QVariant(inDataTmp);
        in << QVariant(mechanism);

        m_isProcessing = true;

        return true;
    }

   bool PluginProxy::processUi(const QString &cancelKey, const QVariantMap &inData)
   {
        TRACE() << inData;

        if (!restartIfRequired())
            return false;

        m_cancelKey = cancelKey;

        QDataStream in(m_process);

        in << (quint32)PLUGIN_OP_PROCESS_UI;
        in << QVariant(inData);

        m_isProcessing = true;

        return true;
    }

   bool PluginProxy::processRefresh(const QString &cancelKey, const QVariantMap &inData)
   {
        TRACE() << inData;

        if (!restartIfRequired())
            return false;

        m_cancelKey = cancelKey;

        QDataStream in(m_process);

        in << (quint32)PLUGIN_OP_REFRESH;
        in << QVariant(inData);

        m_isProcessing = true;

        return true;
    }

   void PluginProxy::cancel()
   {
       TRACE();
       QDataStream in(m_process);
       in << (quint32)PLUGIN_OP_CANCEL;
    }

   void PluginProxy::stop()
   {
       TRACE();
       QDataStream in(m_process);
       in << (quint32)PLUGIN_OP_STOP;
    }

    bool PluginProxy::readOnReady(QByteArray &buffer, int timeout)
    {
        bool ready = m_process->waitForReadyRead(timeout);

        if (ready) {
            if (!m_process->bytesAvailable())
                return false;

            while (m_process->bytesAvailable())
                buffer += m_process->readAllStandardOutput();
        }

        return ready;
    }

    bool PluginProxy::isProcessing()
    {
        return m_isProcessing;
    }

    void PluginProxy::onReadStandardOutput()
    {
        disconnect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(onReadStandardOutput()));

        QByteArray token;

        QVariant infoVa;
        QVariantMap info;

        if (!m_process->bytesAvailable()) {
            qCritical() << "No information available on process";
            m_isProcessing = false;
            emit processError(m_cancelKey, Error::InternalServer, QString());
            return;
        }

        QByteArray buffer;

        while (m_process->bytesAvailable())
            buffer += m_process->readAllStandardOutput();

        /*
         * we need to analyze the whole buffer
         * and if it contains error then emit only error
         * otherwise process/emit the incoming information
         * one by one
         * */
        QDataStream out(buffer);
        bool isResultObtained = false;

        while (out.status() == QDataStream::Ok) {
            quint32 opres;
            out >> opres; //result of operation: error code

            TRACE() << opres;

            if (opres == PLUGIN_RESPONSE_RESULT) {
                TRACE() << "PLUGIN_RESPONSE_RESULT";
                out >> infoVa; //SessionData in QVariant
                info = infoVa.toMap();
                m_isProcessing = false;

                if (!isResultObtained)
                    emit processResultReply(m_cancelKey, info);
                else
                    BLAME() << "Unexpected plugin response: " << info;

                isResultObtained = true;
            } else if (opres == PLUGIN_RESPONSE_STORE) {
                TRACE() << "PLUGIN_RESPONSE_STORE";
                out >> infoVa; //SessionData in QVariant
                info = infoVa.toMap();

                if (!isResultObtained)
                    emit processStore(m_cancelKey, info);
                else
                    BLAME() << "Unexpected plugin store: " << info;

            } else if (opres == PLUGIN_RESPONSE_UI) {
                TRACE() << "PLUGIN_RESPONSE_UI";
                out >> infoVa; //UiSessionData in QVariant
                info = infoVa.toMap();

                if (!isResultObtained) {
                    bool allowed = true;

                    if (m_uiPolicy == NoUserInteractionPolicy)
                        allowed = false;

                    if (m_uiPolicy == ValidationPolicy) {
                        bool credentialsQueried =
                            (info.contains(SSOUI_KEY_QUERYUSERNAME)
                            || info.contains(SSOUI_KEY_QUERYPASSWORD));

                        bool captchaQueried  =
                            (info.contains(SSOUI_KEY_CAPTCHAIMG)
                             || info.contains(SSOUI_KEY_CAPTCHAURL));

                        if (credentialsQueried && !captchaQueried)
                            allowed = false;
                    }

                    if (!allowed) {
                        //set error and return;
                        TRACE() << "ui policy prevented ui launch";
                        info.insert(SSOUI_KEY_ERROR, QUERY_ERROR_FORBIDDEN);
                        processUi(m_cancelKey, info);
                    } else {
                        TRACE() << "open ui";
                        emit processUiRequest(m_cancelKey, info);
                    }
                } else {
                    BLAME() << "Unexpected plugin ui response: " << info;
                }
            } else if (opres == PLUGIN_RESPONSE_REFRESHED) {
                TRACE() << "PLUGIN_RESPONSE_REFRESHED";
                out >> infoVa; //UiSessionData in QVariant
                info = infoVa.toMap();

                if (!isResultObtained)
                    emit processRefreshRequest(m_cancelKey, info);
                else
                    BLAME() << "Unexpected plugin ui response: " << info;
            } else if (opres == PLUGIN_RESPONSE_ERROR) {
                TRACE() << "PLUGIN_RESPONSE_ERROR";
                quint32 err;
                QString errorMessage;
                out >> err;
                out >> errorMessage;
                m_isProcessing = false;

                if (!isResultObtained)
                    emit processError(m_cancelKey, (int)err, errorMessage);
                else
                    BLAME() << "Unexpected plugin error: " << errorMessage;

                isResultObtained = true;
            } else if (opres == PLUGIN_RESPONSE_SIGNAL) {
                TRACE() << "PLUGIN_RESPONSE_SIGNAL";
                quint32 state;
                QString message;

                out >> state;
                out >> message;

                if (!isResultObtained)
                    emit stateChanged(m_cancelKey, (int)state, message);
                else
                    BLAME() << "Unexpected plugin signal: " << state << " " << message;
            }
        }

        connect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(onReadStandardOutput()));
    }

    void PluginProxy::onReadStandardError()
    {
        QString ba = QString::fromLatin1(m_process->readAllStandardError());
        TRACE() << ba;
    }

    void PluginProxy::onExit(int exitCode, QProcess::ExitStatus exitStatus)
    {
        TRACE() << "Plugin process exit with code " << exitCode << " : " << exitStatus;

        if (m_isProcessing || exitStatus == QProcess::CrashExit) {
            qCritical() << "Challenge produces CRASH!";
            emit processError(m_cancelKey, Error::InternalServer, QLatin1String("plugin processed crashed"));
        }
        if (exitCode == 2) {
            TRACE() << "plugin process terminated because cannot change user";
        }

        m_isProcessing = false;
    }

    void PluginProxy::onError(QProcess::ProcessError err)
    {
        TRACE() << "Error: " << err;
    }

    QString PluginProxy::queryType()
    {
        TRACE();

        if (!restartIfRequired())
            return QString();

        QDataStream ds(m_process);
        ds << (quint32)PLUGIN_OP_TYPE;

        QByteArray typeBa, buffer;
        bool result;

        if ((result = readOnReady(buffer, PLUGINPROCESS_TIMEOUT))) {
            QDataStream out(buffer);
            out >> typeBa;
        } else
            qCritical("PluginProxy returned NULL result");

        return QString::fromLatin1(typeBa);
    }

    QStringList PluginProxy::queryMechanisms()
    {
        TRACE();

        if (!restartIfRequired())
            return QStringList();

        QDataStream in(m_process);
        in << (quint32)PLUGIN_OP_MECHANISMS;

        QByteArray buffer;
        QStringList strList;
        bool result;

        if ((result = readOnReady(buffer, PLUGINPROCESS_TIMEOUT))) {
            QVariant mechanismsVar;
            QDataStream out(buffer);

            out >> mechanismsVar;
            QVariantList varList = mechanismsVar.toList();

            for (int i = 0; i < varList.count(); i++)
                    strList << varList.at(i).toString();

            TRACE() << strList;
        } else
            qCritical("PluginProxy returned NULL result");

        return strList;
    }

    bool PluginProxy::waitForStarted(int timeout)
    {
        return m_process->waitForStarted(timeout);
    }

    bool PluginProxy::waitForFinished(int timeout)
    {
        return m_process->waitForFinished(timeout);
    }

    bool PluginProxy::restartIfRequired()
    {
        if (m_process->state() == QProcess::NotRunning) {
            TRACE() << "RESTART REQUIRED";
            m_process->start(REMOTEPLUGIN_BIN_PATH, QStringList(m_type));

            QByteArray tmp;
            if (!waitForStarted(PLUGINPROCESS_TIMEOUT) || !readOnReady(tmp, PLUGINPROCESS_TIMEOUT))
                return false;
        }
        return true;
    }

} //namespace SignonDaemonNS
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>

#include <time.h>
#include <unistd.h>

#include "realm/realm.h"
#include "realm/profiling.h"

using namespace Realm;
using namespace Realm::ProfilingMeasurements;
using namespace LegionRuntime::LowLevel;

// Task IDs, some IDs are reserved so start at first available number
enum {
  TOP_LEVEL_TASK = Processor::TASK_ID_FIRST_AVAILABLE+0,
  CHILD_TASK     = Processor::TASK_ID_FIRST_AVAILABLE+1,
  RESPONSE_TASK,
};

// some of the code in here needs the fault-tolerance stuff in Realm to show up
#define NO_TRACK_MACHINE_UPDATES
#define NO_TEST_FAULTS

#ifdef TRACK_MACHINE_UPDATES
class MyMachineUpdateTracker : public Machine::MachineUpdateSubscriber {
public:
  MyMachineUpdateTracker(void) {}
  virtual ~MyMachineUpdateTracker(void) {}

  virtual void processor_updated(Processor p, UpdateType update_type,
				 const void *payload, size_t payload_size)
  {
    printf("machine processor update: " IDFMT " %s (%zd payload_bytes)\n",
	   p.id, (update_type == Machine::MachineUpdateSubscriber::THING_ADDED ? "added" :
		  update_type == Machine::MachineUpdateSubscriber::THING_REMOVED ? "removed" : "updated"),
	   payload_size);
  }

  virtual void memory_updated(Memory m, UpdateType update_type,
			      const void *payload, size_t payload_size)
  {
    printf("machine memory update: " IDFMT " %s (%zd payload_bytes)\n",
	   m.id, (update_type == Machine::MachineUpdateSubscriber::THING_ADDED ? "added" :
		  update_type == Machine::MachineUpdateSubscriber::THING_REMOVED ? "removed" : "updated"),
	   payload_size);
  }
};

MyMachineUpdateTracker tracker;
#endif

void child_task(const void *args, size_t arglen, Processor p)
{
  printf("starting task on processor " IDFMT "\n", p.id);
  sleep(1);
#ifdef TEST_FAULTS
  bool inject_fault = *(const bool *)args;
  if(inject_fault) {
    int buffer[4];
    buffer[0] = 11;
    buffer[1] = 22;
    buffer[2] = 33;
    buffer[3] = 44;
    Processor::report_execution_fault(44, buffer, 4*sizeof(int));
  }
#endif
  printf("ending task on processor " IDFMT "\n", p.id);
}

void response_task(const void *args, size_t arglen, Processor p)
{
  printf("got profiling response - %zd bytes\n", arglen);
  printf("Bytes:");
  for(size_t i = 0; i < arglen; i++)
    printf(" %02x", ((unsigned char *)args)[i]);
  printf("\n");

  Realm::ProfilingResponse pr(args, arglen);

  if(pr.has_measurement<OperationStatus>()) {
    OperationStatus *op_status = pr.get_measurement<OperationStatus>();
    printf("op status = %d (code = %d, details = %zd bytes)\n",
	   (int)(op_status->result),
	   op_status->error_code,
	   op_status->error_details.size());
    delete op_status;
  } else
    printf("no status\n");

  if(pr.has_measurement<OperationTimeline>()) {
    OperationTimeline *op_timeline = pr.get_measurement<OperationTimeline>();
    printf("op timeline = %llu %llu %llu (%lld %lld)\n",
	   op_timeline->ready_time,
	   op_timeline->start_time,
	   op_timeline->end_time,
	   op_timeline->start_time - op_timeline->ready_time,
	   op_timeline->end_time - op_timeline->start_time);
    delete op_timeline;
  } else
    printf("no timeline\n");

  if(pr.user_data_size() > 0) {
    printf("user data = %zd (", pr.user_data_size());
    unsigned char *data = (unsigned char *)(pr.user_data());
    for(size_t i = 0; i < pr.user_data_size(); i++)
      printf(" %02x", data[i]);
    printf(" )\n");
  } else
    printf("no user data\n");
}

void top_level_task(const void *args, size_t arglen, Processor p)
{
  printf("top level task - getting machine and list of CPUs\n");

  Machine machine = Machine::get_machine();
  std::vector<Processor> all_cpus;
  {
    std::set<Processor> all_processors;
    machine.get_all_processors(all_processors);
    for(std::set<Processor>::const_iterator it = all_processors.begin();
	it != all_processors.end();
	it++)
      if(it->kind() == Processor::LOC_PROC)
	all_cpus.push_back(*it);
  }

#ifdef TEST_FAULTS
  // touch all of the new resilience-based calls (just to test linking)
  if(arglen == 97) {  // if the compiler can DCE this, no link errors...  :(
    Processor::report_execution_fault(0, 0, 0);
    Processor::NO_PROC.report_processor_fault(0, 0, 0);
    Memory::NO_MEMORY.report_memory_fault(0, 0, 0);
    RegionInstance::NO_INST.report_instance_fault(0, 0, 0);
    RegionInstance::NO_INST.get_accessor().report_fault(ptr_t(0), 0, 0);
    RegionInstance::NO_INST.get_accessor().report_fault(DomainPoint(), 0, 0);
    RegionInstance::NO_INST.get_accessor().typeify<int>().report_fault(ptr_t(0));
    RegionInstance::NO_INST.get_accessor().typeify<int>().report_fault(DomainPoint());
    bool poisoned;
    Event::NO_EVENT.has_triggered_faultaware(poisoned);
    Event::NO_EVENT.wait_faultaware(poisoned);
    Processor::cancel_task(Event::NO_EVENT);
    Domain::cancel_copy(Event::NO_EVENT);
    UserEvent::create_user_event().cancel();
  }
#endif

  // launch a child task and perform some measurements on it
  Processor first_cpu = all_cpus[0];
  ProfilingRequestSet prs;
  prs.add_request(first_cpu, RESPONSE_TASK, &first_cpu, sizeof(first_cpu))
    .add_measurement<OperationStatus>()
    .add_measurement<OperationTimeline>();

  bool inject_fault = false;
  Event e1 = first_cpu.spawn(CHILD_TASK, &inject_fault, sizeof(inject_fault), prs);
  inject_fault = true;
  Event e2 = first_cpu.spawn(CHILD_TASK, &inject_fault, sizeof(inject_fault), prs, e1);
  inject_fault = false;
  Event e3 = first_cpu.spawn(CHILD_TASK, &inject_fault, sizeof(inject_fault), prs, e2);

  bool poisoned = false;
#ifdef TEST_FAULTS
  e3.wait_faultaware(poisoned);
#else
  e3.wait();
#endif
  printf("done! (poisoned=%d)\n", poisoned);

  sleep(10);
  // shutdown the runtime - this should implicitly wait for the report task to run
  {
    std::set<Processor> all_procs;
    machine.get_all_processors(all_procs);
    for (std::set<Processor>::const_iterator it = all_procs.begin();
          it != all_procs.end(); it++)
    {
      // Damn you C++ and your broken const qualifiers
      Processor handle_copy = *it;
      // Send the kill pill
      handle_copy.spawn(0,NULL,0);
    }
  }
}

int main(int argc, char **argv)
{
  Runtime rt;

  rt.init(&argc, &argv);

  rt.register_task(TOP_LEVEL_TASK, top_level_task);
  rt.register_task(CHILD_TASK, child_task);
  rt.register_task(RESPONSE_TASK, response_task);

  // Start the machine running
  // Control never returns from this call
  // Note we only run the top level task on one processor
  // You can also run the top level task on all processors or one processor per node
  rt.run(TOP_LEVEL_TASK, Runtime::ONE_TASK_ONLY);

  rt.shutdown();
  return -1;
}
<commit_msg>use last processor to cause inter-node traffic<commit_after>#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>

#include <time.h>
#include <unistd.h>

#include "realm/realm.h"
#include "realm/profiling.h"

using namespace Realm;
using namespace Realm::ProfilingMeasurements;
using namespace LegionRuntime::LowLevel;

// Task IDs, some IDs are reserved so start at first available number
enum {
  TOP_LEVEL_TASK = Processor::TASK_ID_FIRST_AVAILABLE+0,
  CHILD_TASK     = Processor::TASK_ID_FIRST_AVAILABLE+1,
  RESPONSE_TASK,
};

// some of the code in here needs the fault-tolerance stuff in Realm to show up
#define NO_TRACK_MACHINE_UPDATES
#define NO_TEST_FAULTS

#ifdef TRACK_MACHINE_UPDATES
class MyMachineUpdateTracker : public Machine::MachineUpdateSubscriber {
public:
  MyMachineUpdateTracker(void) {}
  virtual ~MyMachineUpdateTracker(void) {}

  virtual void processor_updated(Processor p, UpdateType update_type,
				 const void *payload, size_t payload_size)
  {
    printf("machine processor update: " IDFMT " %s (%zd payload_bytes)\n",
	   p.id, (update_type == Machine::MachineUpdateSubscriber::THING_ADDED ? "added" :
		  update_type == Machine::MachineUpdateSubscriber::THING_REMOVED ? "removed" : "updated"),
	   payload_size);
  }

  virtual void memory_updated(Memory m, UpdateType update_type,
			      const void *payload, size_t payload_size)
  {
    printf("machine memory update: " IDFMT " %s (%zd payload_bytes)\n",
	   m.id, (update_type == Machine::MachineUpdateSubscriber::THING_ADDED ? "added" :
		  update_type == Machine::MachineUpdateSubscriber::THING_REMOVED ? "removed" : "updated"),
	   payload_size);
  }
};

MyMachineUpdateTracker tracker;
#endif

void child_task(const void *args, size_t arglen, Processor p)
{
  printf("starting task on processor " IDFMT "\n", p.id);
  sleep(1);
#ifdef TEST_FAULTS
  bool inject_fault = *(const bool *)args;
  if(inject_fault) {
    int buffer[4];
    buffer[0] = 11;
    buffer[1] = 22;
    buffer[2] = 33;
    buffer[3] = 44;
    Processor::report_execution_fault(44, buffer, 4*sizeof(int));
  }
#endif
  printf("ending task on processor " IDFMT "\n", p.id);
}

void response_task(const void *args, size_t arglen, Processor p)
{
  printf("got profiling response - %zd bytes\n", arglen);
  printf("Bytes:");
  for(size_t i = 0; i < arglen; i++)
    printf(" %02x", ((unsigned char *)args)[i]);
  printf("\n");

  Realm::ProfilingResponse pr(args, arglen);

  if(pr.has_measurement<OperationStatus>()) {
    OperationStatus *op_status = pr.get_measurement<OperationStatus>();
    printf("op status = %d (code = %d, details = %zd bytes)\n",
	   (int)(op_status->result),
	   op_status->error_code,
	   op_status->error_details.size());
    delete op_status;
  } else
    printf("no status\n");

  if(pr.has_measurement<OperationTimeline>()) {
    OperationTimeline *op_timeline = pr.get_measurement<OperationTimeline>();
    printf("op timeline = %llu %llu %llu (%lld %lld)\n",
	   op_timeline->ready_time,
	   op_timeline->start_time,
	   op_timeline->end_time,
	   op_timeline->start_time - op_timeline->ready_time,
	   op_timeline->end_time - op_timeline->start_time);
    delete op_timeline;
  } else
    printf("no timeline\n");

  if(pr.user_data_size() > 0) {
    printf("user data = %zd (", pr.user_data_size());
    unsigned char *data = (unsigned char *)(pr.user_data());
    for(size_t i = 0; i < pr.user_data_size(); i++)
      printf(" %02x", data[i]);
    printf(" )\n");
  } else
    printf("no user data\n");
}

void top_level_task(const void *args, size_t arglen, Processor p)
{
  printf("top level task - getting machine and list of CPUs\n");

  Machine machine = Machine::get_machine();
  std::vector<Processor> all_cpus;
  {
    std::set<Processor> all_processors;
    machine.get_all_processors(all_processors);
    for(std::set<Processor>::const_iterator it = all_processors.begin();
	it != all_processors.end();
	it++)
      if(it->kind() == Processor::LOC_PROC)
	all_cpus.push_back(*it);
  }

#ifdef TEST_FAULTS
  // touch all of the new resilience-based calls (just to test linking)
  if(arglen == 97) {  // if the compiler can DCE this, no link errors...  :(
    Processor::report_execution_fault(0, 0, 0);
    Processor::NO_PROC.report_processor_fault(0, 0, 0);
    Memory::NO_MEMORY.report_memory_fault(0, 0, 0);
    RegionInstance::NO_INST.report_instance_fault(0, 0, 0);
    RegionInstance::NO_INST.get_accessor().report_fault(ptr_t(0), 0, 0);
    RegionInstance::NO_INST.get_accessor().report_fault(DomainPoint(), 0, 0);
    RegionInstance::NO_INST.get_accessor().typeify<int>().report_fault(ptr_t(0));
    RegionInstance::NO_INST.get_accessor().typeify<int>().report_fault(DomainPoint());
    bool poisoned;
    Event::NO_EVENT.has_triggered_faultaware(poisoned);
    Event::NO_EVENT.wait_faultaware(poisoned);
    Processor::cancel_task(Event::NO_EVENT);
    Domain::cancel_copy(Event::NO_EVENT);
    UserEvent::create_user_event().cancel();
  }
#endif

  // launch a child task and perform some measurements on it
  // choose the last cpu, which is likely to be on a different node
  Processor first_cpu = all_cpus.back();
  ProfilingRequestSet prs;
  prs.add_request(first_cpu, RESPONSE_TASK, &first_cpu, sizeof(first_cpu))
    .add_measurement<OperationStatus>()
    .add_measurement<OperationTimeline>();

  bool inject_fault = false;
  Event e1 = first_cpu.spawn(CHILD_TASK, &inject_fault, sizeof(inject_fault), prs);
  inject_fault = true;
  Event e2 = first_cpu.spawn(CHILD_TASK, &inject_fault, sizeof(inject_fault), prs, e1);
  inject_fault = false;
  Event e3 = first_cpu.spawn(CHILD_TASK, &inject_fault, sizeof(inject_fault), prs, e2);

  bool poisoned = false;
#ifdef TEST_FAULTS
  e3.wait_faultaware(poisoned);
#else
  e3.wait();
#endif
  printf("done! (poisoned=%d)\n", poisoned);

  sleep(10);
  // shutdown the runtime - this should implicitly wait for the report task to run
  {
    std::set<Processor> all_procs;
    machine.get_all_processors(all_procs);
    for (std::set<Processor>::const_iterator it = all_procs.begin();
          it != all_procs.end(); it++)
    {
      // Damn you C++ and your broken const qualifiers
      Processor handle_copy = *it;
      // Send the kill pill
      handle_copy.spawn(0,NULL,0);
    }
  }
}

int main(int argc, char **argv)
{
  Runtime rt;

  rt.init(&argc, &argv);

  rt.register_task(TOP_LEVEL_TASK, top_level_task);
  rt.register_task(CHILD_TASK, child_task);
  rt.register_task(RESPONSE_TASK, response_task);

  // Start the machine running
  // Control never returns from this call
  // Note we only run the top level task on one processor
  // You can also run the top level task on all processors or one processor per node
  rt.run(TOP_LEVEL_TASK, Runtime::ONE_TASK_ONLY);

  rt.shutdown();
  return -1;
}
<|endoftext|>


<commit_before>/*
 * ModSecurity, http://www.modsecurity.org/
 * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
 *
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * If any of the files related to licensing are missing or if you have any
 * other questions related to licensing please contact Trustwave Holdings, Inc.
 * directly using the email address security@modsecurity.org.
 *
 */

#include <string.h>

#include <ctime>
#include <iostream>
#include <string>
#include <list>

#include "modsecurity/rules_set_properties.h"
#include "modsecurity/rules_set.h"
#include "modsecurity/modsecurity.h"
#include "src/utils/system.h"
#include "src/parser/driver.h"
#include "src/utils/https_client.h"
#include "modsecurity/transaction.h"

void print_help() {
    std::cout << "Use ./optimization /path/to/files.something" << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;
}

int main(int argc, char **argv) {
    modsecurity::RulesSet *modsecRules = new modsecurity::RulesSet();
    std::list<std::string> files;
    int total = 0;

    int p = 1;
    while (p < argc) {
        std::list<std::string> tfiles = modsecurity::utils::expandEnv(
            argv[p], 0);
        for (const auto &file : tfiles) {
            files.insert(files.begin(), file);
        }
        p++;
    }

    for (auto &x : files) {
        std::cout << "Loading file: " << x << std::endl;
        if (modsecRules->loadFromUri(x.c_str()) < 0) {
            std::cout << "Not able to load the rules" << std::endl;
            std::cout << modsecRules->getParserError() << std::endl;
            delete modsecRules;
            return -1;
        }
    }

    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << "Rules optimization" << std::endl;
    std::cout << std::endl;

    int nphases = modsecurity::Phases::NUMBER_OF_PHASES;
    for (int j = 0; j < nphases; j++) {
        Rules *rules = modsecRules->m_rulesSetPhases[j];
        if (rules->size() == 0) {
            continue;
        }
        std::cout << "Phase: " << std::to_string(j);
        std::cout << " (" << std::to_string(rules->size());
        std::cout << " rules)" << std::endl;

        std::unordered_map<std::string, int> operators;
        std::unordered_map<std::string, int> variables;
        std::unordered_map<std::string, int> op2var;

        for (int i = 0; i < rules->size(); i++) {
            auto z = rules->at(i);
            //std::string key;
            if (z == NULL) {
                continue;
            }
            #if 0
            if (z->isUnconditional() == false) {
                std::string op = z->getOperatorName();
                if (operators.count(op) > 0) {
                    operators[op] = 1 + operators[op];
                } else {
                    operators[op] = 1;
                }
                key = op;
            }
            #endif

            #if 0
            FIXME: This test may not be useful anymore. Disabling it for now.

            if (z->m_variables != NULL) {
                std::string var = std::string("") + z->m_variables;
                if (variables.count(var) > 0) {
                    variables[var] = 1 + variables[var];
                } else {
                    variables[var] = 1;
                }
                key = key + var;
            }
            if (z->m_variables != NULL && z->m_op != NULL) {
                if (op2var.count(key) > 0) {
                    op2var[key] = 1 + op2var[key];
                } else {
                    op2var[key] = 1;
                }
            }
            #endif
        }

        if (operators.empty() && variables.empty() && op2var.empty()) {
            std::cout << " ~ no SecRule found ~ " << std::endl;
            continue;
        }
        std::cout << " Operators" << std::endl;
        for (auto &z : operators) {
            auto &s = z.second;
            std::cout << "   " << std::left << std::setw(20) << z.first;
            std::cout << std::right << std::setw(4) << s;
            std::cout << std::endl;
        }

        std::cout << " Variables" << std::endl;
        for (auto &z : variables) {
            auto &s = z.second;
            std::cout << "   " << std::left << std::setw(20) << z.first;
            std::cout << std::right << std::setw(4) << s;
            std::cout << std::endl;
        }
        std::cout << " Operators applied to variables" << std::endl;
        for (auto &z : op2var) {
            auto &s = z.second;
            std::cout << "   " << std::left << std::setw(40) << z.first;
            std::cout << std::right << std::setw(4) << s;
            std::cout << std::endl;
        }

        total += rules->size();
    }
    std::cout << std::endl;

    std::cout << "Total of: " << std::to_string(total) << " rules.";
    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    delete modsecRules;

    return 0;
}
<commit_msg>test: Fix optimization test<commit_after>/*
 * ModSecurity, http://www.modsecurity.org/
 * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
 *
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * If any of the files related to licensing are missing or if you have any
 * other questions related to licensing please contact Trustwave Holdings, Inc.
 * directly using the email address security@modsecurity.org.
 *
 */

#include <string.h>

#include <ctime>
#include <iostream>
#include <string>
#include <list>

#include "modsecurity/rules_set_properties.h"
#include "modsecurity/rules_set.h"
#include "modsecurity/modsecurity.h"
#include "src/utils/system.h"
#include "src/parser/driver.h"
#include "src/utils/https_client.h"
#include "modsecurity/transaction.h"
#include "modsecurity/rule_unconditional.h"
#include "modsecurity/rule_with_operator.h"

void print_help() {
    std::cout << "Use ./optimization /path/to/files.something" << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;
}

int main(int argc, char **argv) {
    modsecurity::RulesSet *modsecRules = new modsecurity::RulesSet();
    std::list<std::string> files;
    int total = 0;

    int p = 1;
    while (p < argc) {
        std::list<std::string> tfiles = modsecurity::utils::expandEnv(
            argv[p], 0);
        for (const auto &file : tfiles) {
            files.insert(files.begin(), file);
        }
        p++;
    }

    for (auto &x : files) {
        std::cout << "Loading file: " << x << std::endl;
        if (modsecRules->loadFromUri(x.c_str()) < 0) {
            std::cout << "Not able to load the rules" << std::endl;
            std::cout << modsecRules->getParserError() << std::endl;
            delete modsecRules;
            return -1;
        }
    }

    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << "Rules optimization" << std::endl;
    std::cout << std::endl;

    int nphases = modsecurity::Phases::NUMBER_OF_PHASES;
    for (int j = 0; j < nphases; j++) {
        Rules *rules = modsecRules->m_rulesSetPhases[j];
        if (rules->size() == 0) {
            continue;
        }
        std::cout << "Phase: " << std::to_string(j);
        std::cout << " (" << std::to_string(rules->size());
        std::cout << " rules)" << std::endl;

        std::unordered_map<std::string, int> operators;

        for (int i = 0; i < rules->size(); i++) {
            auto z = rules->at(i);
            std::string key;
            if (z == NULL) {
                continue;
            }

            if (dynamic_cast<modsecurity::RuleUnconditional *>(z.get()) != nullptr) {
                std::string op = "Unconditional";
                if (operators.count(op) > 0) {
                    operators[op] = 1 + operators[op];
                } else {
                    operators[op] = 1;
                }
                key = op;
            }

            if (dynamic_cast<modsecurity::RuleWithOperator *>(z.get()) != nullptr) {
                auto *rwo = dynamic_cast<modsecurity::RuleWithOperator *>(z.get());

                std::string op = rwo->getOperatorName();
                if (operators.count(op) > 0) {
                    operators[op] = 1 + operators[op];
                } else {
                    operators[op] = 1;
                }
                key = op;
            }

        }
        if (operators.empty()) {
            std::cout << " ~ no SecRule found ~ " << std::endl;
            continue;
        }

        std::cout << " Operators" << std::endl;
        for (auto &z : operators) {
            auto &s = z.second;
            std::cout << "   " << std::left << std::setw(20) << z.first;
            std::cout << std::right << std::setw(4) << s;
            std::cout << std::endl;
        }

        total += rules->size();
    }
    std::cout << std::endl;

    std::cout << "Total of: " << std::to_string(total) << " rules.";
    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    delete modsecRules;

    return 0;
}
<|endoftext|>


<commit_before>/*
    This file is part of KXForms.

    Copyright (c) 2005,2006 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "mainwindow.h"

#include "manager.h"
#include "guihandler.h"
#include "guihandlerdialogs.h"
#include "guihandlerflat.h"
#include "prefs.h"

#include <kapplication.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <kdebug.h>

#include <QDir>
#include <QByteArray>

#include <unistd.h>
#include <limits.h>

static const char description[] =
    I18N_NOOP("XML Forms Editor");

static KCmdLineOptions options[] =
{
  { "+[URL]", I18N_NOOP( "Document to open" ), 0 },
  { "kxform <URL>", I18N_NOOP( "KXForms description" ), 0 },
  { "schema <URL>", I18N_NOOP( "XML Schema" ), 0 },
  { "ugh <URL>", I18N_NOOP( "UI Generation Hints" ), 0 },
  { "dialogs", I18N_NOOP( "Use dialogs" ), 0 },
  { "developer", I18N_NOOP( "Use developer mode of user interface" ), 0 },
  { "vertical-list-buttons", I18N_NOOP( "Use vertical list buttons" ), 0 },
  { "layout-style <layout-style>", I18N_NOOP( "One of grid, vertical. Arrange elements vertically or in a grid." ), 0 },
  KCmdLineLastOption
};

KUrl makeURL( const QString &arg )
{
   if (!QDir::isRelativePath( arg ))
   {
      KUrl result;
      result.setPath( arg );
      return result; // Absolute path.
   }

   if ( !KUrl::isRelativeUrl( arg ) )
     return KUrl( arg ); // Argument is a URL

  KUrl result;
  char cwd[ PATH_MAX + 1 ];
  getcwd( cwd, PATH_MAX );
  result.setPath( QFile::decodeName( QByteArray( cwd ) ) + '/' + arg );
  result.cleanPath();
  return result;  // Relative path
}

int main(int argc, char **argv)
{
  KAboutData about("kxforms", I18N_NOOP("KXForms"), "0.1", description,
    KAboutData::License_GPL, "(C) 2005 Cornelius Schumacher", 0, 0,
    "schumacher@kde.org");
  about.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );
  KCmdLineArgs::init(argc, argv, &about);
  KCmdLineArgs::addCmdLineOptions(options);
#if 1
  KApplication app;
#else
  QApplication app( argc, argv );
#endif

  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

  Prefs::setDeveloperMode( args->isSet( "developer" ) );
  Prefs::setVerticalListButtons( args->isSet( "vertical-list-buttons" ) );

#if 1
  // Hack: force a decent font
  QFont f( "Arial", 11 );
  QApplication::setFont( f );
#endif

  MainWindow *mainWindow = new MainWindow;
  KXForms::GuiHandler *guiHandler;
  if ( args->isSet( "dialogs" ) ) {
    guiHandler = new KXForms::GuiHandlerDialogs( mainWindow->formsManager() );
  } else {
    guiHandler = new KXForms::GuiHandlerFlat( mainWindow->formsManager() );
  }

  if ( args->isSet( "layout-style" ) ) {
    if( args->getOption( "layout-style" ).toLower() == "grid" ) {
      guiHandler->setLayoutStyle( KXForms::GuiHandler::Grid );
    }
    else {
      guiHandler->setLayoutStyle( KXForms::GuiHandler::Vertical );
    }
  }

  mainWindow->show();

  if ( args->isSet( "schema" ) && args->isSet( "kxform" ) ) {
    kWarning() << "KXForm will be generated from schema. Ignoring --kxform "
      << "option" << endl;
  }

  if ( args->isSet( "ugh" ) ) {
    QString ugh = args->getOption( "ugh" );
    mainWindow->loadHints( makeURL( ugh ) );
  }

  if ( args->isSet( "schema" ) ) {
    QString schema = args->getOption( "schema" );
    mainWindow->loadSchema( makeURL( schema ) );
  } else {
    if ( args->isSet( "kxform" ) ) {
      QString form = args->getOption( "kxform" );
      mainWindow->loadForm( makeURL( form ) );
    }
  }

  if ( args->count() == 1 ) {
    mainWindow->load( args->url( 0 ) );
  }

  return app.exec();
}
<commit_msg>Add command line option for loading an xml file<commit_after>/*
    This file is part of KXForms.

    Copyright (c) 2005,2006 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "mainwindow.h"

#include "manager.h"
#include "guihandler.h"
#include "guihandlerdialogs.h"
#include "guihandlerflat.h"
#include "prefs.h"

#include <kapplication.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <kdebug.h>

#include <QDir>
#include <QByteArray>

#include <unistd.h>
#include <limits.h>

static const char description[] =
    I18N_NOOP("XML Forms Editor");

static KCmdLineOptions options[] =
{
  { "+[URL]", I18N_NOOP( "Document to open" ), 0 },
  { "kxform <URL>", I18N_NOOP( "KXForms description" ), 0 },
  { "schema <URL>", I18N_NOOP( "XML Schema" ), 0 },
  { "ugh <URL>", I18N_NOOP( "UI Generation Hints" ), 0 },
  { "xml <URL>", I18N_NOOP( "XML file" ), 0 },
  { "dialogs", I18N_NOOP( "Use dialogs" ), 0 },
  { "developer", I18N_NOOP( "Use developer mode of user interface" ), 0 },
  { "vertical-list-buttons", I18N_NOOP( "Use vertical list buttons" ), 0 },
  { "layout-style <layout-style>", I18N_NOOP( "One of grid, vertical. Arrange elements vertically or in a grid." ), 0 },
  KCmdLineLastOption
};

KUrl makeURL( const QString &arg )
{
   if (!QDir::isRelativePath( arg ))
   {
      KUrl result;
      result.setPath( arg );
      return result; // Absolute path.
   }

   if ( !KUrl::isRelativeUrl( arg ) )
     return KUrl( arg ); // Argument is a URL

  KUrl result;
  char cwd[ PATH_MAX + 1 ];
  getcwd( cwd, PATH_MAX );
  result.setPath( QFile::decodeName( QByteArray( cwd ) ) + '/' + arg );
  result.cleanPath();
  return result;  // Relative path
}

int main(int argc, char **argv)
{
  KAboutData about("kxforms", I18N_NOOP("KXForms"), "0.1", description,
    KAboutData::License_GPL, "(C) 2005 Cornelius Schumacher", 0, 0,
    "schumacher@kde.org");
  about.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );
  KCmdLineArgs::init(argc, argv, &about);
  KCmdLineArgs::addCmdLineOptions(options);
#if 1
  KApplication app;
#else
  QApplication app( argc, argv );
#endif

  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

  Prefs::setDeveloperMode( args->isSet( "developer" ) );
  Prefs::setVerticalListButtons( args->isSet( "vertical-list-buttons" ) );

#if 1
  // Hack: force a decent font
  QFont f( "Arial", 11 );
  QApplication::setFont( f );
#endif

  MainWindow *mainWindow = new MainWindow;
  KXForms::GuiHandler *guiHandler;
  if ( args->isSet( "dialogs" ) ) {
    guiHandler = new KXForms::GuiHandlerDialogs( mainWindow->formsManager() );
  } else {
    guiHandler = new KXForms::GuiHandlerFlat( mainWindow->formsManager() );
  }

  if ( args->isSet( "layout-style" ) ) {
    if( args->getOption( "layout-style" ).toLower() == "grid" ) {
      guiHandler->setLayoutStyle( KXForms::GuiHandler::Grid );
    }
    else {
      guiHandler->setLayoutStyle( KXForms::GuiHandler::Vertical );
    }
  }

  mainWindow->show();

  if ( args->isSet( "schema" ) && args->isSet( "kxform" ) ) {
    kWarning() << "KXForm will be generated from schema. Ignoring --kxform "
      << "option" << endl;
  }

  if ( args->isSet( "ugh" ) ) {
    QString ugh = args->getOption( "ugh" );
    mainWindow->loadHints( makeURL( ugh ) );
  }

  if ( args->isSet( "schema" ) ) {
    QString schema = args->getOption( "schema" );
    mainWindow->loadSchema( makeURL( schema ) );
  } else {
    if ( args->isSet( "kxform" ) ) {
      QString form = args->getOption( "kxform" );
      mainWindow->loadForm( makeURL( form ) );
    }
  }

  if ( args->isSet( "xml" ) ) {
    QString xml = args->getOption( "xml" );
    mainWindow->load( xml );
  }

  if ( args->count() == 1 ) {
    mainWindow->load( args->url( 0 ) );
  }

  return app.exec();
}
<|endoftext|>


<commit_before>/* rbOOmit: An implementation of the Certified Reduced Basis method. */
/* Copyright (C) 2009, 2010 David J. Knezevic */
/*     This file is part of rbOOmit. */

/* rbOOmit is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */
/* License as published by the Free Software Foundation; either */
/* version 2.1 of the License, or (at your option) any later version. */

/* rbOOmit is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU */
/* Lesser General Public License for more details. */

/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

//
Reduced Basis: Example 6 - Heat transfer on a curved domain in 3D

// In this example we consider heat transfer modeled by a Poisson equation with
// Robin boundary condition:
//  -kappa \Laplacian u = 1, on \Omega
//  -kappa du\dn = kappa Bi u, on \partial\Omega_Biot,
//  u = 0 on \partial\Omega_Dirichlet,
//
// We consider a reference domain \Omega_hat = [-0.2,0.2]x[-0.2,0.2]x[0,3], and the
// physical domain is then obtain via the parametrized mapping:
//  x = -1/mu + (1/mu+x_hat)*cos(mu*z_hat)
//  y = y_hat
//  z = (1/mu+x_hat)*sin(mu*z_hat)
// for (x_hat,y_hat,z_hat) \in \Omega_hat. (Here "hats" denotes reference domain.)
// Also, the "reference Dirichlet boundaries" are [-0.2,0.2]x[-0.2,0.2]x{0} and
// [-0.2,0.2]x[-0.2,0.2]x{3}, and the remaining boundaries are the "Biot" boundaries.

// Then, after putting the PDE into weak form and mapping it to the reference domain,
// we obtain:
//  \kappa \int_\Omega_hat [ (1+mu*x_hat) v_x w_x + (1+mu*x_hat) v_y w_y + 1/(1+mu*x_hat) v_z w_z ]
//    + \kappa Bi \int_\partial\Omega_hat_Biot1 (1-0.2mu) u v
//    + \kappa Bi \int_\partial\Omega_hat_Biot2 (1+mu x_hat) u v
//    + \kappa Bi \int_\partial\Omega_hat_Biot3 (1+0.2mu) u v
//    = \int_\Omega_hat (1+mu x_hat) v
// where
//  \partial\Omega_hat_Biot1 = [-0.2] x [-0.2,0.2] x [0,3]
//  \partial\Omega_hat_Biot2 = [-0.2,0.2] x {-0.2} x [0,3] \UNION [-0.2,0.2] x {0.2} x [0,3]
//  \partial\Omega_hat_Biot3 = [0.2] x [-0.2,0.2] x [0,3]

// The term
//  \kappa \int_\Omega_hat 1/(1+mu*x_hat) v_z w_z
// is "non-affine" (in the Reduced Basis sense), since we can't express it
// in the form \sum theta_q(kappa,mu) a(v,w). As a result, (as in
// reduced_basis_ex4) we must employ the Empirical Interpolation Method (EIM)
// in order to apply the Reduced Basis method here.

// The approach we use is to construct an EIM approximation, G_EIM, to the vector-valued function
//  G(x_hat,y_hat;mu) = (1 + mu*x_hat, 1 + mu*x_hat, 1/(1+mu*x_hat))
// and then we express the "volumetric integral part" of the left-hand side operator as
//  a(v,w;mu) = \int_\hat\Omega G_EIM(x_hat,y_hat;mu) \dot (v_x w_x, v_y w_y, v_z w_z).
// (We actually only need EIM for the third component of G_EIM, but it's helpful to
// demonstrate "vector-valued" EIM here.)

// C++ include files that we need
#include <iostream>
#include <algorithm>
#include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
#include <cmath>
#include <set>

// Basic include file needed for the mesh functionality.
#include "libmesh/libmesh.h"
#include "libmesh/mesh.h"
#include "libmesh/mesh_generation.h"
#include "libmesh/exodusII_io.h"
#include "libmesh/equation_systems.h"
#include "libmesh/dof_map.h"
#include "libmesh/getpot.h"
#include "libmesh/elem.h"

// local includes
#include "rb_classes.h"
#include "eim_classes.h"
#include "assembly.h"

// Bring in everything from the libMesh namespace
using namespace libMesh;

// Define a function to scale the mesh according to the parameter.
void transform_mesh_and_plot(EquationSystems& es, Real curvature, const std::string& filename);

// The main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  LibMeshInit init (argc, argv);

#if !defined(LIBMESH_HAVE_XDR)
  // We need XDR support to write out reduced bases
  libmesh_example_assert(false, "--enable-xdr");
#elif defined(LIBMESH_DEFAULT_SINGLE_PRECISION)
  // XDR binary support requires double precision
  libmesh_example_assert(false, "--disable-singleprecision");
#endif

  // This is a 3D example
  libmesh_example_assert(3 == LIBMESH_DIM, "3D support");

  // Parse the input file using GetPot
  std::string eim_parameters = "eim.in";
  std::string rb_parameters  = "rb.in";
  std::string main_parameters = "reduced_basis_ex6.in";
  GetPot infile(main_parameters);

  unsigned int n_elem_xy = infile("n_elem_xy", 1);
  unsigned int n_elem_z  = infile("n_elem_z", 1);

  // Do we write the RB basis functions to disk?
  bool store_basis_functions = infile("store_basis_functions", true);

  // Read the "online_mode" flag from the command line
  GetPot command_line (argc, argv);
  int online_mode = 0;
  if ( command_line.search(1, "-online_mode") )
    online_mode = command_line.next(online_mode);

  // Build a mesh.
  Mesh mesh;
  MeshTools::Generation::build_cube (mesh,
                                     n_elem_xy, n_elem_xy, n_elem_z,
                                     -0.2, 0.2,
                                     -0.2, 0.2,
                                     0., 3.,
                                     HEX8);

  // Create an equation systems object.
  EquationSystems equation_systems (mesh);

  SimpleEIMConstruction & eim_construction =
    equation_systems.add_system<SimpleEIMConstruction> ("EIM");
  SimpleRBConstruction & rb_construction =
    equation_systems.add_system<SimpleRBConstruction> ("RB");

  // Initialize the data structures for the equation system.
  equation_systems.init ();

  // Print out some information about the "truth" discretization
  equation_systems.print_info();
  mesh.print_info();

  // Initialize the standard RBEvaluation object
  SimpleRBEvaluation rb_eval;

  // Initialize the EIM RBEvaluation object
  SimpleEIMEvaluation eim_rb_eval;

  // Set the rb_eval objects for the RBConstructions
  eim_construction.set_rb_evaluation(eim_rb_eval);
  rb_construction.set_rb_evaluation(rb_eval);

  if(!online_mode) // Perform the Offline stage of the RB method
  {
    // Read data from input file and print state
    eim_construction.process_parameters_file(eim_parameters);
    eim_construction.print_info();

    // Perform the EIM Greedy and write out the data
    eim_construction.initialize_rb_construction();

    eim_construction.train_reduced_basis();
    eim_construction.get_rb_evaluation().write_offline_data_to_files("eim_data");

    // Read data from input file and print state
    rb_construction.process_parameters_file(rb_parameters);

    // attach the EIM theta objects to the RBEvaluation
    eim_rb_eval.initialize_eim_theta_objects();
    rb_eval.get_rb_theta_expansion().attach_multiple_A_theta(eim_rb_eval.get_eim_theta_objects());

    // attach the EIM assembly objects to the RBConstruction
    eim_construction.initialize_eim_assembly_objects();
    rb_construction.get_rb_assembly_expansion().attach_multiple_A_assembly(eim_construction.get_eim_assembly_objects());

    // Print out the state of rb_construction now that the EIM objects have been attached
    rb_construction.print_info();

    // Need to initialize _after_ EIM greedy so that
    // the system knows how many affine terms there are
    rb_construction.initialize_rb_construction();
    rb_construction.train_reduced_basis();
    rb_construction.get_rb_evaluation().write_offline_data_to_files("rb_data");

    // Write out the basis functions, if requested
    if(store_basis_functions)
    {
      // Write out the basis functions
      eim_construction.get_rb_evaluation().write_out_basis_functions(eim_construction,"eim_data");
      rb_construction.get_rb_evaluation().write_out_basis_functions(rb_construction,"rb_data");
    }
  }
  else // Perform the Online stage of the RB method
  {
    eim_rb_eval.read_offline_data_from_files("eim_data");

    // attach the EIM theta objects to rb_eval objects
    eim_rb_eval.initialize_eim_theta_objects();
    rb_eval.get_rb_theta_expansion().attach_multiple_A_theta(eim_rb_eval.get_eim_theta_objects());

    // Read in the offline data for rb_eval
    rb_eval.read_offline_data_from_files("rb_data");

    // Get the parameters at which we will do a reduced basis solve
    Real online_curvature = infile("online_curvature", 0.);
    Real online_Bi        = infile("online_Bi", 0.);
    Real online_kappa     = infile("online_kappa", 0.);
    RBParameters online_mu;
    online_mu.set_value("curvature", online_curvature);
    online_mu.set_value("Bi", online_Bi);
    online_mu.set_value("kappa", online_kappa);
    rb_eval.set_parameters(online_mu);
    rb_eval.print_parameters();
    rb_eval.rb_solve( rb_eval.get_n_basis_functions() );

    // plot the solution, if requested
    if(store_basis_functions)
    {
      // read in the data from files
      eim_rb_eval.read_in_basis_functions(eim_construction,"eim_data");
      rb_eval.read_in_basis_functions(rb_construction,"rb_data");

      eim_construction.load_rb_solution();
      rb_construction.load_rb_solution();

      transform_mesh_and_plot(equation_systems,online_curvature,"RB_sol.e");
    }
  }

  return 0;
}

void transform_mesh_and_plot(EquationSystems& es, Real curvature, const std::string& filename)
{
  // Loop over the mesh nodes and move them!
  MeshBase& mesh = es.get_mesh();

  MeshBase::node_iterator       node_it  = mesh.nodes_begin();
  const MeshBase::node_iterator node_end = mesh.nodes_end();

  for( ; node_it != node_end; node_it++)
  {
    Node* node = *node_it;

    Real x = (*node)(0);
    Real z = (*node)(2);

    (*node)(0) = -1./curvature + (1./curvature + x)*cos(curvature*z);
    (*node)(2) = (1./curvature + x)*sin(curvature*z);
  }

#ifdef LIBMESH_HAVE_EXODUS_API
  ExodusII_IO(mesh).write_equation_systems(filename, es);
#endif
}

<commit_msg>reduced_basis example 6 (at least...) isn't distributed mesh compatible yet.<commit_after>/* rbOOmit: An implementation of the Certified Reduced Basis method. */
/* Copyright (C) 2009, 2010 David J. Knezevic */
/*     This file is part of rbOOmit. */

/* rbOOmit is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */
/* License as published by the Free Software Foundation; either */
/* version 2.1 of the License, or (at your option) any later version. */

/* rbOOmit is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU */
/* Lesser General Public License for more details. */

/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

//
Reduced Basis: Example 6 - Heat transfer on a curved domain in 3D

// In this example we consider heat transfer modeled by a Poisson equation with
// Robin boundary condition:
//  -kappa \Laplacian u = 1, on \Omega
//  -kappa du\dn = kappa Bi u, on \partial\Omega_Biot,
//  u = 0 on \partial\Omega_Dirichlet,
//
// We consider a reference domain \Omega_hat = [-0.2,0.2]x[-0.2,0.2]x[0,3], and the
// physical domain is then obtain via the parametrized mapping:
//  x = -1/mu + (1/mu+x_hat)*cos(mu*z_hat)
//  y = y_hat
//  z = (1/mu+x_hat)*sin(mu*z_hat)
// for (x_hat,y_hat,z_hat) \in \Omega_hat. (Here "hats" denotes reference domain.)
// Also, the "reference Dirichlet boundaries" are [-0.2,0.2]x[-0.2,0.2]x{0} and
// [-0.2,0.2]x[-0.2,0.2]x{3}, and the remaining boundaries are the "Biot" boundaries.

// Then, after putting the PDE into weak form and mapping it to the reference domain,
// we obtain:
//  \kappa \int_\Omega_hat [ (1+mu*x_hat) v_x w_x + (1+mu*x_hat) v_y w_y + 1/(1+mu*x_hat) v_z w_z ]
//    + \kappa Bi \int_\partial\Omega_hat_Biot1 (1-0.2mu) u v
//    + \kappa Bi \int_\partial\Omega_hat_Biot2 (1+mu x_hat) u v
//    + \kappa Bi \int_\partial\Omega_hat_Biot3 (1+0.2mu) u v
//    = \int_\Omega_hat (1+mu x_hat) v
// where
//  \partial\Omega_hat_Biot1 = [-0.2] x [-0.2,0.2] x [0,3]
//  \partial\Omega_hat_Biot2 = [-0.2,0.2] x {-0.2} x [0,3] \UNION [-0.2,0.2] x {0.2} x [0,3]
//  \partial\Omega_hat_Biot3 = [0.2] x [-0.2,0.2] x [0,3]

// The term
//  \kappa \int_\Omega_hat 1/(1+mu*x_hat) v_z w_z
// is "non-affine" (in the Reduced Basis sense), since we can't express it
// in the form \sum theta_q(kappa,mu) a(v,w). As a result, (as in
// reduced_basis_ex4) we must employ the Empirical Interpolation Method (EIM)
// in order to apply the Reduced Basis method here.

// The approach we use is to construct an EIM approximation, G_EIM, to the vector-valued function
//  G(x_hat,y_hat;mu) = (1 + mu*x_hat, 1 + mu*x_hat, 1/(1+mu*x_hat))
// and then we express the "volumetric integral part" of the left-hand side operator as
//  a(v,w;mu) = \int_\hat\Omega G_EIM(x_hat,y_hat;mu) \dot (v_x w_x, v_y w_y, v_z w_z).
// (We actually only need EIM for the third component of G_EIM, but it's helpful to
// demonstrate "vector-valued" EIM here.)

// C++ include files that we need
#include <iostream>
#include <algorithm>
#include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
#include <cmath>
#include <set>

// Basic include file needed for the mesh functionality.
#include "libmesh/libmesh.h"
#include "libmesh/mesh.h"
#include "libmesh/mesh_generation.h"
#include "libmesh/exodusII_io.h"
#include "libmesh/equation_systems.h"
#include "libmesh/dof_map.h"
#include "libmesh/getpot.h"
#include "libmesh/elem.h"

// local includes
#include "rb_classes.h"
#include "eim_classes.h"
#include "assembly.h"

// Bring in everything from the libMesh namespace
using namespace libMesh;

// Define a function to scale the mesh according to the parameter.
void transform_mesh_and_plot(EquationSystems& es, Real curvature, const std::string& filename);

// The main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  LibMeshInit init (argc, argv);

#if !defined(LIBMESH_HAVE_XDR)
  // We need XDR support to write out reduced bases
  libmesh_example_assert(false, "--enable-xdr");
#elif defined(LIBMESH_DEFAULT_SINGLE_PRECISION)
  // XDR binary support requires double precision
  libmesh_example_assert(false, "--disable-singleprecision");
#endif

#ifdef LIBMESH_ENABLE_PARMESH
  // RBEIMConstruction currently tries to query the entire mesh on
  // every processor
  libmesh_example_assert(false, "--disable-parmesh");
#endif

  // This is a 3D example
  libmesh_example_assert(3 == LIBMESH_DIM, "3D support");

  // Parse the input file using GetPot
  std::string eim_parameters = "eim.in";
  std::string rb_parameters  = "rb.in";
  std::string main_parameters = "reduced_basis_ex6.in";
  GetPot infile(main_parameters);

  unsigned int n_elem_xy = infile("n_elem_xy", 1);
  unsigned int n_elem_z  = infile("n_elem_z", 1);

  // Do we write the RB basis functions to disk?
  bool store_basis_functions = infile("store_basis_functions", true);

  // Read the "online_mode" flag from the command line
  GetPot command_line (argc, argv);
  int online_mode = 0;
  if ( command_line.search(1, "-online_mode") )
    online_mode = command_line.next(online_mode);

  // Build a mesh.
  Mesh mesh;
  MeshTools::Generation::build_cube (mesh,
                                     n_elem_xy, n_elem_xy, n_elem_z,
                                     -0.2, 0.2,
                                     -0.2, 0.2,
                                     0., 3.,
                                     HEX8);

  // Create an equation systems object.
  EquationSystems equation_systems (mesh);

  SimpleEIMConstruction & eim_construction =
    equation_systems.add_system<SimpleEIMConstruction> ("EIM");
  SimpleRBConstruction & rb_construction =
    equation_systems.add_system<SimpleRBConstruction> ("RB");

  // Initialize the data structures for the equation system.
  equation_systems.init ();

  // Print out some information about the "truth" discretization
  equation_systems.print_info();
  mesh.print_info();

  // Initialize the standard RBEvaluation object
  SimpleRBEvaluation rb_eval;

  // Initialize the EIM RBEvaluation object
  SimpleEIMEvaluation eim_rb_eval;

  // Set the rb_eval objects for the RBConstructions
  eim_construction.set_rb_evaluation(eim_rb_eval);
  rb_construction.set_rb_evaluation(rb_eval);

  if(!online_mode) // Perform the Offline stage of the RB method
  {
    // Read data from input file and print state
    eim_construction.process_parameters_file(eim_parameters);
    eim_construction.print_info();

    // Perform the EIM Greedy and write out the data
    eim_construction.initialize_rb_construction();

    eim_construction.train_reduced_basis();
    eim_construction.get_rb_evaluation().write_offline_data_to_files("eim_data");

    // Read data from input file and print state
    rb_construction.process_parameters_file(rb_parameters);

    // attach the EIM theta objects to the RBEvaluation
    eim_rb_eval.initialize_eim_theta_objects();
    rb_eval.get_rb_theta_expansion().attach_multiple_A_theta(eim_rb_eval.get_eim_theta_objects());

    // attach the EIM assembly objects to the RBConstruction
    eim_construction.initialize_eim_assembly_objects();
    rb_construction.get_rb_assembly_expansion().attach_multiple_A_assembly(eim_construction.get_eim_assembly_objects());

    // Print out the state of rb_construction now that the EIM objects have been attached
    rb_construction.print_info();

    // Need to initialize _after_ EIM greedy so that
    // the system knows how many affine terms there are
    rb_construction.initialize_rb_construction();
    rb_construction.train_reduced_basis();
    rb_construction.get_rb_evaluation().write_offline_data_to_files("rb_data");

    // Write out the basis functions, if requested
    if(store_basis_functions)
    {
      // Write out the basis functions
      eim_construction.get_rb_evaluation().write_out_basis_functions(eim_construction,"eim_data");
      rb_construction.get_rb_evaluation().write_out_basis_functions(rb_construction,"rb_data");
    }
  }
  else // Perform the Online stage of the RB method
  {
    eim_rb_eval.read_offline_data_from_files("eim_data");

    // attach the EIM theta objects to rb_eval objects
    eim_rb_eval.initialize_eim_theta_objects();
    rb_eval.get_rb_theta_expansion().attach_multiple_A_theta(eim_rb_eval.get_eim_theta_objects());

    // Read in the offline data for rb_eval
    rb_eval.read_offline_data_from_files("rb_data");

    // Get the parameters at which we will do a reduced basis solve
    Real online_curvature = infile("online_curvature", 0.);
    Real online_Bi        = infile("online_Bi", 0.);
    Real online_kappa     = infile("online_kappa", 0.);
    RBParameters online_mu;
    online_mu.set_value("curvature", online_curvature);
    online_mu.set_value("Bi", online_Bi);
    online_mu.set_value("kappa", online_kappa);
    rb_eval.set_parameters(online_mu);
    rb_eval.print_parameters();
    rb_eval.rb_solve( rb_eval.get_n_basis_functions() );

    // plot the solution, if requested
    if(store_basis_functions)
    {
      // read in the data from files
      eim_rb_eval.read_in_basis_functions(eim_construction,"eim_data");
      rb_eval.read_in_basis_functions(rb_construction,"rb_data");

      eim_construction.load_rb_solution();
      rb_construction.load_rb_solution();

      transform_mesh_and_plot(equation_systems,online_curvature,"RB_sol.e");
    }
  }

  return 0;
}

void transform_mesh_and_plot(EquationSystems& es, Real curvature, const std::string& filename)
{
  // Loop over the mesh nodes and move them!
  MeshBase& mesh = es.get_mesh();

  MeshBase::node_iterator       node_it  = mesh.nodes_begin();
  const MeshBase::node_iterator node_end = mesh.nodes_end();

  for( ; node_it != node_end; node_it++)
  {
    Node* node = *node_it;

    Real x = (*node)(0);
    Real z = (*node)(2);

    (*node)(0) = -1./curvature + (1./curvature + x)*cos(curvature*z);
    (*node)(2) = (1./curvature + x)*sin(curvature*z);
  }

#ifdef LIBMESH_HAVE_EXODUS_API
  ExodusII_IO(mesh).write_equation_systems(filename, es);
#endif
}

<|endoftext|>