/******************************************************************************* * Copyright (c) 2007, Perforce Software, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE * SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *******************************************************************************/ #define NEED_GETUID #include "stdhdrs.h" #include "strbuf.h" #include "vararray.h" #include "strdict.h" #include "strtable.h" #include "error.h" #include "errorlog.h" #include "filesys.h" #include "p4dctlerr.h" #include "p4dctldebug.h" #include "parsesupp.h" #include "cmdline.h" #include "varlist.h" #include "server.h" #include "config.h" // // Our global config pointer // Config * parsed_config = 0; //------------------------------------------------------------------------------ // Config class implementation //------------------------------------------------------------------------------ int Config::DropPrivs( Error *e ) { uid_t uid = getuid(); if( !uid ) return 1; if( seteuid( uid ) < 0 ) e->Sys( "seteuid", "" ); return !e->Test(); } int Config::RestorePrivs( Error *e ) { if( seteuid( 0 ) < 0 ) e->Sys( "seteuid", "root" ); return !e->Test(); } Config::Config() { env = new VarList; } Config::~Config() { for( int i = 0; i < servers.Count(); i++ ) delete (Server *)servers.Get( i ); delete env; } void Config::Parse( const char *cfg_file, Error *e ) { yyin = fopen( cfg_file, "r" ); if( !yyin ) { e->Sys( "fopen", cfg_file ); return; } // // Ensure the results of the parse go into this object. // parsed_config = this; if( yyparse() ) { e->Set( CtlErr::ConfigParseError ) << cfg_file << lineno; return; } if( DEBUG_PARSE ) this->Dump(); parsed_config = 0; if( !ServerCount() ) { e->Set( CtlErr::NoServersConfigured ); return; } } // // Get servers by number Server * Config::GetServer( int i ) { if( i < servers.Count() ) return (Server *)servers.Get( i ); return 0; } // // Get server by name // Server * Config::GetServer( StrPtr &name ) { for( int i = 0; i < servers.Count(); i++ ) { Server *s = GetServer( i ); if( name == s->Name() ) return s; } return 0; } // // Add a server to the configuration // Server * Config::AddServer( const char *name, int type, VarList *env ) { Server *s = 0; switch( type ) { case SERVER_P4D: s = new P4D( name, env, this ); servers.Put( s ); break; case SERVER_P4P: s = new P4P( name, env, this ); servers.Put( s ); break; case SERVER_P4WEB: s = new P4Web( name, env, this ); servers.Put( s ); break; case SERVER_P4FTP: s = new P4Ftp( name, env, this ); servers.Put( s ); break; case SERVER_P4BROKER: s = new P4Broker( name, env, this ); servers.Put( s ); break; case SERVER_OTHER: s = new OtherServer( name, env, this ); servers.Put( s ); break; default: fprintf( stderr, "Warning: No support for servers of type %d\n", type); } return s; } int Config::ServerType( const char *t ) { if( !strcmp( "p4d", t ) ) return SERVER_P4D; if( !strcmp( "p4p", t ) ) return SERVER_P4P; if( !strcmp( "p4web", t ) ) return SERVER_P4WEB; if( !strcmp( "p4ftp", t ) ) return SERVER_P4FTP; if( !strcmp( "p4broker", t ) ) return SERVER_P4BROKER; if( !strcmp( "other", t ) ) return SERVER_OTHER; return SERVER_NONE; } void Config::SetGlobals( VarList *vars ) { env->Import( vars ); delete vars; } void Config::Dump() { Server *s; printf( "Globals\n-------\n\n" ); env->Dump(); printf( "Servers\n-------\n\n" ); for( int i = 0; i < servers.Count(); i++ ) { s = (Server *)servers.Get( i ); s->Dump(); printf( "\n" ); } } //------------------------------------------------------------------------------ // C/C++ shims for the parser //------------------------------------------------------------------------------ // // Returns a VarList // void * MakeVar( char *var, char *val ) { VarList *vl = new VarList; vl->SetVar( var, val ); free( var ); free( val ); return (void *) vl; } // // Add a variable to an existing list. Both inputs here are VarLists in // fact - merge the first into the second, delete the second and return // the first. // void * AddVar( void *listA, void *listB ) { VarList *a = (VarList *)listA; VarList *b = (VarList *)listB; a->Import( b ); delete b; return (void *)a; } // // Make a new Server object // void * MakeServer( char *name, char *type, void *env ) { Server *s = 0; int t = parsed_config->ServerType( type ); if( t == SERVER_NONE ) { StrBuf t; t << "Invalid server type: " << type; yyerror( t.Text() ); // This sucker exits... return 0; } s = parsed_config->AddServer( name, t, (VarList*)env ); free( name ); return (void *) s; } // // Add an environment list to the global configuration // void * AddEnviron( void *varList ) { parsed_config->SetGlobals( (VarList *)varList ); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 8069 | Mark Allender | Merged Tony Smith's changes. | ||
#1 | 7584 | Mark Allender | Initial checkin of p4dctl code in order to cleanly make other modifications (better support for compressed checkpoints, prefixes for checkpoints, etc) | ||
//guest/tony_smith/perforce/p4dctl/src/config.cpp | |||||
#4 | 7184 | Tony Smith |
Fix bug that prevented globally defined environment variables from being overridden by local definitions. The diffs here are a little large because the most sensible way to do this was to switch to using dictionaries for building the environment vars (to make replacing values easy), and then convert them to a VarArray later in a format that can be used as an environ pointer. |
||
#3 | 6285 | Tony Smith |
Add support for starting arbitrary daemons through this framework using configuration entries like this: other <name> { Execute = <binary> Owner = <username> [ Port = <listen port (if any)> ] [ Umask = <umask> ] PATH = "/usr/bin: etc. etc." } |
||
#2 | 6184 | Tony Smith | Some minor changes to debugging output | ||
#1 | 5945 | Tony Smith |
Release p4dctl, a program for starting/stopping Perforce services on Unix operating systems. Similar to, and developed in concert with, Sven Erik Knop's p4dcfg. For example: p4dctl start -a Can start multiple P4D, P4P, P4Web, or P4FTP servers in one easy command line. It can be executed by root, or by the 'owners' of the configured services and it maintains pidfiles no matter who uses it (so they remain accurate). An init script using p4dctl will typically just use: p4dctl start -a p4dctl stop -a p4dctl restart -a And check the exit status. |