~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201207201942

« back to all changes in this revision

Viewing changes to guestd/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-03-20 10:19:00 UTC
  • mfrom: (1.1.4 upstream) (2.4.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090320101900-1o604camiubq2de8
Tags: 2009.03.18-154848-2
Correcting patch system depends (Closes: #520493).

Show diffs side-by-side

added added

removed removed

Lines of Context:
68
68
#   include "miscSolaris.h"
69
69
#endif
70
70
 
71
 
/* XXX Refactor this.  Push VM_GUESTD_MOUNTS_HGFS to whomever builds this file. */
72
 
#if defined(sun)
73
 
#   define VM_GUESTD_MOUNTS_HGFS 1
74
 
#   define VM_GUESTD_RUNS_HGFS_PSERVER 1
75
 
#endif
76
 
 
77
 
 
78
 
/* Headers needed by the hgfs pserver */
79
 
#if defined(VM_GUESTD_MOUNTS_HGFS)
80
 
#   if defined(sun)
81
 
#      include <sys/param.h>
82
 
#      include <sys/mount.h>
83
 
#      include <sys/stat.h>
84
 
#      include <fcntl.h>
85
 
#   endif
86
 
#endif
87
 
#if defined(VM_GUESTD_RUNS_HGFS_PSERVER)
88
 
#   include "hgfsDevLinux.h"
89
 
#   include "hgfsBd.h"
90
 
#   include "hgfsProto.h"
91
 
#   include "hgfs.h"
92
 
#endif
93
71
#include "procMgr.h"
94
72
#include "guestd_version.h"
95
73
 
109
87
#define EXEC_LOG                    "/var/log/vmware-tools-guestd"
110
88
#define UPGRADER_FILENAME           "vmware-tools-upgrader"
111
89
 
112
 
#if defined(VM_GUESTD_MOUNTS_HGFS)
113
 
 /*
114
 
  * The Hgfs device is in /dev.  Solaris' umount program doesn't
115
 
  * unmount filesystem's with name's longer than 8 characters, so we shorten
116
 
  * it.  Solaris' mount(2) doesn't take NULL as the mount source, so we
117
 
  * specify anything to get past the Kernel's VFS mount function.  We also
118
 
  * need to specify MS_DATA so it looks for the optional data we pass in.
119
 
  */
120
 
#   define HGFS_FS_NAME           "vmhgfs"
121
 
#   define HGFS_MOUNT_SRC         "/hgfs"
122
 
#   if defined(sun)
123
 
#      define HGFS_DEVICE            "/dev/vmware-hgfs"
124
 
#      define HGFS_MOUNT_FLAGS       MS_DATA                    /* from <sys/mount.h> */
125
 
#   endif
126
 
#endif
127
90
 
128
91
/*
129
92
 * All signals that:
152
115
static int gDaemonSignal;
153
116
static int gCommandLineRpciSignal;
154
117
 
155
 
#ifdef VM_GUESTD_MOUNTS_HGFS
156
 
typedef struct HgfsMountState {
157
 
   const char *mountPoint; /* Mount point for hgfs filesystem */
158
 
   Bool mounted;           /* TRUE if mounted, FALSE if not */
159
 
} HgfsMountState;
160
 
#endif
161
 
 
162
 
#ifdef VM_GUESTD_RUNS_HGFS_PSERVER
163
 
/* Hgfs state needed per mounted filesystem */
164
 
typedef struct PserverState {
165
 
   HgfsMountState mountState;
166
 
   char *requestPacket;    /* Buffer for request packets */
167
 
   RpcOut *out;            /* Backdoor communications channel */
168
 
   int fd;                 /* Hgfs device fd (communication with kernel) */
169
 
} PserverState;
170
 
 
171
 
static PserverState globalHgfsState = {
172
 
   {NULL, FALSE},  /* mountState */
173
 
   NULL,           /* requestPacket */
174
 
   NULL,           /* out */
175
 
   -1              /* fd */
176
 
};
177
 
#elif defined(VM_GUESTD_MOUNTS_HGFS)
178
 
static HgfsMountState globalHgfsState = {
179
 
   NULL, /* mountPoint */
180
 
   FALSE /* mounted */
181
 
};
182
 
#endif
183
 
 
184
 
#ifdef VM_GUESTD_MOUNTS_HGFS
185
 
/*
186
 
 *-----------------------------------------------------------------------------
187
 
 *
188
 
 * HgfsMountState_Cleanup --
189
 
 *
190
 
 *      Unmounts the hgfs filesystem
191
 
 *
192
 
 * Results:
193
 
 *      TRUE on success.
194
 
 *      FALSE if one or more steps failed.
195
 
 *
196
 
 * Side effects:
197
 
 *      Unmounts the filesystem and cleans up the HgfsMountState structure.
198
 
 *
199
 
 *-----------------------------------------------------------------------------
200
 
 */
201
 
 
202
 
static Bool
203
 
HgfsMountState_Cleanup(HgfsMountState *state) // IN: Hgfs mount state
204
 
{
205
 
   Bool success = TRUE;
206
 
   int result;
207
 
 
208
 
   ASSERT(state);
209
 
 
210
 
   /* Try to unmount hgfs */
211
 
   if (state->mounted) {
212
 
      Debug("HgfsMountState_Cleanup: attempting to unmount %s\n",
213
 
            state->mountPoint);
214
 
#if defined(sun)
215
 
      result = umount(state->mountPoint);
216
 
#endif
217
 
      if (result < 0) {
218
 
         int error = errno;
219
 
         Debug("HgfsMountState_Cleanup: error %d (%s) unmounting filesystem\n",
220
 
               error,
221
 
               strerror(error));
222
 
         success = FALSE;
223
 
      } else {
224
 
         state->mounted = FALSE;
225
 
         Debug("HgfsMountState_Cleanup: unmount succeeded\n");
226
 
      }
227
 
   }
228
 
   if (state->mountPoint) {
229
 
      free((void *)state->mountPoint);
230
 
      state->mountPoint = NULL;
231
 
   }
232
 
 
233
 
   return success;
234
 
}
235
 
 
236
 
/*
237
 
 *-----------------------------------------------------------------------------
238
 
 *
239
 
 * HgfsMountState_Init --
240
 
 *
241
 
 *      Mounts the hgfs filesystem
242
 
 *
243
 
 * Results:
244
 
 *      TRUE on success.
245
 
 *      FALSE if one or more steps failed.
246
 
 *
247
 
 * Side effects:
248
 
 *      Allocates a copy of the mount point string, updates the HgfsMountState structure,
249
 
 *      and mounts the filesystem.
250
 
 *
251
 
 *-----------------------------------------------------------------------------
252
 
 */
253
 
 
254
 
static Bool
255
 
HgfsMountState_Init(HgfsMountState *state,   // IN: Hgfs mount state
256
 
                    const char *pMountPoint, // IN: Shared folder mount target
257
 
                    int fd)                  // IN: Pserver file descriptor, or -1
258
 
{
259
 
   int mntRes;
260
 
 
261
 
   ASSERT(state);
262
 
   ASSERT(pMountPoint);
263
 
 
264
 
   state->mountPoint = strdup(pMountPoint);
265
 
   state->mounted = FALSE;
266
 
 
267
 
#if defined(sun)
268
 
   {
269
 
      HgfsMountInfo mntInfo;   /* Data to pass to kernel when mounting */
270
 
 
271
 
      mntInfo.fd = fd;
272
 
      mntInfo.version = HGFS_PROTOCOL_VERSION;
273
 
      mntInfo.magicNumber = HGFS_SUPER_MAGIC;
274
 
 
275
 
      Debug("HgfsMountState_Init: trying to mount %s...\n", state->mountPoint);
276
 
      mntRes = mount(HGFS_MOUNT_SRC, state->mountPoint, HGFS_MOUNT_FLAGS,
277
 
                     HGFS_FS_NAME, &mntInfo, sizeof mntInfo);
278
 
   }
279
 
#endif
280
 
 
281
 
   if (mntRes == -1) {
282
 
      int error = errno;
283
 
      Debug("HgfsMountState_Init: mount failed: %s\n", strerror(error));
284
 
      HgfsMountState_Cleanup(state);
285
 
      return FALSE;
286
 
   }
287
 
   state->mounted = TRUE;
288
 
   Debug("HgfsMountState_Init: mount succeeded\n");
289
 
 
290
 
   return TRUE;
291
 
}
292
 
#endif
293
 
 
294
 
/*
295
 
 * Hgfs pserver functions
296
 
 */
297
 
 
298
 
#ifdef VM_GUESTD_RUNS_HGFS_PSERVER
299
 
/*
300
 
 *-----------------------------------------------------------------------------
301
 
 *
302
 
 * HgfsPserver_Cleanup --
303
 
 *
304
 
 *    Teardown the communication channel with the server, unmount this
305
 
 *    hgfs filesystem, and close the driver proc file.
306
 
 *
307
 
 * Results:
308
 
 *    TRUE on success.
309
 
 *    FALSE if one or more steps failed.
310
 
 *
311
 
 * Side effects:
312
 
 *    None.
313
 
 *
314
 
 *-----------------------------------------------------------------------------
315
 
 */
316
 
 
317
 
static Bool
318
 
HgfsPserver_Cleanup(PserverState *state) // IN: State for this mount
319
 
{
320
 
   Bool success = TRUE;
321
 
   int result;
322
 
 
323
 
   ASSERT(state);
324
 
 
325
 
   /* Try to close the backdoor */
326
 
   if (!HgfsBd_CloseBackdoor(&state->out)) {
327
 
      Debug("HgfsPserver_Cleanup: failed to close backdoor\n");
328
 
      success = FALSE;
329
 
   }
330
 
   state->out = NULL;
331
 
 
332
 
   /* Release the request packet buffer */
333
 
   if (state->requestPacket) {
334
 
      HgfsBd_PutBuf(state->requestPacket);
335
 
      state->requestPacket = NULL;
336
 
   }
337
 
 
338
 
   /*
339
 
    * XXX The unmount should be done in the driver (NOT here), in case
340
 
    * the pserver gets killed or is misbehaved.
341
 
    */
342
 
   if (!HgfsMountState_Cleanup(&state->mountState)) {
343
 
      success = FALSE;
344
 
   }
345
 
 
346
 
   /* Try to close the hgfs device */
347
 
   if (state->fd >= 0) {
348
 
      result = close(state->fd);
349
 
      if (result < 0) {
350
 
         int error = errno;
351
 
         Debug("HgfsPserver_Cleanup: failed to close file: %s\n",
352
 
               strerror(error));
353
 
         success = FALSE;
354
 
      }
355
 
      state->fd = -1;
356
 
   }
357
 
 
358
 
   return success;
359
 
}
360
 
 
361
 
 
362
 
/*
363
 
 *-----------------------------------------------------------------------------
364
 
 *
365
 
 * HgfsPserver_Init --
366
 
 *
367
 
 *    Set up pserver communication state.
368
 
 *
369
 
 *    Specifically: open the proc file, try to mount the filesystem,
370
 
 *    get a request packet buffer from the backdoor layer and open the
371
 
 *    backdoor communication channel.
372
 
 *
373
 
 * Results:
374
 
 *    TRUE on success
375
 
 *    FALSE on failure
376
 
 *
377
 
 * Side effects:
378
 
 *    None
379
 
 *
380
 
 *-----------------------------------------------------------------------------
381
 
 */
382
 
 
383
 
static Bool
384
 
HgfsPserver_Init(PserverState *state,     // IN/OUT: State for this mount
385
 
                 const char *pMountPoint) // IN: Shared folder mount target
386
 
{
387
 
   ASSERT(state);
388
 
   ASSERT(pMountPoint);
389
 
 
390
 
   state->fd = -1;
391
 
   state->out = NULL;
392
 
   state->requestPacket = NULL;
393
 
 
394
 
   state->fd = open(HGFS_DEVICE, O_RDWR | O_NONBLOCK);
395
 
   if (state->fd < 0) {
396
 
      int error = errno;
397
 
      Debug("HgfsPserver_Init: error opening proc file: %s\n",
398
 
            strerror(error));
399
 
      HgfsPserver_Cleanup(state);
400
 
      return FALSE;
401
 
   }
402
 
 
403
 
   /*
404
 
    * We need to make sure children of guestd do not inherit
405
 
    * this file descriptor, otherwise they'll keep references to
406
 
    * the hgfs module.
407
 
    */
408
 
   if ((fcntl(state->fd, F_SETFD, FD_CLOEXEC)) < 0) {
409
 
      int error = errno;
410
 
      Debug("HgfsPserver_Init: error setting proc file flags: %s\n",
411
 
            strerror(error));
412
 
      HgfsPserver_Cleanup(state);
413
 
      return FALSE;
414
 
   }
415
 
 
416
 
   if (HgfsMountState_Init(&state->mountState, pMountPoint, state->fd) == FALSE) {
417
 
      HgfsPserver_Cleanup(state);
418
 
      return FALSE;
419
 
   }
420
 
 
421
 
   /*
422
 
    * Eventually we may want to frob /etc/mtab here to reflect the
423
 
    * mount.
424
 
    */
425
 
 
426
 
   state->requestPacket = HgfsBd_GetBuf();
427
 
   if (!state->requestPacket) {
428
 
      Debug("HgfsPserver_Init: couldn't get bd buffer\n");
429
 
      HgfsPserver_Cleanup(state);
430
 
      return FALSE;
431
 
   }
432
 
 
433
 
   return TRUE;
434
 
}
435
 
 
436
 
 
437
 
/*
438
 
 *-----------------------------------------------------------------------------
439
 
 *
440
 
 * HgfsPserverHandleRequest --
441
 
 *
442
 
 *      Read a request from the driver, send it to the server, and
443
 
 *      pass the reply back to the driver.
444
 
 *
445
 
 * Results:
446
 
 *      TRUE on success
447
 
 *      FALSE on failure
448
 
 *
449
 
 * Side effects:
450
 
 *      None
451
 
 *
452
 
 *-----------------------------------------------------------------------------
453
 
 */
454
 
 
455
 
static Bool
456
 
HgfsPserverHandleRequest(PserverState *pState) // IN: Pserver state
457
 
{
458
 
   char const *replyPacket; // Buffer returned by HgfsBd_Dispatch
459
 
   size_t packetSize;
460
 
   int error;
461
 
   int n;
462
 
 
463
 
   ASSERT(pState);
464
 
 
465
 
   /* Get the request from the driver. */
466
 
   n = read(pState->fd, pState->requestPacket, HGFS_PACKET_MAX);
467
 
   if (n < 0) {
468
 
      error = errno;
469
 
      Debug("HgfsPserverHandleRequest: Read error from hgfs fd: %s\n",
470
 
            strerror(error));
471
 
      return FALSE;
472
 
   }
473
 
 
474
 
   packetSize = n;
475
 
 
476
 
   /*
477
 
    * Ensure the backdoor is open and then attempt to send the request across it
478
 
    * to the hgfs server. 
479
 
    *
480
 
    * Failure of either action may indicate that Shared Folders have been disabled,
481
 
    * in which case we send an error response to the fs module and clean up the
482
 
    * backdoor (so that it might be re-opened with a subsequent request).
483
 
    *
484
 
    * If both actions succeed, the replyPacket will have a valid reply and the
485
 
    * packetSize will be set to the size of the replyPacket contents.
486
 
    */
487
 
   if (!HgfsBd_OpenBackdoor(&pState->out) ||
488
 
       (HgfsBd_Dispatch(pState->out,
489
 
                        pState->requestPacket,
490
 
                        &packetSize,
491
 
                        &replyPacket) < 0)) {
492
 
      HgfsRequest *request = (HgfsRequest *)pState->requestPacket;
493
 
      HgfsReply errorReply;
494
 
 
495
 
      Debug("HgfsPserverHandleRequest: Problem sending request across backdoor\n");
496
 
 
497
 
      errorReply.id = request->id;
498
 
      errorReply.status = HGFS_STATUS_PROTOCOL_ERROR;
499
 
 
500
 
      n = write(pState->fd, &errorReply, sizeof errorReply);
501
 
      if (n < 0) {
502
 
         error = errno;
503
 
         Debug("HgfsPserverHandleRequest: Problem writing error reply: %s\n",
504
 
               strerror(error));
505
 
      }
506
 
 
507
 
      if (!HgfsBd_CloseBackdoor(&pState->out)) {
508
 
         Debug("HgfsPserverHandleRequest: Problem closing backdoor\n");
509
 
      }
510
 
 
511
 
      return FALSE;
512
 
   }
513
 
 
514
 
   ASSERT(replyPacket);
515
 
   ASSERT(packetSize);
516
 
 
517
 
   /* Send reply to driver */
518
 
   n = write(pState->fd, replyPacket, packetSize);
519
 
   if (n < 0) {
520
 
      error = errno;
521
 
      Debug("HgfsPserverHandleRequest: Write error to file: %s\n", strerror(error));
522
 
      return FALSE;
523
 
   }
524
 
 
525
 
   return TRUE;
526
 
}
527
 
#endif
528
 
 
529
 
#if defined(VM_GUESTD_MOUNTS_HGFS)
530
 
/*
531
 
 *-----------------------------------------------------------------------------
532
 
 *
533
 
 * GuestdGetValidMountPt --
534
 
 *
535
 
 *    Return returns the shared folder mount point from the configuration
536
 
 *    dictionary with trailing /'s removed.  The caller is responsible for
537
 
 *    freeing the returned string.
538
 
 *
539
 
 * Return value:
540
 
 *    NULL on failure (No entry in configuration dictionary or the entry
541
 
 *    consisted of 0 or more consecutive /'s.
542
 
 *    non-NULL on success (Pointer to valid name, with trailing /'s
543
 
 *    removed).
544
 
 *
545
 
 * Side effects:
546
 
 *    None
547
 
 *
548
 
 *-----------------------------------------------------------------------------
549
 
 */
550
 
 
551
 
static const char *
552
 
GuestdGetValidMountPt(GuestApp_Dict *Dict) // IN: Configuration dictionary
553
 
{
554
 
   const char *pMount = GuestApp_GetDictEntry(Dict, CONFNAME_MOUNT_POINT);
555
 
   const char *end;
556
 
   char *p;
557
 
   int len;
558
 
 
559
 
   if (!pMount) {
560
 
      return NULL;
561
 
   }
562
 
 
563
 
   len = strlen(pMount);
564
 
   if (len <= 0) {
565
 
      return NULL;
566
 
   }
567
 
 
568
 
   for (end = &pMount[len - 1]; end > pMount; end--) {
569
 
      if (*end != '/') {
570
 
         break;
571
 
      }
572
 
   }
573
 
   if (end == pMount) {
574
 
      /*
575
 
       * Pathological case string consisting of all /'s
576
 
       */
577
 
      return NULL;
578
 
   }
579
 
 
580
 
   /*
581
 
    * end points to the last non-/ (and non-'\0') character in pMount.
582
 
    */
583
 
   p = strdup(pMount);
584
 
   if (p) {
585
 
      p[end - pMount + 1] = '\0';
586
 
   }
587
 
   return p;
588
 
}
589
 
#endif /* VM_GUESTD_MOUNTS_HGFS */
590
 
 
591
118
 
592
119
/*
593
120
 *-----------------------------------------------------------------------------
873
400
#endif
874
401
   struct timeval tv;
875
402
   int status;
876
 
#if defined(VM_GUESTD_RUNS_HGFS_PSERVER)
877
 
   PserverState *pState = &globalHgfsState;
878
 
#endif
879
403
 
880
404
   ASSERT(tdData);
881
405
 
901
425
      maxFd = asyncFd;
902
426
   }
903
427
 
904
 
#if defined(VM_GUESTD_RUNS_HGFS_PSERVER)
905
 
   /* If hgfs is enabled, add its fd */
906
 
   if (pState->fd >= 0) {
907
 
      FD_SET(pState->fd, &readFds);
908
 
      if (pState->fd > maxFd) {
909
 
         maxFd = pState->fd;
910
 
      }
911
 
   }
912
 
#endif
913
 
 
914
428
#if !defined(__FreeBSD__) && !defined(sun) && !defined(__APPLE__)
915
429
   SocketMgr_GetSelectables(SOCKETMGR_IN,
916
430
                            &sockReadFds,
943
457
   } else if (status > 0) {
944
458
      Debug("Select returned status > 0\n");
945
459
 
946
 
#ifdef VM_GUESTD_RUNS_HGFS_PSERVER
947
 
      if (pState->fd >= 0 && FD_ISSET(pState->fd, &readFds)) {
948
 
         /* There is an hgfs request waiting in the driver. */
949
 
         HgfsPserverHandleRequest(pState);
950
 
      }
951
 
#endif
952
 
 
953
460
      if (curAsyncProc && FD_ISSET(asyncFd, &readFds)) {
954
461
         /* The async proc fd was written to */
955
462
 
1017
524
   ToolsDaemon_Data *data = NULL;
1018
525
   VmBackupSyncProvider *syncProvider = NULL;
1019
526
 
1020
 
#if VM_GUESTD_MOUNTS_HGFS
1021
 
   const char *mountPoint = GuestdGetValidMountPt(*pConfDict);
1022
 
 
1023
 
   if (!mountPoint) {
1024
 
      Warning("Could not determine shared folder mount point, %s occurred.\n",
1025
 
              strerror(errno));
1026
 
   } else if (!Util_MakeSureDirExistsAndAccessible(mountPoint, 0755)) {
1027
 
      Warning("Shared folder mount point %s is not an accessible directory.\n",
1028
 
              mountPoint);
1029
 
      /*
1030
 
       * free what GuestdGetValidMountPt allocated.
1031
 
       */
1032
 
      free((void *)mountPoint);
1033
 
      mountPoint = NULL;
1034
 
   } else {
1035
 
#   ifdef VM_GUESTD_RUNS_HGFS_PSERVER
1036
 
      /* Setup the hgfs pserver (guest can operate on host file name space) */
1037
 
      if (HgfsPserver_Init(&globalHgfsState, mountPoint) == FALSE) {
1038
 
         Warning("Unable to start hgfs.\n");
1039
 
      }
1040
 
#   else
1041
 
      /* Just mount the hgfs filesystem */
1042
 
      if (HgfsMountState_Init(&globalHgfsState, mountPoint, -1) == FALSE) {
1043
 
         Warning("Unable to mount hgfs.\n");
1044
 
      }
1045
 
#   endif
1046
 
 
1047
 
      free((void *)mountPoint);
1048
 
   }
1049
 
#endif
1050
 
 
1051
527
   data = ToolsDaemon_Init(pConfDict, EXEC_LOG,
1052
528
                           GuestdExecuteHalt, pConfDict,
1053
529
                           GuestdExecuteReboot, pConfDict,
1083
559
   syncProvider = VmBackup_NewSyncDriverProvider();
1084
560
   if (syncProvider != NULL) {
1085
561
      Bool loggingEnabled = GuestApp_GetDictEntryBool(*pConfDict, CONFNAME_LOG);
1086
 
      VmBackup_Init(data->in, ToolsDaemonEventQueue, syncProvider, 
 
562
      VmBackup_Init(data->in, ToolsDaemonEventQueue, syncProvider,
1087
563
                    loggingEnabled);
1088
564
   } else {
1089
565
      Debug("No vmBackup implementation available!\n");
1137
613
   if (guestInfoEnabled) {
1138
614
      GuestInfoServer_Cleanup();
1139
615
   }
1140
 
#if defined(VM_GUESTD_RUNS_HGFS_PSERVER)
1141
 
   HgfsPserver_Cleanup(&globalHgfsState);
1142
 
#elif defined(VM_GUESTD_MOUNTS_HGFS)
1143
 
   HgfsMountState_Cleanup(&globalHgfsState);
1144
 
#endif
 
616
 
1145
617
   if (syncProvider != NULL) {
1146
618
      VmBackup_Shutdown(data->in);
1147
619
   }
1241
713
 
1242
714
      /*
1243
715
       * XXX There is an assumption that if the process with pid is alive,
1244
 
       * the process is just guestd. Actually the process name should be 
1245
 
       * also checked because it is possible that there is another process 
 
716
       * the process is just guestd. Actually the process name should be
 
717
       * also checked because it is possible that there is another process
1246
718
       * with same pid. 2 reasons it is not checked. First we can not find
1247
719
       * a cross-platform method to check the process name. Second is that
1248
720
       * the possibility is very low in our case because the PID file should
1249
721
       * always be with guestd process. Even user manually kills the guestd,
1250
 
       * the PID file will also be removed. Perhaps longer term we should 
1251
 
       * add a function like System_GetProcessName(pid_t) to 
1252
 
       * bora-vmsoft/lib/system that will hide the platform-specific 
1253
 
       * messiness. 
 
722
       * the PID file will also be removed. Perhaps longer term we should
 
723
       * add a function like System_GetProcessName(pid_t) to
 
724
       * bora-vmsoft/lib/system that will hide the platform-specific
 
725
       * messiness.
1254
726
       */
1255
 
      if (pid != getpid() && kill(pid, 0) == 0) {  
 
727
      if (pid != getpid() && kill(pid, 0) == 0) {
1256
728
         return TRUE;
1257
729
      }
1258
730
      /*
1259
731
       * If process with pid is dead, the PID file will be removed. If pid
1260
 
       * is same as getpid(), PID file will also be removed. 
 
732
       * is same as getpid(), PID file will also be removed.
1261
733
       */
1262
734
      unlink(pidFileName);
1263
735
   }