<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <cstring>
#include <stdio.h>
#include <cstdlib>
#include <sys/wait.h>
#include<boost/tokenizer.hpp>
using namespace std;
using namespace boost;
int main()
{
    string username=getlogin();
    char hostname[999];
    gethostname(hostname, 999);
    string stringinput;
    char* input[999];
    char_separator<char> ands("&&");
    char_separator<char> ors("||");
    char_separator<char> semico(";");
    while(true)
    {
        //if the user name and hostname both exists, then the program displays it before the dollar sign.
        if(getlogin() != '\0' && gethostname(hostname,999) != -1)
            cout << username << "@" << hostname << "$ ";
        else{
                perror("your hostname or username couldn't be found!");
                cout << "$ ";
        }
        getline(cin,stringinput);
        //this checks for exit and Exit command
        if(stringinput.find("exit")==0||stringinput.find("Exit")==0)
                exit(1);
       //this checks for comments. Basically, everything after the hash symbol is useless
       if(stringinput.find("#") != string::npos)
       {
           stringinput=stringinput.substr(0,stringinput.find("#"));
       }
       if(stringinput.find("||")!=string::npos )
       {
                tokenizer<char_separator<char> > toke(stringinput,ors);
                tokenizer<char_separator<char> >::iterator it=toke.begin();
                for(; it != toke.end(); it++)
                {
                    char_separator<char> space(" ");
                    tokenizer<char_separator<char> > tok(*it, space);
                    int status=0;
                    pid_t pid = fork();
                    if(pid==-1)
                    {
                        perror("this is an error with fork()");
                        exit(1);
                    }
                    else if(pid==0)
                    {
                        int counter=0;
                        for(tokenizer<char_separator<char> >::iterator
                                it1=tok.begin(); it1 != tok.end();
                                it1++,counter++)
                        {
                            input[counter]=new char[(*it1).size()];
                            strcpy(input[counter],(*it1).c_str());
                        }
                        input[counter]=0;
                        int good=execvp(input[0],input);
                        if(good==-1)
                        {
                                perror("Command is bad and not good!");
                                exit(1);
                        }
                        else{
                                cout << "Good!" << execvp(input[0],input) << endl;
                        }
                    }
                    else if(pid>=1)
                    {
                        waitpid(-1,&status,0);
                        if(status<=0)
                                break;
                        /*{
                                perror("Please take care of your child!");
                                exit(1);
                        }*/
                    }
                }
            }
           else  if(stringinput.find("&&")!=string::npos )
            {
                tokenizer<char_separator<char> > toke(stringinput,ands);
                tokenizer<char_separator<char> >::iterator it=toke.begin();
                for(; it != toke.end(); it++)
                {
                    char_separator<char> space(" ");
                    tokenizer<char_separator<char> > tok(*it, space);
                    int status=0;
                    pid_t pid = fork();
                    if(pid==-1)
                    {
                        perror("this is an error with fork()");
                        exit(1);
                    }
                    else if(pid==0)
                    {
                        int counter=0;
                        for(tokenizer<char_separator<char> >::iterator
                                it1=tok.begin(); it1 != tok.end();
                                it1++,counter++)
                        {
                            input[counter]=new char[(*it1).size()];
                            strcpy(input[counter],(*it1).c_str());
                        }
                        input[counter]=0;
                        int good=execvp(input[0],input);
                        if(good==-1)
                        {
                                perror("Command is bad and not good!");
                                exit(1);
                        }
                        else{
                                cout << "Good!" << execvp(input[0],input) << endl;
                        }
                    }
                    else if(pid>=1)
                    {
                        waitpid(-1,&status,0);
                        if(status > 0)
                            break;
                        /*{
                                perror("Please take care of your child!");
                                exit(1);
                        }*/
                    }
                }
            }
            else
                {
                tokenizer<char_separator<char> > toke(stringinput,semico);
                tokenizer<char_separator<char> >::iterator it=toke.begin();
                for(; it != toke.end(); it++)
                {
                    char_separator<char> space(" ");
                    tokenizer<char_separator<char> > tok(*it, space);
                    int status=0;
                    pid_t pid = fork();
                    if(pid==-1)
                    {
                        perror("this is an error with fork()");
                        exit(1);
                    }
                    else if(pid==0)
                    {
                        int counter=0;
                        for(tokenizer<char_separator<char> >::iterator
                                it1=tok.begin(); it1 != tok.end();
                                it1++,counter++)
                        {
                            input[counter]=new char[(*it1).size()];
                            strcpy(input[counter],(*it1).c_str());
                        }
                        input[counter]=0;
                        int good=execvp(input[0],input);
                        if(good==-1)
                        {
                                perror("Command is bad and not good!");
                                exit(1);
                        }
                        else{
                                cout << "Good!" << execvp(input[0],input) << endl;
                        }
                    }
                    else if(pid>=1)
                    {
                        waitpid(-1,&status,0);
                        /*{
                                perror("Please take care of your child!");
                                exit(1);
                        }*/
                    }
                }
    }

    }
    return 0;

}

<commit_msg>changed the way exit works for connectors<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <cstring>
#include <stdio.h>
#include <cstdlib>
#include <sys/wait.h>
#include<boost/tokenizer.hpp>
using namespace std;
using namespace boost;
int main()
{
    string username=getlogin();
    char hostname[999];
    gethostname(hostname, 999);
    string stringinput;
    char* input[999];
    char_separator<char> ands("&&");
    char_separator<char> ors("||");
    char_separator<char> semico(";");
    while(true)
    {
        //if the user name and hostname both exists, then the program displays it before the dollar sign.
        if(getlogin() != '\0' && gethostname(hostname,999) != -1)
            cout << username << "@" << hostname << "$ ";
        else{
                perror("your hostname or username couldn't be found!");
                cout << "$ ";
        }
        getline(cin,stringinput);
        //this checks for exit and Exit command
        if(stringinput.find("exit")==0||stringinput.find("Exit")==0)
                exit(1);
       //this checks for comments. Basically, everything after the hash symbol is useless
       if(stringinput.find("#") != string::npos)
       {
           stringinput=stringinput.substr(0,stringinput.find("#"));
       }
       if(stringinput.find("||")!=string::npos )
       {
                tokenizer<char_separator<char> > toke(stringinput,ors);
                tokenizer<char_separator<char> >::iterator it=toke.begin();
                for(; it != toke.end(); it++)
                {
                    char_separator<char> space(" ");
                    tokenizer<char_separator<char> > tok(*it, space);
                    int status=0;
                    pid_t pid = fork();
                    if(pid==-1)
                    {
                        perror("this is an error with fork()");
                        exit(1);
                    }
                    else if(pid==0)
                    {
                        int counter=0;
                        for(tokenizer<char_separator<char> >::iterator
                                it1=tok.begin(); it1 != tok.end();
                                it1++,counter++)
                        {
                            input[counter]=new char[(*it1).size()];
                            strcpy(input[counter],(*it1).c_str());
                        }
                        input[counter]=0;
                        int good=execvp(input[0],input);
                        if(strcmp(input[0],"exit")==0)
                                exit(1);
                        if(good==-1)
                        {
                                perror("Command is bad and not good!");
                                exit(1);
                        }
                        else{
                                cout << "Good!" << execvp(input[0],input) << endl;
                        }
                    }
                    else if(pid>=1)
                    {
                        waitpid(-1,&status,0);
                        if(status<=0)
                                break;
                        /*{
                                perror("Please take care of your child!");
                                exit(1);
                        }*/
                    }
                }
            }
           else  if(stringinput.find("&&")!=string::npos )
            {
                tokenizer<char_separator<char> > toke(stringinput,ands);
                tokenizer<char_separator<char> >::iterator it=toke.begin();
                for(; it != toke.end(); it++)
                {
                    char_separator<char> space(" ");
                    tokenizer<char_separator<char> > tok(*it, space);
                    int status=0;
                    pid_t pid = fork();
                    if(pid==-1)
                    {
                        perror("this is an error with fork()");
                        exit(1);
                    }
                    else if(pid==0)
                    {
                        int counter=0;
                        for(tokenizer<char_separator<char> >::iterator
                                it1=tok.begin(); it1 != tok.end();
                                it1++,counter++)
                        {
                            input[counter]=new char[(*it1).size()];
                            strcpy(input[counter],(*it1).c_str());
                        }
                        input[counter]=0;
                        int good=execvp(input[0],input);
                        if(strcmp(input[0],"exit")==0)
                                exit(1);
                       if(good==-1)
                        {
                                perror("Command is bad and not good!");
                                exit(1);
                        }
                        else{
                                cout << "Good!" << execvp(input[0],input) << endl;
                        }
                    }
                    else if(pid>=1)
                    {
                        waitpid(-1,&status,0);
                        if(status > 0)
                            break;
                        /*{
                                perror("Please take care of your child!");
                                exit(1);
                        }*/
                    }
                }
            }
            else
                {
                tokenizer<char_separator<char> > toke(stringinput,semico);
                tokenizer<char_separator<char> >::iterator it=toke.begin();
                for(; it != toke.end(); it++)
                {
                    char_separator<char> space(" ");
                    tokenizer<char_separator<char> > tok(*it, space);
                    int status=0;
                    pid_t pid = fork();
                    if(pid==-1)
                    {
                        perror("this is an error with fork()");
                        exit(1);
                    }
                    else if(pid==0)
                    {
                        int counter=0;
                        for(tokenizer<char_separator<char> >::iterator
                                it1=tok.begin(); it1 != tok.end();
                                it1++,counter++)
                        {
                            input[counter]=new char[(*it1).size()];
                            strcpy(input[counter],(*it1).c_str());
                        }
                        input[counter]=0;
                        int good=execvp(input[0],input);
                       if(strcmp(input[0],"exit")==0)
                               exit(1);
                       if(good==-1)
                        {
                                perror("Command is bad and not good!");
                                exit(1);
                        }
                        else{
                                cout << "Good!" << execvp(input[0],input) << endl;
                        }
                    }
                    else if(pid>=1)
                    {
                        waitpid(-1,&status,0);
                        /*{
                                perror("Please take care of your child!");
                                exit(1);
                        }*/
                    }
                }
    }

    }
    return 0;

}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlfonte.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: kz $ $Date: 2007-05-10 16:52:26 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
#ifdef PRECOMPILED
#include "filt_pch.hxx"
#endif

#ifndef SC_ITEMS_HXX
#include "scitems.hxx"
#endif

#include <svx/eeitem.hxx>

#ifndef _XMLOFF_XMLFONTAUTOSTYLEPOOL_HXX
#include <xmloff/XMLFontAutoStylePool.hxx>
#endif
#ifndef _SVX_FONTITEM_HXX
#include <svx/fontitem.hxx>
#endif
#ifndef _EEITEM_HXX
#include <svx/eeitem.hxx>
#endif
#ifndef _MyEDITENG_HXX
#include <svx/editeng.hxx>
#endif

#ifndef SC_DOCUMENT_HXX
#include "document.hxx"
#endif
#ifndef SC_SCDOCPOL_HXX
#include "docpool.hxx"
#endif
#ifndef SC_XMLEXPRT_HXX
#include "xmlexprt.hxx"
#endif
#ifndef SC_STLPOOL_HXX
#include "stlpool.hxx"
#endif
#ifndef SC_SCATTR_HXX
#include "attrib.hxx"
#endif

class ScXMLFontAutoStylePool_Impl: public XMLFontAutoStylePool
{
    void AddFontItems(sal_uInt16* pWhichIds, sal_uInt8 nIdCount, const SfxItemPool* pItemPool, const sal_Bool bExportDefaults);
    public:

    ScXMLFontAutoStylePool_Impl( ScXMLExport& rExport );

};

void ScXMLFontAutoStylePool_Impl::AddFontItems(sal_uInt16* pWhichIds, sal_uInt8 nIdCount, const SfxItemPool* pItemPool, const sal_Bool bExportDefaults)
{
    const SfxPoolItem* pItem;
    for( sal_uInt16 i=0; i < nIdCount; ++i )
    {
        sal_uInt16 nWhichId(pWhichIds[i]);
        if (bExportDefaults && (0 != (pItem = &pItemPool->GetDefaultItem(nWhichId))))
        {
            const SvxFontItem *pFont((const SvxFontItem *)pItem);
            Add( pFont->GetFamilyName(), pFont->GetStyleName(),
                    sal::static_int_cast<sal_Int16>(pFont->GetFamily()),
                    sal::static_int_cast<sal_Int16>(pFont->GetPitch()),
                    pFont->GetCharSet() );
        }
        sal_uInt16 nItems(pItemPool->GetItemCount( nWhichId ));
        for( sal_uInt16 j = 0; j < nItems; ++j )
        {
            if( 0 != (pItem = pItemPool->GetItem( nWhichId, j ) ) )
            {
                const SvxFontItem *pFont((const SvxFontItem *)pItem);
                Add( pFont->GetFamilyName(), pFont->GetStyleName(),
                     sal::static_int_cast<sal_Int16>(pFont->GetFamily()),
                     sal::static_int_cast<sal_Int16>(pFont->GetPitch()),
                     pFont->GetCharSet() );
            }
        }
    }
}

ScXMLFontAutoStylePool_Impl::ScXMLFontAutoStylePool_Impl(
    ScXMLExport& rExportP ) :
    XMLFontAutoStylePool( rExportP )
{
    sal_uInt16 aWhichIds[3] = { ATTR_FONT, ATTR_CJK_FONT,
                                ATTR_CTL_FONT };
    sal_uInt16 aEditWhichIds[3] = { EE_CHAR_FONTINFO, EE_CHAR_FONTINFO_CJK,
                                    EE_CHAR_FONTINFO_CTL };
    sal_uInt16 aPageWhichIds[4] = { ATTR_PAGE_HEADERLEFT, ATTR_PAGE_FOOTERLEFT,
                                    ATTR_PAGE_HEADERRIGHT, ATTR_PAGE_FOOTERRIGHT };

    const SfxItemPool* pItemPool(rExportP.GetDocument() ? rExportP.GetDocument()->GetPool() : NULL);
    AddFontItems(aWhichIds, 3, pItemPool, sal_True);
    const SfxItemPool* pEditPool(rExportP.GetDocument()->GetEditPool());
    AddFontItems(aEditWhichIds, 3, pEditPool, sal_False);

    SfxStyleSheetIterator* pItr(rExportP.GetDocument() ? rExportP.GetDocument()->GetStyleSheetPool()->CreateIterator(SFX_STYLE_FAMILY_PAGE, 0xFFFF) : NULL);
    if(pItr)
    {
        SfxStyleSheetBase* pStyle(pItr->First());
        SfxItemPool* pPageEditPool(EditEngine::CreatePool());
        EditEngine aEditEngine(pPageEditPool);
        while (pStyle)
        {
            const SfxItemPool& rPagePool(pStyle->GetPool().GetPool());
            for (sal_uInt8 j = 0; j < 4; ++j)
            {
                sal_uInt16 nPageWhichId(aPageWhichIds[j]);
                sal_uInt16 nPageHFItems(rPagePool.GetItemCount(nPageWhichId));
                const ScPageHFItem* pPageItem;
                for (sal_uInt16 k = 0; k < nPageHFItems; ++k)
                {
                    if (0 != (pPageItem = static_cast<const ScPageHFItem*>(rPagePool.GetItem(nPageWhichId, k))))
                    {
                        const EditTextObject* pLeftArea(pPageItem->GetLeftArea());
                        if (pLeftArea)
                        {
                            aEditEngine.SetText(*pLeftArea);
                            AddFontItems(aEditWhichIds, 3, pPageEditPool, sal_False);
                        }
                        const EditTextObject* pCenterArea(pPageItem->GetCenterArea());
                        if (pCenterArea)
                        {
                            aEditEngine.SetText(*pCenterArea);
                            AddFontItems(aEditWhichIds, 3, pPageEditPool, sal_False);
                        }
                        const EditTextObject* pRightArea(pPageItem->GetRightArea());
                        if (pRightArea)
                        {
                            aEditEngine.SetText(*pRightArea);
                            AddFontItems(aEditWhichIds, 3, pPageEditPool, sal_False);
                        }
                    }
                }
            }
            pStyle = pItr->Next();
        }
    }
}

XMLFontAutoStylePool* ScXMLExport::CreateFontAutoStylePool()
{
    return new ScXMLFontAutoStylePool_Impl( *this );
}
<commit_msg>INTEGRATION: CWS changefileheader (1.11.300); FILE MERGED 2008/04/01 15:30:32 thb 1.11.300.3: #i85898# Stripping all external header guards 2008/04/01 12:36:34 thb 1.11.300.2: #i85898# Stripping all external header guards 2008/03/31 17:14:58 rt 1.11.300.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: xmlfonte.cxx,v $
 * $Revision: 1.12 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
#ifdef PRECOMPILED
#include "filt_pch.hxx"
#endif

#include "scitems.hxx"

#include <svx/eeitem.hxx>

#include <xmloff/XMLFontAutoStylePool.hxx>
#include <svx/fontitem.hxx>
#include <svx/eeitem.hxx>
#include <svx/editeng.hxx>
#include "document.hxx"
#include "docpool.hxx"
#include "xmlexprt.hxx"
#include "stlpool.hxx"
#include "attrib.hxx"

class ScXMLFontAutoStylePool_Impl: public XMLFontAutoStylePool
{
    void AddFontItems(sal_uInt16* pWhichIds, sal_uInt8 nIdCount, const SfxItemPool* pItemPool, const sal_Bool bExportDefaults);
    public:

    ScXMLFontAutoStylePool_Impl( ScXMLExport& rExport );

};

void ScXMLFontAutoStylePool_Impl::AddFontItems(sal_uInt16* pWhichIds, sal_uInt8 nIdCount, const SfxItemPool* pItemPool, const sal_Bool bExportDefaults)
{
    const SfxPoolItem* pItem;
    for( sal_uInt16 i=0; i < nIdCount; ++i )
    {
        sal_uInt16 nWhichId(pWhichIds[i]);
        if (bExportDefaults && (0 != (pItem = &pItemPool->GetDefaultItem(nWhichId))))
        {
            const SvxFontItem *pFont((const SvxFontItem *)pItem);
            Add( pFont->GetFamilyName(), pFont->GetStyleName(),
                    sal::static_int_cast<sal_Int16>(pFont->GetFamily()),
                    sal::static_int_cast<sal_Int16>(pFont->GetPitch()),
                    pFont->GetCharSet() );
        }
        sal_uInt16 nItems(pItemPool->GetItemCount( nWhichId ));
        for( sal_uInt16 j = 0; j < nItems; ++j )
        {
            if( 0 != (pItem = pItemPool->GetItem( nWhichId, j ) ) )
            {
                const SvxFontItem *pFont((const SvxFontItem *)pItem);
                Add( pFont->GetFamilyName(), pFont->GetStyleName(),
                     sal::static_int_cast<sal_Int16>(pFont->GetFamily()),
                     sal::static_int_cast<sal_Int16>(pFont->GetPitch()),
                     pFont->GetCharSet() );
            }
        }
    }
}

ScXMLFontAutoStylePool_Impl::ScXMLFontAutoStylePool_Impl(
    ScXMLExport& rExportP ) :
    XMLFontAutoStylePool( rExportP )
{
    sal_uInt16 aWhichIds[3] = { ATTR_FONT, ATTR_CJK_FONT,
                                ATTR_CTL_FONT };
    sal_uInt16 aEditWhichIds[3] = { EE_CHAR_FONTINFO, EE_CHAR_FONTINFO_CJK,
                                    EE_CHAR_FONTINFO_CTL };
    sal_uInt16 aPageWhichIds[4] = { ATTR_PAGE_HEADERLEFT, ATTR_PAGE_FOOTERLEFT,
                                    ATTR_PAGE_HEADERRIGHT, ATTR_PAGE_FOOTERRIGHT };

    const SfxItemPool* pItemPool(rExportP.GetDocument() ? rExportP.GetDocument()->GetPool() : NULL);
    AddFontItems(aWhichIds, 3, pItemPool, sal_True);
    const SfxItemPool* pEditPool(rExportP.GetDocument()->GetEditPool());
    AddFontItems(aEditWhichIds, 3, pEditPool, sal_False);

    SfxStyleSheetIterator* pItr(rExportP.GetDocument() ? rExportP.GetDocument()->GetStyleSheetPool()->CreateIterator(SFX_STYLE_FAMILY_PAGE, 0xFFFF) : NULL);
    if(pItr)
    {
        SfxStyleSheetBase* pStyle(pItr->First());
        SfxItemPool* pPageEditPool(EditEngine::CreatePool());
        EditEngine aEditEngine(pPageEditPool);
        while (pStyle)
        {
            const SfxItemPool& rPagePool(pStyle->GetPool().GetPool());
            for (sal_uInt8 j = 0; j < 4; ++j)
            {
                sal_uInt16 nPageWhichId(aPageWhichIds[j]);
                sal_uInt16 nPageHFItems(rPagePool.GetItemCount(nPageWhichId));
                const ScPageHFItem* pPageItem;
                for (sal_uInt16 k = 0; k < nPageHFItems; ++k)
                {
                    if (0 != (pPageItem = static_cast<const ScPageHFItem*>(rPagePool.GetItem(nPageWhichId, k))))
                    {
                        const EditTextObject* pLeftArea(pPageItem->GetLeftArea());
                        if (pLeftArea)
                        {
                            aEditEngine.SetText(*pLeftArea);
                            AddFontItems(aEditWhichIds, 3, pPageEditPool, sal_False);
                        }
                        const EditTextObject* pCenterArea(pPageItem->GetCenterArea());
                        if (pCenterArea)
                        {
                            aEditEngine.SetText(*pCenterArea);
                            AddFontItems(aEditWhichIds, 3, pPageEditPool, sal_False);
                        }
                        const EditTextObject* pRightArea(pPageItem->GetRightArea());
                        if (pRightArea)
                        {
                            aEditEngine.SetText(*pRightArea);
                            AddFontItems(aEditWhichIds, 3, pPageEditPool, sal_False);
                        }
                    }
                }
            }
            pStyle = pItr->Next();
        }
    }
}

XMLFontAutoStylePool* ScXMLExport::CreateFontAutoStylePool()
{
    return new ScXMLFontAutoStylePool_Impl( *this );
}
<|endoftext|>


<commit_before>#include <tinyxml2.h>
#include <chrono>
#include <sstream>
#include <ctime>

#include "feed.h"

#include "storage.h"

namespace C3 {
  namespace Feed {
    std::string feed_str = "";
    uint16_t feed_length;
    std::string title;
    std::string url;

    std::string generate_rfc3999(uint64_t ms_since_epoch) {
      std::chrono::milliseconds duration(ms_since_epoch);
      std::chrono::time_point<std::chrono::system_clock> point(duration);
      time_t tt = std::chrono::system_clock::to_time_t(point);

      std::tm *cal = gmtime(&tt);

      std::stringstream ss;
      ss<<cal->tm_year + 1900<<'-'<<cal->tm_mon + 1<<'-'<<cal->tm_mday<<'T'<<cal->tm_hour<<':'<<cal->tm_min<<':'<<cal->tm_sec<<'Z';
      return ss.str();
    }

    void setup(const Config &c) {
      feed_length = c.app_feedLength;
      title = c.app_title;
      url = c.app_url;
      update();
    }

    void update(void) {
      bool dummy;
      auto posts = list_posts(0, feed_length, dummy);

      tinyxml2::XMLDocument doc;

      auto dec = doc.NewDeclaration();
      auto root = doc.NewElement("feed");
      root->SetAttribute("xmlns", "http://www.w3.org/2005/Atom");

      auto id_e = doc.NewElement("id");
      id_e->SetText(url.c_str());
      root->InsertEndChild(id_e);

      auto title_e = doc.NewElement("title");
      title_e->SetText(title.c_str());
      root->InsertEndChild(title_e);

      auto link_e = doc.NewElement("link");
      link_e->SetAttribute("href", url.c_str());
      root->InsertEndChild(link_e);

      auto dur = std::chrono::system_clock::now().time_since_epoch();
      auto durStr = generate_rfc3999(std::chrono::duration_cast<std::chrono::milliseconds>(dur).count());
      auto updated_e = doc.NewElement("updated");
      updated_e->SetText(durStr.c_str());
      root->InsertEndChild(updated_e);

      for(auto i = posts.begin(); i != posts.end(); ++i) {
        auto entry_e = doc.NewElement("entry");

        auto entry_id_e = doc.NewElement("id");
        entry_id_e->SetText((url + "[" + std::to_string(i->post_time) + "]").c_str());
        entry_e->InsertEndChild(entry_id_e);

        auto entry_title_e = doc.NewElement("title");
        entry_title_e->SetText(i->topic.c_str());
        entry_e->InsertEndChild(entry_title_e);

        auto entry_content_e = doc.NewElement("content");
        entry_content_e->SetText(markdown(i->content).c_str());
        entry_content_e->SetAttribute("type", "html");
        entry_e->InsertEndChild(entry_content_e);

        auto entry_updated_e = doc.NewElement("updated");
        entry_updated_e->SetText(generate_rfc3999(i->update_time).c_str());
        entry_e->InsertEndChild(entry_updated_e);

        auto entry_link_e = doc.NewElement("link");
        entry_link_e->SetAttribute("href", (url + "/" + i->url).c_str());
        entry_link_e->SetAttribute("rel", "alternative");
        entry_e->InsertEndChild(entry_link_e);

        root->InsertEndChild(entry_e);
      }

      doc.InsertEndChild(dec);
      doc.InsertEndChild(root);

      tinyxml2::XMLPrinter printer(NULL, true, 0);
      doc.Print(&printer);
      feed_str = printer.CStr();
    }

    std::string fetch(void) {
      return feed_str;
    }
  }
}
<commit_msg>Added fallback link element in feeds<commit_after>#include <tinyxml2.h>
#include <chrono>
#include <sstream>
#include <ctime>

#include "feed.h"

#include "storage.h"

namespace C3 {
  namespace Feed {
    std::string feed_str = "";
    uint16_t feed_length;
    std::string title;
    std::string url;

    std::string generate_rfc3999(uint64_t ms_since_epoch) {
      std::chrono::milliseconds duration(ms_since_epoch);
      std::chrono::time_point<std::chrono::system_clock> point(duration);
      time_t tt = std::chrono::system_clock::to_time_t(point);

      std::tm *cal = gmtime(&tt);

      std::stringstream ss;
      ss<<cal->tm_year + 1900<<'-'<<cal->tm_mon + 1<<'-'<<cal->tm_mday<<'T'<<cal->tm_hour<<':'<<cal->tm_min<<':'<<cal->tm_sec<<'Z';
      return ss.str();
    }

    void setup(const Config &c) {
      feed_length = c.app_feedLength;
      title = c.app_title;
      url = c.app_url;
      update();
    }

    void update(void) {
      bool dummy;
      auto posts = list_posts(0, feed_length, dummy);

      tinyxml2::XMLDocument doc;

      auto dec = doc.NewDeclaration();
      auto root = doc.NewElement("feed");
      root->SetAttribute("xmlns", "http://www.w3.org/2005/Atom");

      auto id_e = doc.NewElement("id");
      id_e->SetText(url.c_str());
      root->InsertEndChild(id_e);

      auto title_e = doc.NewElement("title");
      title_e->SetText(title.c_str());
      root->InsertEndChild(title_e);

      auto link_e = doc.NewElement("link");
      link_e->SetAttribute("href", url.c_str());
      root->InsertEndChild(link_e);

      auto dur = std::chrono::system_clock::now().time_since_epoch();
      auto durStr = generate_rfc3999(std::chrono::duration_cast<std::chrono::milliseconds>(dur).count());
      auto updated_e = doc.NewElement("updated");
      updated_e->SetText(durStr.c_str());
      root->InsertEndChild(updated_e);

      for(auto i = posts.begin(); i != posts.end(); ++i) {
        auto entry_e = doc.NewElement("entry");

        auto entry_id_e = doc.NewElement("id");
        entry_id_e->SetText((url + "[" + std::to_string(i->post_time) + "]").c_str());
        entry_e->InsertEndChild(entry_id_e);

        auto entry_title_e = doc.NewElement("title");
        entry_title_e->SetText(i->topic.c_str());
        entry_e->InsertEndChild(entry_title_e);

        auto entry_content_e = doc.NewElement("content");
        entry_content_e->SetText(markdown(i->content).c_str());
        entry_content_e->SetAttribute("type", "html");
        entry_e->InsertEndChild(entry_content_e);

        auto entry_updated_e = doc.NewElement("updated");
        entry_updated_e->SetText(generate_rfc3999(i->update_time).c_str());
        entry_e->InsertEndChild(entry_updated_e);

        auto entry_link_e = doc.NewElement("link");
        entry_link_e->SetAttribute("href", (url + "/" + i->url).c_str());
        entry_link_e->SetAttribute("rel", "alternative");
        entry_e->InsertEndChild(entry_link_e);

        auto entry_link_fb = doc.NewElement("link");
        entry_link_fb->SetText((url + "/" + i->url).c_str());
        entry_e->InsertEndChild(entry_link_fb);

        root->InsertEndChild(entry_e);
      }

      doc.InsertEndChild(dec);
      doc.InsertEndChild(root);

      tinyxml2::XMLPrinter printer(NULL, true, 0);
      doc.Print(&printer);
      feed_str = printer.CStr();
    }

    std::string fetch(void) {
      return feed_str;
    }
  }
}
<|endoftext|>


<commit_before>#include "avxprocessing.h"
#include "benchmark.h"
#include "jsonstruct.h"
// #define RAPIDJSON_SSE2 // bad
// #define RAPIDJSON_SSE42 // bad
#include "rapidjson/document.h"
#include "rapidjson/reader.h" // you have to check in the submodule
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "scalarprocessing.h"
#include "util.h"

// colorfuldisplay(ParsedJson & pj, const u8 * buf)

using namespace rapidjson;
using namespace std;

std::string rapidstringme(char * json) {
    Document d;
    d.Parse(json);
    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    d.Accept(writer);
    return buffer.GetString();
}

int main(int argc, char *argv[]) {
  if (argc < 2) {
    cerr << "Usage: " << argv[0] << " <jsonfile>\n";
    cerr << "Or " << argv[0] << " -v <jsonfile>\n";
    exit(1);
  }
  bool verbose = false;
  if (argc > 2) {
    if (strcmp(argv[1], "-v"))
      verbose = true;
  }
  pair<u8 *, size_t> p = get_corpus(argv[argc - 1]);
  ParsedJson pj;
  std::cout << "Input has ";
  if (p.second > 1024 * 1024)
    std::cout << p.second / (1024 * 1024) << " MB ";
  else if (p.second > 1024)
    std::cout << p.second / 1024 << " KB ";
  else
    std::cout << p.second << " B ";
  std::cout << std::endl;

  if (posix_memalign((void **)&pj.structurals, 8,
                     ROUNDUP_N(p.second, 64) / 8)) {
    throw "Allocation failed";
  };

  pj.n_structural_indexes = 0;
  // we have potentially 1 structure per byte of input
  // as well as a dummy structure and a root structure
  // we also potentially write up to 7 iterations beyond
  // in our 'cheesy flatten', so make some worst-case
  // sapce for that too
  u32 max_structures = ROUNDUP_N(p.second, 64) + 2 + 7;
  pj.structural_indexes = new u32[max_structures];
  pj.nodes = new JsonNode[max_structures];
  if (verbose) {
    std::cout << "Parsing SIMD (once) " << std::endl;
    avx_json_parse(p.first, p.second, pj);
    colorfuldisplay(pj, p.first);
    debugdisplay(pj, p.first);
    std::cout << "Parsing scalar (once) " << std::endl;
    scalar_json_parse(p.first, p.second, pj);
    colorfuldisplay(pj, p.first);
    debugdisplay(pj, p.first);
  }

  int repeat = 10;
  int volume = p.second;
  BEST_TIME_NOCHECK(avx_json_parse(p.first, p.second, pj), , repeat, volume,
                    true);
  BEST_TIME_NOCHECK(scalar_json_parse(p.first, p.second, pj), , repeat, volume,
                    true);

  rapidjson::Document d;
  char * buffer = (char *) malloc(p.second);
  memcpy(buffer, p.first, p.second);
  buffer[p.second] = '\0';
  BEST_TIME(d.Parse<kParseValidateEncodingFlag>((const char *)buffer).HasParseError(), false,
          memcpy(buffer, p.first, p.second), repeat, volume, true);
  BEST_TIME(d.Parse((const char *)buffer).HasParseError(), false,
            memcpy(buffer, p.first, p.second), repeat, volume, true);
  BEST_TIME(d.ParseInsitu(buffer).HasParseError(), false,
            memcpy(buffer, p.first, p.second), repeat, volume, true);
  size_t strlength = rapidstringme((char*) p.first).size();
  std::cout << "input length is "<< p.second << " stringified length is " << strlength << std::endl;
  BEST_TIME_NOCHECK(rapidstringme((char*) p.first), , repeat, volume,
                    true);
  free(buffer);
}
<commit_msg>Adding more benchmarks.<commit_after>#include "avxprocessing.h"
#include "benchmark.h"
#include "jsonstruct.h"
// #define RAPIDJSON_SSE2 // bad
// #define RAPIDJSON_SSE42 // bad
#include "rapidjson/document.h"
#include "rapidjson/reader.h" // you have to check in the submodule
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "scalarprocessing.h"
#include "util.h"

// colorfuldisplay(ParsedJson & pj, const u8 * buf)

using namespace rapidjson;
using namespace std;

std::string rapidstringmeInsitu(char * json) {
    Document d;
    d.ParseInsitu(json);
    if(d.HasParseError()) {
       std::cerr << "problem!" << std::endl;
       return "";// should do something
    }
    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    d.Accept(writer);
    return buffer.GetString();
}

std::string rapidstringme(char * json) {
    Document d;
    d.Parse(json);
    if(d.HasParseError()) {
       std::cerr << "problem!" << std::endl;
       return "";// should do something
    }
    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    d.Accept(writer);
    return buffer.GetString();
}

int main(int argc, char *argv[]) {
  if (argc < 2) {
    cerr << "Usage: " << argv[0] << " <jsonfile>\n";
    cerr << "Or " << argv[0] << " -v <jsonfile>\n";
    exit(1);
  }
  bool verbose = false;
  if (argc > 2) {
    if (strcmp(argv[1], "-v"))
      verbose = true;
  }
  pair<u8 *, size_t> p = get_corpus(argv[argc - 1]);
  ParsedJson pj;
  std::cout << "Input has ";
  if (p.second > 1024 * 1024)
    std::cout << p.second / (1024 * 1024) << " MB ";
  else if (p.second > 1024)
    std::cout << p.second / 1024 << " KB ";
  else
    std::cout << p.second << " B ";
  std::cout << std::endl;

  if (posix_memalign((void **)&pj.structurals, 8,
                     ROUNDUP_N(p.second, 64) / 8)) {
    throw "Allocation failed";
  };

  pj.n_structural_indexes = 0;
  // we have potentially 1 structure per byte of input
  // as well as a dummy structure and a root structure
  // we also potentially write up to 7 iterations beyond
  // in our 'cheesy flatten', so make some worst-case
  // sapce for that too
  u32 max_structures = ROUNDUP_N(p.second, 64) + 2 + 7;
  pj.structural_indexes = new u32[max_structures];
  pj.nodes = new JsonNode[max_structures];
  if (verbose) {
    std::cout << "Parsing SIMD (once) " << std::endl;
    avx_json_parse(p.first, p.second, pj);
    colorfuldisplay(pj, p.first);
    debugdisplay(pj, p.first);
    std::cout << "Parsing scalar (once) " << std::endl;
    scalar_json_parse(p.first, p.second, pj);
    colorfuldisplay(pj, p.first);
    debugdisplay(pj, p.first);
  }

  int repeat = 10;
  int volume = p.second;
  BEST_TIME_NOCHECK(avx_json_parse(p.first, p.second, pj), , repeat, volume,
                    true);
  BEST_TIME_NOCHECK(scalar_json_parse(p.first, p.second, pj), , repeat, volume,
                    true);

  rapidjson::Document d;
  char * buffer = (char *) malloc(p.second);
  memcpy(buffer, p.first, p.second);
  buffer[p.second] = '\0';
  BEST_TIME(d.Parse<kParseValidateEncodingFlag>((const char *)buffer).HasParseError(), false,
          memcpy(buffer, p.first, p.second), repeat, volume, true);
  BEST_TIME(d.Parse((const char *)buffer).HasParseError(), false,
            memcpy(buffer, p.first, p.second), repeat, volume, true);
  BEST_TIME(d.ParseInsitu(buffer).HasParseError(), false,
            memcpy(buffer, p.first, p.second), repeat, volume, true);
  size_t strlength = rapidstringme((char*) p.first).size();
  std::cout << "input length is "<< p.second << " stringified length is " << strlength << std::endl;
  BEST_TIME_NOCHECK(rapidstringme((char*) p.first), , repeat, volume,
                    true);
  BEST_TIME_NOCHECK(rapidstringmeInsitu((char*) buffer), memcpy(buffer, p.first, p.second) , repeat, volume,
                    true);
  free(buffer);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: weakeventlistener.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef COMPHELPER_WEAKEVENTLISTENER_HXX
#define COMPHELPER_WEAKEVENTLISTENER_HXX

#include <cppuhelper/compbase1.hxx>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/uno/XWeak.hpp>
#include <cppuhelper/weakref.hxx>
#include <comphelper/broadcasthelper.hxx>
#include "comphelper/comphelperdllapi.h"

//.........................................................................
namespace comphelper
{
//.........................................................................

    //=====================================================================
    //= OWeakListenerAdapterBase
    //=====================================================================
    /** (the base for) an adapter which allows to add as listener to a foreign component, without
        being held hard.

The idea is that this adapter is added as listener to a foreign component, which usually
        holds it's listener hard. The adapter itself knows the real listener as weak reference,
        thus not affecting it's life time.

    */
    class OWeakListenerAdapterBase : public OBaseMutex
    {
    private:
        ::com::sun::star::uno::WeakReference< ::com::sun::star::uno::XInterface >
                m_aListener;
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
                m_xBroadcaster;

    protected:
        inline ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
                getListener( ) const
        {
            return m_aListener.get();
        }

        inline const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >&
                getBroadcaster( ) const
        {
            return m_xBroadcaster;
        }

        inline void resetListener( )
        {
            m_aListener = ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >();
        }

    protected:
        inline OWeakListenerAdapterBase(
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XWeak >& _rxListener,
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxBroadcaster
        )
            :m_aListener    (  _rxListener )
            ,m_xBroadcaster ( _rxBroadcaster )
        {
        }

    protected:
        virtual ~OWeakListenerAdapterBase();
    };

    //=====================================================================
    //= OWeakListenerAdapter
    //=====================================================================
    template< class BROADCASTER, class LISTENER >
    /** yet another base for weak listener adapters, this time with some type safety

Note that derived classes need to overwrite all virtual methods of their interface
        except XEventListener::disposing, and forward it to their master listener.

Addtionally, derived classes need to add themself as listener to the broadcaster,
        as this can't be done in a generic way

    */
    class OWeakListenerAdapter
            :public ::cppu::WeakComponentImplHelper1 < LISTENER >
            ,public OWeakListenerAdapterBase
    {
    protected:
        /** ctor

Note that derived classes still need to add themself as listener to the broadcaster,
            as this can't be done in a generic way

        */
        OWeakListenerAdapter(
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XWeak >& _rxListener,
            const ::com::sun::star::uno::Reference< BROADCASTER >& _rxBroadcaster
        );

    protected:
        inline  ::com::sun::star::uno::Reference< LISTENER > getListener( ) const
        {
            return  ::com::sun::star::uno::Reference< LISTENER >( OWeakListenerAdapterBase::getListener(), ::com::sun::star::uno::UNO_QUERY );
        }

        // XEventListener overridables
        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);

    protected:
        // OComponentHelper overridables
        // to be overridden, again - the derived class should revoke the listener from the broadcaster
        virtual void SAL_CALL disposing( ) = 0;
    };

    //=====================================================================
    //= OWeakEventListenerAdapter
    //=====================================================================
    typedef OWeakListenerAdapter    <   ::com::sun::star::lang::XComponent
                                    ,   ::com::sun::star::lang::XEventListener
                                    >   OWeakEventListenerAdapter_Base;
    /** the most simple listener adapter: for XEventListeners at XComponents
    */
    class COMPHELPER_DLLPUBLIC OWeakEventListenerAdapter : public OWeakEventListenerAdapter_Base
    {
    public:
        OWeakEventListenerAdapter(
            ::com::sun::star::uno::Reference< ::com::sun::star::uno::XWeak > _rxListener,
            ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > _rxBroadcaster
        );

        // nothing to do except an own ctor - the forwarding of the "disposing" is already done
        // in the base class

    protected:
        using OWeakEventListenerAdapter_Base::disposing;
        virtual void SAL_CALL disposing( );
    };

    //=====================================================================
    //= OWeakListenerAdapter
    //=====================================================================
    //---------------------------------------------------------------------
    template< class BROADCASTER, class LISTENER >
    OWeakListenerAdapter< BROADCASTER, LISTENER >::OWeakListenerAdapter(
        const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XWeak >& _rxListener,
        const ::com::sun::star::uno::Reference< BROADCASTER >& _rxBroadcaster
    )
        : ::cppu::WeakComponentImplHelper1< LISTENER >( m_aMutex )
        , OWeakListenerAdapterBase( _rxListener, _rxBroadcaster )
    {
    }

    //---------------------------------------------------------------------
    template< class BROADCASTER, class LISTENER >
    void SAL_CALL OWeakListenerAdapter< BROADCASTER, LISTENER >::disposing( const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException)
    {
        ::com::sun::star::uno::Reference< LISTENER > xListener( getListener() );
        if ( xListener.is() )
            xListener->disposing( _rSource );
    }

//.........................................................................
}   // namespace comphelper
//.........................................................................

#endif// COMPHELPER_WEAKEVENTLISTENER_HXX

<commit_msg>CWS-TOOLING: integrate CWS swunolocking1<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: weakeventlistener.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef COMPHELPER_WEAKEVENTLISTENER_HXX
#define COMPHELPER_WEAKEVENTLISTENER_HXX

#include <cppuhelper/compbase1.hxx>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/uno/XWeak.hpp>
#include <cppuhelper/weakref.hxx>
#include <comphelper/broadcasthelper.hxx>
#include "comphelper/comphelperdllapi.h"

//.........................................................................
namespace comphelper
{
//.........................................................................

    //=====================================================================
    //= OWeakListenerAdapterBase
    //=====================================================================
    /** (the base for) an adapter which allows to add as listener to a foreign component, without
        being held hard.

The idea is that this adapter is added as listener to a foreign component, which usually
        holds it's listener hard. The adapter itself knows the real listener as weak reference,
        thus not affecting it's life time.

    */
    class OWeakListenerAdapterBase : public OBaseMutex
    {
    private:
        ::com::sun::star::uno::WeakReference< ::com::sun::star::uno::XInterface >
                m_aListener;
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
                m_xBroadcaster;

    protected:
        inline ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
                getListener( ) const
        {
            return m_aListener.get();
        }

        inline const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >&
                getBroadcaster( ) const
        {
            return m_xBroadcaster;
        }

        inline void resetListener( )
        {
            m_aListener.clear();
        }

    protected:
        inline OWeakListenerAdapterBase(
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XWeak >& _rxListener,
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxBroadcaster
        )
            :m_aListener    (  _rxListener )
            ,m_xBroadcaster ( _rxBroadcaster )
        {
        }

    protected:
        virtual ~OWeakListenerAdapterBase();
    };

    //=====================================================================
    //= OWeakListenerAdapter
    //=====================================================================
    template< class BROADCASTER, class LISTENER >
    /** yet another base for weak listener adapters, this time with some type safety

Note that derived classes need to overwrite all virtual methods of their interface
        except XEventListener::disposing, and forward it to their master listener.

Addtionally, derived classes need to add themself as listener to the broadcaster,
        as this can't be done in a generic way

    */
    class OWeakListenerAdapter
            :public ::cppu::WeakComponentImplHelper1 < LISTENER >
            ,public OWeakListenerAdapterBase
    {
    protected:
        /** ctor

Note that derived classes still need to add themself as listener to the broadcaster,
            as this can't be done in a generic way

        */
        OWeakListenerAdapter(
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XWeak >& _rxListener,
            const ::com::sun::star::uno::Reference< BROADCASTER >& _rxBroadcaster
        );

    protected:
        inline  ::com::sun::star::uno::Reference< LISTENER > getListener( ) const
        {
            return  ::com::sun::star::uno::Reference< LISTENER >( OWeakListenerAdapterBase::getListener(), ::com::sun::star::uno::UNO_QUERY );
        }

        // XEventListener overridables
        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);

    protected:
        // OComponentHelper overridables
        // to be overridden, again - the derived class should revoke the listener from the broadcaster
        virtual void SAL_CALL disposing( ) = 0;
    };

    //=====================================================================
    //= OWeakEventListenerAdapter
    //=====================================================================
    typedef OWeakListenerAdapter    <   ::com::sun::star::lang::XComponent
                                    ,   ::com::sun::star::lang::XEventListener
                                    >   OWeakEventListenerAdapter_Base;
    /** the most simple listener adapter: for XEventListeners at XComponents
    */
    class COMPHELPER_DLLPUBLIC OWeakEventListenerAdapter : public OWeakEventListenerAdapter_Base
    {
    public:
        OWeakEventListenerAdapter(
            ::com::sun::star::uno::Reference< ::com::sun::star::uno::XWeak > _rxListener,
            ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > _rxBroadcaster
        );

        // nothing to do except an own ctor - the forwarding of the "disposing" is already done
        // in the base class

    protected:
        using OWeakEventListenerAdapter_Base::disposing;
        virtual void SAL_CALL disposing( );
    };

    //=====================================================================
    //= OWeakListenerAdapter
    //=====================================================================
    //---------------------------------------------------------------------
    template< class BROADCASTER, class LISTENER >
    OWeakListenerAdapter< BROADCASTER, LISTENER >::OWeakListenerAdapter(
        const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XWeak >& _rxListener,
        const ::com::sun::star::uno::Reference< BROADCASTER >& _rxBroadcaster
    )
        : ::cppu::WeakComponentImplHelper1< LISTENER >( m_aMutex )
        , OWeakListenerAdapterBase( _rxListener, _rxBroadcaster )
    {
    }

    //---------------------------------------------------------------------
    template< class BROADCASTER, class LISTENER >
    void SAL_CALL OWeakListenerAdapter< BROADCASTER, LISTENER >::disposing( const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException)
    {
        ::com::sun::star::uno::Reference< LISTENER > xListener( getListener() );
        if ( xListener.is() )
            xListener->disposing( _rSource );
    }

//.........................................................................
}   // namespace comphelper
//.........................................................................

#endif// COMPHELPER_WEAKEVENTLISTENER_HXX

<|endoftext|>


<commit_before>#include "game.hpp"
#include "exception.hpp"

namespace Quoridor {

// order in which pawns are adding
// pawns rotates according to their indexes: 0 -> 1 -> 2 -> 3 -> 0 -> ...
static const std::vector<int> pawn_idx_list = {0, 2, 1, 3};

Game::Game(int board_size) : board_size_(board_size), pawn_data_list_(),
    cur_pawn_idx_(-1), bg_(board_size_, board_size_), wg_(board_size_ + 1)
{
}

Game::~Game()
{
}

void Game::set_pawns(std::vector<std::shared_ptr<Pawn>> &pawn_list)
{
    size_t pawn_num = pawn_list.size();
    if ((pawn_num != 2) && (pawn_num != 4)) {
        throw Exception("Invalid number of players: " + std::to_string(pawn_num));
    }

    for (size_t i = 0; i < pawn_list.size(); ++i) {
        pawn_data_t pawn_data;
        pawn_data.pawn = pawn_list[i];

        pawn_data.idx = pawn_idx_list[i];
        switch (pawn_data.idx) {
        case 0:
            pawn_data.node.set_row(0);
            pawn_data.node.set_col(board_size_ / 2);
            bg_.block_node(pawn_data.node);
            for (int j = 0; j < board_size_; ++j) {
                Node gn(board_size_ - 1, j);
                pawn_data.goal_nodes.insert(gn);
            }
            break;
        case 1:
            pawn_data.node.set_row(board_size_ / 2);
            pawn_data.node.set_col(0);
            bg_.block_node(pawn_data.node);
            for (int j = 0; j < board_size_; ++j) {
                Node gn(j, board_size_ - 1);
                pawn_data.goal_nodes.insert(gn);
            }
            break;
        case 2:
            pawn_data.node.set_row(board_size_ - 1);
            pawn_data.node.set_col(board_size_ / 2);
            bg_.block_node(pawn_data.node);
            for (int j = 0; j < board_size_; ++j) {
                Node gn(0, j);
                pawn_data.goal_nodes.insert(gn);
            }
            break;
        case 3:
            pawn_data.node.set_row(board_size_ / 2);
            pawn_data.node.set_col(board_size_ - 1);
            bg_.block_node(pawn_data.node);
            for (int j = 0; j < board_size_; ++j) {
                Node gn(j, 0);
                pawn_data.goal_nodes.insert(gn);
            }
            break;
        }

        pawn_data_list_.insert(pawn_data);
    }
}

void Game::switch_pawn()
{
    auto it = pawn_data_list_.upper_bound(cur_pawn_idx_);
    if (it == pawn_data_list_.end()) {
        it = pawn_data_list_.begin();
    }
    cur_pawn_idx_ = it->idx;
}

const pawn_data_t &Game::cur_pawn_data() const
{
    return *pawn_data_list_.find(cur_pawn_idx_);
}

const pawn_data_list_t &Game::pawn_data_list() const
{
    return pawn_data_list_;
}

const pawn_data_t &Game::pawn_data(const std::shared_ptr<Pawn> &pawn) const
{
    return *pawn_data_list_.get<by_pawn>().find(pawn);
}

int Game::move_pawn(const Node &node)
{
    const Node &cur_node = pawn_data_list_.find(cur_pawn_idx_)->node;

    if (bg_.is_adjacent(cur_node, node)) {
        bg_.unblock_node(cur_node);
        pawn_data_list_t::iterator it = pawn_data_list_.find(cur_pawn_idx_);
        pawn_data_list_.modify(it, [=](pawn_data_t &e){ e.node = node; });
        bg_.block_node(node);
        return 0;
    }
    else {
        return -1;
    }
}

int Game::add_wall(const Wall &wall)
{
    std::vector<std::pair<Node, Node>> edges;

    if (try_add_wall(wall, &edges) < 0) {
        return -1;
    }

    wg_.apply_tmp_wall();
    for (auto edge : edges) {
        bg_.remove_edges(edge.first, edge.second);
    }

    return 0;
}

bool Game::is_finished() const
{
    Node cur_node = pawn_data_list_.find(cur_pawn_idx_)->node;
    if (pawn_data_list_.find(cur_pawn_idx_)->goal_nodes.count(cur_node) != 0) {
        return true;
    }
    return false;
}

size_t Game::shortest_path(const Node &start_node,
        const std::set<Node> &goal_nodes, std::list<Node> *path) const
{
    return bg_.shortest_path(start_node, goal_nodes, path);
}

bool Game::get_path(std::shared_ptr<Pawn> pawn, const Node &node,
        std::list<Node> *path) const
{
    return bg_.find_path(pawn_data(pawn).node, node, path);
}

void Game::possible_moves(std::shared_ptr<Pawn> pawn,
        std::vector<IMove*> *moves) const
{
    std::vector<Node> nodes;
    bg_.get_out_node_list(pawn_data_list_.get<by_pawn>().find(pawn)->node, &nodes);
    for (auto node : nodes) {
        moves->push_back(new WalkMove(node));
    }

    std::vector<Wall> walls;
    wg_.possible_walls(&walls);
    for (auto wall : walls) {
        moves->push_back(new WallMove(wall));
    }
}

int Game::try_add_wall(const Wall &wall,
        std::vector<std::pair<Node, Node>> *edges)
{
    if (wg_.add_tmp_wall(wall) < 0) {
        return -1;
    }

    std::vector<std::pair<Node, Node>> edge_list;

    Node node1;
    Node node2;
    Node node_tmp;
    if (wall.orientation() == Wall::kHorizontal) {
        for (int i = 0; i < wall.cnt(); ++i) {
            node1 = Node(wall.row() - 1, wall.col() + i);
            node2 = Node(wall.row(), wall.col() + i);
            edge_list.push_back(std::make_pair(node1, node2));
            edges->push_back(std::make_pair(node1, node2));

            node_tmp = Node(wall.row() + 1, wall.col() + i);
            if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                    && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                edge_list.push_back(std::make_pair(node1, node_tmp));
                edges->push_back(std::make_pair(node1, node_tmp));
            }

            node_tmp = Node(wall.row() - 2, wall.col() + i);
            if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                    && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                edge_list.push_back(std::make_pair(node_tmp, node2));
                edges->push_back(std::make_pair(node_tmp, node2));
            }

            for (int j = i - 1; j <= i + 1; j += 2) {
                node_tmp = Node(wall.row(), wall.col() + j);
                if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                        && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                    edge_list.push_back(std::make_pair(node1, node_tmp));
                    edges->push_back(std::make_pair(node1, node_tmp));
                }

                node_tmp = Node(wall.row() - 1, wall.col() + j);
                if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                        && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                    edge_list.push_back(std::make_pair(node_tmp, node2));
                    edges->push_back(std::make_pair(node_tmp, node2));
                }
            }
        }
    }
    else if (wall.orientation() == Wall::kVertical) {
        for (int i = 0; i < wall.cnt(); ++i) {
            node1 = Node(wall.row() + i, wall.col() - 1);
            node2 = Node(wall.row() + i, wall.col());
            edge_list.push_back(std::make_pair(node1, node2));
            edges->push_back(std::make_pair(node1, node2));

            node_tmp = Node(wall.row() + i, wall.col() + 1);
            if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                    && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                edge_list.push_back(std::make_pair(node1, node_tmp));
                edges->push_back(std::make_pair(node1, node_tmp));
            }

            node_tmp = Node(wall.row() + i, wall.col() - 2);
            if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                    && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                edge_list.push_back(std::make_pair(node_tmp, node2));
                edges->push_back(std::make_pair(node_tmp, node2));
            }

            for (int j = i - 1; j <= i + 1; j += 2) {
                node_tmp = Node(wall.row() + j, wall.col());
                if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                        && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                    edge_list.push_back(std::make_pair(node1, node_tmp));
                    edges->push_back(std::make_pair(node1, node_tmp));
                }

                node_tmp = Node(wall.row() + j, wall.col() - 1);
                if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                        && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                    edge_list.push_back(std::make_pair(node_tmp, node2));
                    edges->push_back(std::make_pair(node_tmp, node2));
                }
            }
        }
    }
    else {
        return -1;
    }

    bool path_blocked = false;

    for (auto pawn_data : pawn_data_list_) {
        path_blocked = true;
        for (auto goal_node : pawn_data.goal_nodes) {
            if (bg_.is_path_exists(pawn_data.node, goal_node, edge_list)) {
                path_blocked = false;
                break;
            }
        }

        // wall blocks all pathes to the opposite side for one of pawns
        if (path_blocked) {
            break;
        }
    }

    if (path_blocked) {
        return -1;
    }

    return 0;
}

}  // namespace Quoridor
<commit_msg>Sort possible moves by path length<commit_after>#include "game.hpp"
#include "exception.hpp"

namespace Quoridor {

// order in which pawns are adding
// pawns rotates according to their indexes: 0 -> 1 -> 2 -> 3 -> 0 -> ...
static const std::vector<int> pawn_idx_list = {0, 2, 1, 3};

Game::Game(int board_size) : board_size_(board_size), pawn_data_list_(),
    cur_pawn_idx_(-1), bg_(board_size_, board_size_), wg_(board_size_ + 1)
{
}

Game::~Game()
{
}

void Game::set_pawns(std::vector<std::shared_ptr<Pawn>> &pawn_list)
{
    size_t pawn_num = pawn_list.size();
    if ((pawn_num != 2) && (pawn_num != 4)) {
        throw Exception("Invalid number of players: " + std::to_string(pawn_num));
    }

    for (size_t i = 0; i < pawn_list.size(); ++i) {
        pawn_data_t pawn_data;
        pawn_data.pawn = pawn_list[i];

        pawn_data.idx = pawn_idx_list[i];
        switch (pawn_data.idx) {
        case 0:
            pawn_data.node.set_row(0);
            pawn_data.node.set_col(board_size_ / 2);
            bg_.block_node(pawn_data.node);
            for (int j = 0; j < board_size_; ++j) {
                Node gn(board_size_ - 1, j);
                pawn_data.goal_nodes.insert(gn);
            }
            break;
        case 1:
            pawn_data.node.set_row(board_size_ / 2);
            pawn_data.node.set_col(0);
            bg_.block_node(pawn_data.node);
            for (int j = 0; j < board_size_; ++j) {
                Node gn(j, board_size_ - 1);
                pawn_data.goal_nodes.insert(gn);
            }
            break;
        case 2:
            pawn_data.node.set_row(board_size_ - 1);
            pawn_data.node.set_col(board_size_ / 2);
            bg_.block_node(pawn_data.node);
            for (int j = 0; j < board_size_; ++j) {
                Node gn(0, j);
                pawn_data.goal_nodes.insert(gn);
            }
            break;
        case 3:
            pawn_data.node.set_row(board_size_ / 2);
            pawn_data.node.set_col(board_size_ - 1);
            bg_.block_node(pawn_data.node);
            for (int j = 0; j < board_size_; ++j) {
                Node gn(j, 0);
                pawn_data.goal_nodes.insert(gn);
            }
            break;
        }

        pawn_data_list_.insert(pawn_data);
    }
}

void Game::switch_pawn()
{
    auto it = pawn_data_list_.upper_bound(cur_pawn_idx_);
    if (it == pawn_data_list_.end()) {
        it = pawn_data_list_.begin();
    }
    cur_pawn_idx_ = it->idx;
}

const pawn_data_t &Game::cur_pawn_data() const
{
    return *pawn_data_list_.find(cur_pawn_idx_);
}

const pawn_data_list_t &Game::pawn_data_list() const
{
    return pawn_data_list_;
}

const pawn_data_t &Game::pawn_data(const std::shared_ptr<Pawn> &pawn) const
{
    return *pawn_data_list_.get<by_pawn>().find(pawn);
}

int Game::move_pawn(const Node &node)
{
    const Node &cur_node = pawn_data_list_.find(cur_pawn_idx_)->node;

    if (bg_.is_adjacent(cur_node, node)) {
        bg_.unblock_node(cur_node);
        pawn_data_list_t::iterator it = pawn_data_list_.find(cur_pawn_idx_);
        pawn_data_list_.modify(it, [=](pawn_data_t &e){ e.node = node; });
        bg_.block_node(node);
        return 0;
    }
    else {
        return -1;
    }
}

int Game::add_wall(const Wall &wall)
{
    std::vector<std::pair<Node, Node>> edges;

    if (try_add_wall(wall, &edges) < 0) {
        return -1;
    }

    wg_.apply_tmp_wall();
    for (auto edge : edges) {
        bg_.remove_edges(edge.first, edge.second);
    }

    return 0;
}

bool Game::is_finished() const
{
    Node cur_node = pawn_data_list_.find(cur_pawn_idx_)->node;
    if (pawn_data_list_.find(cur_pawn_idx_)->goal_nodes.count(cur_node) != 0) {
        return true;
    }
    return false;
}

size_t Game::shortest_path(const Node &start_node,
        const std::set<Node> &goal_nodes, std::list<Node> *path) const
{
    return bg_.shortest_path(start_node, goal_nodes, path);
}

bool Game::get_path(std::shared_ptr<Pawn> pawn, const Node &node,
        std::list<Node> *path) const
{
    return bg_.find_path(pawn_data(pawn).node, node, path);
}

void Game::possible_moves(std::shared_ptr<Pawn> pawn,
        std::vector<IMove*> *moves) const
{
    const pawn_data_t &pawn_data = *pawn_data_list_.get<by_pawn>().find(pawn);
    std::vector<Node> nodes;
    bg_.get_out_node_list(pawn_data.node, &nodes);
    std::vector<std::pair<Node, size_t>> node_pathes;
    for (auto node : nodes) {
        node_pathes.push_back(std::make_pair(node, shortest_path(node, pawn_data.goal_nodes, NULL)));
    }

    std::sort(node_pathes.begin(), node_pathes.end(),
            [](std::pair<Node, size_t> a, std::pair<Node, size_t> b) {
                return a.second < b.second;
            }
    );

    for (auto p : node_pathes) {
        moves->push_back(new WalkMove(p.first));
    }

    std::vector<Wall> walls;
    wg_.possible_walls(&walls);
    for (auto wall : walls) {
        moves->push_back(new WallMove(wall));
    }
}

int Game::try_add_wall(const Wall &wall,
        std::vector<std::pair<Node, Node>> *edges)
{
    if (wg_.add_tmp_wall(wall) < 0) {
        return -1;
    }

    std::vector<std::pair<Node, Node>> edge_list;

    Node node1;
    Node node2;
    Node node_tmp;
    if (wall.orientation() == Wall::kHorizontal) {
        for (int i = 0; i < wall.cnt(); ++i) {
            node1 = Node(wall.row() - 1, wall.col() + i);
            node2 = Node(wall.row(), wall.col() + i);
            edge_list.push_back(std::make_pair(node1, node2));
            edges->push_back(std::make_pair(node1, node2));

            node_tmp = Node(wall.row() + 1, wall.col() + i);
            if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                    && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                edge_list.push_back(std::make_pair(node1, node_tmp));
                edges->push_back(std::make_pair(node1, node_tmp));
            }

            node_tmp = Node(wall.row() - 2, wall.col() + i);
            if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                    && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                edge_list.push_back(std::make_pair(node_tmp, node2));
                edges->push_back(std::make_pair(node_tmp, node2));
            }

            for (int j = i - 1; j <= i + 1; j += 2) {
                node_tmp = Node(wall.row(), wall.col() + j);
                if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                        && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                    edge_list.push_back(std::make_pair(node1, node_tmp));
                    edges->push_back(std::make_pair(node1, node_tmp));
                }

                node_tmp = Node(wall.row() - 1, wall.col() + j);
                if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                        && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                    edge_list.push_back(std::make_pair(node_tmp, node2));
                    edges->push_back(std::make_pair(node_tmp, node2));
                }
            }
        }
    }
    else if (wall.orientation() == Wall::kVertical) {
        for (int i = 0; i < wall.cnt(); ++i) {
            node1 = Node(wall.row() + i, wall.col() - 1);
            node2 = Node(wall.row() + i, wall.col());
            edge_list.push_back(std::make_pair(node1, node2));
            edges->push_back(std::make_pair(node1, node2));

            node_tmp = Node(wall.row() + i, wall.col() + 1);
            if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                    && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                edge_list.push_back(std::make_pair(node1, node_tmp));
                edges->push_back(std::make_pair(node1, node_tmp));
            }

            node_tmp = Node(wall.row() + i, wall.col() - 2);
            if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                    && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                edge_list.push_back(std::make_pair(node_tmp, node2));
                edges->push_back(std::make_pair(node_tmp, node2));
            }

            for (int j = i - 1; j <= i + 1; j += 2) {
                node_tmp = Node(wall.row() + j, wall.col());
                if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                        && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                    edge_list.push_back(std::make_pair(node1, node_tmp));
                    edges->push_back(std::make_pair(node1, node_tmp));
                }

                node_tmp = Node(wall.row() + j, wall.col() - 1);
                if ((node_tmp.row() >= 0) && (node_tmp.row() < board_size_)
                        && (node_tmp.col() >= 0) && (node_tmp.col() < board_size_)) {
                    edge_list.push_back(std::make_pair(node_tmp, node2));
                    edges->push_back(std::make_pair(node_tmp, node2));
                }
            }
        }
    }
    else {
        return -1;
    }

    bool path_blocked = false;

    for (auto pawn_data : pawn_data_list_) {
        path_blocked = true;
        for (auto goal_node : pawn_data.goal_nodes) {
            if (bg_.is_path_exists(pawn_data.node, goal_node, edge_list)) {
                path_blocked = false;
                break;
            }
        }

        // wall blocks all pathes to the opposite side for one of pawns
        if (path_blocked) {
            break;
        }
    }

    if (path_blocked) {
        return -1;
    }

    return 0;
}

}  // namespace Quoridor
<|endoftext|>


<commit_before>// Copyright 2014 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 "components/nacl/loader/nonsfi/nonsfi_sandbox.h"

#include <errno.h>
#include <fcntl.h>
#include <linux/net.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/time.h>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/public/common/sandbox_init.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/system_headers/linux_futex.h"
#include "sandbox/linux/system_headers/linux_signal.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"

// Chrome OS Daisy (ARM) build environment and PNaCl toolchain do not define
// MAP_STACK.
#if !defined(MAP_STACK)
# if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY)
#  define MAP_STACK 0x20000
# else
// Note that, on other architecture, MAP_STACK has different value (e.g. mips'
// MAP_STACK is 0x40000), though Non-SFI is not supported on such
// architectures.
#  error "Unknown platform."
# endif
#endif  // !defined(MAP_STACK)

#define CASES SANDBOX_BPF_DSL_CASES

using sandbox::CrashSIGSYS;
using sandbox::CrashSIGSYSClone;
using sandbox::CrashSIGSYSFutex;
using sandbox::CrashSIGSYSPrctl;
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::Arg;
using sandbox::bpf_dsl::BoolExpr;
using sandbox::bpf_dsl::Error;
using sandbox::bpf_dsl::If;
using sandbox::bpf_dsl::ResultExpr;

namespace nacl {
namespace nonsfi {
namespace {

ResultExpr RestrictFcntlCommands() {
  const Arg<int> cmd(1);
  const Arg<long> long_arg(2);

  // We allow following cases:
  // 1. F_SETFD + FD_CLOEXEC: libevent's epoll_init uses this.
  // 2. F_GETFL: Used by SetNonBlocking in
  // message_pump_libevent.cc and Channel::ChannelImpl::CreatePipe
  // in ipc_channel_posix.cc. Note that the latter does not work
  // with EPERM.
  // 3. F_SETFL: Used by evutil_make_socket_nonblocking in
  // libevent and SetNonBlocking. As the latter mix O_NONBLOCK to
  // the return value of F_GETFL, so we need to allow O_ACCMODE in
  // addition to O_NONBLOCK.
  const uint64_t kAllowedMask = O_ACCMODE | O_NONBLOCK;
  return If((cmd == F_SETFD && long_arg == FD_CLOEXEC) || cmd == F_GETFL ||
                (cmd == F_SETFL && (long_arg & ~kAllowedMask) == 0),
            Allow()).Else(CrashSIGSYS());
}

ResultExpr RestrictClone() {
  // We allow clone only for new thread creation.
  int clone_flags =
      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
      CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS;
#if !defined(OS_NACL_NONSFI)
  clone_flags |= CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
#endif
  const Arg<int> flags(0);
  // TODO(lhchavez): Add CLONE_PARENT_SETTID unconditionally to the allowed
  // flags after the NaCl roll.
  return If(flags == clone_flags ||
                flags == (clone_flags | CLONE_PARENT_SETTID),
            Allow()).Else(CrashSIGSYSClone());
}

ResultExpr RestrictFutexOperation() {
  // TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG futexes.
  const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME;
  const Arg<int> op(1);
  return Switch(op & ~kAllowedFutexFlags)
      .CASES((FUTEX_WAIT,
              FUTEX_WAKE,
              FUTEX_REQUEUE,
              FUTEX_CMP_REQUEUE,
              FUTEX_WAKE_OP,
              FUTEX_WAIT_BITSET,
              FUTEX_WAKE_BITSET),
             Allow())
      .Default(CrashSIGSYSFutex());
}

ResultExpr RestrictPrctl() {
  // base::PlatformThread::SetName() uses PR_SET_NAME so we return
  // EPERM for it. Otherwise, we will raise SIGSYS.
  const Arg<int> option(0);
  return If(option == PR_SET_NAME, Error(EPERM)).Else(CrashSIGSYSPrctl());
}

#if defined(__i386__)
ResultExpr RestrictSocketcall() {
  // We only allow socketpair, sendmsg, and recvmsg.
  const Arg<int> call(0);
  return If(
#if !defined(OS_NACL_NONSFI)
      // nacl_helper in Non-SFI mode still uses socketpair() internally
      // via libevent.
      // TODO(hidehiko): Remove this when the switching to nacl_helper_nonsfi
      // is completed.
      call == SYS_SOCKETPAIR ||
#endif
      call == SYS_SHUTDOWN || call == SYS_SENDMSG || call == SYS_RECVMSG,
      Allow()).Else(CrashSIGSYS());
}
#endif

ResultExpr RestrictMprotect() {
  // TODO(jln, keescook, drewry): Limit the use of mprotect by adding
  // some features to linux kernel.
  const uint64_t kAllowedMask = PROT_READ | PROT_WRITE | PROT_EXEC;
  const Arg<int> prot(2);
  return If((prot & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS());
}

ResultExpr RestrictMmap() {
  const uint64_t kAllowedFlagMask =
      MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_FIXED;
  // When PROT_EXEC is specified, IRT mmap of Non-SFI NaCl helper
  // calls mmap without PROT_EXEC and then adds PROT_EXEC by mprotect,
  // so we do not need to allow PROT_EXEC in mmap.
  const uint64_t kAllowedProtMask = PROT_READ | PROT_WRITE;
  const Arg<int> prot(2), flags(3);
  return If((prot & ~kAllowedProtMask) == 0 && (flags & ~kAllowedFlagMask) == 0,
            Allow()).Else(CrashSIGSYS());
}

ResultExpr RestrictTgkill(int policy_pid) {
  const Arg<int> tgid(0), tid(1), signum(2);
  // Only sending SIGUSR1 to a thread in the same process is allowed.
  return If(tgid == policy_pid &&
            // Arg does not support a greater-than operator, so two separate
            // checks are needed to ensure tid is positive.
            tid != 0 &&
            (tid & (1u << 31)) == 0 &&  // tid is non-negative.
            signum == LINUX_SIGUSR1,
            Allow()).Else(CrashSIGSYS());
}

#if !defined(OS_NACL_NONSFI) && (defined(__x86_64__) || defined(__arm__))
ResultExpr RestrictSocketpair() {
  // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
  static_assert(AF_UNIX == PF_UNIX, "AF_UNIX must equal PF_UNIX.");
  const Arg<int> domain(0);
  return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS());
}
#endif

bool IsGracefullyDenied(int sysno) {
  switch (sysno) {
    // libevent tries this first and then falls back to poll if
    // epoll_create fails.
    case __NR_epoll_create:
    // third_party/libevent uses them, but we can just return -1 from
    // them as it is just checking getuid() != geteuid() and
    // getgid() != getegid()
#if defined(__i386__) || defined(__arm__)
    case __NR_getegid32:
    case __NR_geteuid32:
    case __NR_getgid32:
    case __NR_getuid32:
#endif
    case __NR_getegid:
    case __NR_geteuid:
    case __NR_getgid:
    case __NR_getuid:
    // tcmalloc calls madvise in TCMalloc_SystemRelease.
    case __NR_madvise:
    // EPERM instead of SIGSYS as glibc tries to open files in /proc.
    // openat via opendir via get_nprocs_conf and open via get_nprocs.
    // TODO(hamaji): Remove this when we switch to newlib.
    case __NR_open:
    case __NR_openat:
    // For RunSandboxSanityChecks().
    case __NR_ptrace:
    // glibc uses this for its pthread implementation. If we return
    // EPERM for this, glibc will stop using this.
    // TODO(hamaji): newlib does not use this. Make this SIGTRAP once
    // we have switched to newlib.
    case __NR_set_robust_list:
    // This is obsolete in ARM EABI, but x86 glibc indirectly calls
    // this in sysconf.
#if defined(__i386__) || defined(__x86_64__)
    case __NR_time:
#endif
      return true;

    default:
      return false;
  }
}

void RunSandboxSanityChecks() {
  errno = 0;
  // Make a ptrace request with an invalid PID.
  long ptrace_ret = syscall(
      __NR_ptrace, 3 /* = PTRACE_PEEKUSER */, -1 /* pid */, NULL, NULL);
  CHECK_EQ(-1, ptrace_ret);
  // Without the sandbox on, this ptrace call would ESRCH instead.
  CHECK_EQ(EPERM, errno);
}

}  // namespace

NaClNonSfiBPFSandboxPolicy::NaClNonSfiBPFSandboxPolicy()
    : policy_pid_(getpid()) {
}

NaClNonSfiBPFSandboxPolicy::~NaClNonSfiBPFSandboxPolicy() {
  // Make sure that this policy is created, used and destroyed by a single
  // process.
  DCHECK_EQ(getpid(), policy_pid_);
}

ResultExpr NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(int sysno) const {
  switch (sysno) {
    // Allowed syscalls.
#if defined(__i386__) || defined(__arm__)
    case __NR__llseek:
#elif defined(__x86_64__)
    case __NR_lseek:
#endif
    case __NR_close:
    case __NR_dup:
    case __NR_dup2:
    case __NR_exit:
    case __NR_exit_group:
#if defined(__i386__) || defined(__arm__)
    case __NR_fstat64:
#elif defined(__x86_64__)
    case __NR_fstat:
#endif
    // TODO(hamaji): Remove the need of gettid. Currently, this is
    // called from PlatformThread::CurrentId().
    case __NR_gettid:
    case __NR_gettimeofday:
    case __NR_munmap:
    case __NR_nanosleep:
    // TODO(hamaji): Remove the need of pipe. Currently, this is
    // called from base::MessagePumpLibevent::Init().
    case __NR_pipe:
    case __NR_poll:
    case __NR_pread64:
    case __NR_pwrite64:
    case __NR_read:
    case __NR_restart_syscall:
    case __NR_sched_yield:
    // __NR_times needed as clock() is called by CommandBufferHelper, which is
    // used by NaCl applications that use Pepper's 3D interfaces.
    // See crbug.com/264856 for details.
    case __NR_times:
    case __NR_write:
#if defined(__arm__)
    case __ARM_NR_cacheflush:
#endif
      return Allow();

    case __NR_clock_getres:
    case __NR_clock_gettime:
      return sandbox::RestrictClockID();

    case __NR_clone:
      return RestrictClone();

#if defined(__x86_64__)
    case __NR_fcntl:
#endif
#if defined(__i386__) || defined(__arm__)
    case __NR_fcntl64:
#endif
      return RestrictFcntlCommands();

    case __NR_futex:
      return RestrictFutexOperation();

#if defined(__x86_64__)
    case __NR_mmap:
#endif
#if defined(__i386__) || defined(__arm__)
    case __NR_mmap2:
#endif
      return RestrictMmap();
    case __NR_mprotect:
      return RestrictMprotect();

    case __NR_prctl:
      return RestrictPrctl();

#if defined(__i386__)
    case __NR_socketcall:
      return RestrictSocketcall();
#endif
#if defined(__x86_64__) || defined(__arm__)
    case __NR_recvmsg:
    case __NR_sendmsg:
    case __NR_shutdown:
      return Allow();
#if !defined(OS_NACL_NONSFI)
    // nacl_helper in Non-SFI mode still uses socketpair() internally
    // via libevent.
    // TODO(hidehiko): Remove this when the switching to nacl_helper_nonsfi
    // is completed.
    case __NR_socketpair:
      return RestrictSocketpair();
#endif
#endif

    case __NR_tgkill:
      return RestrictTgkill(policy_pid_);

    case __NR_brk:
      // The behavior of brk on Linux is different from other system
      // calls. It does not return errno but the current break on
      // failure. glibc thinks brk failed if the return value of brk
      // is less than the requested address (i.e., brk(addr) < addr).
      // So, glibc thinks brk succeeded if we return -EPERM and we
      // need to return zero instead.
      return Error(0);

    default:
      if (IsGracefullyDenied(sysno))
        return Error(EPERM);
      return CrashSIGSYS();
  }
}

ResultExpr NaClNonSfiBPFSandboxPolicy::InvalidSyscall() const {
  return CrashSIGSYS();
}

bool InitializeBPFSandbox(base::ScopedFD proc_fd) {
  bool sandbox_is_initialized = content::InitializeSandbox(
      scoped_ptr<sandbox::bpf_dsl::Policy>(
          new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy()),
      proc_fd.Pass());
  if (!sandbox_is_initialized)
    return false;
  RunSandboxSanityChecks();
  return true;
}

}  // namespace nonsfi
}  // namespace nacl
<commit_msg>Non-SFI mode: Cleanup clone() flags after NaCl roll<commit_after>// Copyright 2014 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 "components/nacl/loader/nonsfi/nonsfi_sandbox.h"

#include <errno.h>
#include <fcntl.h>
#include <linux/net.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/time.h>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/public/common/sandbox_init.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/system_headers/linux_futex.h"
#include "sandbox/linux/system_headers/linux_signal.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"

// Chrome OS Daisy (ARM) build environment and PNaCl toolchain do not define
// MAP_STACK.
#if !defined(MAP_STACK)
# if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY)
#  define MAP_STACK 0x20000
# else
// Note that, on other architecture, MAP_STACK has different value (e.g. mips'
// MAP_STACK is 0x40000), though Non-SFI is not supported on such
// architectures.
#  error "Unknown platform."
# endif
#endif  // !defined(MAP_STACK)

#define CASES SANDBOX_BPF_DSL_CASES

using sandbox::CrashSIGSYS;
using sandbox::CrashSIGSYSClone;
using sandbox::CrashSIGSYSFutex;
using sandbox::CrashSIGSYSPrctl;
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::Arg;
using sandbox::bpf_dsl::BoolExpr;
using sandbox::bpf_dsl::Error;
using sandbox::bpf_dsl::If;
using sandbox::bpf_dsl::ResultExpr;

namespace nacl {
namespace nonsfi {
namespace {

ResultExpr RestrictFcntlCommands() {
  const Arg<int> cmd(1);
  const Arg<long> long_arg(2);

  // We allow following cases:
  // 1. F_SETFD + FD_CLOEXEC: libevent's epoll_init uses this.
  // 2. F_GETFL: Used by SetNonBlocking in
  // message_pump_libevent.cc and Channel::ChannelImpl::CreatePipe
  // in ipc_channel_posix.cc. Note that the latter does not work
  // with EPERM.
  // 3. F_SETFL: Used by evutil_make_socket_nonblocking in
  // libevent and SetNonBlocking. As the latter mix O_NONBLOCK to
  // the return value of F_GETFL, so we need to allow O_ACCMODE in
  // addition to O_NONBLOCK.
  const uint64_t kAllowedMask = O_ACCMODE | O_NONBLOCK;
  return If((cmd == F_SETFD && long_arg == FD_CLOEXEC) || cmd == F_GETFL ||
                (cmd == F_SETFL && (long_arg & ~kAllowedMask) == 0),
            Allow()).Else(CrashSIGSYS());
}

ResultExpr RestrictClone() {
  // We allow clone only for new thread creation.
  int clone_flags =
      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
      CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID;
#if !defined(OS_NACL_NONSFI)
  clone_flags |= CLONE_CHILD_CLEARTID;
#endif
  const Arg<int> flags(0);
  return If(flags == clone_flags, Allow()).Else(CrashSIGSYSClone());
}

ResultExpr RestrictFutexOperation() {
  // TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG futexes.
  const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME;
  const Arg<int> op(1);
  return Switch(op & ~kAllowedFutexFlags)
      .CASES((FUTEX_WAIT,
              FUTEX_WAKE,
              FUTEX_REQUEUE,
              FUTEX_CMP_REQUEUE,
              FUTEX_WAKE_OP,
              FUTEX_WAIT_BITSET,
              FUTEX_WAKE_BITSET),
             Allow())
      .Default(CrashSIGSYSFutex());
}

ResultExpr RestrictPrctl() {
  // base::PlatformThread::SetName() uses PR_SET_NAME so we return
  // EPERM for it. Otherwise, we will raise SIGSYS.
  const Arg<int> option(0);
  return If(option == PR_SET_NAME, Error(EPERM)).Else(CrashSIGSYSPrctl());
}

#if defined(__i386__)
ResultExpr RestrictSocketcall() {
  // We only allow socketpair, sendmsg, and recvmsg.
  const Arg<int> call(0);
  return If(
#if !defined(OS_NACL_NONSFI)
      // nacl_helper in Non-SFI mode still uses socketpair() internally
      // via libevent.
      // TODO(hidehiko): Remove this when the switching to nacl_helper_nonsfi
      // is completed.
      call == SYS_SOCKETPAIR ||
#endif
      call == SYS_SHUTDOWN || call == SYS_SENDMSG || call == SYS_RECVMSG,
      Allow()).Else(CrashSIGSYS());
}
#endif

ResultExpr RestrictMprotect() {
  // TODO(jln, keescook, drewry): Limit the use of mprotect by adding
  // some features to linux kernel.
  const uint64_t kAllowedMask = PROT_READ | PROT_WRITE | PROT_EXEC;
  const Arg<int> prot(2);
  return If((prot & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS());
}

ResultExpr RestrictMmap() {
  const uint64_t kAllowedFlagMask =
      MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_FIXED;
  // When PROT_EXEC is specified, IRT mmap of Non-SFI NaCl helper
  // calls mmap without PROT_EXEC and then adds PROT_EXEC by mprotect,
  // so we do not need to allow PROT_EXEC in mmap.
  const uint64_t kAllowedProtMask = PROT_READ | PROT_WRITE;
  const Arg<int> prot(2), flags(3);
  return If((prot & ~kAllowedProtMask) == 0 && (flags & ~kAllowedFlagMask) == 0,
            Allow()).Else(CrashSIGSYS());
}

ResultExpr RestrictTgkill(int policy_pid) {
  const Arg<int> tgid(0), tid(1), signum(2);
  // Only sending SIGUSR1 to a thread in the same process is allowed.
  return If(tgid == policy_pid &&
            // Arg does not support a greater-than operator, so two separate
            // checks are needed to ensure tid is positive.
            tid != 0 &&
            (tid & (1u << 31)) == 0 &&  // tid is non-negative.
            signum == LINUX_SIGUSR1,
            Allow()).Else(CrashSIGSYS());
}

#if !defined(OS_NACL_NONSFI) && (defined(__x86_64__) || defined(__arm__))
ResultExpr RestrictSocketpair() {
  // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
  static_assert(AF_UNIX == PF_UNIX, "AF_UNIX must equal PF_UNIX.");
  const Arg<int> domain(0);
  return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS());
}
#endif

bool IsGracefullyDenied(int sysno) {
  switch (sysno) {
    // libevent tries this first and then falls back to poll if
    // epoll_create fails.
    case __NR_epoll_create:
    // third_party/libevent uses them, but we can just return -1 from
    // them as it is just checking getuid() != geteuid() and
    // getgid() != getegid()
#if defined(__i386__) || defined(__arm__)
    case __NR_getegid32:
    case __NR_geteuid32:
    case __NR_getgid32:
    case __NR_getuid32:
#endif
    case __NR_getegid:
    case __NR_geteuid:
    case __NR_getgid:
    case __NR_getuid:
    // tcmalloc calls madvise in TCMalloc_SystemRelease.
    case __NR_madvise:
    // EPERM instead of SIGSYS as glibc tries to open files in /proc.
    // openat via opendir via get_nprocs_conf and open via get_nprocs.
    // TODO(hamaji): Remove this when we switch to newlib.
    case __NR_open:
    case __NR_openat:
    // For RunSandboxSanityChecks().
    case __NR_ptrace:
    // glibc uses this for its pthread implementation. If we return
    // EPERM for this, glibc will stop using this.
    // TODO(hamaji): newlib does not use this. Make this SIGTRAP once
    // we have switched to newlib.
    case __NR_set_robust_list:
    // This is obsolete in ARM EABI, but x86 glibc indirectly calls
    // this in sysconf.
#if defined(__i386__) || defined(__x86_64__)
    case __NR_time:
#endif
      return true;

    default:
      return false;
  }
}

void RunSandboxSanityChecks() {
  errno = 0;
  // Make a ptrace request with an invalid PID.
  long ptrace_ret = syscall(
      __NR_ptrace, 3 /* = PTRACE_PEEKUSER */, -1 /* pid */, NULL, NULL);
  CHECK_EQ(-1, ptrace_ret);
  // Without the sandbox on, this ptrace call would ESRCH instead.
  CHECK_EQ(EPERM, errno);
}

}  // namespace

NaClNonSfiBPFSandboxPolicy::NaClNonSfiBPFSandboxPolicy()
    : policy_pid_(getpid()) {
}

NaClNonSfiBPFSandboxPolicy::~NaClNonSfiBPFSandboxPolicy() {
  // Make sure that this policy is created, used and destroyed by a single
  // process.
  DCHECK_EQ(getpid(), policy_pid_);
}

ResultExpr NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(int sysno) const {
  switch (sysno) {
    // Allowed syscalls.
#if defined(__i386__) || defined(__arm__)
    case __NR__llseek:
#elif defined(__x86_64__)
    case __NR_lseek:
#endif
    case __NR_close:
    case __NR_dup:
    case __NR_dup2:
    case __NR_exit:
    case __NR_exit_group:
#if defined(__i386__) || defined(__arm__)
    case __NR_fstat64:
#elif defined(__x86_64__)
    case __NR_fstat:
#endif
    // TODO(hamaji): Remove the need of gettid. Currently, this is
    // called from PlatformThread::CurrentId().
    case __NR_gettid:
    case __NR_gettimeofday:
    case __NR_munmap:
    case __NR_nanosleep:
    // TODO(hamaji): Remove the need of pipe. Currently, this is
    // called from base::MessagePumpLibevent::Init().
    case __NR_pipe:
    case __NR_poll:
    case __NR_pread64:
    case __NR_pwrite64:
    case __NR_read:
    case __NR_restart_syscall:
    case __NR_sched_yield:
    // __NR_times needed as clock() is called by CommandBufferHelper, which is
    // used by NaCl applications that use Pepper's 3D interfaces.
    // See crbug.com/264856 for details.
    case __NR_times:
    case __NR_write:
#if defined(__arm__)
    case __ARM_NR_cacheflush:
#endif
      return Allow();

    case __NR_clock_getres:
    case __NR_clock_gettime:
      return sandbox::RestrictClockID();

    case __NR_clone:
      return RestrictClone();

#if defined(__x86_64__)
    case __NR_fcntl:
#endif
#if defined(__i386__) || defined(__arm__)
    case __NR_fcntl64:
#endif
      return RestrictFcntlCommands();

    case __NR_futex:
      return RestrictFutexOperation();

#if defined(__x86_64__)
    case __NR_mmap:
#endif
#if defined(__i386__) || defined(__arm__)
    case __NR_mmap2:
#endif
      return RestrictMmap();
    case __NR_mprotect:
      return RestrictMprotect();

    case __NR_prctl:
      return RestrictPrctl();

#if defined(__i386__)
    case __NR_socketcall:
      return RestrictSocketcall();
#endif
#if defined(__x86_64__) || defined(__arm__)
    case __NR_recvmsg:
    case __NR_sendmsg:
    case __NR_shutdown:
      return Allow();
#if !defined(OS_NACL_NONSFI)
    // nacl_helper in Non-SFI mode still uses socketpair() internally
    // via libevent.
    // TODO(hidehiko): Remove this when the switching to nacl_helper_nonsfi
    // is completed.
    case __NR_socketpair:
      return RestrictSocketpair();
#endif
#endif

    case __NR_tgkill:
      return RestrictTgkill(policy_pid_);

    case __NR_brk:
      // The behavior of brk on Linux is different from other system
      // calls. It does not return errno but the current break on
      // failure. glibc thinks brk failed if the return value of brk
      // is less than the requested address (i.e., brk(addr) < addr).
      // So, glibc thinks brk succeeded if we return -EPERM and we
      // need to return zero instead.
      return Error(0);

    default:
      if (IsGracefullyDenied(sysno))
        return Error(EPERM);
      return CrashSIGSYS();
  }
}

ResultExpr NaClNonSfiBPFSandboxPolicy::InvalidSyscall() const {
  return CrashSIGSYS();
}

bool InitializeBPFSandbox(base::ScopedFD proc_fd) {
  bool sandbox_is_initialized = content::InitializeSandbox(
      scoped_ptr<sandbox::bpf_dsl::Policy>(
          new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy()),
      proc_fd.Pass());
  if (!sandbox_is_initialized)
    return false;
  RunSandboxSanityChecks();
  return true;
}

}  // namespace nonsfi
}  // namespace nacl
<|endoftext|>