<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/content_settings/content_settings_provider.h"

namespace content_settings {

ProviderInterface::Rule::Rule() {
}

ProviderInterface::Rule::Rule(const ContentSettingsPattern& requesting_pattern,
                              const ContentSettingsPattern& embedding_pattern,
                              ContentSetting setting)
    : requesting_url_pattern(requesting_pattern),
      embedding_url_pattern(embedding_pattern),
      content_setting(setting) {
}

}  // namespace content_settings
<commit_msg>Uninitialized struct member in ProviderInterface::Rule.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/content_settings/content_settings_provider.h"

namespace content_settings {

ProviderInterface::Rule::Rule()
    : content_setting(CONTENT_SETTING_DEFAULT) {
}

ProviderInterface::Rule::Rule(const ContentSettingsPattern& requesting_pattern,
                              const ContentSettingsPattern& embedding_pattern,
                              ContentSetting setting)
    : requesting_url_pattern(requesting_pattern),
      embedding_url_pattern(embedding_pattern),
      content_setting(setting) {
}

}  // namespace content_settings
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_path.h"
#include "base/string_util.h"
#include "chrome/browser/password_manager/password_manager.h"
#include "chrome/browser/password_manager/password_store.h"
#include "chrome/browser/pref_service.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gmock/include/gmock/gmock.h"

using webkit_glue::PasswordForm;
using testing::_;
using testing::DoAll;
using ::testing::Exactly;
using ::testing::WithArg;
using ::testing::Return;

class MockPasswordManagerDelegate : public PasswordManager::Delegate {
 public:
  MOCK_METHOD1(FillPasswordForm, void(
     const webkit_glue::PasswordFormDomManager::FillData&));
  MOCK_METHOD1(AddSavePasswordInfoBar, void(PasswordFormManager*));
  MOCK_METHOD0(GetProfileForPasswordManager, Profile*());
  MOCK_METHOD0(DidLastPageLoadEncounterSSLErrors, bool());
};

class TestingProfileWithPasswordStore : public TestingProfile {
 public:
  explicit TestingProfileWithPasswordStore(PasswordStore* store)
      : store_(store) {}
  virtual PasswordStore* GetPasswordStore(ServiceAccessType access) {
    return store_;
  }
 private:
  PasswordStore* store_;
};

class MockPasswordStore : public PasswordStore {
 public:
  MOCK_METHOD1(RemoveLogin, void(const PasswordForm&));
  MOCK_METHOD2(GetLogins, int(const PasswordForm&, PasswordStoreConsumer*));
  MOCK_METHOD1(AddLogin, void(const PasswordForm&));
  MOCK_METHOD1(UpdateLogin, void(const PasswordForm&));
  MOCK_METHOD1(AddLoginImpl, void(const PasswordForm&));
  MOCK_METHOD1(UpdateLoginImpl, void(const PasswordForm&));
  MOCK_METHOD1(RemoveLoginImpl, void(const PasswordForm&));
  MOCK_METHOD2(RemoveLoginsCreatedBetweenImpl, void(const base::Time&,
               const base::Time&));
  MOCK_METHOD2(GetLoginsImpl, void(GetLoginsRequest*, const PasswordForm&));
  MOCK_METHOD1(GetAutofillableLoginsImpl, void(GetLoginsRequest*));
  MOCK_METHOD1(GetBlacklistLoginsImpl, void(GetLoginsRequest*));
  MOCK_METHOD1(FillAutofillableLogins,
      bool(std::vector<webkit_glue::PasswordForm*>*));
  MOCK_METHOD1(FillBlacklistLogins,
      bool(std::vector<webkit_glue::PasswordForm*>*));
};

ACTION_P2(InvokeConsumer, handle, forms) {
  arg0->OnPasswordStoreRequestDone(handle, forms);
}

ACTION_P(SaveToScopedPtr, scoped) {
  scoped->reset(arg0);
}

class PasswordManagerTest : public testing::Test {
 public:
  PasswordManagerTest() {}
 protected:

  virtual void SetUp() {
    store_ = new MockPasswordStore();
    profile_.reset(new TestingProfileWithPasswordStore(store_));
    EXPECT_CALL(delegate_, GetProfileForPasswordManager())
        .WillRepeatedly(Return(profile_.get()));
    manager_.reset(new PasswordManager(&delegate_));
    EXPECT_CALL(delegate_, DidLastPageLoadEncounterSSLErrors())
        .WillRepeatedly(Return(false));
  }

  virtual void TearDown() {
    manager_.reset();
    store_ = NULL;
  }

  PasswordForm MakeSimpleForm() {
    PasswordForm form;
    form.origin = GURL("http://www.google.com/a/LoginAuth");
    form.action = GURL("http://www.google.com/a/Login");
    form.username_element = ASCIIToUTF16("Email");
    form.password_element = ASCIIToUTF16("Passwd");
    form.username_value = ASCIIToUTF16("google");
    form.password_value = ASCIIToUTF16("password");
    form.submit_element = ASCIIToUTF16("signIn");
    form.signon_realm = "http://www.google.com";
    return form;
  }

  PasswordManager* manager() { return manager_.get(); }

  scoped_ptr<Profile> profile_;
  scoped_refptr<MockPasswordStore> store_;
  MockPasswordManagerDelegate delegate_;  // Owned by manager_.
  scoped_ptr<PasswordManager> manager_;
};

MATCHER_P(FormMatches, form, "") {
  return form.signon_realm == arg.signon_realm &&
         form.origin == arg.origin &&
         form.action == arg.action &&
         form.username_element == arg.username_element &&
         form.password_element == arg.password_element &&
         form.submit_element == arg.submit_element;
}

TEST_F(PasswordManagerTest, FormSubmitEmptyStore) {
  // Test that observing a newly submitted form shows the save password bar.
  std::vector<PasswordForm*> result;  // Empty password store.
  EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
  EXPECT_CALL(*store_, GetLogins(_,_))
      .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  manager()->PasswordFormsVisible(observed);  // The initial layout.

  // And the form submit contract is to call ProvisionallySavePassword.
  manager()->ProvisionallySavePassword(form);

  scoped_ptr<PasswordFormManager> form_to_save;
  EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_))
      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));

  // Now the password manager waits for the navigation to complete.
  manager()->DidStopLoading();

  ASSERT_FALSE(NULL == form_to_save.get());
  EXPECT_CALL(*store_, AddLogin(FormMatches(form)));

  // Simulate saving the form, as if the info bar was accepted.
  form_to_save->Save();
}

TEST_F(PasswordManagerTest, FormSubmitNoGoodMatch) {
  // Same as above, except with an existing form for the same signon realm,
  // but different origin.  Detailed cases like this are covered by
  // PasswordFormManagerTest.
  std::vector<PasswordForm*> result;
  PasswordForm* existing_different = new PasswordForm(MakeSimpleForm());
  existing_different->username_value = ASCIIToUTF16("google2");
  result.push_back(existing_different);
  EXPECT_CALL(delegate_, FillPasswordForm(_));
  EXPECT_CALL(*store_, GetLogins(_,_))
      .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));

  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  manager()->PasswordFormsVisible(observed);  // The initial layout.
  manager()->ProvisionallySavePassword(form);

  // We still expect an add, since we didn't have a good match.
  scoped_ptr<PasswordFormManager> form_to_save;
  EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_))
      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));

  manager()->DidStopLoading();

  EXPECT_CALL(*store_, AddLogin(FormMatches(form)));
  // Simulate saving the form.
  form_to_save->Save();
}

TEST_F(PasswordManagerTest, FormSeenThenLeftPage) {
  std::vector<PasswordForm*> result;  // Empty password store.
  EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
  EXPECT_CALL(*store_, GetLogins(_,_))
    .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  manager()->PasswordFormsVisible(observed);  // The initial layout.

  manager()->DidNavigate();

  // No expected calls.
  manager()->DidStopLoading();
}

TEST_F(PasswordManagerTest, FormSubmitFailedLogin) {
  std::vector<PasswordForm*> result;  // Empty password store.
  EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
  EXPECT_CALL(*store_, GetLogins(_,_))
    .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  manager()->PasswordFormsVisible(observed);  // The initial layout.

  manager()->ProvisionallySavePassword(form);

  // The form reappears, and is visible in the layout:
  manager()->PasswordFormsFound(observed);
  manager()->PasswordFormsVisible(observed);

  // No expected calls to the PasswordStore...
  manager()->DidStopLoading();
}

TEST_F(PasswordManagerTest, FormSubmitInvisibleLogin) {
  // Tests fix of issue 28911: if the login form reappears on the subsequent
  // page, but is invisible, it shouldn't count as a failed login.
  std::vector<PasswordForm*> result;  // Empty password store.
  EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
  EXPECT_CALL(*store_, GetLogins(_,_))
      .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  manager()->PasswordFormsVisible(observed);  // The initial layout.

  manager()->ProvisionallySavePassword(form);

  // The form reappears, but is not visible in the layout:
  manager()->PasswordFormsFound(observed);
  // No call to PasswordFormsVisible.

  // Expect info bar to appear:
  scoped_ptr<PasswordFormManager> form_to_save;
  EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_))
      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));

  manager()->DidStopLoading();

  ASSERT_FALSE(NULL == form_to_save.get());
  EXPECT_CALL(*store_, AddLogin(FormMatches(form)));
  // Simulate saving the form.
  form_to_save->Save();
}

TEST_F(PasswordManagerTest, InitiallyInvisibleForm) {
  // Make sure an invisible login form still gets autofilled.
  std::vector<PasswordForm*> result;
  PasswordForm* existing = new PasswordForm(MakeSimpleForm());
  result.push_back(existing);
  EXPECT_CALL(delegate_, FillPasswordForm(_));
  EXPECT_CALL(*store_, GetLogins(_,_))
      .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  // PasswordFormsVisible is not called.

  manager()->DidStopLoading();
}
<commit_msg>build fix in password manager unit tests.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_path.h"
#include "base/string_util.h"
#include "chrome/browser/password_manager/password_manager.h"
#include "chrome/browser/password_manager/password_store.h"
#include "chrome/browser/pref_service.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gmock/include/gmock/gmock.h"

using webkit_glue::PasswordForm;
using testing::_;
using testing::DoAll;
using ::testing::Exactly;
using ::testing::WithArg;
using ::testing::Return;

class MockPasswordManagerDelegate : public PasswordManager::Delegate {
 public:
  MOCK_METHOD1(FillPasswordForm, void(
     const webkit_glue::PasswordFormDomManager::FillData&));
  MOCK_METHOD1(AddSavePasswordInfoBar, void(PasswordFormManager*));
  MOCK_METHOD0(GetProfileForPasswordManager, Profile*());
  MOCK_METHOD0(DidLastPageLoadEncounterSSLErrors, bool());
};

class TestingProfileWithPasswordStore : public TestingProfile {
 public:
  explicit TestingProfileWithPasswordStore(PasswordStore* store)
      : store_(store) {}
  virtual PasswordStore* GetPasswordStore(ServiceAccessType access) {
    return store_;
  }
 private:
  PasswordStore* store_;
};

class MockPasswordStore : public PasswordStore {
 public:
  MOCK_METHOD1(RemoveLogin, void(const PasswordForm&));
  MOCK_METHOD0(ReportMetricsImpl void());
  MOCK_METHOD2(GetLogins, int(const PasswordForm&, PasswordStoreConsumer*));
  MOCK_METHOD1(AddLogin, void(const PasswordForm&));
  MOCK_METHOD1(UpdateLogin, void(const PasswordForm&));
  MOCK_METHOD1(AddLoginImpl, void(const PasswordForm&));
  MOCK_METHOD1(UpdateLoginImpl, void(const PasswordForm&));
  MOCK_METHOD1(RemoveLoginImpl, void(const PasswordForm&));
  MOCK_METHOD2(RemoveLoginsCreatedBetweenImpl, void(const base::Time&,
               const base::Time&));
  MOCK_METHOD2(GetLoginsImpl, void(GetLoginsRequest*, const PasswordForm&));
  MOCK_METHOD1(GetAutofillableLoginsImpl, void(GetLoginsRequest*));
  MOCK_METHOD1(GetBlacklistLoginsImpl, void(GetLoginsRequest*));
  MOCK_METHOD1(FillAutofillableLogins,
      bool(std::vector<webkit_glue::PasswordForm*>*));
  MOCK_METHOD1(FillBlacklistLogins,
      bool(std::vector<webkit_glue::PasswordForm*>*));
};

ACTION_P2(InvokeConsumer, handle, forms) {
  arg0->OnPasswordStoreRequestDone(handle, forms);
}

ACTION_P(SaveToScopedPtr, scoped) {
  scoped->reset(arg0);
}

class PasswordManagerTest : public testing::Test {
 public:
  PasswordManagerTest() {}
 protected:

  virtual void SetUp() {
    store_ = new MockPasswordStore();
    profile_.reset(new TestingProfileWithPasswordStore(store_));
    EXPECT_CALL(delegate_, GetProfileForPasswordManager())
        .WillRepeatedly(Return(profile_.get()));
    manager_.reset(new PasswordManager(&delegate_));
    EXPECT_CALL(delegate_, DidLastPageLoadEncounterSSLErrors())
        .WillRepeatedly(Return(false));
  }

  virtual void TearDown() {
    manager_.reset();
    store_ = NULL;
  }

  PasswordForm MakeSimpleForm() {
    PasswordForm form;
    form.origin = GURL("http://www.google.com/a/LoginAuth");
    form.action = GURL("http://www.google.com/a/Login");
    form.username_element = ASCIIToUTF16("Email");
    form.password_element = ASCIIToUTF16("Passwd");
    form.username_value = ASCIIToUTF16("google");
    form.password_value = ASCIIToUTF16("password");
    form.submit_element = ASCIIToUTF16("signIn");
    form.signon_realm = "http://www.google.com";
    return form;
  }

  PasswordManager* manager() { return manager_.get(); }

  scoped_ptr<Profile> profile_;
  scoped_refptr<MockPasswordStore> store_;
  MockPasswordManagerDelegate delegate_;  // Owned by manager_.
  scoped_ptr<PasswordManager> manager_;
};

MATCHER_P(FormMatches, form, "") {
  return form.signon_realm == arg.signon_realm &&
         form.origin == arg.origin &&
         form.action == arg.action &&
         form.username_element == arg.username_element &&
         form.password_element == arg.password_element &&
         form.submit_element == arg.submit_element;
}

TEST_F(PasswordManagerTest, FormSubmitEmptyStore) {
  // Test that observing a newly submitted form shows the save password bar.
  std::vector<PasswordForm*> result;  // Empty password store.
  EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
  EXPECT_CALL(*store_, GetLogins(_,_))
      .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  manager()->PasswordFormsVisible(observed);  // The initial layout.

  // And the form submit contract is to call ProvisionallySavePassword.
  manager()->ProvisionallySavePassword(form);

  scoped_ptr<PasswordFormManager> form_to_save;
  EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_))
      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));

  // Now the password manager waits for the navigation to complete.
  manager()->DidStopLoading();

  ASSERT_FALSE(NULL == form_to_save.get());
  EXPECT_CALL(*store_, AddLogin(FormMatches(form)));

  // Simulate saving the form, as if the info bar was accepted.
  form_to_save->Save();
}

TEST_F(PasswordManagerTest, FormSubmitNoGoodMatch) {
  // Same as above, except with an existing form for the same signon realm,
  // but different origin.  Detailed cases like this are covered by
  // PasswordFormManagerTest.
  std::vector<PasswordForm*> result;
  PasswordForm* existing_different = new PasswordForm(MakeSimpleForm());
  existing_different->username_value = ASCIIToUTF16("google2");
  result.push_back(existing_different);
  EXPECT_CALL(delegate_, FillPasswordForm(_));
  EXPECT_CALL(*store_, GetLogins(_,_))
      .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));

  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  manager()->PasswordFormsVisible(observed);  // The initial layout.
  manager()->ProvisionallySavePassword(form);

  // We still expect an add, since we didn't have a good match.
  scoped_ptr<PasswordFormManager> form_to_save;
  EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_))
      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));

  manager()->DidStopLoading();

  EXPECT_CALL(*store_, AddLogin(FormMatches(form)));
  // Simulate saving the form.
  form_to_save->Save();
}

TEST_F(PasswordManagerTest, FormSeenThenLeftPage) {
  std::vector<PasswordForm*> result;  // Empty password store.
  EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
  EXPECT_CALL(*store_, GetLogins(_,_))
    .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  manager()->PasswordFormsVisible(observed);  // The initial layout.

  manager()->DidNavigate();

  // No expected calls.
  manager()->DidStopLoading();
}

TEST_F(PasswordManagerTest, FormSubmitFailedLogin) {
  std::vector<PasswordForm*> result;  // Empty password store.
  EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
  EXPECT_CALL(*store_, GetLogins(_,_))
    .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  manager()->PasswordFormsVisible(observed);  // The initial layout.

  manager()->ProvisionallySavePassword(form);

  // The form reappears, and is visible in the layout:
  manager()->PasswordFormsFound(observed);
  manager()->PasswordFormsVisible(observed);

  // No expected calls to the PasswordStore...
  manager()->DidStopLoading();
}

TEST_F(PasswordManagerTest, FormSubmitInvisibleLogin) {
  // Tests fix of issue 28911: if the login form reappears on the subsequent
  // page, but is invisible, it shouldn't count as a failed login.
  std::vector<PasswordForm*> result;  // Empty password store.
  EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
  EXPECT_CALL(*store_, GetLogins(_,_))
      .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  manager()->PasswordFormsVisible(observed);  // The initial layout.

  manager()->ProvisionallySavePassword(form);

  // The form reappears, but is not visible in the layout:
  manager()->PasswordFormsFound(observed);
  // No call to PasswordFormsVisible.

  // Expect info bar to appear:
  scoped_ptr<PasswordFormManager> form_to_save;
  EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_))
      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));

  manager()->DidStopLoading();

  ASSERT_FALSE(NULL == form_to_save.get());
  EXPECT_CALL(*store_, AddLogin(FormMatches(form)));
  // Simulate saving the form.
  form_to_save->Save();
}

TEST_F(PasswordManagerTest, InitiallyInvisibleForm) {
  // Make sure an invisible login form still gets autofilled.
  std::vector<PasswordForm*> result;
  PasswordForm* existing = new PasswordForm(MakeSimpleForm());
  result.push_back(existing);
  EXPECT_CALL(delegate_, FillPasswordForm(_));
  EXPECT_CALL(*store_, GetLogins(_,_))
      .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
  std::vector<PasswordForm> observed;
  PasswordForm form(MakeSimpleForm());
  observed.push_back(form);
  manager()->PasswordFormsFound(observed);  // The initial load.
  // PasswordFormsVisible is not called.

  manager()->DidStopLoading();
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/debug/stack_trace.h"

#include <errno.h>
#include <execinfo.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#if defined(__GLIBCXX__)
#include <cxxabi.h>
#endif

#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#endif

#include <iostream>

#include "base/basictypes.h"
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/safe_strerror_posix.h"
#include "base/string_piece.h"
#include "base/stringprintf.h"

#if defined(USE_SYMBOLIZE)
#include "base/third_party/symbolize/symbolize.h"
#endif

namespace base {
namespace debug {

namespace {

// The prefix used for mangled symbols, per the Itanium C++ ABI:
// http://www.codesourcery.com/cxx-abi/abi.html#mangling
const char kMangledSymbolPrefix[] = "_Z";

// Characters that can be used for symbols, generated by Ruby:
// (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join
const char kSymbolCharacters[] =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";

#if !defined(USE_SYMBOLIZE)
// Demangles C++ symbols in the given text. Example:
//
// "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]"
// =>
// "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]"
void DemangleSymbols(std::string* text) {
#if defined(__GLIBCXX__)

  std::string::size_type search_from = 0;
  while (search_from < text->size()) {
    // Look for the start of a mangled symbol, from search_from.
    std::string::size_type mangled_start =
        text->find(kMangledSymbolPrefix, search_from);
    if (mangled_start == std::string::npos) {
      break;  // Mangled symbol not found.
    }

    // Look for the end of the mangled symbol.
    std::string::size_type mangled_end =
        text->find_first_not_of(kSymbolCharacters, mangled_start);
    if (mangled_end == std::string::npos) {
      mangled_end = text->size();
    }
    std::string mangled_symbol =
        text->substr(mangled_start, mangled_end - mangled_start);

    // Try to demangle the mangled symbol candidate.
    int status = 0;
    scoped_ptr_malloc<char> demangled_symbol(
        abi::__cxa_demangle(mangled_symbol.c_str(), NULL, 0, &status));
    if (status == 0) {  // Demangling is successful.
      // Remove the mangled symbol.
      text->erase(mangled_start, mangled_end - mangled_start);
      // Insert the demangled symbol.
      text->insert(mangled_start, demangled_symbol.get());
      // Next time, we'll start right after the demangled symbol we inserted.
      search_from = mangled_start + strlen(demangled_symbol.get());
    } else {
      // Failed to demangle.  Retry after the "_Z" we just found.
      search_from = mangled_start + 2;
    }
  }

#endif  // defined(__GLIBCXX__)
}
#endif  // !defined(USE_SYMBOLIZE)

// Gets the backtrace as a vector of strings. If possible, resolve symbol
// names and attach these. Otherwise just use raw addresses. Returns true
// if any symbol name is resolved.  Returns false on error and *may* fill
// in |error_message| if an error message is available.
bool GetBacktraceStrings(void *const *trace, int size,
                         std::vector<std::string>* trace_strings,
                         std::string* error_message) {
  bool symbolized = false;

#if defined(USE_SYMBOLIZE)
  for (int i = 0; i < size; ++i) {
    char symbol[1024];
    // Subtract by one as return address of function may be in the next
    // function when a function is annotated as noreturn.
    if (google::Symbolize(static_cast<char *>(trace[i]) - 1,
                          symbol, sizeof(symbol))) {
      // Don't call DemangleSymbols() here as the symbol is demangled by
      // google::Symbolize().
      trace_strings->push_back(
          base::StringPrintf("%s [%p]", symbol, trace[i]));
      symbolized = true;
    } else {
      trace_strings->push_back(base::StringPrintf("%p", trace[i]));
    }
  }
#else
  scoped_ptr_malloc<char*> trace_symbols(backtrace_symbols(trace, size));
  if (trace_symbols.get()) {
    for (int i = 0; i < size; ++i) {
      std::string trace_symbol = trace_symbols.get()[i];
      DemangleSymbols(&trace_symbol);
      trace_strings->push_back(trace_symbol);
    }
    symbolized = true;
  } else {
    if (error_message)
      *error_message = safe_strerror(errno);
    for (int i = 0; i < size; ++i) {
      trace_strings->push_back(base::StringPrintf("%p", trace[i]));
    }
  }
#endif  // defined(USE_SYMBOLIZE)

  return symbolized;
}

}  // namespace

StackTrace::StackTrace() {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (backtrace == NULL) {
    count_ = 0;
    return;
  }
#endif
  // Though the backtrace API man page does not list any possible negative
  // return values, we take no chance.
  count_ = std::max(backtrace(trace_, arraysize(trace_)), 0);
}

void StackTrace::PrintBacktrace() const {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (backtrace_symbols_fd == NULL)
    return;
#endif
  fflush(stderr);
  std::vector<std::string> trace_strings;
  GetBacktraceStrings(trace_, count_, &trace_strings, NULL);
  for (size_t i = 0; i < trace_strings.size(); ++i) {
    std::cerr << "\t" << trace_strings[i] << "\n";
  }
}

void StackTrace::OutputToStream(std::ostream* os) const {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (backtrace_symbols == NULL)
    return;
#endif
  std::vector<std::string> trace_strings;
  std::string error_message;
  if (GetBacktraceStrings(trace_, count_, &trace_strings, &error_message)) {
    (*os) << "Backtrace:\n";
  } else {
    if (!error_message.empty())
      error_message = " (" + error_message + ")";
    (*os) << "Unable to get symbols for backtrace" << error_message << ". "
          << "Dumping raw addresses in trace:\n";
  }

  for (size_t i = 0; i < trace_strings.size(); ++i) {
    (*os) << "\t" << trace_strings[i] << "\n";
  }
}

}  // namespace debug
}  // namespace base
<commit_msg>Get rid of <iostream> include in stack_trace_posix (forces a static initializer)<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/debug/stack_trace.h"

#include <errno.h>
#include <execinfo.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#if defined(__GLIBCXX__)
#include <cxxabi.h>
#endif

#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#endif

#include "base/basictypes.h"
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/safe_strerror_posix.h"
#include "base/string_piece.h"
#include "base/stringprintf.h"

#if defined(USE_SYMBOLIZE)
#include "base/third_party/symbolize/symbolize.h"
#endif

namespace base {
namespace debug {

namespace {

// The prefix used for mangled symbols, per the Itanium C++ ABI:
// http://www.codesourcery.com/cxx-abi/abi.html#mangling
const char kMangledSymbolPrefix[] = "_Z";

// Characters that can be used for symbols, generated by Ruby:
// (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join
const char kSymbolCharacters[] =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";

#if !defined(USE_SYMBOLIZE)
// Demangles C++ symbols in the given text. Example:
//
// "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]"
// =>
// "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]"
void DemangleSymbols(std::string* text) {
#if defined(__GLIBCXX__)

  std::string::size_type search_from = 0;
  while (search_from < text->size()) {
    // Look for the start of a mangled symbol, from search_from.
    std::string::size_type mangled_start =
        text->find(kMangledSymbolPrefix, search_from);
    if (mangled_start == std::string::npos) {
      break;  // Mangled symbol not found.
    }

    // Look for the end of the mangled symbol.
    std::string::size_type mangled_end =
        text->find_first_not_of(kSymbolCharacters, mangled_start);
    if (mangled_end == std::string::npos) {
      mangled_end = text->size();
    }
    std::string mangled_symbol =
        text->substr(mangled_start, mangled_end - mangled_start);

    // Try to demangle the mangled symbol candidate.
    int status = 0;
    scoped_ptr_malloc<char> demangled_symbol(
        abi::__cxa_demangle(mangled_symbol.c_str(), NULL, 0, &status));
    if (status == 0) {  // Demangling is successful.
      // Remove the mangled symbol.
      text->erase(mangled_start, mangled_end - mangled_start);
      // Insert the demangled symbol.
      text->insert(mangled_start, demangled_symbol.get());
      // Next time, we'll start right after the demangled symbol we inserted.
      search_from = mangled_start + strlen(demangled_symbol.get());
    } else {
      // Failed to demangle.  Retry after the "_Z" we just found.
      search_from = mangled_start + 2;
    }
  }

#endif  // defined(__GLIBCXX__)
}
#endif  // !defined(USE_SYMBOLIZE)

// Gets the backtrace as a vector of strings. If possible, resolve symbol
// names and attach these. Otherwise just use raw addresses. Returns true
// if any symbol name is resolved.  Returns false on error and *may* fill
// in |error_message| if an error message is available.
bool GetBacktraceStrings(void *const *trace, int size,
                         std::vector<std::string>* trace_strings,
                         std::string* error_message) {
  bool symbolized = false;

#if defined(USE_SYMBOLIZE)
  for (int i = 0; i < size; ++i) {
    char symbol[1024];
    // Subtract by one as return address of function may be in the next
    // function when a function is annotated as noreturn.
    if (google::Symbolize(static_cast<char *>(trace[i]) - 1,
                          symbol, sizeof(symbol))) {
      // Don't call DemangleSymbols() here as the symbol is demangled by
      // google::Symbolize().
      trace_strings->push_back(
          base::StringPrintf("%s [%p]", symbol, trace[i]));
      symbolized = true;
    } else {
      trace_strings->push_back(base::StringPrintf("%p", trace[i]));
    }
  }
#else
  scoped_ptr_malloc<char*> trace_symbols(backtrace_symbols(trace, size));
  if (trace_symbols.get()) {
    for (int i = 0; i < size; ++i) {
      std::string trace_symbol = trace_symbols.get()[i];
      DemangleSymbols(&trace_symbol);
      trace_strings->push_back(trace_symbol);
    }
    symbolized = true;
  } else {
    if (error_message)
      *error_message = safe_strerror(errno);
    for (int i = 0; i < size; ++i) {
      trace_strings->push_back(base::StringPrintf("%p", trace[i]));
    }
  }
#endif  // defined(USE_SYMBOLIZE)

  return symbolized;
}

}  // namespace

StackTrace::StackTrace() {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (backtrace == NULL) {
    count_ = 0;
    return;
  }
#endif
  // Though the backtrace API man page does not list any possible negative
  // return values, we take no chance.
  count_ = std::max(backtrace(trace_, arraysize(trace_)), 0);
}

void StackTrace::PrintBacktrace() const {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (backtrace_symbols_fd == NULL)
    return;
#endif
  fflush(stderr);
  std::vector<std::string> trace_strings;
  GetBacktraceStrings(trace_, count_, &trace_strings, NULL);
  for (size_t i = 0; i < trace_strings.size(); ++i) {
    fprintf(stderr, "\t%s\n", trace_strings[i].c_str());
  }
}

void StackTrace::OutputToStream(std::ostream* os) const {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (backtrace_symbols == NULL)
    return;
#endif
  std::vector<std::string> trace_strings;
  std::string error_message;
  if (GetBacktraceStrings(trace_, count_, &trace_strings, &error_message)) {
    (*os) << "Backtrace:\n";
  } else {
    if (!error_message.empty())
      error_message = " (" + error_message + ")";
    (*os) << "Unable to get symbols for backtrace" << error_message << ". "
          << "Dumping raw addresses in trace:\n";
  }

  for (size_t i = 0; i < trace_strings.size(); ++i) {
    (*os) << "\t" << trace_strings[i] << "\n";
  }
}

}  // namespace debug
}  // namespace base
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <process.h>

#include "base/message_loop.h"
#include "base/object_watcher.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

typedef testing::Test ObjectWatcherTest;

class QuitDelegate : public base::ObjectWatcher::Delegate {
 public:
  virtual void OnObjectSignaled(HANDLE object) {
    MessageLoop::current()->Quit();
  }
};

class DecrementCountDelegate : public base::ObjectWatcher::Delegate {
 public:
  DecrementCountDelegate(int* counter) : counter_(counter) {
  }
  virtual void OnObjectSignaled(HANDLE object) {
    --(*counter_);
  }
 private:
  int* counter_;
};

}  // namespace

TEST(ObjectWatcherTest, BasicSignal) {
  MessageLoop message_loop;

  base::ObjectWatcher watcher;

  // A manual-reset event that is not yet signaled.
  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);

  QuitDelegate delegate;
  bool ok = watcher.StartWatching(event, &delegate);
  EXPECT_TRUE(ok);

  SetEvent(event);

  MessageLoop::current()->Run();

  CloseHandle(event);
}

TEST(ObjectWatcherTest, BasicCancel) {
  MessageLoop message_loop;

  base::ObjectWatcher watcher;

  // A manual-reset event that is not yet signaled.
  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);

  QuitDelegate delegate;
  bool ok = watcher.StartWatching(event, &delegate);
  EXPECT_TRUE(ok);

  watcher.StopWatching();

  CloseHandle(event);
}

TEST(ObjectWatcherTest, CancelAfterSet) {
  MessageLoop message_loop;

  base::ObjectWatcher watcher;

  int counter = 1;
  DecrementCountDelegate delegate(&counter);

    // A manual-reset event that is not yet signaled.
  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);

  bool ok = watcher.StartWatching(event, &delegate);
  EXPECT_TRUE(ok);

  SetEvent(event);

  // Let the background thread do its business
  Sleep(30);

  watcher.StopWatching();

  MessageLoop::current()->RunAllPending();

  // Our delegate should not have fired.
  EXPECT_EQ(1, counter);

  CloseHandle(event);
}

TEST(ObjectWatcherTest, OutlivesMessageLoop) {
  // Simulate a MessageLoop that dies before an ObjectWatcher.  This ordinarily
  // doesn't happen when people use the Thread class, but it can happen when
  // people use the Singleton pattern or atexit.
  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);  // not signaled
  {
    base::ObjectWatcher watcher;
    {
      MessageLoop message_loop;

      QuitDelegate delegate;
      watcher.StartWatching(event, &delegate);
    }
  }
  CloseHandle(event);
}
<commit_msg>Run ObjectWatcher unit tests against all types of message loops.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <process.h>

#include "base/message_loop.h"
#include "base/object_watcher.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

class QuitDelegate : public base::ObjectWatcher::Delegate {
 public:
  virtual void OnObjectSignaled(HANDLE object) {
    MessageLoop::current()->Quit();
  }
};

class DecrementCountDelegate : public base::ObjectWatcher::Delegate {
 public:
  DecrementCountDelegate(int* counter) : counter_(counter) {
  }
  virtual void OnObjectSignaled(HANDLE object) {
    --(*counter_);
  }
 private:
  int* counter_;
};

}  // namespace

void RunTest_BasicSignal(MessageLoop::Type message_loop_type) {
  MessageLoop message_loop(message_loop_type);

  base::ObjectWatcher watcher;

  // A manual-reset event that is not yet signaled.
  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);

  QuitDelegate delegate;
  bool ok = watcher.StartWatching(event, &delegate);
  EXPECT_TRUE(ok);

  SetEvent(event);

  MessageLoop::current()->Run();

  CloseHandle(event);
}

void RunTest_BasicCancel(MessageLoop::Type message_loop_type) {
  MessageLoop message_loop(message_loop_type);

  base::ObjectWatcher watcher;

  // A manual-reset event that is not yet signaled.
  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);

  QuitDelegate delegate;
  bool ok = watcher.StartWatching(event, &delegate);
  EXPECT_TRUE(ok);

  watcher.StopWatching();

  CloseHandle(event);
}

void RunTest_CancelAfterSet(MessageLoop::Type message_loop_type) {
  MessageLoop message_loop(message_loop_type);

  base::ObjectWatcher watcher;

  int counter = 1;
  DecrementCountDelegate delegate(&counter);

    // A manual-reset event that is not yet signaled.
  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);

  bool ok = watcher.StartWatching(event, &delegate);
  EXPECT_TRUE(ok);

  SetEvent(event);

  // Let the background thread do its business
  Sleep(30);

  watcher.StopWatching();

  MessageLoop::current()->RunAllPending();

  // Our delegate should not have fired.
  EXPECT_EQ(1, counter);

  CloseHandle(event);
}

void RunTest_OutlivesMessageLoop(MessageLoop::Type message_loop_type) {
  // Simulate a MessageLoop that dies before an ObjectWatcher.  This ordinarily
  // doesn't happen when people use the Thread class, but it can happen when
  // people use the Singleton pattern or atexit.
  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);  // not signaled
  {
    base::ObjectWatcher watcher;
    {
      MessageLoop message_loop(message_loop_type);

      QuitDelegate delegate;
      watcher.StartWatching(event, &delegate);
    }
  }
  CloseHandle(event);
}

//-----------------------------------------------------------------------------

TEST(ObjectWatcherTest, BasicSignal) {
  RunTest_BasicSignal(MessageLoop::TYPE_DEFAULT);
  RunTest_BasicSignal(MessageLoop::TYPE_IO);
  RunTest_BasicSignal(MessageLoop::TYPE_UI);
}

TEST(ObjectWatcherTest, BasicCancel) {
  RunTest_BasicCancel(MessageLoop::TYPE_DEFAULT);
  RunTest_BasicCancel(MessageLoop::TYPE_IO);
  RunTest_BasicCancel(MessageLoop::TYPE_UI);
}

TEST(ObjectWatcherTest, CancelAfterSet) {
  RunTest_CancelAfterSet(MessageLoop::TYPE_DEFAULT);
  RunTest_CancelAfterSet(MessageLoop::TYPE_IO);
  RunTest_CancelAfterSet(MessageLoop::TYPE_UI);
}

TEST(ObjectWatcherTest, OutlivesMessageLoop) {
  RunTest_OutlivesMessageLoop(MessageLoop::TYPE_DEFAULT);
  RunTest_OutlivesMessageLoop(MessageLoop::TYPE_IO);
  RunTest_OutlivesMessageLoop(MessageLoop::TYPE_UI);
}
<|endoftext|>


<commit_before>#include "loader.h"
#include "elf.h"
#include "except.h"
#include <fstream>
#include <iostream>
using namespace Simulator;
using namespace std;

static const int PAGE_SIZE = 4096;

// Throws an exception if the expression is false
static void Verify(bool expr, const char* error = "invalid ELF file")
{
	if (!expr) {
		throw Exception(error);
	}
}

// Load the program image into the memory
static MemAddr LoadProgram(IMemoryAdmin* memory, void* _data, MemSize size, bool quiet)
{
	char*      data =  static_cast<char*>(_data);
	Elf64_Ehdr ehdr = *static_cast<Elf64_Ehdr*>(_data);

	// Unmarshall header
	ehdr.e_type      = letohs (ehdr.e_type);
	ehdr.e_machine   = letohs (ehdr.e_machine);
	ehdr.e_version   = letohl (ehdr.e_version);
	ehdr.e_entry     = letohll(ehdr.e_entry);
	ehdr.e_phoff     = letohll(ehdr.e_phoff);
	ehdr.e_shoff     = letohll(ehdr.e_shoff);
	ehdr.e_flags     = letohl (ehdr.e_flags);
	ehdr.e_ehsize    = letohs (ehdr.e_ehsize);
	ehdr.e_phentsize = letohs (ehdr.e_phentsize);
	ehdr.e_phnum     = letohs (ehdr.e_phnum);
	ehdr.e_shentsize = letohs (ehdr.e_shentsize);
	ehdr.e_shnum     = letohs (ehdr.e_shnum);
	ehdr.e_shstrndx  = letohs (ehdr.e_shstrndx);

	// Check file signature
	if (size < sizeof(Elf64_Ehdr) ||
		ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
		ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3)
	{
		// Not an ELF file, load as flat binary, starts at address 0
		if (!quiet)
		{
    		cout << "Loaded flat binary to address 0" << endl;
    	}
		memory->write(0, data, size, IMemory::PERM_READ | IMemory::PERM_WRITE | IMemory::PERM_EXECUTE);
		return 0;
	}

	// Check that this file is for our 'architecture'
	Verify(ehdr.e_ident[EI_CLASS]   == ELFCLASS64,  "file is not 64-bit");
	Verify(ehdr.e_ident[EI_DATA]    == ELFDATA2LSB, "file is not little-endian");
	Verify(ehdr.e_ident[EI_VERSION] == EV_CURRENT,  "ELF version mismatch");
	Verify(ehdr.e_type              == ET_EXEC,     "file is not an executable file");
	Verify(ehdr.e_machine           == EM_ALPHA,    "target architecture is not Alpha");
	Verify(ehdr.e_phoff != 0 && ehdr.e_phnum != 0, "file has no program header");
	Verify(ehdr.e_phentsize == sizeof(Elf64_Phdr),  "file has an invalid program header");
	Verify(ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize <= size, "file has an invalid program header");

	Elf64_Phdr* phdr = static_cast<Elf64_Phdr*>(static_cast<void*>(data + ehdr.e_phoff));

	// Determine base address and check for loadable segments
	bool       hasLoadable = false;
	Elf64_Addr base = 0;
	for (Elf64_Half i = 0; i < ehdr.e_phnum; i++)
	{
	    phdr[i].p_type   = letohl (phdr[i].p_type);
	    phdr[i].p_flags  = letohl (phdr[i].p_flags);
	    phdr[i].p_offset = letohll(phdr[i].p_offset);
	    phdr[i].p_vaddr  = letohll(phdr[i].p_vaddr);
	    phdr[i].p_paddr  = letohll(phdr[i].p_paddr);
	    phdr[i].p_filesz = letohll(phdr[i].p_filesz);
	    phdr[i].p_memsz  = letohll(phdr[i].p_memsz);
	    phdr[i].p_align  = letohll(phdr[i].p_align);

		if (phdr[i].p_type == PT_LOAD)
		{
			if (!hasLoadable || phdr[i].p_vaddr < base) {
				base = phdr[i].p_vaddr;
			}
			hasLoadable = true;
		}
	}
	Verify(hasLoadable, "file has no loadable segments");
	base = base & -PAGE_SIZE;

	// Then copy the LOAD segments into their right locations
	for (Elf64_Half i = 0; i < ehdr.e_phnum; i++)
	{
		if (phdr[i].p_type == PT_LOAD)
		{
  			Verify(phdr[i].p_memsz >= phdr[i].p_filesz, "file has an invalid segment");

			int perm = 0;
			if (phdr[i].p_flags & PF_R) perm |= IMemory::PERM_READ;
			if (phdr[i].p_flags & PF_W) perm |= IMemory::PERM_WRITE;
			if (phdr[i].p_flags & PF_X) perm |= IMemory::PERM_EXECUTE;

			if (phdr[i].p_filesz > 0)
			{
				Verify(phdr[i].p_offset + phdr[i].p_filesz <= size, "file has an invalid segment");

				memory->write(phdr[i].p_vaddr, data + phdr[i].p_offset, phdr[i].p_filesz, perm);
			}

			// Clear the difference between filesz and memsz
			static const char zero[256] = {0};
			Elf64_Xword size = phdr[i].p_memsz - phdr[i].p_filesz;
			while (size > 0)
			{
				Elf64_Xword num  = min(size, 256ULL);
				Elf64_Addr addr = phdr[i].p_vaddr + phdr[i].p_filesz;
				memory->write(addr, zero, num, perm);
				size -= num;
				addr += num;
			}
		}
	}

	if (!quiet)
	{
    	cout << "Loaded ELF binary at address 0x" << hex << base << endl;
    	cout << "Entry point: 0x" << hex << ehdr.e_entry << endl;
    }
	return ehdr.e_entry;
}

// Load the program file into the memory
MemAddr LoadProgram(IMemoryAdmin* memory, const string& path, bool quiet)
{
    ifstream input(path.c_str(), ios::binary);
    if (!input.is_open() || !input.good())
    {
        throw Exception("Unable to load program: " + path);
    }

	// Read the entire file
    input.seekg(0, ios::end);
    streampos size = input.tellg();
    char* data = new char[size];
	try
	{
		input.seekg(0, ios::beg);
		input.read(data, size);
		MemAddr entry = LoadProgram(memory, data, size, quiet);
		delete[] data;
		return entry;
	}
	catch (Exception& e)
	{
		delete[] data;
		throw Exception(string("Unable to load program: ") + e.getMessage());
	}
}
<commit_msg>Fixed ELF loader bug with large bss segments<commit_after>#include "loader.h"
#include "elf.h"
#include "except.h"
#include <fstream>
#include <iostream>
using namespace Simulator;
using namespace std;

static const int PAGE_SIZE = 4096;

// Throws an exception if the expression is false
static void Verify(bool expr, const char* error = "invalid ELF file")
{
	if (!expr) {
		throw Exception(error);
	}
}

// Load the program image into the memory
static MemAddr LoadProgram(IMemoryAdmin* memory, void* _data, MemSize size, bool quiet)
{
	char*      data =  static_cast<char*>(_data);
	Elf64_Ehdr ehdr = *static_cast<Elf64_Ehdr*>(_data);

	// Unmarshall header
	ehdr.e_type      = letohs (ehdr.e_type);
	ehdr.e_machine   = letohs (ehdr.e_machine);
	ehdr.e_version   = letohl (ehdr.e_version);
	ehdr.e_entry     = letohll(ehdr.e_entry);
	ehdr.e_phoff     = letohll(ehdr.e_phoff);
	ehdr.e_shoff     = letohll(ehdr.e_shoff);
	ehdr.e_flags     = letohl (ehdr.e_flags);
	ehdr.e_ehsize    = letohs (ehdr.e_ehsize);
	ehdr.e_phentsize = letohs (ehdr.e_phentsize);
	ehdr.e_phnum     = letohs (ehdr.e_phnum);
	ehdr.e_shentsize = letohs (ehdr.e_shentsize);
	ehdr.e_shnum     = letohs (ehdr.e_shnum);
	ehdr.e_shstrndx  = letohs (ehdr.e_shstrndx);

	// Check file signature
	if (size < sizeof(Elf64_Ehdr) ||
		ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
		ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3)
	{
		// Not an ELF file, load as flat binary, starts at address 0
		if (!quiet)
		{
    		cout << "Loaded flat binary to address 0" << endl;
    	}
		memory->write(0, data, size, IMemory::PERM_READ | IMemory::PERM_WRITE | IMemory::PERM_EXECUTE);
		return 0;
	}

	// Check that this file is for our 'architecture'
	Verify(ehdr.e_ident[EI_CLASS]   == ELFCLASS64,  "file is not 64-bit");
	Verify(ehdr.e_ident[EI_DATA]    == ELFDATA2LSB, "file is not little-endian");
	Verify(ehdr.e_ident[EI_VERSION] == EV_CURRENT,  "ELF version mismatch");
	Verify(ehdr.e_type              == ET_EXEC,     "file is not an executable file");
	Verify(ehdr.e_machine           == EM_ALPHA,    "target architecture is not Alpha");
	Verify(ehdr.e_phoff != 0 && ehdr.e_phnum != 0, "file has no program header");
	Verify(ehdr.e_phentsize == sizeof(Elf64_Phdr),  "file has an invalid program header");
	Verify(ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize <= size, "file has an invalid program header");

	Elf64_Phdr* phdr = static_cast<Elf64_Phdr*>(static_cast<void*>(data + ehdr.e_phoff));

	// Determine base address and check for loadable segments
	bool       hasLoadable = false;
	Elf64_Addr base = 0;
	for (Elf64_Half i = 0; i < ehdr.e_phnum; i++)
	{
	    phdr[i].p_type   = letohl (phdr[i].p_type);
	    phdr[i].p_flags  = letohl (phdr[i].p_flags);
	    phdr[i].p_offset = letohll(phdr[i].p_offset);
	    phdr[i].p_vaddr  = letohll(phdr[i].p_vaddr);
	    phdr[i].p_paddr  = letohll(phdr[i].p_paddr);
	    phdr[i].p_filesz = letohll(phdr[i].p_filesz);
	    phdr[i].p_memsz  = letohll(phdr[i].p_memsz);
	    phdr[i].p_align  = letohll(phdr[i].p_align);

		if (phdr[i].p_type == PT_LOAD)
		{
			if (!hasLoadable || phdr[i].p_vaddr < base) {
				base = phdr[i].p_vaddr;
			}
			hasLoadable = true;
		}
	}
	Verify(hasLoadable, "file has no loadable segments");
	base = base & -PAGE_SIZE;

	// Then copy the LOAD segments into their right locations
	for (Elf64_Half i = 0; i < ehdr.e_phnum; i++)
	{
		if (phdr[i].p_type == PT_LOAD)
		{
  			Verify(phdr[i].p_memsz >= phdr[i].p_filesz, "file has an invalid segment");

			int perm = 0;
			if (phdr[i].p_flags & PF_R) perm |= IMemory::PERM_READ;
			if (phdr[i].p_flags & PF_W) perm |= IMemory::PERM_WRITE;
			if (phdr[i].p_flags & PF_X) perm |= IMemory::PERM_EXECUTE;

			if (phdr[i].p_filesz > 0)
			{
				Verify(phdr[i].p_offset + phdr[i].p_filesz <= size, "file has an invalid segment");

				memory->write(phdr[i].p_vaddr, data + phdr[i].p_offset, phdr[i].p_filesz, perm);
			}

			// Clear the difference between filesz and memsz
			static const char zero[256] = {0};
			Elf64_Xword size = phdr[i].p_memsz - phdr[i].p_filesz;
    		Elf64_Addr  addr = phdr[i].p_vaddr + phdr[i].p_filesz;
			while (size > 0)
			{
				Elf64_Xword num  = min(size, 256ULL);
				memory->write(addr, zero, num, perm);
				size -= num;
				addr += num;
			}
		}
	}

	if (!quiet)
	{
    	cout << "Loaded ELF binary at address 0x" << hex << base << endl;
    	cout << "Entry point: 0x" << hex << ehdr.e_entry << endl;
    }
	return ehdr.e_entry;
}

// Load the program file into the memory
MemAddr LoadProgram(IMemoryAdmin* memory, const string& path, bool quiet)
{
    ifstream input(path.c_str(), ios::binary);
    if (!input.is_open() || !input.good())
    {
        throw Exception("Unable to load program: " + path);
    }

	// Read the entire file
    input.seekg(0, ios::end);
    streampos size = input.tellg();
    char* data = new char[size];
	try
	{
		input.seekg(0, ios::beg);
		input.read(data, size);
		MemAddr entry = LoadProgram(memory, data, size, quiet);
		delete[] data;
		return entry;
	}
	catch (Exception& e)
	{
		delete[] data;
		throw Exception(string("Unable to load program: ") + e.getMessage());
	}
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <ctype.h>
#include <list>
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <RhIO.hpp>
#include "Stream.h"
#include "Shell.h"
#include "utils.h"

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

namespace RhIO
{
    Shell::Shell(std::string server_)
        : server(server_), client(NULL), clientSub(NULL), stream(NULL)
    {
    }

    void Shell::terminal_set_ioconfig() {
        struct termios custom;
        int fd=fileno(stdin);
        tcgetattr(fd, &termsave);
        custom=termsave;
        custom.c_lflag &= ~(ICANON|ECHO);
        tcsetattr(fd,TCSANOW,&custom);
        // fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
        fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)); //blocking
    }

    void Shell::displayPrompt()
    {
        Terminal::setColor("yellow", true);
        std::cout << "RhIO";
        Terminal::clear();
        std::cout << ":";
        Terminal::setColor("blue", true);
        std::cout << getPath();
        Terminal::clear();
        std::cout << "# " << std::flush;
    }

    void Shell::run()
    {

        terminal_set_ioconfig();

        std::string reqServer = "tcp://"+server+":"+ServerRepPort;
        std::string subServer = "tcp://"+server+":"+ServerPubPort;
        terminate = false;
        Terminal::setColor("white", true);
        std::cout << "Rhoban I/O shell, welcome!" << std::endl;
        std::cout << "Connecting to " << server << std::endl;
        client = new ClientReq(reqServer);
        clientSub = new ClientSub(subServer);
        stream = new Stream(this);
        std::cout << "Downloading the tree..." << std::endl;
        tree = new Node(client, "");
        Terminal::clear();

        // Reading lines from stdin
        while (!terminate ) {
            displayPrompt();
            std::string line;
            // std::getline(std::cin, line);
            line=getLine();
            parse(line);
        }

        tcsetattr(fileno(stdin),TCSANOW,&termsave);
        std::cout << std::endl << std::flush;

    }

    std::string Shell::getLine()
    {

        char c;
        std::string line("");
        bool done=false;
        bool esc_mode=false;
        std::deque<std::string>::iterator hist_it=shell_history.end();
        int cursorpos=0;
        std::string lastcmd("");

        while(!done)
        {
            if ((c = getchar())>0)
            {
                switch(c)
                {
                    case 0x0a: //enter

                        putchar(c);
                        done=true;

                        lastcmd="";
                        if(shell_history.size()>0)
                            lastcmd=shell_history.back();

                        if(line.compare("")!=0 and line.compare(lastcmd)!=0) //store in history if non null and different than the last cmd
                        {
                            shell_history.push_back(line);
                            if(shell_history.size()>MAX_HISTORY)
                                shell_history.pop_front();
                            hist_it=shell_history.begin();
                        }
                        return line;
                        break;//useless

                    case 0x01: //Ctrl-a goto begin of line
                        Terminal::clearLine();
                        displayPrompt();
                        std::cout<<line;
                        cursorpos=0;
                        if(line.size()>0)
                            Terminal::cursorNLeft(line.size());

                        break;

                    case 0x05: //Ctrl-e goto end of line
                        Terminal::clearLine();
                        displayPrompt();
                        std::cout<<line;

                        if(cursorpos<line.size())
                        {
                            Terminal::cursorNRight(line.size()-cursorpos);
                            cursorpos=line.size();
                        }

                        break;

                    case 0xc: //Ctrl-l clear screen
                        Terminal::clearScreen();
                        Terminal::clearLine();
                        Terminal::initCursor();
                        displayPrompt();
                        line="";
                        cursorpos=0;
                        break;

                    case 0x1b: //begin break mode (arrows)
                        esc_mode=true;

                        break;

                    case 0x5b: //just after 0x1b

                        break;

                    case 0x41: //up
                        if(esc_mode)
                        {

                            if(shell_history.size()>0 and hist_it!= shell_history.begin())
                            {
                                line=*--hist_it;
                                cursorpos=line.size();
                                Terminal::clearLine();
                                displayPrompt();
                                std::cout<<line;
                            }
                            esc_mode=false;
                        }
                        break;

                    case 0x42: //down
                        if(esc_mode)
                        {
                            if(shell_history.size()>0 and hist_it!= shell_history.end())
                            {
                                line=*hist_it++;
                                cursorpos=line.size();
                                Terminal::clearLine();
                                displayPrompt();
                                std::cout<<line;
                            }
                            else if( hist_it== shell_history.end())
                            {
                                Terminal::clearLine();
                                displayPrompt();
                                line="";
                                cursorpos=0;
                            }

                            esc_mode=false;
                        }
                        break;

                    case 0x43: //right
                        if(esc_mode)
                        {

                            if(cursorpos<line.size())
                            {
                                Terminal::cursorRight();
                                cursorpos++;
                            }
                            esc_mode=false;
                        }
                        break;

                    case 0x44: //left
                        if(esc_mode)
                        {

                            if(cursorpos>0)
                            {
                                Terminal::cursorLeft();
                                cursorpos--;
                            }
                            esc_mode=false;
                        }
                        break;

                    case 0x7f: //backspace
                        if(line.size()>0)
                        {
                            line.pop_back();
                            Terminal::clearLine();
                            displayPrompt();
                            cursorpos--;
                            std::cout<<line;
                        }
                        break;

                    default:

                        if(line.size()>0)
                        {
                            std::string tmp("");
                            tmp+=c;
                            line.insert(cursorpos,tmp);
                        }
                        else{
                            line+=c;
                        }
                        cursorpos++;
                        Terminal::clearLine();
                        displayPrompt();

                        std::cout<<line;

                        if(line.size()-cursorpos>0)
                            Terminal::cursorNLeft(line.size()-cursorpos);

                        break;
                }
            }
        }

    }

    void Shell::parse(std::string line)
    {
        // Try to interpret command as a set
        for (int i=0; i<line.size(); i++) {
            if (line[i] == '=') {
                std::string lvalue = line.substr(0, i);
                std::string rvalue = line.substr(i+1);
                trim(lvalue);
                trim(rvalue);
                set(lvalue, rvalue);
                return;
            }
        }

        // Try to split line into parts and execute it
        std::list<std::string> parts;
        std::string part;

        for (int i=0; i<line.size(); i++) {
            if (std::isspace(line[i])) {
                if (part != "") {
                    parts.push_back(part);
                    part = "";
                }
            } else {
                part += line[i];
            }
        }
        if (part != "") {
            parts.push_back(part);
        }

        if (parts.size()) {
            auto command = parts.front();
            parts.pop_front();
            process(command, parts);
        }
    }

    void Shell::process(std::string command, std::list<std::string> args)
    {
        // First, try to quit/exit
        if (command == "quit" || command == "exit") {
            terminate = true;
        } else {
            // Checking for the command in the list
            if (commands.count(command)) {
                std::vector<std::string> argsV;
                for (auto part : args) {
                    argsV.push_back(part);
                }
                commands[command]->process(argsV);
            } else {
                auto nodeValue = getNodeValue(command);
                auto value = nodeValue.value;

                if (value) {
                    Node::get(this, nodeValue);
                    std::cout << command << "=" << Node::toString(value) << std::endl;
                } else {
                    Terminal::setColor("red", true);
                    std::cout << "Unknown command: " << command << std::endl;
                    Terminal::clear();
                }
            }
        }
    }

    void Shell::set(std::string lvalue, std::string rvalue)
    {
        auto node = getCurrentNode();
        auto nodeValue = getNodeValue(lvalue);
        auto value = nodeValue.value;

        if (value) {
            Node::setFromString(this, nodeValue, rvalue);
        } else {
            Terminal::setColor("red", true);
            std::cout << "Unknown parameter: " << lvalue << std::endl;
            Terminal::clear();
        }
    }

    void Shell::registerCommand(Command *command)
    {
        command->setShell(this);
        commands[command->getName()] = command;
    }

    std::map<std::string, Command*> Shell::getCommands()
    {
        return commands;
    }

    ClientReq *Shell::getClient()
    {
        return client;
    }

    ClientSub *Shell::getClientSub()
    {
        return clientSub;
    }

    void Shell::enterPath(std::string path_)
    {
        path.push_back(path_);
    }

    void Shell::upPath()
    {
        if (path.size()) {
            path.pop_back();
        }
    }

    bool Shell::goToPath(std::string spath)
    {
        if (auto node = getNode(spath)) {
            auto parts = pathToParts(node->getPath());

            path.clear();
            for (auto part : parts) {
                path.push_back(part);
            }
            return true;
        } else {
            return false;
        }
    }

    std::string Shell::getPath()
    {
        std::string p = "";

        for (auto part : path) {
            if (p != "") {
                p += "/";
            }
            p += part;
        }

        return p;
    }

    std::vector<std::string> Shell::pathToParts(std::string spath)
    {
        auto parts = split(spath, '/');
        std::vector<std::string> path;

        for (auto part : parts) {
            if (part != "") {
                path.push_back(part);
            }
        }

        return path;
    }

    Node *Shell::getNode(std::string spath)
    {
        if (spath.size()==0 || spath[0]!='/') {
            auto myPath = getPath();
            if (myPath != "") {
                myPath += "/";
            }
            spath = myPath + spath;
        }

        auto path = pathToParts(spath);

        Node *node = tree;
        for (auto part : path) {
            node = node->getChild(part);
            if (node == NULL) {
                return NULL;
            }
        }
        return node;
    }

    NodeValue Shell::getNodeValue(std::string path)
    {
        auto parts = pathToParts(path);

        if (parts.size() == 0) {
            return NodeValue(NULL, NULL);
        }

        // Child name
        auto name = parts[parts.size()-1];
        parts.pop_back();

        // Creating value path
        std::string prefix = "";
        for (auto part : parts) {
            if (prefix != "") prefix += "/";
            prefix += part;
        }
        if (path[0] == '/') {
            prefix = "/" + prefix;
        }

        // Getting node
        auto node = getNode(prefix);
        if (node == NULL) {
            return NodeValue(NULL, NULL);
        }

        return node->getNodeValue(name);
    }

    Stream *Shell::getStream()
    {
        return stream;
    }

    ValueBase *Shell::getValue(std::string path)
    {
        return getNodeValue(path).value;
    }

    Node *Shell::getCurrentNode()
    {
        return getNode();
    }
}
<commit_msg>fix and<commit_after>#include <stdio.h>
#include <ctype.h>
#include <list>
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <RhIO.hpp>
#include "Stream.h"
#include "Shell.h"
#include "utils.h"

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

namespace RhIO
{
    Shell::Shell(std::string server_)
        : server(server_), client(NULL), clientSub(NULL), stream(NULL)
    {
    }

    void Shell::terminal_set_ioconfig() {
        struct termios custom;
        int fd=fileno(stdin);
        tcgetattr(fd, &termsave);
        custom=termsave;
        custom.c_lflag &= ~(ICANON|ECHO);
        tcsetattr(fd,TCSANOW,&custom);
        // fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
        fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)); //blocking
    }

    void Shell::displayPrompt()
    {
        Terminal::setColor("yellow", true);
        std::cout << "RhIO";
        Terminal::clear();
        std::cout << ":";
        Terminal::setColor("blue", true);
        std::cout << getPath();
        Terminal::clear();
        std::cout << "# " << std::flush;
    }

    void Shell::run()
    {

        terminal_set_ioconfig();

        std::string reqServer = "tcp://"+server+":"+ServerRepPort;
        std::string subServer = "tcp://"+server+":"+ServerPubPort;
        terminate = false;
        Terminal::setColor("white", true);
        std::cout << "Rhoban I/O shell, welcome!" << std::endl;
        std::cout << "Connecting to " << server << std::endl;
        client = new ClientReq(reqServer);
        clientSub = new ClientSub(subServer);
        stream = new Stream(this);
        std::cout << "Downloading the tree..." << std::endl;
        tree = new Node(client, "");
        Terminal::clear();

        // Reading lines from stdin
        while (!terminate ) {
            displayPrompt();
            std::string line;
            // std::getline(std::cin, line);
            line=getLine();
            parse(line);
        }

        tcsetattr(fileno(stdin),TCSANOW,&termsave);
        std::cout << std::endl << std::flush;

    }

    std::string Shell::getLine()
    {

        char c;
        std::string line("");
        bool done=false;
        bool esc_mode=false;
        std::deque<std::string>::iterator hist_it=shell_history.end();
        int cursorpos=0;
        std::string lastcmd("");

        while(!done)
        {
            if ((c = getchar())>0)
            {
                switch(c)
                {
                    case 0x0a: //enter

                        putchar(c);
                        done=true;

                        lastcmd="";
                        if(shell_history.size()>0)
                            lastcmd=shell_history.back();

                        if(line.compare("")!=0 && line.compare(lastcmd)!=0) //store in history if non null and different than the last cmd
                        {
                            shell_history.push_back(line);
                            if(shell_history.size()>MAX_HISTORY)
                                shell_history.pop_front();
                            hist_it=shell_history.begin();
                        }
                        return line;
                        break;//useless

                    case 0x01: //Ctrl-a goto begin of line
                        Terminal::clearLine();
                        displayPrompt();
                        std::cout<<line;
                        cursorpos=0;
                        if(line.size()>0)
                            Terminal::cursorNLeft(line.size());

                        break;

                    case 0x05: //Ctrl-e goto end of line
                        Terminal::clearLine();
                        displayPrompt();
                        std::cout<<line;

                        if(cursorpos<line.size() )
                        {
                            Terminal::cursorNRight(line.size()-cursorpos);
                            cursorpos=line.size();
                        }

                        break;

                    case 0xc: //Ctrl-l clear screen
                        Terminal::clearScreen();
                        Terminal::clearLine();
                        Terminal::initCursor();
                        displayPrompt();
                        line="";
                        cursorpos=0;
                        break;

                    case 0x1b: //begin break mode (arrows)
                        esc_mode=true;

                        break;

                    case 0x5b: //just after 0x1b

                        break;

                    case 0x41: //up
                        if(esc_mode)
                        {

                            if(shell_history.size()>0 && hist_it!= shell_history.begin())
                            {
                                line=*--hist_it;
                                cursorpos=line.size();
                                Terminal::clearLine();
                                displayPrompt();
                                std::cout<<line;
                            }
                            esc_mode=false;
                        }
                        break;

                    case 0x42: //down
                        if(esc_mode)
                        {
                            if(shell_history.size()>0 && hist_it!= shell_history.end())
                            {
                                line=*hist_it++;
                                cursorpos=line.size();
                                Terminal::clearLine();
                                displayPrompt();
                                std::cout<<line;
                            }
                            else if( hist_it== shell_history.end())
                            {
                                Terminal::clearLine();
                                displayPrompt();
                                line="";
                                cursorpos=0;
                            }

                            esc_mode=false;
                        }
                        break;

                    case 0x43: //right
                        if(esc_mode)
                        {

                            if(cursorpos<line.size())
                            {
                                Terminal::cursorRight();
                                cursorpos++;
                            }
                            esc_mode=false;
                        }
                        break;

                    case 0x44: //left
                        if(esc_mode)
                        {

                            if(cursorpos>0)
                            {
                                Terminal::cursorLeft();
                                cursorpos--;
                            }
                            esc_mode=false;
                        }
                        break;

                    case 0x7f: //backspace
                        if(line.size()>0)
                        {
                            line.pop_back();
                            Terminal::clearLine();
                            displayPrompt();
                            cursorpos--;
                            std::cout<<line;
                        }
                        break;

                    default:

                        if(line.size()>0)
                        {
                            std::string tmp("");
                            tmp+=c;
                            line.insert(cursorpos,tmp);
                        }
                        else{
                            line+=c;
                        }
                        cursorpos++;
                        Terminal::clearLine();
                        displayPrompt();

                        std::cout<<line;

                        if(line.size()-cursorpos>0)
                            Terminal::cursorNLeft(line.size()-cursorpos);

                        break;
                }
            }
        }

    }

    void Shell::parse(std::string line)
    {
        // Try to interpret command as a set
        for (int i=0; i<line.size(); i++) {
            if (line[i] == '=') {
                std::string lvalue = line.substr(0, i);
                std::string rvalue = line.substr(i+1);
                trim(lvalue);
                trim(rvalue);
                set(lvalue, rvalue);
                return;
            }
        }

        // Try to split line into parts and execute it
        std::list<std::string> parts;
        std::string part;

        for (int i=0; i<line.size(); i++) {
            if (std::isspace(line[i])) {
                if (part != "") {
                    parts.push_back(part);
                    part = "";
                }
            } else {
                part += line[i];
            }
        }
        if (part != "") {
            parts.push_back(part);
        }

        if (parts.size()) {
            auto command = parts.front();
            parts.pop_front();
            process(command, parts);
        }
    }

    void Shell::process(std::string command, std::list<std::string> args)
    {
        // First, try to quit/exit
        if (command == "quit" || command == "exit") {
            terminate = true;
        } else {
            // Checking for the command in the list
            if (commands.count(command)) {
                std::vector<std::string> argsV;
                for (auto part : args) {
                    argsV.push_back(part);
                }
                commands[command]->process(argsV);
            } else {
                auto nodeValue = getNodeValue(command);
                auto value = nodeValue.value;

                if (value) {
                    Node::get(this, nodeValue);
                    std::cout << command << "=" << Node::toString(value) << std::endl;
                } else {
                    Terminal::setColor("red", true);
                    std::cout << "Unknown command: " << command << std::endl;
                    Terminal::clear();
                }
            }
        }
    }

    void Shell::set(std::string lvalue, std::string rvalue)
    {
        auto node = getCurrentNode();
        auto nodeValue = getNodeValue(lvalue);
        auto value = nodeValue.value;

        if (value) {
            Node::setFromString(this, nodeValue, rvalue);
        } else {
            Terminal::setColor("red", true);
            std::cout << "Unknown parameter: " << lvalue << std::endl;
            Terminal::clear();
        }
    }

    void Shell::registerCommand(Command *command)
    {
        command->setShell(this);
        commands[command->getName()] = command;
    }

    std::map<std::string, Command*> Shell::getCommands()
    {
        return commands;
    }

    ClientReq *Shell::getClient()
    {
        return client;
    }

    ClientSub *Shell::getClientSub()
    {
        return clientSub;
    }

    void Shell::enterPath(std::string path_)
    {
        path.push_back(path_);
    }

    void Shell::upPath()
    {
        if (path.size()) {
            path.pop_back();
        }
    }

    bool Shell::goToPath(std::string spath)
    {
        if (auto node = getNode(spath)) {
            auto parts = pathToParts(node->getPath());

            path.clear();
            for (auto part : parts) {
                path.push_back(part);
            }
            return true;
        } else {
            return false;
        }
    }

    std::string Shell::getPath()
    {
        std::string p = "";

        for (auto part : path) {
            if (p != "") {
                p += "/";
            }
            p += part;
        }

        return p;
    }

    std::vector<std::string> Shell::pathToParts(std::string spath)
    {
        auto parts = split(spath, '/');
        std::vector<std::string> path;

        for (auto part : parts) {
            if (part != "") {
                path.push_back(part);
            }
        }

        return path;
    }

    Node *Shell::getNode(std::string spath)
    {
        if (spath.size()==0 || spath[0]!='/') {
            auto myPath = getPath();
            if (myPath != "") {
                myPath += "/";
            }
            spath = myPath + spath;
        }

        auto path = pathToParts(spath);

        Node *node = tree;
        for (auto part : path) {
            node = node->getChild(part);
            if (node == NULL) {
                return NULL;
            }
        }
        return node;
    }

    NodeValue Shell::getNodeValue(std::string path)
    {
        auto parts = pathToParts(path);

        if (parts.size() == 0) {
            return NodeValue(NULL, NULL);
        }

        // Child name
        auto name = parts[parts.size()-1];
        parts.pop_back();

        // Creating value path
        std::string prefix = "";
        for (auto part : parts) {
            if (prefix != "") prefix += "/";
            prefix += part;
        }
        if (path[0] == '/') {
            prefix = "/" + prefix;
        }

        // Getting node
        auto node = getNode(prefix);
        if (node == NULL) {
            return NodeValue(NULL, NULL);
        }

        return node->getNodeValue(name);
    }

    Stream *Shell::getStream()
    {
        return stream;
    }

    ValueBase *Shell::getValue(std::string path)
    {
        return getNodeValue(path).value;
    }

    Node *Shell::getCurrentNode()
    {
        return getNode();
    }
}
<|endoftext|>


<commit_before>#include <netdb.h>
#include <unistd.h>
#include <sys/fcntl.h>

#include "client.h"
#include "duckchat.h"

// Variables
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_socket;
struct addrinfo *server_info;
char *channel;

// Prints an error message and exits the program.
void Error(const char *msg) {
  std::cerr << msg << std::endl;
  exit(1);
}

// Connects to the server at a the given port.
void Connect(char *domain, const char *port) {
  std::cout << "Connecting to " << domain << std::endl;

  struct addrinfo hints;
  struct addrinfo *server_info_tmp;
  int status;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_protocol = 0;

  if ((status = getaddrinfo(domain, port, &hints, &server_info_tmp)) != 0) {
    std::cerr << "client: unable to resolve address: " << gai_strerror(status) << std::endl;
    exit(1);
  }

  // getaddrinfo() returns a list of address structures into server_info_tmp.
  // Try each address until we successfully connect().
  // If socket() (or connect()) fails, close the socket and try the next address.

  for (server_info = server_info_tmp; server_info != NULL; server_info = server_info->ai_next) {
    if ((client_socket = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol)) < 0) {
      continue;
    }
    if (connect(client_socket, server_info->ai_addr, server_info->ai_addrlen) != -1) {
      fcntl(client_socket, F_SETFL, O_NONBLOCK);
      break; // Success
    }
    close(client_socket);
  }

  if (server_info == NULL) {
    Error("client: all sockets failed to connect");
  }
}

// Sends a message to all users in on the active channel.
int RequestSay(const char *message) {
  struct request_say say;
  memset(&say, 0, sizeof(say));
  say.req_type = REQ_SAY;
  strncpy(say.req_text, message, SAY_MAX);
  strncpy(say.req_channel, channel, CHANNEL_MAX);

  if (sendto(client_socket, &say, sizeof(say), 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to send message\n");
  }

  return 0;
}

// Sends login requests to the server.
int RequestLogin(char *username) {
  struct request_login login;
  memset(&login, 0, sizeof(login));
  login.req_type = REQ_LOGIN;
  strncpy(login.req_username, username, USERNAME_MAX);

  size_t message_size = sizeof(struct request_login);

  if (sendto(client_socket, &login, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request login\n");
  }

  return 0;
}

// Sends logout requests to the server.
int RequestLogout() {
  struct request_logout logout;
  memset((char *) &logout, 0, sizeof(logout));
  logout.req_type = REQ_LOGOUT;

  size_t message_size = sizeof(struct request_logout);

  if (sendto(client_socket, &logout, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request logout\n");
  }

  return 0;
}

// Sends join requests to the server.
int RequestJoin(char *channel) {
  struct request_join join;
  memset((char *) &join, 0, sizeof(join));
  join.req_type = REQ_JOIN;
  strncpy(join.req_channel, channel, CHANNEL_MAX);

  size_t message_size = sizeof(struct request_join);

  if (sendto(client_socket, &join, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request join\n");
  }

  return 0;
}

// Splits strings around spaces.
std::vector<std::string> StringSplit(std::string input) {
  std::istringstream iss(input);
  std::vector<std::string> result{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

  return result;
}

// Splits strings around spaces.
std::vector<std::string> SplitString(std::string input, char delimiter) {
  std::vector<std::string> result;
  std::string word = "";

  for (char c : input) {
    if (c != delimiter) {
      word += c;
    } else {
      result.push_back(word);
      word = "";
    }
  }
  result.push_back(word);

  return result;
}

// Processes the input string to decide what type of command it is.
bool ProcessInput(std::string input) {
  std::vector<std::string> inputs = StringSplit(input);
  bool result = true;

  if (inputs[0] == "/exit") {
    RequestLogout();
    result = false;
  } else if (inputs[0] == "/list") {

  } else if (inputs[0] == "/join") {

  } else if (inputs[0] == "/leave") {

  } else if (inputs[0] == "/who") {

  } else if (inputs[0] == "/switch") {

  } else {
    std::cout << "Invalid command" << std::endl;
  }

  return result;
}

int main(int argc, char *argv[]) {
  char *domain;
  char *port_str;
  int port_num;
  char *username;
  std::string input;

  struct timeval timeout;
  fd_set read_set;
  int file_desc = 0;
  int result;
  char receive_buffer[SAY_MAX];
  memset(&receive_buffer, 0, SAY_MAX);

  if (argc < 4) {
    Error("usage: client [server name] [port] [username]");
  }

  domain = argv[1];
  port_str = argv[2];
  port_num = atoi(argv[2]);
  username = argv[3];

  if (strlen(domain) > UNIX_PATH_MAX) {
    Error("client: server name must be less than 108 characters");
  }

  if (port_num < 0 || port_num > 65535) {
    Error("client: port number must be between 0 and 65535");
  }

  if (strlen(username) > USERNAME_MAX) {
    Error("client: username must be less than 32 characters");
  }

  Connect(domain, port_str);

  RequestLogin(username);

  channel = (char *) "Common";
  RequestJoin(channel);

  // TODO handle response from send

  while(1) {
    FD_ZERO(&read_set);
    FD_SET(file_desc, &read_set);

    timeout.tv_sec = 5; // TODO change time value?
    timeout.tv_usec = 0;

//    if ((result = select(file_desc + 1, &read_set, NULL, NULL, NULL)) < 0) {
//      continue;
//    }
    if ((result = select(file_desc + 1, &read_set, NULL, NULL, NULL)) < 0) {
      Error("client: problem using select");
    }

//    size_t size = sizeof(receive_buffer);

//    std::cout << "past select, result: " << result << std::endl;

    if (result > 0) {
      if (FD_ISSET(file_desc, &read_set)) {
        // Socket has data
        result = read(client_socket, receive_buffer, sizeof(receive_buffer));
      }

      if (result == 0) {
        close(file_desc);
      } else {
        // TODO capture user input, store, clean input, then print buffer, afterward replace input
        std::cout << "[" << channel << "]" << "[" << username << "]: " << receive_buffer << std::endl;
      }
    }

//    std::cout << "past check result" << std::endl;

    std::cout << "> ";
    getline(std::cin, input);

    if (input[0] == '/') {
      if (!ProcessInput(input)) {
        break;
      }
    } else {
      // Send chat messages
      RequestSay(input.c_str());
      std::cout << "[" << channel << "]" << "[" << username << "]: " << input << std::endl;
    }

//    if (FD_ISSET(STDIN_FILENO, &read_set)) {
//      std::cout << "> ";
//      getline(std::cin, input);
//
//      if (input[0] == '/') {
//        if (!ProcessInput(input)) {
//          break;
//        }
//      } else {
//        // Send chat messages
//        RequestSay(input.c_str());
//        std::cout << "[" << channel << "]" << "[" << username << "]: " << input << std::endl;
//      }
//    }

//    std::cout << "past getline" << std::endl;

  }

  return 0;
}<commit_msg>remove timeout part 2<commit_after>#include <netdb.h>
#include <unistd.h>
#include <sys/fcntl.h>

#include "client.h"
#include "duckchat.h"

// Variables
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_socket;
struct addrinfo *server_info;
char *channel;

// Prints an error message and exits the program.
void Error(const char *msg) {
  std::cerr << msg << std::endl;
  exit(1);
}

// Connects to the server at a the given port.
void Connect(char *domain, const char *port) {
  std::cout << "Connecting to " << domain << std::endl;

  struct addrinfo hints;
  struct addrinfo *server_info_tmp;
  int status;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_protocol = 0;

  if ((status = getaddrinfo(domain, port, &hints, &server_info_tmp)) != 0) {
    std::cerr << "client: unable to resolve address: " << gai_strerror(status) << std::endl;
    exit(1);
  }

  // getaddrinfo() returns a list of address structures into server_info_tmp.
  // Try each address until we successfully connect().
  // If socket() (or connect()) fails, close the socket and try the next address.

  for (server_info = server_info_tmp; server_info != NULL; server_info = server_info->ai_next) {
    if ((client_socket = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol)) < 0) {
      continue;
    }
    if (connect(client_socket, server_info->ai_addr, server_info->ai_addrlen) != -1) {
      fcntl(client_socket, F_SETFL, O_NONBLOCK);
      break; // Success
    }
    close(client_socket);
  }

  if (server_info == NULL) {
    Error("client: all sockets failed to connect");
  }
}

// Sends a message to all users in on the active channel.
int RequestSay(const char *message) {
  struct request_say say;
  memset(&say, 0, sizeof(say));
  say.req_type = REQ_SAY;
  strncpy(say.req_text, message, SAY_MAX);
  strncpy(say.req_channel, channel, CHANNEL_MAX);

  if (sendto(client_socket, &say, sizeof(say), 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to send message\n");
  }

  return 0;
}

// Sends login requests to the server.
int RequestLogin(char *username) {
  struct request_login login;
  memset(&login, 0, sizeof(login));
  login.req_type = REQ_LOGIN;
  strncpy(login.req_username, username, USERNAME_MAX);

  size_t message_size = sizeof(struct request_login);

  if (sendto(client_socket, &login, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request login\n");
  }

  return 0;
}

// Sends logout requests to the server.
int RequestLogout() {
  struct request_logout logout;
  memset((char *) &logout, 0, sizeof(logout));
  logout.req_type = REQ_LOGOUT;

  size_t message_size = sizeof(struct request_logout);

  if (sendto(client_socket, &logout, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request logout\n");
  }

  return 0;
}

// Sends join requests to the server.
int RequestJoin(char *channel) {
  struct request_join join;
  memset((char *) &join, 0, sizeof(join));
  join.req_type = REQ_JOIN;
  strncpy(join.req_channel, channel, CHANNEL_MAX);

  size_t message_size = sizeof(struct request_join);

  if (sendto(client_socket, &join, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request join\n");
  }

  return 0;
}

// Splits strings around spaces.
std::vector<std::string> StringSplit(std::string input) {
  std::istringstream iss(input);
  std::vector<std::string> result{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

  return result;
}

// Splits strings around spaces.
std::vector<std::string> SplitString(std::string input, char delimiter) {
  std::vector<std::string> result;
  std::string word = "";

  for (char c : input) {
    if (c != delimiter) {
      word += c;
    } else {
      result.push_back(word);
      word = "";
    }
  }
  result.push_back(word);

  return result;
}

// Processes the input string to decide what type of command it is.
bool ProcessInput(std::string input) {
  std::vector<std::string> inputs = StringSplit(input);
  bool result = true;

  if (inputs[0] == "/exit") {
    RequestLogout();
    result = false;
  } else if (inputs[0] == "/list") {

  } else if (inputs[0] == "/join") {

  } else if (inputs[0] == "/leave") {

  } else if (inputs[0] == "/who") {

  } else if (inputs[0] == "/switch") {

  } else {
    std::cout << "Invalid command" << std::endl;
  }

  return result;
}

int main(int argc, char *argv[]) {
  char *domain;
  char *port_str;
  int port_num;
  char *username;
  std::string input;

//  struct timeval timeout;
  fd_set read_set;
  int file_desc = 0;
  int result;
  char receive_buffer[SAY_MAX];
  memset(&receive_buffer, 0, SAY_MAX);

  if (argc < 4) {
    Error("usage: client [server name] [port] [username]");
  }

  domain = argv[1];
  port_str = argv[2];
  port_num = atoi(argv[2]);
  username = argv[3];

  if (strlen(domain) > UNIX_PATH_MAX) {
    Error("client: server name must be less than 108 characters");
  }

  if (port_num < 0 || port_num > 65535) {
    Error("client: port number must be between 0 and 65535");
  }

  if (strlen(username) > USERNAME_MAX) {
    Error("client: username must be less than 32 characters");
  }

  Connect(domain, port_str);

  RequestLogin(username);

  channel = (char *) "Common";
  RequestJoin(channel);

  // TODO handle response from send

  while(1) {
    FD_ZERO(&read_set);
    FD_SET(file_desc, &read_set);

    timeout.tv_sec = 5; // TODO change time value?
    timeout.tv_usec = 0;

//    if ((result = select(file_desc + 1, &read_set, NULL, NULL, NULL)) < 0) {
//      continue;
//    }
    if ((result = select(file_desc + 1, &read_set, NULL, NULL, NULL)) < 0) {
      Error("client: problem using select");
    }

//    size_t size = sizeof(receive_buffer);

//    std::cout << "past select, result: " << result << std::endl;

    if (result > 0) {
      if (FD_ISSET(file_desc, &read_set)) {
        // Socket has data
        result = read(client_socket, receive_buffer, sizeof(receive_buffer));
      }

      if (result == 0) {
        close(file_desc);
      } else {
        // TODO capture user input, store, clean input, then print buffer, afterward replace input
        std::cout << "[" << channel << "]" << "[" << username << "]: " << receive_buffer << std::endl;
      }
    }

//    std::cout << "past check result" << std::endl;

    std::cout << "> ";
    getline(std::cin, input);

    if (input[0] == '/') {
      if (!ProcessInput(input)) {
        break;
      }
    } else {
      // Send chat messages
      RequestSay(input.c_str());
      std::cout << "[" << channel << "]" << "[" << username << "]: " << input << std::endl;
    }

//    if (FD_ISSET(STDIN_FILENO, &read_set)) {
//      std::cout << "> ";
//      getline(std::cin, input);
//
//      if (input[0] == '/') {
//        if (!ProcessInput(input)) {
//          break;
//        }
//      } else {
//        // Send chat messages
//        RequestSay(input.c_str());
//        std::cout << "[" << channel << "]" << "[" << username << "]: " << input << std::endl;
//      }
//    }

//    std::cout << "past getline" << std::endl;

  }

  return 0;
}<|endoftext|>