pre-inst/pre-inst.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Jul 16 11:07:18 2016 +0100 (2016-07-16)
changeset 61 31fb35727621
parent 38 a29623b68ca2
child 80 671df13f1304
permissions -rw-r--r--
Support parallel installations. The idea is that for CAD screener, we want
to be able to install this on the same machine as a standard AVOT setup
(most notably for John's laptop). To allow for the possibility of a second
application that might have the same requirements, we add the concept of
vendor-specific distributions. Thus we can have one distribution for CAD
screener and one for The Next Big Thing. It doesn't seem trivial to have
both CAD screener and AVOT under the same vendor tag so we'll have to have
AVOT under "City Occupational" and CAD screener under "City Occupational Ltd"
or some such kludge.

Most of this is done although we are very short of test cases (in particular
we don't test that it's actually possible to install CAD screener in parallel
with AVOT or to update either of them once installed, which is fundamental).

We also have a lot of baggage left over, including an intercept of razor_set.
The problem that this was introduced to debug has been fixed but it looks
like there are a number of memory leaks which it might be useful to help
track down so it has been left in place for now.

There is still a lot of confusion in plover between path-based and URI-based
API. We should review the API, decide what we want and have a general clear up.

There is also confusion as to the purpose of RAZOR_ROOT (and meaning; path or
URI). This is not used at all in librazor (although it is used in razor.exe).
Ideally we shouldn't use it in plover or plover-gtk either although again, we
might want to support it or an equivalent in (some of) the various executables.

Work that would still to nice to do for CAD screener:

- uninstall (ideally as an installed program that hooks into Add/Remove programs
but even re-running the installer would be acceptable).
- xz support (smaller packages).
- repomd.xml and xml:base (would be needed for an Internet installer).
- graphical installer.
ali@24
     1
/*
ali@24
     2
 * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
ali@24
     3
 *
ali@24
     4
 * This program is free software; you can redistribute it and/or modify
ali@24
     5
 * it under the terms of the GNU General Public License as published by
ali@24
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@24
     7
 * (at your option) any later version.
ali@24
     8
 *
ali@24
     9
 * This program is distributed in the hope that it will be useful,
ali@24
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@24
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@24
    12
 * GNU General Public License for more details.
ali@24
    13
 *
ali@24
    14
 * You should have received a copy of the GNU General Public License along
ali@24
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@24
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@24
    17
 *
ali@24
    18
 * References:
ali@24
    19
 *	http://www.transmissionzero.co.uk/computing/win32-apps-with-mingw/
ali@24
    20
 */
ali@24
    21
ali@24
    22
#include "config.h"
ali@24
    23
#ifndef WIN32
ali@24
    24
#define _XOPEN_SOURCE 500
ali@24
    25
#endif
ali@24
    26
#include <stdlib.h>
ali@24
    27
#include <stdio.h>
ali@24
    28
#include <string.h>
ali@24
    29
#include <lua.h>
ali@24
    30
#include <razor.h>
ali@24
    31
#include <plover/plover.h>
ali@24
    32
#include <whelk/whelk.h>
ali@24
    33
#ifdef WIN32
ali@24
    34
#include <windows.h>
ali@24
    35
#include <process.h>
ali@24
    36
#include <commctrl.h>
ali@24
    37
#include "resource.h"
ali@24
    38
ali@24
    39
#ifndef FOF_NO_UI
ali@24
    40
#define FOF_NO_UI	(FOF_SILENT|FOF_NOCONFIRMATION|FOF_NOERRORUI|\
ali@24
    41
			FOF_NOCONFIRMMKDIR)
ali@24
    42
#endif
ali@24
    43
ali@24
    44
#else	/* WIN32 */
ali@24
    45
#include <ftw.h>
ali@24
    46
#endif	/* WIN32 */
ali@24
    47
ali@24
    48
#ifdef WIN32
ali@24
    49
/* Under WIN32, g_spawn requires a helper program which we'd rather avoid */
ali@24
    50
#undef USE_G_SPAWN
ali@24
    51
#else
ali@24
    52
#define USE_G_SPAWN
ali@24
    53
#endif
ali@24
    54
ali@24
    55
LUALIB_API int luaopen_posix(lua_State *L);
ali@24
    56
ali@24
    57
#ifdef WIN32
ali@24
    58
DWORD main_thread_id;
ali@24
    59
#endif
ali@24
    60
ali@24
    61
gchar *prefix;
ali@24
    62
ali@24
    63
int verify_and_fix(const char *root)
ali@24
    64
{
ali@24
    65
    return 0;
ali@24
    66
}
ali@24
    67
ali@24
    68
#ifdef WIN32
ali@24
    69
INT_PTR CALLBACK ProgressDialogProc(HWND dialog,UINT msg,WPARAM w_param,
ali@24
    70
  LPARAM l_param)
ali@24
    71
{
ali@24
    72
    HWND progress;
ali@24
    73
    DWORD style;
ali@24
    74
    switch (msg)
ali@24
    75
    {
ali@24
    76
	case WM_INITDIALOG:
ali@24
    77
	    progress=GetDlgItem(dialog,IDC_PROGRESS); 
ali@24
    78
	    style=GetWindowLong(progress,GWL_STYLE);
ali@24
    79
	    SetWindowLong(progress,GWL_STYLE,style|PBS_MARQUEE);
ali@24
    80
	    SendMessage(progress,PBM_SETMARQUEE,(WPARAM)TRUE,(LPARAM)30);
ali@24
    81
	    return (INT_PTR)TRUE;
ali@24
    82
    }
ali@24
    83
    return (INT_PTR)FALSE;
ali@24
    84
}
ali@24
    85
#endif
ali@24
    86
ali@24
    87
#ifdef WIN32
ali@24
    88
__stdcall
ali@24
    89
#endif
ali@24
    90
unsigned pre_install_thread(void *data)
ali@24
    91
{
ali@24
    92
    int retval;
ali@24
    93
    char *path=data;
ali@46
    94
    gchar *s,*uri;
ali@24
    95
    char *install[]={"plover-gtkui",NULL};
ali@24
    96
    GError *error=NULL;
ali@24
    97
    prefix=plover_pre_install_prefix();
ali@24
    98
    s=g_strconcat(prefix,"/var/log/pre-install",NULL);
ali@24
    99
    plover_log_open(s);
ali@24
   100
    g_free(s);
ali@24
   101
    s=g_strconcat(prefix,"/var/lib/razor",NULL);
ali@46
   102
    uri=razor_path_to_uri(s);
ali@24
   103
    g_free(s);
ali@46
   104
    razor_set_database_uri(uri);
ali@46
   105
    free(uri);
ali@24
   106
    if (verify_and_fix(prefix))
ali@24
   107
    {
ali@24
   108
	free(path);
ali@24
   109
	g_free(prefix);
ali@24
   110
	return -1;
ali@24
   111
    }
ali@24
   112
    retval=!plover_install(path,prefix,install,&error);
ali@24
   113
    if (!retval)
ali@24
   114
	retval=!plover_update(path,prefix,NULL,&error);
ali@24
   115
    if (error)
ali@24
   116
    {
ali@24
   117
	fprintf(stderr,"%s\n",error->message);
ali@24
   118
	g_error_free(error);
ali@24
   119
    }
ali@24
   120
    free(path);
ali@24
   121
#ifdef WIN32
ali@24
   122
    PostQuitMessage(retval);
ali@24
   123
    PostThreadMessage(main_thread_id,WM_QUIT,retval,0);
ali@24
   124
    _endthreadex(retval);
ali@24
   125
#endif
ali@24
   126
    return retval;
ali@24
   127
}
ali@24
   128
ali@24
   129
/*
ali@24
   130
 * The idea is that if pre_install() fails, update/setup should fall back
ali@24
   131
 * to console interfaces.
ali@24
   132
 */
ali@24
   133
#ifdef WIN32
ali@24
   134
HANDLE
ali@24
   135
#else
ali@24
   136
void *
ali@24
   137
#endif
ali@24
   138
pre_install(const char *argv0)
ali@24
   139
{
ali@24
   140
#ifdef WIN32
ali@24
   141
    HANDLE retval;
ali@24
   142
#else
ali@24
   143
    void *retval;
ali@24
   144
#endif
ali@24
   145
    char *path;
ali@38
   146
    razor_set_lua_loader("posix",(void (*)())luaopen_posix);
ali@38
   147
    razor_set_lua_loader("whelk",(void (*)())luaopen_whelk);
ali@24
   148
    path=plover_get_program_directory(argv0);
ali@24
   149
#ifdef WIN32
ali@24
   150
    retval=(HANDLE)_beginthreadex(NULL,0,pre_install_thread,path,0,NULL);
ali@24
   151
#else
ali@24
   152
    if (pre_install_thread(path))
ali@24
   153
	retval=NULL;
ali@24
   154
    else
ali@24
   155
	retval=(void *)1;		/* Non-NULL to indicate success */
ali@24
   156
#endif
ali@24
   157
    return retval;
ali@24
   158
}
ali@24
   159
ali@24
   160
#ifndef WIN32
ali@24
   161
int remove_ignore(const char *fpath,const struct stat *sb,int typeflag,
ali@24
   162
  struct FTW *ftwbuf)
ali@24
   163
{
ali@24
   164
    (void)remove(fpath);
ali@24
   165
    return 0;
ali@24
   166
}
ali@24
   167
#endif
ali@24
   168
ali@24
   169
gboolean deltree(const char *path)
ali@24
   170
{
ali@24
   171
#ifdef WIN32
ali@24
   172
    /* Based on g_local_file_trash() */
ali@24
   173
    SHFILEOPSTRUCTW op={0};
ali@24
   174
    gboolean success;
ali@24
   175
    wchar_t *wfilename;
ali@24
   176
    long len;
ali@24
   177
    wfilename=g_utf8_to_utf16(path,-1,NULL,&len,NULL);
ali@24
   178
    /* SHFILEOPSTRUCT.pFrom is double-zero-terminated */
ali@24
   179
    wfilename=g_renew(wchar_t,wfilename,len+2);
ali@24
   180
    wfilename[len+1]=0;
ali@24
   181
    op.wFunc=FO_DELETE;
ali@24
   182
    op.pFrom=wfilename;
ali@24
   183
    op.fFlags=FOF_NO_UI;
ali@24
   184
    success=!SHFileOperationW(&op);
ali@24
   185
    if (success && op.fAnyOperationsAborted)
ali@24
   186
	success=FALSE;
ali@24
   187
    g_free(wfilename);
ali@24
   188
    return success;
ali@24
   189
#else
ali@24
   190
    return nftw(path,remove_ignore,64,FTW_DEPTH|FTW_PHYS);
ali@24
   191
#endif
ali@24
   192
}
ali@24
   193
ali@24
   194
gboolean pre_uninstall(void)
ali@24
   195
{
ali@24
   196
    gboolean success;
ali@46
   197
    gchar *s,*uri;
ali@24
   198
    GError *error=NULL;
ali@38
   199
    razor_set_lua_loader("posix",(void (*)())luaopen_posix);
ali@38
   200
    razor_set_lua_loader("whelk",(void (*)())luaopen_whelk);
ali@24
   201
    prefix=plover_pre_install_prefix();
ali@24
   202
    s=g_strconcat(prefix,"/var/lib/razor",NULL);
ali@46
   203
    uri=razor_path_to_uri(s);
ali@24
   204
    g_free(s);
ali@46
   205
    razor_set_database_uri(uri);
ali@46
   206
    free(uri);
ali@24
   207
    success=plover_remove(NULL,&error);
ali@24
   208
    if (error)
ali@24
   209
    {
ali@24
   210
	fprintf(stderr,"%s\n",error->message);
ali@24
   211
	g_error_free(error);
ali@24
   212
    }
ali@24
   213
    deltree(prefix);
ali@24
   214
    return success;
ali@24
   215
}
ali@24
   216
ali@24
   217
#if defined(WIN32) && !defined(USE_G_SPAWN)
ali@24
   218
/* Based on glib's g_spawn_win32.c */
ali@24
   219
ali@24
   220
static gchar *
ali@24
   221
win32_cmdline_quote(const char *string)
ali@24
   222
{
ali@24
   223
    const gchar *p=string;
ali@24
   224
    gchar *retval,*q;
ali@24
   225
    gint len=0;
ali@24
   226
    gboolean need_dblquotes=FALSE;
ali@24
   227
    while (*p)
ali@24
   228
    {
ali@24
   229
	if (*p==' ' || *p=='\t')
ali@24
   230
	    need_dblquotes=TRUE;
ali@24
   231
	else if (*p=='"')
ali@24
   232
	    len++;
ali@24
   233
	else if (*p=='\\')
ali@24
   234
	{
ali@24
   235
	    const gchar *pp=p;
ali@24
   236
	    while (*pp && *pp=='\\')
ali@24
   237
		pp++;
ali@24
   238
	    if (*pp=='"')
ali@24
   239
		len++;
ali@24
   240
	}
ali@24
   241
	len++;
ali@24
   242
	p++;
ali@24
   243
    }
ali@24
   244
    q=retval=g_malloc(len+need_dblquotes*2+1);
ali@24
   245
    p=string;
ali@24
   246
    if (need_dblquotes)
ali@24
   247
	*q++='"';
ali@24
   248
    while (*p)
ali@24
   249
    {
ali@24
   250
	if (*p=='"')
ali@24
   251
	    *q++='\\';
ali@24
   252
	else if (*p=='\\')
ali@24
   253
	{
ali@24
   254
	    const gchar *pp=p;
ali@24
   255
	    while (*pp && *pp=='\\')
ali@24
   256
		pp++;
ali@24
   257
	    if (*pp=='"')
ali@24
   258
		*q++='\\';
ali@24
   259
	}
ali@24
   260
	*q++=*p;
ali@24
   261
	p++;
ali@24
   262
    }
ali@24
   263
    if (need_dblquotes)
ali@24
   264
	*q++='"';
ali@24
   265
    *q++='\0';
ali@24
   266
    return retval;
ali@24
   267
}
ali@24
   268
ali@24
   269
/* Create a win32-style wide-character argv with suitable quoting */
ali@24
   270
wchar_t **win32_argv_import(char **argv,GError **error)
ali@24
   271
{
ali@24
   272
    int i,n;
ali@24
   273
    gchar *s;
ali@24
   274
    wchar_t **wargv;
ali@24
   275
    GError *tmp_error=NULL;
ali@24
   276
    n=g_strv_length(argv);
ali@24
   277
    wargv=g_new(wchar_t *,n+1);
ali@24
   278
    for(i=0;i<n;i++)
ali@24
   279
    {
ali@24
   280
	s=win32_cmdline_quote(argv[i]);
ali@24
   281
	wargv[i]=g_utf8_to_utf16(s,-1,NULL,NULL,&tmp_error);
ali@24
   282
	g_free(s);
ali@24
   283
	if (!wargv[i])
ali@24
   284
	{
ali@24
   285
	    g_set_error(error,G_SPAWN_ERROR,G_SPAWN_ERROR_FAILED,
ali@24
   286
	      "Invalid argument #%d: %s",i,tmp_error->message);
ali@24
   287
	    g_error_free(tmp_error);
ali@24
   288
	    for(i--;i>=0;i--)
ali@24
   289
		g_free(wargv[i]);
ali@24
   290
	    g_free(wargv);
ali@24
   291
	    return FALSE;
ali@24
   292
	}
ali@24
   293
    }
ali@24
   294
    wargv[i]=NULL;
ali@24
   295
    return wargv;
ali@24
   296
}
ali@24
   297
ali@24
   298
gboolean spawn_sync(char **argv,GError **error)
ali@24
   299
{
ali@24
   300
    wchar_t *wargv0,**wargv;
ali@24
   301
    gintptr rc;
ali@24
   302
    GError *tmp_error=NULL;
ali@24
   303
    wargv0=g_utf8_to_utf16(argv[0],-1,NULL,NULL,&tmp_error);
ali@24
   304
    if (!wargv0)
ali@24
   305
    {
ali@24
   306
	fprintf(stderr,"Conversion error in post\n");
ali@24
   307
	g_set_error(error,G_SPAWN_ERROR,G_SPAWN_ERROR_FAILED,
ali@24
   308
	  "Invalid program name: %s",tmp_error->message);
ali@24
   309
	g_error_free(tmp_error);
ali@24
   310
	return FALSE;
ali@24
   311
    }
ali@24
   312
    wargv=win32_argv_import(argv,error);
ali@24
   313
    if (!wargv)
ali@24
   314
    {
ali@24
   315
	fprintf(stderr,"Conversion error in post\n");
ali@24
   316
	g_free(wargv0);
ali@24
   317
	return FALSE;
ali@24
   318
    }
ali@24
   319
    errno=0;
ali@24
   320
    rc=_wspawnvp(P_WAIT,wargv0,(const wchar_t **)wargv);
ali@24
   321
    g_free(wargv0);
ali@24
   322
    g_strfreev((gchar **)wargv);
ali@24
   323
    if (rc==-1 && errno!=0)
ali@24
   324
    {
ali@24
   325
	fprintf(stderr,"Failed to start post command (%s)\n",g_strerror(errno));
ali@24
   326
	g_set_error(error,G_SPAWN_ERROR,G_SPAWN_ERROR_FAILED,
ali@24
   327
	  "Failed to execute post command: %s",g_strerror(errno));
ali@24
   328
	return FALSE;
ali@24
   329
    }
ali@24
   330
    if (rc!=EXIT_SUCCESS)
ali@24
   331
    {
ali@24
   332
	fprintf(stderr,"post command failed (%ld)\n",(long)rc);
ali@24
   333
	g_set_error(error,G_SPAWN_ERROR,G_SPAWN_ERROR_FAILED,
ali@24
   334
	  "Post command exited with code %ld",(long)rc);
ali@24
   335
	return FALSE;
ali@24
   336
    }
ali@24
   337
    return TRUE;
ali@24
   338
}
ali@24
   339
ali@24
   340
#endif /* defined(WIN32) && !defined(USE_G_SPAWN) */
ali@24
   341
ali@24
   342
/*
ali@24
   343
 * Run a command after completing request.
ali@24
   344
 *
ali@24
   345
 * Command may refer to %INSTALL_PREFIX% which will be replaced by the
ali@24
   346
 * (first) install prefix used and/or %TEST_RESULT% which will be replaced
ali@24
   347
 * bu either "pass" or "fail" depending as to whether the request succeeded
ali@24
   348
 * or not. Command may also include double quotes which will be used to
ali@24
   349
 * affect how the command is split into arguments much like a shell does.
ali@24
   350
 */
ali@24
   351
gboolean run_post(int argc,char **argv,gboolean test_result,GError **error)
ali@24
   352
{
ali@24
   353
    int i,post_argc;
ali@24
   354
    char *s;
ali@24
   355
    gchar *expanded;
ali@24
   356
    gchar **post_argv;
ali@24
   357
#ifdef USE_G_SPAWN
ali@24
   358
    gchar *standard_output,*standard_error;
ali@24
   359
    int exit_status;
ali@24
   360
#endif
ali@24
   361
    GError *tmp_error=NULL;
ali@24
   362
    if (argc<1)
ali@24
   363
    {
ali@24
   364
	g_set_error_literal(error,G_FILE_ERROR,G_FILE_ERROR_NOENT,
ali@24
   365
	  "--post: No command given");
ali@24
   366
	return FALSE;
ali@24
   367
    }
ali@24
   368
    printf("Running post command: %s\n",argv[1]);
ali@24
   369
    if (!g_shell_parse_argv(argv[1],&post_argc,&post_argv,&tmp_error))
ali@24
   370
    {
ali@24
   371
	g_propagate_prefixed_error(error,tmp_error,"%s: ",argv[1]);
ali@24
   372
	return FALSE;
ali@24
   373
    }
ali@24
   374
    for(i=0;i<post_argc;i++)
ali@24
   375
    {
ali@24
   376
	s=strstr(post_argv[i],"%INSTALL_PREFIX%");
ali@24
   377
	if (s)
ali@24
   378
	{
ali@24
   379
	    *s='\0';
ali@24
   380
	    s+=strlen("%INSTALL_PREFIX%");
ali@24
   381
	    expanded=g_strconcat(post_argv[i],prefix,s,NULL);
ali@24
   382
	    g_free(post_argv[i]);
ali@24
   383
	    post_argv[i]=expanded;
ali@24
   384
	}
ali@24
   385
	s=strstr(post_argv[i],"%TEST_RESULT%");
ali@24
   386
	if (s)
ali@24
   387
	{
ali@24
   388
	    *s='\0';
ali@24
   389
	    s+=strlen("%TEST_RESULT%");
ali@24
   390
	    expanded=g_strconcat(post_argv[i],test_result?"pass":"fail",s,NULL);
ali@24
   391
	    g_free(post_argv[i]);
ali@24
   392
	    post_argv[i]=expanded;
ali@24
   393
	}
ali@24
   394
    }
ali@24
   395
#ifdef USE_G_SPAWN
ali@24
   396
    if (!g_spawn_sync(NULL,post_argv,NULL,G_SPAWN_SEARCH_PATH,NULL,NULL,
ali@24
   397
      &standard_output,&standard_error,&exit_status,&tmp_error))
ali@24
   398
    {
ali@24
   399
	fprintf(stderr,"Failed to start post command\n");
ali@24
   400
	g_propagate_prefixed_error(error,tmp_error,"%s: ",post_argv[0]);
ali@24
   401
	return FALSE;
ali@24
   402
    }
ali@24
   403
    if (standard_output && *standard_output)
ali@24
   404
    {
ali@24
   405
	printf("Output from post command %s:\n",post_argv[0]);
ali@24
   406
	fputs(standard_output,stdout);
ali@24
   407
    }
ali@24
   408
    g_free(standard_output);
ali@24
   409
    if (standard_error && *standard_error)
ali@24
   410
    {
ali@24
   411
	printf("Error output from post command %s:\n",post_argv[0]);
ali@24
   412
	fputs(standard_error,stdout);
ali@24
   413
    }
ali@24
   414
    g_free(standard_error);
ali@24
   415
    if (!g_spawn_check_exit_status(exit_status,&tmp_error))
ali@24
   416
    {
ali@24
   417
	fprintf(stderr,"post command failed\n");
ali@24
   418
	g_propagate_prefixed_error(error,tmp_error,"%s: ",post_argv[0]);
ali@24
   419
	return FALSE;
ali@24
   420
    }
ali@24
   421
#else
ali@24
   422
    if (!spawn_sync(post_argv,&tmp_error))
ali@24
   423
    {
ali@24
   424
	g_propagate_prefixed_error(error,tmp_error,"%s: ",post_argv[0]);
ali@24
   425
	return FALSE;
ali@24
   426
    }
ali@24
   427
#endif
ali@24
   428
    return TRUE;
ali@24
   429
}
ali@24
   430
ali@24
   431
#ifdef WIN32
ali@24
   432
DWORD win32_pre_install_gui(char *argv0)
ali@24
   433
{
ali@24
   434
    HANDLE thread;
ali@24
   435
    INITCOMMONCONTROLSEX icc={0,};
ali@24
   436
    MSG msg;
ali@24
   437
    DWORD retval;
ali@24
   438
    main_thread_id=GetCurrentThreadId();
ali@24
   439
    thread=(HANDLE)pre_install(argv0);
ali@24
   440
    if (!thread)
ali@24
   441
	return EXIT_FAILURE;
ali@24
   442
    icc.dwSize=sizeof(icc);
ali@24
   443
    icc.dwICC=ICC_WIN95_CLASSES;
ali@24
   444
    InitCommonControlsEx(&icc);
ali@24
   445
    DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_PROGRESSDIALOG),NULL,
ali@24
   446
      &ProgressDialogProc);
ali@24
   447
    while(GetMessage(&msg,NULL,0,0)>0)
ali@24
   448
    {
ali@24
   449
	TranslateMessage(&msg);
ali@24
   450
	DispatchMessage(&msg);
ali@24
   451
    }
ali@24
   452
    WaitForSingleObject(thread,INFINITE);
ali@24
   453
    GetExitCodeThread(thread,&retval);
ali@24
   454
    CloseHandle(thread);
ali@24
   455
    return retval;
ali@24
   456
}
ali@24
   457
#endif	/* WIN32 */
ali@24
   458
ali@24
   459
int main(int argc,char **argv)
ali@24
   460
{
ali@24
   461
    gboolean success;
ali@24
   462
    GError *error=NULL;
ali@24
   463
#ifdef WIN32
ali@24
   464
    /*
ali@24
   465
     * pre-inst is normally a GUI application, but rpm scripts may well
ali@24
   466
     * call console applications and it looks ugly if console windows keep
ali@24
   467
     * popping up. Avoid this by allocating our own console and hiding it.
ali@24
   468
     * Note:
ali@24
   469
     *	- If pre-inst is a console application (typically for debugging),
ali@24
   470
     *    then skip this step.
ali@24
   471
     *  - Call ShowWindow twice to negate special handling on first call.
ali@24
   472
     */
ali@24
   473
    if (!GetConsoleWindow())
ali@24
   474
    {
ali@24
   475
	AllocConsole();
ali@24
   476
	ShowWindow(GetConsoleWindow(),SW_HIDE);
ali@24
   477
	ShowWindow(GetConsoleWindow(),SW_HIDE);
ali@24
   478
    }
ali@24
   479
#endif
ali@31
   480
    plover_exception_handler_init();
ali@24
   481
    if (argc>1 && !strcmp(argv[1],"-u"))
ali@24
   482
    {
ali@24
   483
	success=pre_uninstall();
ali@24
   484
	argc--;
ali@24
   485
	argv++;
ali@24
   486
    }
ali@24
   487
    else
ali@24
   488
#ifdef WIN32
ali@24
   489
	success=win32_pre_install_gui(argv[0])==EXIT_SUCCESS;
ali@24
   490
#else
ali@24
   491
	success=!!pre_install(argv[0]);
ali@24
   492
#endif
ali@24
   493
    if (argc>1 && !strcmp(argv[1],"--post") &&
ali@24
   494
      !run_post(argc-1,argv+1,success,&error))
ali@24
   495
    {
ali@24
   496
#ifndef WIN32
ali@24
   497
	fprintf(stderr,"Error in post: %s\n",error->message);
ali@24
   498
#else
ali@24
   499
	MessageBox(NULL,error->message,"Error in post",MB_ICONERROR|MB_OK);
ali@24
   500
#endif
ali@24
   501
	g_error_free(error);
ali@24
   502
	success=FALSE;
ali@24
   503
    }
ali@24
   504
#ifdef WIN32
ali@24
   505
    return success?EXIT_SUCCESS:EXIT_FAILURE;
ali@24
   506
#else
ali@24
   507
    return success?0:1;
ali@24
   508
#endif
ali@24
   509
}