erlsrv_interactive.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 1,092 行 · 第 1/2 页
C
1,092 行
#include <windows.h>#include <winsvc.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include "erlsrv_global.h"#include "erlsrv_registry.h"#include "erlsrv_interactive.h"#include "erlsrv_util.h" /* service_name */#define DBG fprintf(stderr,"argv[0]:%s line %d\n",argv[0],__LINE__)/* Really HAS to correcpond to the enum in erlsrv_registry.h */static char *arg_tab[] = { "stopaction", "st", "onfail", "on", "machine", "m", "env", "e", "workdir", "w", "priority", "p", "sname", "sn", "name", "n", "args", "ar", "debugtype", "d", NULL, NULL};static char *generate_real_service_name(char *display_name){ SYSTEMTIME systime; FILETIME ftime; char *buff = malloc(strlen(display_name)+ (8*2)+1); char *tmp = _strdup(display_name); int i; /* 2 Hex chars for each byte in a DWORD */ GetSystemTime(&systime); SystemTimeToFileTime(&systime,&ftime); /* Remove trailing version info to avoid user confusion */ for(i = (strlen(tmp)-1);i > 0; --i) if(tmp[i] == '_'){ tmp[i] = '\0'; break; } sprintf(buff,"%s%08x%08x",tmp,ftime.dwHighDateTime, ftime.dwLowDateTime); free(tmp); return buff;}static int lookup_arg(char *arg){ int i; if(*arg != '-' && *arg != '/') return -1; for(i=0; arg_tab[i] != NULL; i += 2){ if(!_strnicmp(arg_tab[i],arg+1,strlen(arg+1)) && !_strnicmp(arg_tab[i+1],arg+1,strlen(arg_tab[i+1]))) return (i / 2); } return -1;}char *edit_env(char *edit, char *oldenv){ char **arg; char *value; char *name = strdup(edit); int i; char *tmp; arg = env_to_arg(oldenv); value = strchr(name,'='); if(value){ *(value++) = '\0'; if(*value == '\0') value = NULL; } for(i=0;arg[i] != NULL; ++i){ tmp = strchr(arg[i],'='); if(((int) strlen(name)) == (tmp - arg[i]) && !_strnicmp(name,arg[i], tmp - arg[i])) break; } if(arg[i] != NULL){ free(arg[i]); if(value){ arg[i] = strdup(edit); } else { do { arg[i] = arg[i+1]; ++i; } while(arg[i] != NULL); } } else if(value){ /* add to arg, which is always allocated to hold one extra environment variable*/ arg[i] = strdup(edit); arg[i+1] = NULL; } free(name); return arg_to_env(arg);}int last_error = 0;void print_last_error(void){ char *mes; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, (last_error) ? last_error : GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &mes, 0, NULL ); fprintf(stderr,"Error: %s",mes); LocalFree(mes);} static BOOL install_service(void){ SC_HANDLE scm; SC_HANDLE service; char filename[MAX_PATH + 3]; DWORD fnsiz=MAX_PATH; char dependant[] = { 'L','a','n','m','a','n', 'W','o','r','k','s','t', 'a','t','i','o','n','\0','\0'}; if(!(fnsiz = GetModuleFileName(NULL, filename, fnsiz))) return FALSE; if(strchr(filename,' ')){ memmove(filename+1,filename,fnsiz); filename[0] ='\"'; /* " */ filename[fnsiz+1] = '\"'; /* " */ filename[fnsiz+2] = '\0'; } if((scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE)) == NULL){ last_error = GetLastError(); return FALSE; } service = CreateService(scm, real_service_name, service_name, SERVICE_ALL_ACCESS & ~(SERVICE_PAUSE_CONTINUE), SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, filename, NULL, NULL, dependant, NULL, NULL); if(service == NULL){ CloseServiceHandle(scm); last_error = GetLastError(); return FALSE; } CloseServiceHandle(service); CloseServiceHandle(scm); return TRUE;}static BOOL remove_service(void){ SC_HANDLE scm; SC_HANDLE service; if((scm = OpenSCManager(NULL, NULL, GENERIC_WRITE)) == NULL) return FALSE; service = OpenService(scm, real_service_name, SERVICE_ALL_ACCESS); if(service == NULL){ CloseServiceHandle(scm); return FALSE; } if(!DeleteService(service)){ last_error = GetLastError(); return FALSE; } CloseServiceHandle(service); CloseServiceHandle(scm); return TRUE;}static BOOL open_service_control(SC_HANDLE *scm, SC_HANDLE *service){ if((*scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL) return FALSE; *service = OpenService(*scm, real_service_name, SERVICE_ALL_ACCESS); if(service == NULL){ CloseServiceHandle(*scm); return FALSE; } return TRUE;}static BOOL open_service_config(SC_HANDLE *scm, SC_HANDLE *service){ if((*scm = OpenSCManager(NULL, NULL, /*GENERIC_WRITE | GENERIC_EXECUTE*/ SC_MANAGER_ALL_ACCESS)) == NULL){ last_error = GetLastError(); return FALSE; } *service = OpenService(*scm, real_service_name, /*GENERIC_WRITE*/ SERVICE_ALL_ACCESS); if(service == NULL){ last_error = GetLastError(); CloseServiceHandle(*scm); return FALSE; } return TRUE;}static BOOL wait_service_trans(DWORD initial, DWORD passes, DWORD goal, int timeout){ SC_HANDLE scm; SC_HANDLE service; int moved = 0; BOOL ret; int i; SERVICE_STATUS stat; if(! open_service_config(&scm,&service)) return FALSE; for(i = 0; i < timeout; ++i){ if(!QueryServiceStatus(service,&stat)){ last_error = GetLastError(); ret = FALSE; goto out; } if(stat.dwCurrentState == initial){ if(moved){ ret = FALSE; /* * The exitcode is usually strange when we tried to stop and failed, * to report a timeout is more appropriate. */ if(goal == SERVICE_STOPPED) last_error = ERROR_SERVICE_REQUEST_TIMEOUT; else last_error = stat.dwWin32ExitCode; goto out; } } else if(stat.dwCurrentState == passes){ moved = 1; } else if(stat.dwCurrentState == goal){ ret = TRUE; goto out; } Sleep(1000); } ret = FALSE; last_error = ERROR_SERVICE_REQUEST_TIMEOUT;out: CloseServiceHandle(scm); CloseServiceHandle(service); return ret; }static BOOL stop_service(void){ SC_HANDLE scm; SC_HANDLE service; BOOL ret; SERVICE_STATUS ss; if(!open_service_control(&scm,&service)){#ifdef HARDDEBUG fprintf(stderr,"Failed to open service.\n");#endif return FALSE; } ret = ControlService(service,SERVICE_CONTROL_STOP,&ss); if(!ret){ last_error = GetLastError(); } CloseServiceHandle(service); CloseServiceHandle(scm);#ifdef HARDDEBUG if(!ret) { fprintf(stderr,"Failed to control service.\n"); print_last_error(); }#endif return ret;}static BOOL start_service(void){ SC_HANDLE scm; SC_HANDLE service; BOOL ret; if(!open_service_control(&scm,&service)) return FALSE; ret = StartService(service,0,NULL); if(!ret){ last_error = GetLastError(); } CloseServiceHandle(service); CloseServiceHandle(scm); return ret;}static BOOL disable_service(void){ SC_HANDLE scm; SC_HANDLE service; BOOL ret; if(!open_service_config(&scm,&service)) return FALSE; ret = ChangeServiceConfig(service, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if(!ret){ last_error = GetLastError(); } CloseServiceHandle(service); CloseServiceHandle(scm); return ret;}static BOOL enable_service(void){ SC_HANDLE scm; SC_HANDLE service; BOOL ret;if(!open_service_config(&scm,&service)) return FALSE; ret = ChangeServiceConfig(service, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if(!ret){ last_error = GetLastError(); } CloseServiceHandle(service); CloseServiceHandle(scm); return ret;}static BOOL set_interactive(BOOL interactive){ SC_HANDLE scm; SC_HANDLE service; BOOL ret; if(!open_service_config(&scm,&service)) return FALSE; ret = ChangeServiceConfig(service, SERVICE_WIN32_OWN_PROCESS | ((interactive) ? SERVICE_INTERACTIVE_PROCESS : 0), SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if(!ret){ last_error = GetLastError(); } CloseServiceHandle(service); CloseServiceHandle(scm); return ret;}RegEntry *old_entries = NULL;BOOL fetch_current(RegEntry *new){ int i; if(!(old_entries = get_keys(service_name))) return FALSE; for(i=0;i<num_reg_entries;++i) new[i] = old_entries[i]; return TRUE;}void cleanup_old(){ if(old_entries != NULL) free_keys(old_entries);}BOOL fill_in_defaults(RegEntry *new){ char filename[MAX_PATH]; char *ptr; if(!GetModuleFileName(NULL, filename, MAX_PATH)) return FALSE; for(ptr = filename + strlen(filename) - 1; ptr > filename && *ptr != '\\'; --ptr) ; if(*ptr == '\\') ++ptr; *ptr = '\0'; ptr = malloc(strlen(filename)+strlen(ERLANG_MACHINE)+1); strcpy(ptr,filename); strcat(ptr,ERLANG_MACHINE); new[StopAction].data.bytes = ""; new[OnFail].data.value = ON_FAIL_IGNORE; new[Machine].data.bytes = ptr; new[Machine].data.expand.unexpanded = ptr; new[Env].data.bytes = "\0"; new[WorkDir].data.bytes = new[WorkDir].data.expand.unexpanded = ""; new[Priority].data.value = NORMAL_PRIORITY_CLASS; new[SName].data.bytes = service_name; new[Name].data.bytes = ""; new[Args].data.bytes = new[Args].data.expand.unexpanded = ""; new[DebugType].data.value = DEBUG_TYPE_NO_DEBUG; new[InternalServiceName].data.bytes = real_service_name; return TRUE;}int do_usage(char *arg0){ printf("Usage:\n"); printf("%s {set | add} <servicename>\n" "\t[-st[opaction] [<erlang shell command>]]\n" "\t[-on[fail] [{reboot | restart | restart_always}]]\n" "\t[-m[achine] [<erl-command>]]\n" "\t[-e[nv] [<variable>[=<value>]]]\n" "\t[-w[orkdir] [<directory>]]\n" "\t[-p[riority] [{low|high|realtime}]]\n" "\t[{-sn[ame] | -n[ame]} [<nodename>]]\n" "\t[-d[ebugtype] [{new|reuse|console}]]\n" "\t[-ar[gs] [<limited erl arguments>]]\n\n" "%s {start | stop | disable | enable} <servicename>\n\n" "%s remove <servicename>\n\n" "%s rename <servicename> <servicename>\n\n" "%s list [<servicename>]\n\n" "%s help\n\n", arg0,arg0,arg0,arg0,arg0,arg0); printf("Manipulates Erlang system services on Windows NT.\n\n"); printf("When no parameter to an option is specified, the option\n" "is reset to it's default value. To set an empty argument\n" "list, give option -args as last option on command line " "with\n" "no arguments.\n\n"); printf("Se Erlang documentation for full description.\n"); return 0;}int do_manage(int argc,char **argv){ char *action = argv[1]; RegEntry *current = empty_reg_tab(); if(argc < 3){ fprintf(stderr,"%s: No servicename given!\n",argv[0]); do_usage(argv[0]); return 1; } service_name = argv[2]; if(!fetch_current(current)){ fprintf(stderr,"%s: The service %s is not an erlsrv controlled service.\n", argv[0],service_name); return 1; } real_service_name = _strdup(current[InternalServiceName].data.bytes); free_keys(current); if(!_stricmp(action,"start")){ if(!start_service()){ fprintf(stderr,"%s: Failed to start service %s.\n", argv[0],service_name); print_last_error(); return 1; } else { if(!wait_service_trans(SERVICE_STOPPED, SERVICE_START_PENDING, SERVICE_RUNNING, 60)){ fprintf(stderr,"%s: Failed to start service %s.\n", argv[0],service_name); print_last_error(); return 1; } printf("%s: Service %s started.\n", argv[0],service_name); return 0; } } if(!_stricmp(action,"stop")){ if(!stop_service()){ fprintf(stderr,"%s: Failed to stop service %s.\n", argv[0],service_name); print_last_error(); return 1; } else { if(!wait_service_trans(SERVICE_RUNNING, SERVICE_STOP_PENDING, SERVICE_STOPPED, 60)){ fprintf(stderr,"%s: Failed to stop service %s.\n", argv[0],service_name); print_last_error(); return 1; } printf("%s: Service %s stopped.\n", argv[0],service_name); return 0; } } if(!_stricmp(action,"disable")){#if 0 if(stop_service()){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?