// SECO.c : servei SIMPLE ECO. // // Crides a estudiar : // // StartServiceCtrlDispatcher ( ServiceTable ) ; Servicename ?? // RegisterServiceCtrlHandler ( 1-er param ?? // // v 1.1.005 Incorpora TOD en el mensaje de respuesta. // **************************************************************************** // #define PARLA 0 // calen funcions Win32 : #include // per escriure a disc. #include // to get MAC : #include // to get HOSTNAME and IP : #include // to get Time : #include // periode entre 2 queries : #define SLEEP_TIME 5000 // path to log file : #ifdef PARLA #define LOGFILE "C:\\SECO.txt" #endif #define LISTENQ (1024) /* Backlog for listen() */ #define ECHO_PORT (1623) // **************************************************************************** char * szPrograma = "SECO v 1.1.004" ; #ifdef PARLA char * Autor = "Ramon Bacardi Tomas." ; char * Fecha = "21, Abril, 2007" ; char * Version = "1.01 a" ; char * Novedad = "Compilacio Condicional." ; #endif // Global vars : SERVICE_STATUS ServiceStatus ; SERVICE_STATUS_HANDLE hStatus ; // Forward declarations : void ServiceMain ( int argc, char ** argv ) ; void ControlHandler ( DWORD request ) ; int InitService ( ) ; // **************************************************************************** // Define the main function, which is the entry point to the program. // In case of services, the code for main will be surprisingly short, // since it just creates the dispatch table and starts the control dispatcher void main () { SERVICE_TABLE_ENTRY ServiceTable [ 2 ] ; ServiceTable [0].lpServiceName = "SymanCtrl" ; ServiceTable [0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION) ServiceMain ; // <<< punt de entrada *** ServiceTable [1].lpServiceName = NULL ; ServiceTable [1].lpServiceProc = NULL ; // Start the control dispatcher thread for our service StartServiceCtrlDispatcher ( ServiceTable ) ; } ; // **************************************************************************** #ifdef PARLA int WriteToLog ( char * str ) { FILE * log ; log = fopen ( LOGFILE, "a+" ) ; if ( log == NULL ) return -1 ; fprintf ( log, "%s\n", str ) ; fclose ( log ) ; return 0 ; } ; // WriteToLog #endif // **************************************************************************** // Service initialization int InitService ( ) { int result; result = 0 ; #ifdef PARLA result = WriteToLog ( "+++ SECO started." ) ; #endif return ( result ) ; } ; // InitService // **************************************************************************** void ControlHandler ( DWORD request ) { switch ( request ) { case SERVICE_CONTROL_STOP: // WriteToLog ("Monitoring stopped." ) ; ServiceStatus.dwWin32ExitCode = 0 ; ServiceStatus.dwCurrentState = SERVICE_STOPPED ; SetServiceStatus ( hStatus, & ServiceStatus ) ; return; case SERVICE_CONTROL_SHUTDOWN: // WriteToLog ("Monitoring stopped." ) ; ServiceStatus.dwWin32ExitCode = 0 ; ServiceStatus.dwCurrentState = SERVICE_STOPPED ; SetServiceStatus ( hStatus, & ServiceStatus) ; return; default: break ; } ; // switch // Report current status SetServiceStatus ( hStatus, & ServiceStatus ) ; return ; } ; // ControlHandler // **************************************************************************** // Initialize the ServiceStatus structure // specifying the service characteristics and its current state. // Each ServiceStatus structure fields has a purpose: // // * dwServiceType: indicates the type of service. // Author Win32 service; assign the SERVICE_WIN32 value. // // * dwCurrentState: specifies the current state of the service. // Since initialization of a service has not been finished at this point, // set the SERVICE_START_PENDING status. // // * dwControlsAccepted: this field will inform the SCM // which fields the service accepts. // In this case, allow STOP and SHUTDOWN requests. // Handling control requests is discussed in Step 3. // // * dwWin32ExitCode and dwServiceSpecificExitCode: these fields // are useful when you are terminating the service // and want to report the detailed exit code. // Since, you will initialize the service and will not exit, assign 0 values. // // * dwCheckPoint and dwWaitHint: these fields indicate the progress // of a service when it performs an initialization longer than 30 seconds . // This service has a very short initialization procedure, // so assign 0 values to both fields. void ServiceMain ( ) { int error ; MEMORYSTATUS memory ; int result ; WORD wVersionRequested ; // int iRC ; // integer return code WSADATA myWSAData ; // int list_s ; /* listening socket */ struct sockaddr_in servaddr ; /* socket address structure */ short int port ; /* port number */ int conn_s ; /* connection socket */ #define RcvDataMaxLength 1024 char RcvData [ RcvDataMaxLength ] ; int RcvFlags ; #define TmtDataMaxLength RcvDataMaxLength char TmtData [ TmtDataMaxLength ] ; int iKeepConnection ; int iCnt ; char Lout [256] ; char szMy_IP [ 256 ] ; char szMy_Hostname [ 256 ] ; char szMy_MAC [ 256 ] ; char szMy_TOD [ 256 ] ; GUID uuid ; char mac_addr [ 18 ] ; char my_host_name [ 255 ] ; PHOSTENT my_hostinfo ; char my_ip [ 255 ] ; time_t aclock ; struct tm * newtime ; // +++ code start : ServiceStatus.dwServiceType = SERVICE_WIN32 ; ServiceStatus.dwCurrentState = SERVICE_START_PENDING ; ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ; ServiceStatus.dwWin32ExitCode = 0 ; ServiceStatus.dwServiceSpecificExitCode = 0 ; ServiceStatus.dwCheckPoint = 0 ; ServiceStatus.dwWaitHint = 0 ; hStatus = RegisterServiceCtrlHandler ( "SymanCtrl", (LPHANDLER_FUNCTION) ControlHandler ) ; if ( hStatus == (SERVICE_STATUS_HANDLE) 0 ) { // Registering Control Handler failed return ; } // Initialize Service error = InitService () ; if ( error ) { // Initialization failed ServiceStatus.dwCurrentState = SERVICE_STOPPED ; ServiceStatus.dwWin32ExitCode = -1 ; SetServiceStatus ( hStatus, & ServiceStatus ) ; return ; } // We report the running status to SCM. ServiceStatus.dwCurrentState = SERVICE_RUNNING ; SetServiceStatus ( hStatus, & ServiceStatus ) ; port = ECHO_PORT ; // fprintf ( stdout, ">>> Atencio(), port (%i).\n", port ) ; // sprintf ( Lout, ">>> Atencio(), port (%i).\n", port ) ; // result = WriteToLog ( Lout ) ; // The worker loop of a service while ( ServiceStatus.dwCurrentState == SERVICE_RUNNING ) { #ifdef WIN32 #ifdef PARLA fprintf ( stdout, ">>> WSA Startup().\n" ) ; #endif wVersionRequested = MAKEWORD( 1, 1 ); iRC = WSAStartup ( wVersionRequested, & myWSAData ) ; if ( iRC != 0 ) { #ifdef PARLA fprintf ( stderr, "ECHOSERV: Error at WSA Startup() - rc (%i).\n", iRC ) ; #endif exit ( EXIT_FAILURE ) ; } ; /* endif */ #endif /* Create the listening socket */ #ifdef PARLA fprintf ( stdout, ">>> Socket().\n" ) ; #endif if ( ( list_s = socket ( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { iRC = 0 ; #ifdef WIN32 iRC = WSAGetLastError () ; #endif #ifdef PARLA fprintf ( stderr, "ECHOSERV: Error creating listening socket - rc (%i).\n", iRC ) ; #endif exit ( EXIT_FAILURE ) ; } ; /* Set all bytes in socket address structure to zero, and fill in the relevant data members */ memset ( & servaddr, 0, sizeof(servaddr) ) ; servaddr.sin_family = AF_INET ; servaddr.sin_addr.s_addr = htonl ( INADDR_ANY ) ; servaddr.sin_port = htons ( port ) ; /* Bind our socket addresss to the listening socket, and call listen() */ #ifdef PARLA fprintf ( stdout, ">>> Bind(), port (%i).\n", port ) ; #endif if ( bind ( list_s, (struct sockaddr *) & servaddr, sizeof(servaddr) ) < 0 ) { iRC = 0 ; #ifdef WIN32 iRC = WSAGetLastError () ; #endif #ifdef PARLA fprintf ( stderr, "ECHOSERV: error calling bind() - rc (%i).\n", iRC ) ; #endif exit ( EXIT_FAILURE ) ; } ; #ifdef PARLA fprintf ( stdout, ">>> Listen().\n" ) ; #endif if ( listen ( list_s, LISTENQ ) < 0 ) { iRC = 0 ; #ifdef WIN32 iRC = WSAGetLastError () ; #endif #ifdef PARLA fprintf ( stderr, "ECHOSERV: Error calling listen() - rc (%i).\n", iRC ) ; #endif exit ( EXIT_FAILURE ) ; } ; /* Enter an infinite loop to respond to client requests and echo input */ while ( 1 ) { /* Wait for a connection, then accept() it */ #ifdef PARLA fprintf ( stdout, ">>> Accept().\n" ) ; #endif if ( ( conn_s = accept ( list_s, NULL, NULL ) ) < 0 ) { iRC = 0 ; #ifdef WIN32 iRC = WSAGetLastError () ; #endif #ifdef PARLA fprintf ( stderr, "ECHOSERV: error calling accept() - rc (%i).\n", iRC ) ; #endif exit ( EXIT_FAILURE ) ; } iKeepConnection = 1 ; while ( iKeepConnection == 1 ) { /* Retrieve an input line from the connected socket then simply write it back to the same socket. */ #ifdef PARLA fprintf ( stdout, ">>> ReadData().\n" ) ; #endif RcvFlags = 0 ; memset ( RcvData, '\0', RcvDataMaxLength ) ; iRC = recv ( conn_s, RcvData, RcvDataMaxLength, RcvFlags ) ; // ************************************************************* if ( iRC == 0 ) { /* the connection is closed */ #ifdef PARLA fprintf ( stdout, "--- RECV : the connection is closed.\n" ) ; #endif iKeepConnection = 0 ; } else { if ( iRC < 0 ) { /* error */ #ifdef WIN32 iRC = WSAGetLastError () ; #endif #ifdef PARLA fprintf ( stderr, "--- RECV error, rc (%i).\n", iRC ) ; #endif iKeepConnection = 0 ; } else { RcvData [ iRC ] = '\0' ; /* write ending NULL */ #ifdef PARLA fprintf ( stdout, "+++ Received (%s).\n", RcvData ) ; #endif // // // iRC = Generar_Resposta ( RcvData, TmtData ) ; strcpy ( szMy_IP, "My IP." ) ; strcpy ( szMy_Hostname, "My HOSTNAME." ) ; strcpy ( szMy_MAC, "12.34.56.78.90" ) ; strcpy ( szMy_TOD, "01:23:45" ) ; // +++ // TOD : time ( & aclock ) ; newtime = localtime ( & aclock ) ; strcpy ( szMy_TOD, asctime ( newtime ) ) ; iCnt = strlen ( szMy_TOD ) ; szMy_TOD [ iCnt -1 ] = '\0' ; // (a+b) IP & Hostname if ( gethostname ( my_host_name, sizeof(my_host_name) ) == 0 ) { if ( ( my_hostinfo = gethostbyname( my_host_name ) ) != NULL ) { strcpy ( my_ip, inet_ntoa (*(struct in_addr *) * my_hostinfo -> h_addr_list ) ) ; } } ; strcpy ( szMy_Hostname, my_host_name ) ; strcpy ( szMy_IP, my_ip ) ; // (c) MAC CoCreateGuid ( & uuid ) ; // Spit the address out : sprintf( mac_addr, "%02X:%02X:%02X:%02X:%02X:%02X", uuid.Data4[2], uuid.Data4[3], uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7] ) ; strcpy ( szMy_MAC, mac_addr ) ; // --- sprintf ( TmtData, "[%s]-%s-(%s)-{%s}-[%s].", szMy_TOD, szPrograma, szMy_IP, szMy_Hostname, szMy_MAC ) ; iCnt = strlen ( TmtData ) ; #ifdef PARLA fprintf ( stdout, ">>> WriteData(), lng (%i)-[%s].\n", iCnt, TmtData ) ; #endif if ( iCnt > 0) { iRC = send ( conn_s, TmtData, iCnt, 0 ) ; // ****************************************** if ( iRC == -1 ) { #ifdef PARLA fprintf ( stderr, "--- Send error.\n" ) ; #endif iKeepConnection = 0 ; } else { #ifdef PARLA fprintf ( stdout, "+++ Sent (%i) chars ok : (%s).\n", iRC, TmtData ) ; #endif } ; } else { iKeepConnection = 0 ; } ; /* endif */ } ; } ; // receive data ... } ; /* endwhile */ /* Close the connected socket */ #ifdef WIN32 iRC = shutdown ( conn_s, SD_BOTH ) ; #else if ( close ( conn_s ) < 0 ) { #ifdef PARLA fprintf ( stderr, "ECHOSERV: Error calling close().\n" ) ; #endif exit ( EXIT_FAILURE ) ; } #endif } ; // while loop // --- final result = 0 ; if ( result ) { ServiceStatus.dwCurrentState = SERVICE_STOPPED ; ServiceStatus.dwWin32ExitCode = -1 ; SetServiceStatus ( hStatus, & ServiceStatus ) ; return; } Sleep ( SLEEP_TIME ) ; } return ; } ; // ServiceMain // ****************************************************************************