diff options
author | Sverker Eriksson <[email protected]> | 2017-08-30 20:55:08 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2017-08-30 20:55:08 +0200 |
commit | 7c67bbddb53c364086f66260701bc54a61c9659c (patch) | |
tree | 92ab0d4b91d5e2f6e7a3f9d61ea25089e8a71fe0 /erts/etc/win32/erlsrv/erlsrv_interactive.c | |
parent | 97dc5e7f396129222419811c173edc7fa767b0f8 (diff) | |
parent | 3b7a6ffddc819bf305353a593904cea9e932e7dc (diff) | |
download | otp-7c67bbddb53c364086f66260701bc54a61c9659c.tar.gz otp-7c67bbddb53c364086f66260701bc54a61c9659c.tar.bz2 otp-7c67bbddb53c364086f66260701bc54a61c9659c.zip |
Merge tag 'OTP-19.0' into sverker/19/binary_to_atom-utf8-crash/ERL-474/OTP-14590
Diffstat (limited to 'erts/etc/win32/erlsrv/erlsrv_interactive.c')
-rw-r--r-- | erts/etc/win32/erlsrv/erlsrv_interactive.c | 692 |
1 files changed, 356 insertions, 336 deletions
diff --git a/erts/etc/win32/erlsrv/erlsrv_interactive.c b/erts/etc/win32/erlsrv/erlsrv_interactive.c index e8d73ae047..c616ef86e3 100644 --- a/erts/etc/win32/erlsrv/erlsrv_interactive.c +++ b/erts/etc/win32/erlsrv/erlsrv_interactive.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2013. All Rights Reserved. + * Copyright Ericsson AB 1998-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ @@ -27,54 +28,60 @@ #include "erlsrv_interactive.h" #include "erlsrv_util.h" /* service_name */ -#define DBG fprintf(stderr,"argv[0]:%s line %d\n",argv[0],__LINE__) +#define DBG fwprintf(stderr,L"argv[0]:%s line %d\n",argv[0],__LINE__) +/* #define HARDDEBUG 1 */ + +#include <fcntl.h> /* 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", - "internalservicename","i", - "comment","c", +static wchar_t *arg_tab[] = { + L"stopaction", L"st", + L"onfail", L"on", + L"machine", L"m", + L"env", L"e", + L"workdir", L"w", + L"priority", L"p", + L"sname", L"sn", + L"name", L"n", + L"args", L"ar", + L"debugtype", L"d", + L"internalservicename",L"i", + L"comment",L"c", NULL, NULL }; -static char *generate_real_service_name(char *display_name){ +static wchar_t *generate_real_service_name(wchar_t *display_name){ SYSTEMTIME systime; FILETIME ftime; - char *buff = malloc(strlen(display_name)+ - (8*2)+1); - char *tmp = _strdup(display_name); + int len=(wcslen(display_name)+(8*2)+1); + wchar_t *buff; + wchar_t *tmp = _wcsdup(display_name); int i; + buff = (wchar_t*) malloc(len*sizeof(wchar_t)); + /* 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'; + for(i = (wcslen(tmp)-1);i > 0; --i) + if(tmp[i] == L'_'){ + tmp[i] = L'\0'; break; } - sprintf(buff,"%s%08x%08x",tmp,ftime.dwHighDateTime, - ftime.dwLowDateTime); + swprintf(buff,len,L"%s%08x%08x",tmp, + ftime.dwHighDateTime, + ftime.dwLowDateTime); free(tmp); return buff; } -static int lookup_arg(char *arg){ +static int lookup_arg(wchar_t *arg){ int i; - if(*arg != '-' && *arg != '/') + if(*arg != L'-' && *arg != L'/') 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]))) + if(!_wcsnicmp(arg_tab[i],arg+1,wcslen(arg+1)) && + !_wcsnicmp(arg_tab[i+1],arg+1,wcslen(arg_tab[i+1]))) return (i / 2); } return -1; @@ -82,29 +89,29 @@ static int lookup_arg(char *arg){ -char *edit_env(char *edit, char *oldenv){ - char **arg; - char *value; - char *name = strdup(edit); +wchar_t *edit_env(wchar_t *edit, wchar_t *oldenv){ + wchar_t **arg; + wchar_t *value; + wchar_t *name = wcsdup(edit); int i; - char *tmp; + wchar_t *tmp; arg = env_to_arg(oldenv); - value = strchr(name,'='); + value = wcschr(name,L'='); if(value){ - *(value++) = '\0'; - if(*value == '\0') + *(value++) = L'\0'; + if(*value == L'\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])) + tmp = wcschr(arg[i],L'='); + if(((int) wcslen(name)) == (tmp - arg[i]) && + !_wcsnicmp(name,arg[i], tmp - arg[i])) break; } if(arg[i] != NULL){ free(arg[i]); if(value){ - arg[i] = strdup(edit); + arg[i] = wcsdup(edit); } else { do { arg[i] = arg[i+1]; @@ -113,7 +120,7 @@ char *edit_env(char *edit, char *oldenv){ } } else if(value){ /* add to arg, which is always allocated to hold one extra environment variable*/ - arg[i] = strdup(edit); + arg[i] = wcsdup(edit); arg[i+1] = NULL; } free(name); @@ -132,8 +139,8 @@ void print_last_error(void){ (LPTSTR) &mes, 0, NULL ); - fprintf(stderr,"Error: %s",mes); - LocalFree(mes); + fwprintf(stderr,L"Error: %S",mes); + LocalFree(mes); } static int get_last_error(void) @@ -144,19 +151,19 @@ static int get_last_error(void) static BOOL install_service(void){ SC_HANDLE scm; SC_HANDLE service; - char filename[MAX_PATH + 3]; + wchar_t 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'}; + wchar_t dependant[] = { L'L',L'a',L'n',L'm',L'a',L'n', + L'W',L'o',L'r',L'k',L's',L't', + L'a',L't',L'i',L'o',L'n',L'\0',L'\0'}; - if(!(fnsiz = GetModuleFileName(NULL, filename, fnsiz))) + if(!(fnsiz = GetModuleFileNameW(NULL, filename, fnsiz))) return FALSE; - if(strchr(filename,' ')){ - memmove(filename+1,filename,fnsiz); - filename[0] ='\"'; /* " */ - filename[fnsiz+1] = '\"'; /* " */ - filename[fnsiz+2] = '\0'; + if(wcschr(filename,L' ')){ + memmove(filename+1,filename,fnsiz*sizeof(wchar_t)); + filename[0] = L'\"'; /* " */ + filename[fnsiz+1] = L'\"'; /* " */ + filename[fnsiz+2] = L'\0'; } if((scm = OpenSCManager(NULL, NULL, @@ -166,20 +173,20 @@ static BOOL install_service(void){ 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); + service = CreateServiceW(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(); @@ -198,9 +205,9 @@ static BOOL remove_service(void){ GENERIC_WRITE)) == NULL) return FALSE; - service = OpenService(scm, - real_service_name, - SERVICE_ALL_ACCESS); + service = OpenServiceW(scm, + real_service_name, + SERVICE_ALL_ACCESS); if(service == NULL){ CloseServiceHandle(scm); return FALSE; @@ -220,9 +227,9 @@ static BOOL open_service_control(SC_HANDLE *scm, SC_HANDLE *service){ SC_MANAGER_ALL_ACCESS)) == NULL) return FALSE; - *service = OpenService(*scm, - real_service_name, - SERVICE_ALL_ACCESS); + *service = OpenServiceW(*scm, + real_service_name, + SERVICE_ALL_ACCESS); if(service == NULL){ CloseServiceHandle(*scm); return FALSE; @@ -239,10 +246,10 @@ static BOOL open_service_config(SC_HANDLE *scm, SC_HANDLE *service){ last_error = GetLastError(); return FALSE; } - *service = OpenService(*scm, - real_service_name, - /*GENERIC_WRITE*/ - SERVICE_ALL_ACCESS); + *service = OpenServiceW(*scm, + real_service_name, + /*GENERIC_WRITE*/ + SERVICE_ALL_ACCESS); if(service == NULL){ last_error = GetLastError(); CloseServiceHandle(*scm); @@ -251,16 +258,16 @@ static BOOL open_service_config(SC_HANDLE *scm, SC_HANDLE *service){ return TRUE; } -static BOOL set_service_comment(char *comment) { +static BOOL set_service_comment(wchar_t *comment) { SC_HANDLE scm; SC_HANDLE service; - SERVICE_DESCRIPTION sd; + SERVICE_DESCRIPTIONW sd; BOOL ret = TRUE; sd.lpDescription = comment; if (!open_service_config(&scm,&service)) { return FALSE; } - if (!ChangeServiceConfig2(service,SERVICE_CONFIG_DESCRIPTION,&sd)) { + if (!ChangeServiceConfig2W(service,SERVICE_CONFIG_DESCRIPTION,&sd)) { last_error = GetLastError(); ret = FALSE; } @@ -325,7 +332,7 @@ static BOOL stop_service(void){ if(!open_service_control(&scm,&service)){ #ifdef HARDDEBUG - fprintf(stderr,"Failed to open service.\n"); + fwprintf(stderr,L"Failed to open service.\n"); #endif return FALSE; } @@ -338,7 +345,7 @@ static BOOL stop_service(void){ #ifdef HARDDEBUG if(!ret) { - fprintf(stderr,"Failed to control service.\n"); + fwprintf(stderr,L"Failed to control service.\n"); print_last_error(); } #endif @@ -466,115 +473,114 @@ void cleanup_old(){ } BOOL fill_in_defaults(RegEntry *new){ - char filename[MAX_PATH]; - char *ptr; + wchar_t filename[MAX_PATH]; + wchar_t *ptr; - if(!GetModuleFileName(NULL, filename, MAX_PATH)) + if(!GetModuleFileNameW(NULL, filename, MAX_PATH)) return FALSE; - for(ptr = filename + strlen(filename) - 1; - ptr > filename && *ptr != '\\'; + for(ptr = filename + wcslen(filename) - 1; + ptr > filename && *ptr != L'\\'; --ptr) ; - if(*ptr == '\\') + if(*ptr == L'\\') ++ptr; - *ptr = '\0'; + *ptr = L'\0'; - ptr = malloc(strlen(filename)+strlen(ERLANG_MACHINE)+1); - strcpy(ptr,filename); - strcat(ptr,ERLANG_MACHINE); + ptr = (wchar_t*) malloc((wcslen(filename)+wcslen(ERLANG_MACHINE)+1)*sizeof(wchar_t)); + wcscpy(ptr,filename); + wcscat(ptr,ERLANG_MACHINE); - new[StopAction].data.bytes = ""; + new[StopAction].data.string = L""; 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[Machine].data.string = ptr; + new[Machine].data.expand.unexpanded = ptr; + new[Env].data.string = L"\0"; + new[WorkDir].data.string = new[WorkDir].data.expand.unexpanded = L""; 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[SName].data.string = service_name; + new[Name].data.string = L""; + new[Args].data.string = new[Args].data.expand.unexpanded = L""; new[DebugType].data.value = DEBUG_TYPE_NO_DEBUG; - new[InternalServiceName].data.bytes = real_service_name; - new[Comment].data.bytes = ""; + new[InternalServiceName].data.string = real_service_name; + new[Comment].data.string = L""; 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 | start_disabled | 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", +int do_usage(wchar_t *arg0){ + wprintf(L"Usage:\n"); + wprintf(L"%s {set | add} <servicename>\n" + L"\t[-st[opaction] [<erlang shell command>]]\n" + L"\t[-on[fail] [{reboot | restart | restart_always}]]\n" + L"\t[-m[achine] [<erl-command>]]\n" + L"\t[-e[nv] [<variable>[=<value>]]]\n" + L"\t[-w[orkdir] [<directory>]]\n" + L"\t[-p[riority] [{low|high|realtime}]]\n" + L"\t[{-sn[ame] | -n[ame]} [<nodename>]]\n" + L"\t[-d[ebugtype] [{new|reuse|console}]]\n" + L"\t[-ar[gs] [<limited erl arguments>]]\n\n" + L"%s {start | start_disabled | stop | disable | enable} <servicename>\n\n" + L"%s remove <servicename>\n\n" + L"%s rename <servicename> <servicename>\n\n" + L"%s list [<servicename>]\n\n" + L"%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("See Erlang documentation for full description.\n"); + wprintf(L"Manipulates Erlang system services on Windows NT.\n\n"); + wprintf(L"When no parameter to an option is specified, the option\n" + L"is reset to it's default value. To set an empty argument\n" + L"list, give option -args as last option on command line " + L"with\n" + L"no arguments.\n\n"); + wprintf(L"See Erlang documentation for full description.\n"); return 0; } -int do_manage(int argc,char **argv){ - char *action = argv[1]; +int do_manage(int argc, wchar_t **argv){ + wchar_t *action = argv[1]; RegEntry *current = empty_reg_tab(); if(argc < 3){ - fprintf(stderr,"%s: No servicename given!\n",argv[0]); + fwprintf(stderr,L"%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", + fwprintf(stderr,L"%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); + real_service_name = _wcsdup(current[InternalServiceName].data.string); free_keys(current); - if(!_stricmp(action,"start")){ + if(!_wcsicmp(action,L"start")){ if(!start_service()){ - fprintf(stderr,"%s: Failed to start service %s.\n", + fwprintf(stderr,L"%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", + fwprintf(stderr,L"%s: Failed to start service %s.\n", argv[0],service_name); print_last_error(); return 1; } - printf("%s: Service %s started.\n", + wprintf(L"%s: Service %s started.\n", argv[0],service_name); return 0; } } - if(!_stricmp(action,"start_disabled")){ + if(!_wcsicmp(action,L"start_disabled")){ if(!enable_service()){ - fprintf(stderr,"%s: Failed to enable service %s.\n", + fwprintf(stderr,L"%s: Failed to enable service %s.\n", argv[0],service_name); print_last_error(); return 1; } if(!start_service() && get_last_error() != ERROR_SERVICE_ALREADY_RUNNING){ - fprintf(stderr,"%s: Failed to start service %s.\n", + fwprintf(stderr,L"%s: Failed to start service %s.\n", argv[0],service_name); print_last_error(); goto failure_starting; @@ -582,84 +588,84 @@ int do_manage(int argc,char **argv){ if(!wait_service_trans(SERVICE_STOPPED, SERVICE_START_PENDING, SERVICE_RUNNING, 60)){ - fprintf(stderr,"%s: Failed to start service %s.\n", + fwprintf(stderr,L"%s: Failed to start service %s.\n", argv[0],service_name); print_last_error(); goto failure_starting; } if(!disable_service()){ - fprintf(stderr,"%s: Failed to disable service %s.\n", + fwprintf(stderr,L"%s: Failed to disable service %s.\n", argv[0],service_name); print_last_error(); return 1; } - printf("%s: Service %s started.\n", + wprintf(L"%s: Service %s started.\n", argv[0],service_name); return 0; failure_starting: if(!disable_service()){ - fprintf(stderr,"%s: Failed to disable service %s.\n", + fwprintf(stderr,L"%s: Failed to disable service %s.\n", argv[0],service_name); print_last_error(); } return 1; } - if(!_stricmp(action,"stop")){ + if(!_wcsicmp(action,L"stop")){ if(!stop_service()){ - fprintf(stderr,"%s: Failed to stop service %s.\n", + fwprintf(stderr,L"%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", + fwprintf(stderr,L"%s: Failed to stop service %s.\n", argv[0],service_name); print_last_error(); return 1; } - printf("%s: Service %s stopped.\n", + wprintf(L"%s: Service %s stopped.\n", argv[0],service_name); return 0; } } - if(!_stricmp(action,"disable")){ + if(!_wcsicmp(action,L"disable")){ #if 0 if(stop_service()){ - printf("%s: Service %s stopped.\n", + wprintf(L"%s: Service %s stopped.\n", argv[0],service_name); } #endif if(!disable_service()){ - fprintf(stderr,"%s: Failed to disable service %s.\n", + fwprintf(stderr,L"%s: Failed to disable service %s.\n", argv[0],service_name); print_last_error(); return 1; } else { - printf("%s: Service %s disabled.\n", + wprintf(L"%s: Service %s disabled.\n", argv[0],service_name); return 0; } } - if(!_stricmp(action,"enable")){ + if(!_wcsicmp(action,L"enable")){ if(!enable_service()){ - fprintf(stderr,"%s: Failed to enable service %s.\n", + fwprintf(stderr,L"%s: Failed to enable service %s.\n", argv[0],service_name); print_last_error(); return 1; } else { - printf("%s: Service %s enabled.\n", + wprintf(L"%s: Service %s enabled.\n", argv[0],service_name); return 0; } } - fprintf(stderr,"%s: Unrecignized argument %s.\n", + fwprintf(stderr,L"%s: Unrecignized argument %s.\n", argv[0],action); return 1; } -int do_add_or_set(int argc, char **argv){ +int do_add_or_set(int argc, wchar_t **argv){ RegEntry *new_entries; RegEntry *default_entries; int add = 0; @@ -669,40 +675,40 @@ int do_add_or_set(int argc, char **argv){ new_entries = empty_reg_tab(); default_entries = empty_reg_tab(); if(argc < 3){ - fprintf(stderr,"%s: No servicename given!\n",argv[0]); + fwprintf(stderr,L"%s: No servicename given!\n",argv[0]); do_usage(argv[0]); return 1; } service_name = argv[2]; - if(!_stricmp(argv[1],"add")){ + if(!_wcsicmp(argv[1],L"add")){ if(fetch_current(default_entries)){ - fprintf(stderr,"%s: A service with the name %s already " - "exists.\n", + fwprintf(stderr,L"%s: A service with the name %s already " + L"exists.\n", argv[0],service_name); return 1; } real_service_name = generate_real_service_name(service_name); if(!fill_in_defaults(new_entries)){ - fprintf(stderr,"%s: Internal error.\n", argv[0]); + fwprintf(stderr,L"%s: Internal error.\n", argv[0]); return 1; } add = 1; } else { if(!fetch_current(new_entries)){ - fprintf(stderr,"%s: No service with the name %s exists.\n", + fwprintf(stderr,L"%s: No service with the name %s exists.\n", argv[0], service_name); return 1; } - real_service_name = new_entries[InternalServiceName].data.bytes; + real_service_name = new_entries[InternalServiceName].data.string; } if(!fill_in_defaults(default_entries)){ - fprintf(stderr,"%s: Internal error.\n", argv[0]); + fwprintf(stderr,L"%s: Internal error.\n", argv[0]); return 1; } /* make sure env is malloced... */ - new_entries[Env].data.bytes = envdup(new_entries[Env].data.bytes); + new_entries[Env].data.string = envdup(new_entries[Env].data.string); for(i = 3; i < argc; ++i){ switch((current = lookup_arg(argv[i]))){ @@ -712,43 +718,43 @@ int do_add_or_set(int argc, char **argv){ case WorkDir: case Args: if(i+1 >= argc){ - new_entries[current].data.bytes = - default_entries[current].data.bytes; + new_entries[current].data.string = + default_entries[current].data.string; new_entries[current].data.expand.unexpanded = default_entries[current].data.expand.unexpanded; } else { new_entries[current].data.expand.unexpanded = - new_entries[current].data.bytes = argv[i+1]; + new_entries[current].data.string = argv[i+1]; ++i; } break; case SName: - new_entries[Name].data.bytes = ""; + new_entries[Name].data.string = L""; case StopAction: case Name: if(i+1 >= argc || - *argv[i+1] == '-' || *argv[i+1] == '/'){ - new_entries[current].data.bytes = - default_entries[current].data.bytes; + *argv[i+1] == L'-' || *argv[i+1] == L'/'){ + new_entries[current].data.string = + default_entries[current].data.string; } else { - new_entries[current].data.bytes = argv[i+1]; + new_entries[current].data.string = argv[i+1]; ++i; } break; case OnFail: if(i+1 >= argc || - *argv[i+1] == '-' || *argv[i+1] == '/'){ + *argv[i+1] == L'-' || *argv[i+1] == L'/'){ new_entries[current].data.value = default_entries[current].data.value; } else { - if(!_stricmp(argv[i+1],"reboot")) + if(!_wcsicmp(argv[i+1],L"reboot")) new_entries[current].data.value = ON_FAIL_REBOOT; - else if(!_stricmp(argv[i+1],"restart")) + else if(!_wcsicmp(argv[i+1],L"restart")) new_entries[current].data.value = ON_FAIL_RESTART; - else if(!_stricmp(argv[i+1],"restart_always")) + else if(!_wcsicmp(argv[i+1],L"restart_always")) new_entries[current].data.value = ON_FAIL_RESTART_ALWAYS; else { - fprintf(stderr,"%s: Unrecognized keyword value %s.\n", + fwprintf(stderr,L"%s: Unrecognized keyword value %s.\n", argv[0],argv[i+1]); return 1; } @@ -757,18 +763,18 @@ int do_add_or_set(int argc, char **argv){ break; case DebugType: if(i+1 >= argc || - *argv[i+1] == '-' || *argv[i+1] == '/'){ + *argv[i+1] == L'-' || *argv[i+1] == L'/'){ new_entries[current].data.value = default_entries[current].data.value; } else { - if(!_stricmp(argv[i+1],"new")) + if(!_wcsicmp(argv[i+1],L"new")) new_entries[current].data.value = DEBUG_TYPE_NEW; - else if(!_stricmp(argv[i+1],"reuse")) + else if(!_wcsicmp(argv[i+1],L"reuse")) new_entries[current].data.value = DEBUG_TYPE_REUSE; - else if(!_stricmp(argv[i+1],"console")) + else if(!_wcsicmp(argv[i+1],L"console")) new_entries[current].data.value = DEBUG_TYPE_CONSOLE; else { - fprintf(stderr,"%s: Unrecognized keyword value %s.\n", + fwprintf(stderr,L"%s: Unrecognized keyword value %s.\n", argv[0],argv[i+1]); return 1; } @@ -777,18 +783,18 @@ int do_add_or_set(int argc, char **argv){ break; case Priority: if(i+1 >= argc || - *argv[i+1] == '-' || *argv[i+1] == '/'){ + *argv[i+1] == L'-' || *argv[i+1] == L'/'){ new_entries[current].data.value = default_entries[current].data.value; } else { - if(!_stricmp(argv[i+1],"high")) + if(!_wcsicmp(argv[i+1],L"high")) new_entries[current].data.value = HIGH_PRIORITY_CLASS; - else if(!_stricmp(argv[i+1],"low")) + else if(!_wcsicmp(argv[i+1],L"low")) new_entries[current].data.value = IDLE_PRIORITY_CLASS; - else if(!_stricmp(argv[i+1],"realtime")) + else if(!_wcsicmp(argv[i+1],L"realtime")) new_entries[current].data.value = REALTIME_PRIORITY_CLASS; else { - fprintf(stderr,"%s: Unrecognized keyword value %s.\n", + fwprintf(stderr,L"%s: Unrecognized keyword value %s.\n", argv[0],argv[i+1]); return 1; } @@ -798,64 +804,64 @@ int do_add_or_set(int argc, char **argv){ case Env: if(i+1 >= argc || - *argv[i+1] == '-' || *argv[i+1] == '/'){ - fprintf(stderr,"%s: %s requires a parameter.\n", + *argv[i+1] == L'-' || *argv[i+1] == L'/'){ + fwprintf(stderr,L"%s: %s requires a parameter.\n", argv[0],argv[i]); return 1; } - new_entries[current].data.bytes = - edit_env(argv[i+1], - new_entries[current].data.bytes); + new_entries[current].data.string = + edit_env(argv[i+1], new_entries[current].data.string); ++i; break; case InternalServiceName: if (!add) { - fprintf(stderr,"%s: %s only allowed when adding a new service.\n", + fwprintf(stderr,L"%s: %s only allowed when adding a new service.\n", argv[0],argv[i]); return 1; } if(i+1 >= argc){ - fprintf(stderr,"%s: %s requires a parameter.\n", + fwprintf(stderr,L"%s: %s requires a parameter.\n", argv[0],argv[i]); return 1; } new_entries[InternalServiceName].data.expand.unexpanded = - new_entries[InternalServiceName].data.bytes = argv[i+1]; + new_entries[InternalServiceName].data.string = argv[i+1]; ++i; /* Discard old, should maybe be fred' but we'll exit anyway */ - real_service_name = new_entries[InternalServiceName].data.bytes; + real_service_name = new_entries[InternalServiceName].data.string; break; default: - fprintf(stderr,"%s: Unrecognized option %s.\n", argv[0], + fwprintf(stderr,L"%s: Unrecognized option %s.\n", argv[0], argv[i]); return 1; } } - if(*new_entries[SName].data.bytes && - *new_entries[Name].data.bytes){ + if(*new_entries[SName].data.string && + *new_entries[Name].data.string){ #if 0 - fprintf(stderr,"%s: Both -sname and -name specified.\n", + fwprintf(stderr,L"%s: Both -sname and -name specified.\n", argv[0]); return 1; #else - new_entries[SName].data.bytes = ""; + new_entries[SName].data.string = L""; #endif } - if(add && !(*new_entries[SName].data.bytes) && - !(*new_entries[Name].data.bytes)){ - fprintf(stderr,"%s: Neither -sname nor -name specified.\n", + if(add && !(*new_entries[SName].data.string) && + !(*new_entries[Name].data.string)){ + fwprintf(stderr,L"%s: Neither -sname nor -name specified.\n", argv[0]); return 1; } + if(add && !install_service()){ - fprintf(stderr,"%s: Unable to register service with service manager.\n", + fwprintf(stderr,L"%s: Unable to register %s service with service manager.\n", argv[0], service_name); print_last_error(); return 1; } if(!set_interactive(new_entries[DebugType].data.value == DEBUG_TYPE_CONSOLE)){ - fprintf(stderr,"%s: Warning, could not set correct interactive mode.\n", + fwprintf(stderr,L"%s: Warning, could not set correct interactive mode. %s\n", argv[0], service_name); print_last_error(); /* Not severe or??? */ @@ -865,9 +871,9 @@ int do_add_or_set(int argc, char **argv){ set_keys(service_name, new_entries); /* Update service comment if needed */ if(set_comment) { - if (!set_service_comment(new_entries[Comment].data.bytes)) { - fprintf(stderr,"%s: Warning, could not set correct " - "service description (comment)", + if (!set_service_comment(new_entries[Comment].data.string)) { + fwprintf(stderr,L"%s: Warning, could not set correct " + L"service description (comment) %s", argv[0], service_name); print_last_error(); } @@ -878,64 +884,64 @@ int do_add_or_set(int argc, char **argv){ malloced, but we'll exit anyway, so... */ cleanup_old(); if(add) - printf("%s: Service %s added to system.\n", + wprintf(L"%s: Service %s added to system.\n", argv[0], service_name); else - printf("%s: Service %s updated.\n", + wprintf(L"%s: Service %s updated.\n", argv[0], service_name); return 0; } -int do_rename(int argc, char **argv){ +int do_rename(int argc, wchar_t **argv){ RegEntry *current = empty_reg_tab(); RegEntry *dummy = empty_reg_tab(); SC_HANDLE scm; SC_HANDLE service; if(argc < 3){ - fprintf(stderr,"%s: No old servicename given!\n",argv[0]); + fwprintf(stderr,L"%s: No old servicename given!\n",argv[0]); do_usage(argv[0]); return 1; } if(argc < 4){ - fprintf(stderr,"%s: No new servicename given!\n",argv[0]); + fwprintf(stderr,L"%s: No new servicename given!\n",argv[0]); do_usage(argv[0]); return 1; } service_name = argv[3]; if(fetch_current(dummy)){ - fprintf(stderr,"%s: A service with the name %s already " - "exists.\n", + fwprintf(stderr,L"%s: A service with the name %s already " + L"exists.\n", argv[0],service_name); return 1; } service_name = argv[2]; if(!fetch_current(current)){ - fprintf(stderr,"%s: Error, old service name %s does not exist.\n", + fwprintf(stderr,L"%s: Error, old service name %s does not exist.\n", argv[0],service_name); return 1; } - real_service_name = _strdup(current[InternalServiceName].data.bytes); + real_service_name = _wcsdup(current[InternalServiceName].data.string); if(!open_service_config(&scm,&service)){ - fprintf(stderr,"%s: Error, unable to communicate with service control" - " manager.\n", + fwprintf(stderr,L"%s: Error, unable to communicate with service control" + L" manager.\n", argv[0]); print_last_error(); return 1; } - if(!ChangeServiceConfig(service, - SERVICE_NO_CHANGE, - SERVICE_NO_CHANGE, - SERVICE_NO_CHANGE, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - argv[3])){ - fprintf(stderr,"%s: Error, unable to communicate with service control" - " manager.\n", + if(!ChangeServiceConfigW(service, + SERVICE_NO_CHANGE, + SERVICE_NO_CHANGE, + SERVICE_NO_CHANGE, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + argv[3])){ + fwprintf(stderr,L"%s: Error, unable to communicate with service control" + L" manager.\n", argv[0]); print_last_error(); CloseServiceHandle(scm); @@ -946,154 +952,154 @@ int do_rename(int argc, char **argv){ CloseServiceHandle(service); if(remove_keys(service_name) != 0) - fprintf(stderr,"%s: Warning, old service parameter keys could not " - "be removed, continuing.\n", argv[0]); + fwprintf(stderr,L"%s: Warning, old service parameter keys could not " + L"be removed, continuing.\n", argv[0]); /* Update registry */ register_logkeys(); set_keys(argv[3], current); - printf("%s: Service %s renamed to %s.\n", + wprintf(L"%s: Service %s renamed to %s.\n", argv[0], service_name, argv[3]); return 0; } -int do_remove(int argc, char **argv){ +int do_remove(int argc, wchar_t **argv){ RegEntry *current = empty_reg_tab(); int rem_res; BOOL found; if(argc < 3){ - fprintf(stderr,"%s: No servicename given!\n",argv[0]); + fwprintf(stderr,L"%s: No servicename given!\n",argv[0]); do_usage(argv[0]); return 1; } service_name = argv[2]; found = fetch_current(current); if(found){ - real_service_name = _strdup(current[InternalServiceName].data.bytes); + real_service_name = _wcsdup(current[InternalServiceName].data.string); } else { - real_service_name = _strdup(service_name); + real_service_name = _wcsdup(service_name); } if(found) free_keys(current); if(stop_service() && !wait_service_trans(SERVICE_RUNNING, SERVICE_STOP_PENDING, SERVICE_STOPPED, 60)){ - fprintf(stderr,"%s: Failed to stop running service %s.\n", + fwprintf(stderr,L"%s: Failed to stop running service %s.\n", argv[0],service_name); print_last_error(); return 1; } if(!remove_service()){ - fprintf(stderr,"%s: Unable to remove service (not enough " - "privileges?)\n",argv[0]); + fwprintf(stderr,L"%s: Unable to remove service (not enough " + L"privileges?)\n",argv[0]); print_last_error(); return 1; } if((rem_res = remove_keys(service_name)) > 0){ - fprintf(stderr,"%s: Warning, service parameter keys belonged to old " - "erlsrv version.\n", argv[0]); + fwprintf(stderr,L"%s: Warning, service parameter keys belonged to old " + L"erlsrv version.\n", argv[0]); /* Backward compatibility... */ } else if(rem_res < 0) { - fprintf(stderr,"%s: Error, service parameter keys nonexistent.\n", + fwprintf(stderr,L"%s: Error, service parameter keys nonexistent.\n", argv[0]); return 1; } - printf("%s: Service %s removed from system.\n", + wprintf(L"%s: Service %s removed from system.\n", argv[0], service_name); return 0; } -BOOL list_one(char *servicename, RegEntry *keys, BOOL longlist){ - char *onfail; - char *prio; - char *debugtype; +BOOL list_one(wchar_t *servicename, RegEntry *keys, BOOL longlist){ + wchar_t *onfail; + wchar_t *prio; + wchar_t *debugtype; switch(keys[OnFail].data.value){ case ON_FAIL_RESTART: - onfail = "restart"; + onfail = L"restart"; break; case ON_FAIL_RESTART_ALWAYS: - onfail = "restart_always"; + onfail = L"restart_always"; break; case ON_FAIL_REBOOT: - onfail = "reboot"; + onfail = L"reboot"; break; default: - onfail = "ignore"; + onfail = L"ignore"; } switch(keys[DebugType].data.value){ case DEBUG_TYPE_NEW: - debugtype = "new"; + debugtype = L"new"; break; case DEBUG_TYPE_REUSE: - debugtype = "reuse"; + debugtype = L"reuse"; break; case DEBUG_TYPE_CONSOLE: - debugtype = "console"; + debugtype = L"console"; break; default: - debugtype = "none"; + debugtype = L"none"; } switch(keys[Priority].data.value){ case HIGH_PRIORITY_CLASS: - prio = "high"; + prio = L"high"; break; case IDLE_PRIORITY_CLASS: - prio = "low"; + prio = L"low"; break; case REALTIME_PRIORITY_CLASS: - prio = "realtime"; + prio = L"realtime"; break; case NORMAL_PRIORITY_CLASS: - prio = "default"; + prio = L"default"; break; default: - prio = "unknown/faulty"; + prio = L"unknown/faulty"; } if(longlist){ - char *env = envdup(keys[Env].data.bytes); - char **arg = env_to_arg(env); - char **pek = arg; - printf("Service name: %s\n", + wchar_t *env = envdup(keys[Env].data.string); + wchar_t **arg = env_to_arg(env); + wchar_t **pek = arg; + wprintf(L"Service name: %s\n", servicename); - printf("StopAction: %s\n", - keys[StopAction].data.bytes); - printf("OnFail: %s\n",onfail); - printf("Machine: %s\n", + wprintf(L"StopAction: %s\n", + keys[StopAction].data.string); + wprintf(L"OnFail: %s\n",onfail); + wprintf(L"Machine: %s\n", keys[Machine].data.expand.unexpanded); - printf("WorkDir: %s\n", + wprintf(L"WorkDir: %s\n", keys[WorkDir].data.expand.unexpanded); - if(*keys[SName].data.bytes) - printf("SName: %s\n", - keys[SName].data.bytes); + if(*keys[SName].data.string) + wprintf(L"SName: %s\n", + keys[SName].data.string); else - printf("Name: %s\n", - keys[Name].data.bytes); - printf("Priority: %s\n",prio); - printf("DebugType: %s\n",debugtype); - printf("Args: %s\n", + wprintf(L"Name: %s\n", + keys[Name].data.string); + wprintf(L"Priority: %s\n",prio); + wprintf(L"DebugType: %s\n",debugtype); + wprintf(L"Args: %s\n", keys[Args].data.expand.unexpanded); - printf("InternalServiceName: %s\n", - keys[InternalServiceName].data.bytes); - printf("Comment: %s\n", - keys[Comment].data.bytes); - printf("Env:\n"); + wprintf(L"InternalServiceName: %s\n", + keys[InternalServiceName].data.string); + wprintf(L"Comment: %s\n", + keys[Comment].data.string); + wprintf(L"Env:\n"); while(*pek){ - printf("\t%s\n",*pek); + wprintf(L"\t%s\n",*pek); ++pek; } /* env is easier to free...*/ env = arg_to_env(arg); free(env); } else { - printf("%s\t%s\t%s\t%s\t%s\n", + wprintf(L"%s\t%s\t%s\t%s\t%s\n", servicename, - (*keys[Name].data.bytes) ? - keys[Name].data.bytes : - keys[SName].data.bytes, + (*keys[Name].data.string) ? + keys[Name].data.string : + keys[SName].data.string, prio, onfail, keys[Args].data.expand.unexpanded); @@ -1102,15 +1108,15 @@ BOOL list_one(char *servicename, RegEntry *keys, BOOL longlist){ } -int do_list(int argc, char **argv){ +int do_list(int argc, wchar_t **argv){ if(argc < 3){ RegEntryDesc *all_keys = get_all_keys(); if(!all_keys){ - fprintf(stderr,"%s: No services found in registry.\n", + fwprintf(stderr,L"%s: No services found in registry.\n", argv[0]); return 0; } - printf("Service\t(S)Name\tPrio\tOnFail\tArgs\n"); + wprintf(L"Service\t(S)Name\tPrio\tOnFail\tArgs\n"); while(all_keys->servicename){ list_one(all_keys->servicename,all_keys->entries,FALSE); ++all_keys; @@ -1121,8 +1127,8 @@ int do_list(int argc, char **argv){ service_name = argv[2]; keys = get_keys(service_name); if(!keys){ - fprintf(stderr,"%s: Could not retrieve any " - "registered data for %s.\n",argv[0],service_name); + fwprintf(stderr,L"%s: Could not retrieve any " + L"registered data for %s.\n",argv[0],service_name); return 1; } list_one(service_name, keys, TRUE); @@ -1133,15 +1139,15 @@ int do_list(int argc, char **argv){ #define READ_CHUNK 100 #define ARGV_CHUNK 20 -char *safe_get_line(void){ +wchar_t *safe_get_line(void){ int lsize = READ_CHUNK; - char *line = malloc(READ_CHUNK); + wchar_t *line = malloc(READ_CHUNK*sizeof(wchar_t)); int pos = 0; int ch; - while((ch = getchar()) != EOF && ch != '\n'){ + while((ch = getwchar()) != EOF && ch != L'\n'){ if(pos + 1 >= lsize){ - line = realloc(line,(lsize += READ_CHUNK)); + line = realloc(line,(lsize += READ_CHUNK)*sizeof(wchar_t)); assert(line); } line[pos++] = ch; @@ -1150,22 +1156,22 @@ char *safe_get_line(void){ free(line); return NULL; } - line[pos] = '\0'; + line[pos] = L'\0'; return line; } -void read_arguments(int *pargc, char ***pargv){ +void read_arguments(int *pargc, wchar_t ***pargv){ int argc = 0; int asize = ARGV_CHUNK; - char **argv = malloc(ARGV_CHUNK*sizeof(char *)); - char *tmp; + wchar_t **argv = malloc(ARGV_CHUNK*sizeof(wchar_t *)); + wchar_t *tmp; argv[0] = (*pargv)[0]; argc = 1; while((tmp = safe_get_line()) != NULL){ if(argc + 1 >= asize){ - argv = realloc(argv,(asize += ARGV_CHUNK)*sizeof(char *)); + argv = realloc(argv,(asize += ARGV_CHUNK)*sizeof(wchar_t *)); assert(argv); } argv[argc++] = tmp; @@ -1258,40 +1264,54 @@ void release_lock(void) { -int interactive_main(int argc, char **argv){ - char *action = argv[1]; +int interactive_main(int argc, wchar_t **argv){ + wchar_t *action = argv[1]; int res; - + + _setmode(_fileno(stdin), _O_U8TEXT); /* set stdin to UTF8 */ + _setmode(_fileno(stdout), _O_U8TEXT); /* set stdout to UTF8 */ + _setmode(_fileno(stderr), _O_U8TEXT); /* set stderr to UTF8 */ + if (take_lock() != 0) { - fprintf(stderr,"%s: unable to acquire global lock (%s).\n",argv[0], + fwprintf(stderr,L"%s: unable to acquire global lock (%s).\n",argv[0], ERLSRV_INTERACTIVE_GLOBAL_SEMAPHORE); return 1; } - if(!_stricmp(action,"readargs")){ + if(!_wcsicmp(action,L"readargs")){ read_arguments(&argc,&argv); action = argv[1]; } - if(!_stricmp(action,"set") || !_stricmp(action,"add")) + +#ifdef HARDDEBUG + {int i; + for(i=0; i < argc; i++) { + fwprintf(stderr, L"%s ", argv[i]); + } + fwprintf(stderr, L"\n"); + } +#endif + + if(!_wcsicmp(action,L"set") || !_wcsicmp(action,L"add")) res = do_add_or_set(argc,argv); - else if(!_stricmp(action,"rename")) + else if(!_wcsicmp(action,L"rename")) res = do_rename(argc,argv); - else if(!_stricmp(action,"remove")) + else if(!_wcsicmp(action,L"remove")) res = do_remove(argc,argv); - else if(!_stricmp(action,"list")) + else if(!_wcsicmp(action,L"list")) res = do_list(argc,argv); - else if(!_stricmp(action,"start") || - !_stricmp(action,"start_disabled") || - !_stricmp(action,"stop") || - !_stricmp(action,"enable") || - !_stricmp(action,"disable")) + else if(!_wcsicmp(action,L"start") || + !_wcsicmp(action,L"start_disabled") || + !_wcsicmp(action,L"stop") || + !_wcsicmp(action,L"enable") || + !_wcsicmp(action,L"disable")) res = do_manage(argc,argv); - else if(_stricmp(action,"?") && - _stricmp(action,"/?") && - _stricmp(action,"-?") && - *action != 'h' && - *action != 'H') { - fprintf(stderr,"%s: action %s not implemented.\n",argv[0],action); + else if(_wcsicmp(action,L"?") && + _wcsicmp(action,L"/?") && + _wcsicmp(action,L"-?") && + *action != L'h' && + *action != L'H') { + fwprintf(stderr,L"%s: action %s not implemented.\n",argv[0],action); do_usage(argv[0]); res = 1; } else { |