The following patch implements the options -Q and --query to determine if a service is installed and if so whether it is up and what controls it will accept.
If there is a more appropriate place to send this patch, please let me know. Mike diff -cr ../cygrunsrv-0.95-1/ChangeLog cygrunsrv-0.95-1/ChangeLog *** ../cygrunsrv-0.95-1/ChangeLog Tue Feb 26 06:22:29 2002 --- cygrunsrv-0.95-1/ChangeLog Fri Mar 8 08:26:55 2002 *************** *** 1,3 **** --- 1,17 ---- + 2002-03-08 Mike Gerdts <[EMAIL PROTECTED]> + + * utils.h (reason_t): Add code for --query errors. + * utils.cc (reason_list): Add error string for --query errors. + * (usage): Add help text for --query parameter. + * cygrunsrv.cc (longopts): Add --query parameter. + * (opts): Add -Q option. + * (main): Add handling --query parameter. + * (serviceTypeToString): New function to support --query parameter. + * (serviceStateToString): New function to support --query parameter. + * (serviceStateToString): New function to support --query parameter. + * (controlsToString): New function to support --query parameter. + * (query_service): New function to support --query parameter. + 2002-02-26 Corinna Vinschen <[EMAIL PROTECTED]> * Bump version to 0.95. diff -cr ../cygrunsrv-0.95-1/cygrunsrv.README cygrunsrv-0.95-1/cygrunsrv.README *** ../cygrunsrv-0.95-1/cygrunsrv.README Tue Feb 26 06:22:29 2002 --- cygrunsrv-0.95-1/cygrunsrv.README Fri Mar 8 08:28:38 2002 *************** *** 3,8 **** --- 3,9 ---- What does it do? How do I use it? Informative options... + Querying a service Removing a service Starting a service Stopping a service *************** *** 55,60 **** --- 56,68 ---- cygrunsrv -v cygrunsrv --version print version information about the cygrunsrv executable + + ********************************************** + Query a service: + + cygrunsrv -Q <svc_name> + cygrunsrv --query <svc_name> + reports on the existence and status of the service. ********************************************** Remove a service: diff -cr ../cygrunsrv-0.95-1/cygrunsrv.cc cygrunsrv-0.95-1/cygrunsrv.cc *** ../cygrunsrv-0.95-1/cygrunsrv.cc Tue Feb 26 06:22:29 2002 --- cygrunsrv-0.95-1/cygrunsrv.cc Fri Mar 8 08:07:11 2002 *************** *** 50,55 **** --- 50,56 ---- { "remove", required_argument, NULL, 'R' }, { "start", required_argument, NULL, 'S' }, { "stop", required_argument, NULL, 'E' }, + { "query", required_argument, NULL, 'Q' }, { "path", required_argument, NULL, 'p' }, { "args", required_argument, NULL, 'a' }, { "chdir", required_argument, NULL, 'c' }, *************** *** 70,76 **** { 0, no_argument, NULL, 0 } }; ! char *opts = "I:R:S:E:p:a:c:e:d:f:ou:w:t:s:y:0:1:2:hv"; char *appname; char *svcname; --- 71,77 ---- { 0, no_argument, NULL, 0 } }; ! char *opts = "I:R:S:Q:E:p:a:c:e:d:f:ou:w:t:s:y:0:1:2:hv"; char *appname; char *svcname; *************** *** 82,88 **** Install, Remove, Start, ! Stop }; enum type_t { --- 83,90 ---- Install, Remove, Start, ! Stop, ! Query }; enum type_t { *************** *** 812,817 **** --- 814,934 ---- return err == 0 ? 0 : error (StopErr, err_func, err); } + char * + serviceTypeToString(DWORD stype) + { + switch (stype) { + case SERVICE_WIN32_OWN_PROCESS: + return "Own Process"; + break; + case SERVICE_WIN32_SHARE_PROCESS: + return "Share Process"; + break; + case SERVICE_KERNEL_DRIVER: + return "Kernel Driver"; + case SERVICE_FILE_SYSTEM_DRIVER: + return "File System Driver"; + case SERVICE_INTERACTIVE_PROCESS: + return "Interactive Process"; + default: + return "Undefined type"; + } + } + + char * + serviceStateToString(DWORD state) + { + switch (state) { + case SERVICE_STOPPED: + return "Stopped"; + case SERVICE_START_PENDING: + return "Start Pending"; + case SERVICE_STOP_PENDING: + return "Stop Pending"; + case SERVICE_RUNNING: + return "Running"; + case SERVICE_CONTINUE_PENDING: + return "Continue Pending"; + case SERVICE_PAUSE_PENDING: + return "Pause Pending"; + case SERVICE_PAUSED: + return "Paused"; + default: + return "Undefined state"; + } + } + + #define ACCEPT_STOP_MSG "Accept Stop" + #define ACCEPT_PAUSE_CONTINUE_MSG "Accept Pause Continue" + #define ACCEPT_SHUTDOWN_MSG "Accept Shutdown" + char * + controlsToString(DWORD controls) + { + static char buf[sizeof(ACCEPT_STOP_MSG) + sizeof(ACCEPT_PAUSE_CONTINUE_MSG) + + sizeof(ACCEPT_SHUTDOWN_MSG) + 5]; + buf[0] = '\0'; + + if ( controls & SERVICE_ACCEPT_STOP ) { + strcat(buf, ACCEPT_STOP_MSG); + } + if ( controls & SERVICE_ACCEPT_PAUSE_CONTINUE ) { + if ( buf[0] != '\0' ) + strcat(buf, ", "); + strcat(buf, ACCEPT_STOP_MSG); + } + if ( controls & SERVICE_ACCEPT_SHUTDOWN ) { + if ( buf[0] != '\0' ) + strcat(buf, ", "); + strcat(buf, ACCEPT_SHUTDOWN_MSG); + } + return(buf); + } + + /* Query service `name'. */ + int + query_service (const char *name) + { + SC_HANDLE sm = (SC_HANDLE) 0; + SC_HANDLE sh = (SC_HANDLE) 0; + SC_LOCK sl = (SC_LOCK) 0; + SERVICE_STATUS ss; + int cnt = 0; + char *err_func; + DWORD err = 0; + + /* Open service manager database. */ + if (!(sm = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS))) + err_out (OpenSCManager); + /* Lock service database. */ + if (!(sl = LockServiceDatabase (sm))) + err_out (LockServiceDatabase); + /* Check whether service exists. */ + if (!(sh = OpenService (sm, name, SERVICE_ALL_ACCESS))) + err_out (OpenService); + printf("Service %s exists\n", name); + + /* Get the status and print it out */ + if (!QueryServiceStatus(sh, &ss)) + err_out (QueryServiceStatus); + printf("%-20s: %s\n", "Type", serviceTypeToString(ss.dwServiceType)); + printf("%-20s: %s\n", "Current State", + serviceStateToString(ss.dwCurrentState)); + printf("%-20s: %s\n", "Controls Accepted", \ + controlsToString(ss.dwControlsAccepted)); + + err = 0; + + out: + if (sh) + CloseServiceHandle (sh); + if (sl) + UnlockServiceDatabase (sl); + if (sm) + CloseServiceHandle (sm); + return err == 0 ? 0 : error (QueryErr, err_func, err); + } + + #undef err_out int server_pid; *************** *** 1107,1112 **** --- 1224,1235 ---- action = Stop; in_name = optarg; break; + case 'Q': + if (action != Undefined) + return error (ReqAction); + action = Query; + in_name = optarg; + break; case 'p': if (action != Install) return error (PathNotAllowed); *************** *** 1260,1265 **** --- 1383,1391 ---- break; case Stop: return stop_service (in_name); + break; + case Query: + return query_service (in_name); break; } return error (ReqAction); diff -cr ../cygrunsrv-0.95-1/utils.cc cygrunsrv-0.95-1/utils.cc *** ../cygrunsrv-0.95-1/utils.cc Tue Feb 26 06:22:29 2002 --- cygrunsrv-0.95-1/utils.cc Fri Mar 8 08:29:28 2002 *************** *** 67,72 **** --- 67,73 ---- "Error removing a service", "Error starting a service", "Error stopping a service", + "Error querying a service", NULL }; *************** *** 126,131 **** --- 127,133 ---- uprint (" -R, --remove <svc_name> Removes a service named <svc_name>."); uprint (" -S, --start <svc_name> Starts a service named <svc_name>."); uprint (" -E, --stop <svc_name> Stops a service named <svc_name>."); + uprint (" -Q, --query <svc_name> Queries a service named <svc_name>."); uprint ("\nRequired install options:"); uprint (" -p, --path <app_path> Application path which is run as a service."); uprint ("\nMiscellaneous install options:"); diff -cr ../cygrunsrv-0.95-1/utils.h cygrunsrv-0.95-1/utils.h *** ../cygrunsrv-0.95-1/utils.h Tue Feb 26 06:22:29 2002 --- cygrunsrv-0.95-1/utils.h Fri Mar 8 08:07:27 2002 *************** *** 58,63 **** --- 58,64 ---- RemoveErr, StartErr, StopErr, + QueryErr, MaxReason /* Always the last element */ }; -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/