~ubuntu-branches/ubuntu/karmic/gnustep-base/karmic

« back to all changes in this revision

Viewing changes to Source/NSTask.m

  • Committer: Bazaar Package Importer
  • Author(s): Eric Heintzmann
  • Date: 2005-04-17 00:14:38 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050417001438-enf0y07c9tku85z1
Tags: 1.10.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
22
22
 
23
23
   <title>NSTask class reference</title>
24
 
   $Date: 2002/02/24 06:14:31 $ $Revision: 1.47 $
 
24
   $Date: 2005/04/12 18:12:43 $ $Revision: 1.70.2.1 $
25
25
   */
26
26
 
27
 
#include <config.h>
28
 
#include <base/preface.h>
29
 
#include <Foundation/NSObject.h>
30
 
#include <Foundation/NSBundle.h>
31
 
#include <Foundation/NSData.h>
32
 
#include <Foundation/NSDate.h>
33
 
#include <Foundation/NSString.h>
34
 
#include <Foundation/NSException.h>
35
 
#include <Foundation/NSFileHandle.h>
36
 
#include <Foundation/NSFileManager.h>
37
 
#include <Foundation/NSMapTable.h>
38
 
#include <Foundation/NSProcessInfo.h>
39
 
#include <Foundation/NSRunLoop.h>
40
 
#include <Foundation/NSNotification.h>
41
 
#include <Foundation/NSNotificationQueue.h>
42
 
#include <Foundation/NSTask.h>
43
 
#include <Foundation/NSTimer.h>
44
 
#include <Foundation/NSLock.h>
45
 
#include <Foundation/NSDebug.h>
 
27
#include "config.h"
 
28
#include "GNUstepBase/preface.h"
 
29
#include "Foundation/NSObject.h"
 
30
#include "Foundation/NSAutoreleasePool.h"
 
31
#include "Foundation/NSBundle.h"
 
32
#include "Foundation/NSCharacterSet.h"
 
33
#include "Foundation/NSData.h"
 
34
#include "Foundation/NSDate.h"
 
35
#include "Foundation/NSEnumerator.h"
 
36
#include "Foundation/NSString.h"
 
37
#include "Foundation/NSException.h"
 
38
#include "Foundation/NSFileHandle.h"
 
39
#include "Foundation/NSFileManager.h"
 
40
#include "Foundation/NSMapTable.h"
 
41
#include "Foundation/NSProcessInfo.h"
 
42
#include "Foundation/NSRunLoop.h"
 
43
#include "Foundation/NSNotification.h"
 
44
#include "Foundation/NSNotificationQueue.h"
 
45
#include "Foundation/NSTask.h"
 
46
#include "Foundation/NSTimer.h"
 
47
#include "Foundation/NSLock.h"
 
48
#include "Foundation/NSDebug.h"
46
49
 
47
50
#include <string.h>
48
 
#if HAVE_UNISTD_H
 
51
#ifdef HAVE_UNISTD_H
49
52
#include <unistd.h>
50
53
#endif
51
54
#include <sys/types.h>
53
56
#include <fcntl.h>
54
57
#endif
55
58
 
56
 
#if HAVE_WINDOWS_H
 
59
#ifdef HAVE_WINDOWS_H
57
60
#  include <windows.h>
58
61
#endif
59
62
 
60
 
#if     HAVE_SYS_SIGNAL_H
 
63
#ifdef  HAVE_SYS_SIGNAL_H
61
64
#include <sys/signal.h>
62
65
#endif
63
 
#if     HAVE_SIGNAL_H
 
66
#ifdef  HAVE_SIGNAL_H
64
67
#include <signal.h>
65
68
#endif
66
 
#if     HAVE_SYS_FILE_H
 
69
#ifdef  HAVE_SYS_FILE_H
67
70
#include <sys/file.h>
68
71
#endif
69
 
#if     HAVE_SYS_FCNTL_H
 
72
#ifdef  HAVE_SYS_FCNTL_H
70
73
#include <sys/fcntl.h>
71
74
#endif
72
 
#if     HAVE_SYS_IOCTL_H
 
75
#ifdef  HAVE_SYS_IOCTL_H
73
76
#include <sys/ioctl.h>
74
77
#endif
75
 
#if     HAVE_SYS_WAIT_H
 
78
#ifdef  HAVE_SYS_WAIT_H
76
79
#include <sys/wait.h>
77
80
#endif
78
 
#if     HAVE_SYS_PARAM_H
 
81
#ifdef  HAVE_SYS_PARAM_H
79
82
#include <sys/param.h>
80
83
#endif
81
84
 
83
86
 *      If we are on a streams based system, we need to include stropts.h
84
87
 *      for definitions needed to set up slave pseudo-terminal stream.
85
88
 */
86
 
#if     HAVE_SYS_STROPTS_H
 
89
#ifdef  HAVE_SYS_STROPTS_H
87
90
#include <sys/stropts.h>
88
91
#endif
89
92
 
98
101
#define NOFILE  256
99
102
#endif
100
103
 
101
 
NSString *NSTaskDidTerminateNotification = @"NSTaskDidTerminateNotification";
102
104
 
103
105
static NSRecursiveLock  *tasksLock = nil;
104
106
static NSMapTable       *activeTasks = 0;
115
117
#ifdef __MINGW__
116
118
@interface NSConcreteWindowsTask : NSTask
117
119
{
118
 
  PROCESS_INFORMATION proc_info;
 
120
@public
 
121
  PROCESS_INFORMATION   procInfo;
 
122
  HANDLE                wThread;
119
123
}
120
124
@end
121
125
#define NSConcreteTask NSConcreteWindowsTask
137
141
   *    If we have grantpt(), assume we are using sysv-style pseudo-terminals,
138
142
   *    otherwise assume bsd style.
139
143
   */
140
 
#if     HAVE_GRANTPT
 
144
#ifdef  HAVE_GRANTPT
141
145
  master = open("/dev/ptmx", O_RDWR);
142
146
  if (master >= 0)
143
147
    {
192
196
  int   slave;
193
197
 
194
198
  slave = open(name, O_RDWR);
195
 
#if     HAVE_SYS_STROPTS_H
196
 
#if     HAVE_PTS_STREAM_MODULES
 
199
#ifdef  HAVE_SYS_STROPTS_H
 
200
#ifdef  HAVE_PTS_STREAM_MODULES
197
201
  if (slave >= 0 && isastream(slave))
198
202
    {
199
203
      if (ioctl(slave, I_PUSH, "ptem") < 0)
499
503
 */
500
504
- (void) setStandardError: (id)hdl
501
505
{
502
 
  NSAssert([hdl isKindOfClass: [NSFileHandle class]] ||
503
 
           [hdl isKindOfClass: [NSPipe class]], NSInvalidArgumentException);
504
506
  if (_hasLaunched)
505
507
    {
506
508
      [NSException raise: NSInvalidArgumentException
507
509
                  format: @"NSTask - task has been launched"];
508
510
    }
 
511
  NSAssert(hdl != nil && ([hdl isKindOfClass: [NSFileHandle class]] ||
 
512
    [hdl isKindOfClass: [NSPipe class]]), NSInvalidArgumentException);
509
513
  ASSIGN(_standardError, hdl);
510
514
}
511
515
 
521
525
 */
522
526
- (void) setStandardInput: (id)hdl
523
527
{
524
 
  NSAssert([hdl isKindOfClass: [NSFileHandle class]] ||
525
 
           [hdl isKindOfClass: [NSPipe class]], NSInvalidArgumentException);
526
528
  if (_hasLaunched)
527
529
    {
528
530
      [NSException raise: NSInvalidArgumentException
529
531
                  format: @"NSTask - task has been launched"];
530
532
    }
 
533
  NSAssert(hdl != nil && ([hdl isKindOfClass: [NSFileHandle class]] ||
 
534
    [hdl isKindOfClass: [NSPipe class]]), NSInvalidArgumentException);
531
535
  ASSIGN(_standardInput, hdl);
532
536
}
533
537
 
539
543
 * The default behavior is to inherit the parent processes
540
544
 * stdout stream.<br />
541
545
 * This method cannot be used after a task is launched ...
542
 
 * it raises an NSInvalidArgumentException. 
 
546
 * it raises an NSInvalidArgumentException.
543
547
 */
544
548
- (void) setStandardOutput: (id)hdl
545
549
{
546
 
  NSAssert([hdl isKindOfClass: [NSFileHandle class]] ||
547
 
           [hdl isKindOfClass: [NSPipe class]], NSInvalidArgumentException);
548
550
  if (_hasLaunched)
549
551
    {
550
552
      [NSException raise: NSInvalidArgumentException
551
553
                  format: @"NSTask - task has been launched"];
552
554
    }
 
555
  NSAssert(hdl != nil && ([hdl isKindOfClass: [NSFileHandle class]] ||
 
556
    [hdl isKindOfClass: [NSPipe class]]), NSInvalidArgumentException);
553
557
  ASSIGN(_standardOutput, hdl);
554
558
}
555
559
 
606
610
    }
607
611
#ifndef __MINGW__
608
612
#ifdef  HAVE_KILLPG
609
 
  killpg(_taskId, SIGTERM);
 
613
  killpg(_taskId, SIGSTOP);
610
614
#else
611
 
  kill(-_taskId, SIGTERM);
 
615
  kill(-_taskId, SIGSTOP);
612
616
#endif
613
617
#endif
614
618
  return YES;
617
621
/**
618
622
 * Sends a terminate signal to the receiver and any subtasks.<br />
619
623
 * If the task has not been launched, raises an
620
 
 * NSInvalidArgumentException.<br />
 
624
 * <code>NSInvalidArgumentException</code>.<br />
621
625
 * Has no effect on a task that has already terminated.<br />
622
 
 * When a task temrinates, either due to this method being called,
623
 
 * or normal termination, an NSTaskDidTerminateNotification is
 
626
 * When a task terminates, either due to this method being called,
 
627
 * or normal termination, an <code>NSTaskDidTerminateNotification</code> is
624
628
 * posted.
625
629
 */
626
630
- (void) terminate
737
741
  full_path = [arch_path stringByAppendingPathComponent: libs];
738
742
 
739
743
  lpath = [full_path stringByAppendingPathComponent: prog];
 
744
#ifdef  __MINGW__
 
745
  if ([mgr isExecutableFileAtPath: lpath] == NO
 
746
    && [mgr isExecutableFileAtPath:
 
747
    (lpath = [lpath stringByAppendingPathExtension: @"exe"])] == NO)
 
748
#else
740
749
  if ([mgr isExecutableFileAtPath: lpath] == NO)
 
750
#endif
741
751
    {
742
752
      lpath = [arch_path stringByAppendingPathComponent: prog];
 
753
#ifdef  __MINGW__
 
754
      if ([mgr isExecutableFileAtPath: lpath] == NO
 
755
        && [mgr isExecutableFileAtPath:
 
756
        (lpath = [lpath stringByAppendingPathExtension: @"exe"])] == NO)
 
757
#else
743
758
      if ([mgr isExecutableFileAtPath: lpath] == NO)
 
759
#endif
744
760
        {
745
761
          lpath = [base_path stringByAppendingPathComponent: prog];
 
762
#ifdef  __MINGW__
 
763
          if ([mgr isExecutableFileAtPath: lpath] == NO
 
764
            && [mgr isExecutableFileAtPath:
 
765
            (lpath = [lpath stringByAppendingPathExtension: @"exe"])] == NO)
 
766
#else
746
767
          if ([mgr isExecutableFileAtPath: lpath] == NO)
 
768
#endif
747
769
            {
748
770
              /*
749
771
               * Last resort - if the launch path was simply a program name
754
776
                {
755
777
                  lpath = [NSBundle _absolutePathOfExecutable: prog];
756
778
                }
757
 
              if (lpath != nil && [mgr isExecutableFileAtPath: lpath] == NO)
 
779
              if (lpath != nil)
758
780
                {
759
 
                  lpath = nil;
 
781
#ifdef  __MINGW__
 
782
                  if ([mgr isExecutableFileAtPath: lpath] == NO
 
783
                    && [mgr isExecutableFileAtPath:
 
784
                    (lpath = [lpath stringByAppendingPathExtension: @"exe"])]
 
785
                    == NO)
 
786
#else
 
787
                  if ([mgr isExecutableFileAtPath: lpath] == NO)
 
788
#endif
 
789
                    {
 
790
                      lpath = nil;
 
791
                    }
760
792
                }
761
793
            }
762
794
        }
877
909
BOOL
878
910
GSCheckTasks()
879
911
{
880
 
  /* FIXME: Implement */
881
 
  return YES;
 
912
  BOOL  found = NO;
 
913
 
 
914
  if (hadChildSignal == YES)
 
915
    {
 
916
      NSArray   *a;
 
917
      unsigned  c;
 
918
 
 
919
      hadChildSignal = NO;
 
920
      [tasksLock lock];
 
921
      a = NSAllMapTableValues(activeTasks);
 
922
      [tasksLock unlock];
 
923
      c = [a count];
 
924
      while (c-- > 0)
 
925
        {
 
926
          NSConcreteWindowsTask *t = [a objectAtIndex: c];
 
927
          DWORD                 eCode;
 
928
 
 
929
          if (GetExitCodeProcess(t->procInfo.hProcess, &eCode) != 0)
 
930
            {
 
931
              if (eCode != STILL_ACTIVE)
 
932
                {
 
933
                  [t _terminatedChild: eCode];
 
934
                  found = YES;
 
935
                }
 
936
            }
 
937
        }
 
938
    }
 
939
  return found;
882
940
}
883
941
 
884
942
- (void) gcFinalize
885
943
{
886
944
  [super gcFinalize];
887
 
  if (proc_info.hProcess != NULL)
888
 
    CloseHandle(proc_info.hProcess);
889
 
  if (proc_info.hThread != NULL)
890
 
    CloseHandle(proc_info.hThread);
 
945
  if (wThread != NULL)
 
946
    {
 
947
      CloseHandle(wThread);
 
948
    }
 
949
  if (procInfo.hProcess != NULL)
 
950
    {
 
951
      CloseHandle(procInfo.hProcess);
 
952
    }
 
953
  if (procInfo.hThread != NULL)
 
954
    {
 
955
      CloseHandle(procInfo.hThread);
 
956
    }
891
957
}
892
958
 
893
959
- (void) interrupt
907
973
    }
908
974
 
909
975
  _hasTerminated = YES;
910
 
  TerminateProcess(proc_info.hProcess, 10);
 
976
  TerminateProcess(procInfo.hProcess, 10);
 
977
}
 
978
 
 
979
/*
 
980
 * Wait for child process completion.
 
981
 */
 
982
static DWORD WINAPI _threadFunction(LPVOID t)
 
983
{
 
984
  DWORD milliseconds = 60000;
 
985
  int   taskId = [(NSTask*)t processIdentifier];
 
986
 
 
987
  for (;;)
 
988
    {
 
989
      NSConcreteWindowsTask     *task;
 
990
 
 
991
      [tasksLock lock];
 
992
      task = (NSConcreteWindowsTask*)NSMapGet(activeTasks, (void*)taskId);
 
993
      [tasksLock unlock];
 
994
      if (task == nil)
 
995
        {
 
996
          return 0;     // Task gone away.
 
997
        }
 
998
      switch (WaitForSingleObject(task->procInfo.hProcess, milliseconds))
 
999
        {
 
1000
          case WAIT_OBJECT_0:
 
1001
            handleSignal(0);    // Signal child process state change.
 
1002
            return 0;
 
1003
 
 
1004
          case WAIT_TIMEOUT:
 
1005
            break;              // Timeout ... retry
 
1006
 
 
1007
          default:
 
1008
            return 0;           // Error ... stop watching.
 
1009
        }
 
1010
    }
 
1011
}
 
1012
 
 
1013
 
 
1014
static NSString*
 
1015
endSlashesDoubledFromString(NSString *aString)
 
1016
{
 
1017
  int                   i = [aString length] - 2;
 
1018
  NSMutableString       *returnString;
 
1019
 
 
1020
  if (![aString hasSuffix:@"\\"])
 
1021
    {
 
1022
      return aString;
 
1023
    }
 
1024
  returnString = [NSMutableString stringWithFormat: @"%@\\", aString];
 
1025
  while ([aString characterAtIndex: i] == '\\' && i >= 0)
 
1026
    {
 
1027
      [returnString appendString:@"\\"];
 
1028
      i--;
 
1029
    }
 
1030
 
 
1031
  return returnString;
 
1032
}
 
1033
 
 
1034
static NSString*
 
1035
quotedFromString(NSString *aString)
 
1036
{
 
1037
  NSString              *resultString;
 
1038
  NSMutableArray        *components;
 
1039
  int                   i;
 
1040
 
 
1041
  /* First split on "'s */
 
1042
  components = [NSMutableArray arrayWithArray:
 
1043
    [aString componentsSeparatedByString: @"\""]];
 
1044
 
 
1045
  /* Iterate over all but the last component and double slashes if needed */
 
1046
  i = [components count];
 
1047
  while (i-- > 0)
 
1048
    {
 
1049
      [components replaceObjectAtIndex: i withObject:
 
1050
        endSlashesDoubledFromString([components objectAtIndex: i])];
 
1051
    }
 
1052
 
 
1053
  /* Join them again with \" as separator */
 
1054
  resultString = [components componentsJoinedByString: @"\\\""];
 
1055
 
 
1056
  /* Put in in "'s if it contains spaces */
 
1057
  if ([resultString rangeOfCharacterFromSet:
 
1058
    [NSCharacterSet whitespaceCharacterSet]].length > 0)
 
1059
    {
 
1060
      resultString = [NSString stringWithFormat: @"\"%@\"", resultString];
 
1061
    }
 
1062
  return resultString;
911
1063
}
912
1064
 
913
1065
- (void) launch
914
1066
{
915
 
  STARTUPINFO   start_info;
 
1067
  DWORD         tid;
 
1068
  STARTUPINFOW  start_info;
916
1069
  NSString      *lpath;
917
1070
  NSString      *arg;
918
1071
  NSEnumerator  *arg_enum;
919
1072
  NSMutableString *args;
920
 
  char          *c_args;
 
1073
  wchar_t       *w_args;
921
1074
  int           result;
 
1075
  const wchar_t *wexecutable;
 
1076
  LPVOID        envp = 0;
 
1077
  NSDictionary  *env;
922
1078
 
923
1079
  if (_hasLaunched)
924
1080
    {
926
1082
    }
927
1083
 
928
1084
  lpath = [self _fullLaunchPath];
929
 
  args = [lpath mutableCopy];
 
1085
  lpath = [lpath localFromOpenStepPath];
 
1086
  wexecutable = [lpath unicharString];
 
1087
 
 
1088
  args = [[NSMutableString alloc] initWithString: quotedFromString(lpath)];
930
1089
  arg_enum = [[self arguments] objectEnumerator];
931
1090
  while ((arg = [arg_enum nextObject]))
932
1091
    {
933
1092
      [args appendString: @" "];
934
 
      [args appendString: arg];
935
 
    }
936
 
  c_args = NSZoneMalloc(NSDefaultMallocZone(), [args cStringLength]+1);
937
 
  [args getCString: c_args];
 
1093
      [args appendString: quotedFromString(arg)];
 
1094
    }
 
1095
 
 
1096
  w_args = NSZoneMalloc(NSDefaultMallocZone(),
 
1097
    sizeof(wchar_t) * ([args length] + 1));
 
1098
  [args getCharacters: (unichar*)w_args];
 
1099
  w_args[[args length]] = 0;
 
1100
 
 
1101
  env = [self environment];
 
1102
  if ([env count] > 0)
 
1103
    {
 
1104
      NSMutableData     *data = [NSMutableData dataWithCapacity: 10240];
 
1105
      NSEnumerator      *enumerator;
 
1106
      NSString          *key;
 
1107
      unichar           terminator = 0;
 
1108
      CREATE_AUTORELEASE_POOL(pool);
 
1109
 
 
1110
      // Win32 environment variables must be sorted by name
 
1111
      enumerator = [[[env allKeys]
 
1112
        sortedArrayUsingSelector: @selector(compare:)] objectEnumerator];
 
1113
      while ((key = [enumerator nextObject]))
 
1114
        {
 
1115
          NSString      *value = [env objectForKey:key];
 
1116
          NSString      *setting;
 
1117
          unsigned      l;
 
1118
          NSRange       r = NSMakeRange(0,0);
 
1119
          unichar       buffer[1024];
 
1120
 
 
1121
          setting = [NSString stringWithFormat: @"%@=%@", key, value];
 
1122
          l = [setting length];
 
1123
          while (r.location < l)
 
1124
            {
 
1125
              r.length = l - r.location;
 
1126
              if (r.length > 1024)
 
1127
                {
 
1128
                  r.length = 1024;
 
1129
                }
 
1130
        
 
1131
              [setting getCharacters: buffer range: r];
 
1132
              [data appendBytes: buffer length: (r.length)*sizeof(unichar)];
 
1133
        
 
1134
              r.location += r.length;
 
1135
            }
 
1136
          [data appendBytes: &terminator length: 2];    // end of setting
 
1137
        }
 
1138
      [data appendBytes: &terminator length: 2];        // end of environment
 
1139
      RELEASE(pool);
 
1140
      envp = [data bytes];
 
1141
    }
938
1142
 
939
1143
  memset (&start_info, 0, sizeof(start_info));
940
1144
  start_info.cb = sizeof(start_info);
941
1145
  start_info.dwFlags |= STARTF_USESTDHANDLES;
942
 
  start_info.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
943
 
  start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
944
 
  start_info.hStdError  = GetStdHandle(STD_ERROR_HANDLE);
 
1146
  start_info.hStdInput = [[self standardInput] nativeHandle];
 
1147
  start_info.hStdOutput = [[self standardOutput] nativeHandle];
 
1148
  start_info.hStdError = [[self standardError] nativeHandle];
945
1149
 
946
 
  result = CreateProcess([lpath fileSystemRepresentation],
947
 
                         c_args,
948
 
                         NULL,      /* proc attrs */
949
 
                         NULL,      /* thread attrs */
950
 
                         1,         /* inherit handles */
951
 
                         0,         /* creation flags */
952
 
                         NULL,      /* env block */
953
 
                         [[self currentDirectoryPath] fileSystemRepresentation],
954
 
                         &start_info,
955
 
                         &proc_info);
956
 
  NSZoneFree(NSDefaultMallocZone(), c_args);
 
1150
  result = CreateProcessW(wexecutable,
 
1151
    w_args,
 
1152
    NULL,                       /* proc attrs */
 
1153
    NULL,                       /* thread attrs */
 
1154
    1,                          /* inherit handles */
 
1155
    CREATE_UNICODE_ENVIRONMENT, /* creation flags */
 
1156
    envp,                       /* env block */
 
1157
    [[[self currentDirectoryPath] localFromOpenStepPath] unicharString],
 
1158
    &start_info,
 
1159
    &procInfo);
 
1160
  NSZoneFree(NSDefaultMallocZone(), w_args);
957
1161
  if (result == 0)
958
1162
    {
959
1163
      NSLog(@"Error launching task: %@", lpath);
960
1164
      return;
961
1165
    }
962
 
  _taskId = proc_info.dwProcessId;
 
1166
 
 
1167
  _taskId = procInfo.dwProcessId;
963
1168
  _hasLaunched = YES;
964
1169
  ASSIGN(_launchPath, lpath);   // Actual path used.
965
1170
 
966
1171
  [tasksLock lock];
967
1172
  NSMapInsert(activeTasks, (void*)_taskId, (void*)self);
968
1173
  [tasksLock unlock];
 
1174
  /*
 
1175
   * Create thread to watch for termination of process.
 
1176
   */
 
1177
  wThread = CreateThread(NULL, 0, _threadFunction, (LPVOID)self, 0, &tid);
969
1178
}
970
1179
 
971
1180
- (void) _collectChild
972
1181
{
973
1182
  if (_hasCollected == NO)
974
1183
    {
975
 
      /* FIXME: Implement */
976
 
    }
977
 
}
978
 
 
979
 
- (int) terminationStatus
980
 
{
981
 
  DWORD exit_code;
982
 
  int   result;
983
 
 
984
 
  [super terminationStatus];
985
 
  result = GetExitCodeProcess(proc_info.hProcess, &exit_code);
986
 
  _terminationStatus = exit_code;
987
 
  if (result == 0)
988
 
    {
989
 
      NSLog(@"Error getting exit code");
990
 
      return -1;
991
 
    }
992
 
  return exit_code;
993
 
}
994
 
 
995
 
- (void) waitUntilExit
996
 
{
997
 
  DWORD result;
998
 
 
999
 
  result = WaitForSingleObject(proc_info.hProcess, INFINITE);
1000
 
}
1001
 
  
 
1184
      DWORD             eCode;
 
1185
 
 
1186
      if (GetExitCodeProcess(procInfo.hProcess, &eCode) == 0)
 
1187
        {
 
1188
          NSLog(@"Error getting exit code for process %d", _taskId);
 
1189
        }
 
1190
      else if (eCode != STILL_ACTIVE)
 
1191
        {
 
1192
          [self _terminatedChild: eCode];
 
1193
        }
 
1194
    }
 
1195
}
 
1196
 
1002
1197
@end
1003
1198
 
1004
1199
#else /* !MINGW */
1047
1242
                }
1048
1243
            }
1049
1244
        }
1050
 
      while (result > 0);  
 
1245
      while (result > 0);
1051
1246
    }
1052
1247
  return found;
1053
1248
}
1159
1354
      /*
1160
1355
       * Make sure task is run in it's own process group.
1161
1356
       */
1162
 
#if     HAVE_SETPGRP
 
1357
#ifdef     HAVE_SETPGRP
1163
1358
#ifdef  SETPGRP_VOID
1164
1359
      setpgrp();
1165
1360
#else
1171
1366
#else
1172
1367
      pid = (int)getpid();
1173
1368
#endif
1174
 
#if     HAVE_SETPGID
 
1369
#ifdef     HAVE_SETPGID
1175
1370
      setpgid(pid, pid);
1176
1371
#endif
1177
1372
#endif
1186
1381
              exit(1);                  /* Failed to open slave!        */
1187
1382
            }
1188
1383
 
1189
 
#if     HAVE_SETSID
 
1384
#ifdef  HAVE_SETSID
1190
1385
          i = setsid();
1191
1386
#endif
1192
1387
#ifdef  TIOCNOTTY
1311
1506
      if (result < 0)
1312
1507
        {
1313
1508
          NSLog(@"waitpid %d, result %d, error %s",
1314
 
                _taskId, result, GSLastErrorStr(errno));
 
1509
            _taskId, result, GSLastErrorStr(errno));
1315
1510
          [self _terminatedChild: -1];
1316
1511
        }
1317
1512
      else if (result == _taskId || (result > 0 && errno == 0))
1320
1515
            {
1321
1516
#ifdef  WAITDEBUG
1322
1517
              NSLog(@"waitpid %d, termination status = %d",
1323
 
                        _taskId, _terminationStatus);
 
1518
                _taskId, _terminationStatus);
1324
1519
#endif
1325
1520
              [self _terminatedChild: WEXITSTATUS(_terminationStatus)];
1326
1521
            }
1328
1523
            {
1329
1524
#ifdef  WAITDEBUG
1330
1525
              NSLog(@"waitpid %d, termination status = %d",
1331
 
                        _taskId, _terminationStatus);
 
1526
                _taskId, _terminationStatus);
1332
1527
#endif
1333
1528
              [self _terminatedChild: WTERMSIG(_terminationStatus)];
1334
1529
            }
1335
1530
#ifdef  WAITDEBUG
1336
1531
          else
1337
 
            NSLog(@"waitpid %d, event status = %d",
1338
 
                        _taskId, _terminationStatus);
 
1532
            {
 
1533
              NSLog(@"waitpid %d, event status = %d",
 
1534
                _taskId, _terminationStatus);
 
1535
            }
1339
1536
#endif
1340
1537
        }
1341
1538
#ifdef  WAITDEBUG
1342
1539
      else
1343
 
        NSLog(@"waitpid %d, result %d, error %s",
1344
 
                _taskId, result, GSLastErrorStr(errno));
 
1540
        {
 
1541
          NSLog(@"waitpid %d, result %d, error %s",
 
1542
            _taskId, result, GSLastErrorStr(errno));
 
1543
        }
1345
1544
#endif
1346
1545
    }
1347
1546
}