957 errorTo:nil |
957 errorTo:nil |
958 inDirectory:aDirectory |
958 inDirectory:aDirectory |
959 onError:aBlock |
959 onError:aBlock |
960 |
960 |
961 "Modified: / 10.11.1998 / 20:54:37 / cg" |
961 "Modified: / 10.11.1998 / 20:54:37 / cg" |
|
962 ! |
|
963 |
|
964 executeCommand:aCommandString inputFrom:anInStream outputTo:anOutStream errorTo:anErrStream auxFrom:anAuxStream inDirectory:dirOrNil lineWise:lineWise onError:aBlock |
|
965 "execute the unix command specified by the argument, aCommandString. |
|
966 The commandString is passed to a shell for execution - see the description of |
|
967 'sh -c' in your UNIX manual. |
|
968 Return true if successful. |
|
969 If not successfull, aBlock is called with an OsProcessStatus |
|
970 (containing the exit status) as argument. |
|
971 The given in, out and err streams may be arbitrary (Smalltalk-) streams; |
|
972 if any is not an external stream (which is required by the command), |
|
973 extra pipes and shuffler processes are created, which stuff the data into |
|
974 those internal stream(s). |
|
975 Nil stream args will execute the command connected to ST/X's standard input, output or |
|
976 error resp. - i.e. usually, i/o will be from/to the terminal" |
|
977 |
|
978 |pid exitStatus sema pIn pOut pErr pAux externalInStream externalOutStream externalErrStream externalAuxStream |
|
979 shuffledInStream shuffledOutStream shuffledErrStream shuffledAuxStream |
|
980 inputShufflerProcess outputShufflerProcess errorShufflerProcess auxShufflerProcess stopShufflers |
|
981 inStreamToClose outStreamToClose errStreamToClose auxStreamToClose terminateLock| |
|
982 |
|
983 terminateLock := Semaphore forMutualExclusion. |
|
984 ((externalInStream := anInStream) notNil |
|
985 and:[externalInStream isExternalStream not]) ifTrue:[ |
|
986 pIn := ExternalStream makePipe. |
|
987 inStreamToClose := externalInStream := pIn at:1. |
|
988 shuffledInStream := pIn at:2. |
|
989 lineWise ifTrue:[shuffledInStream buffered:false]. |
|
990 |
|
991 "/ start a reader process, shuffling data from the given |
|
992 "/ inStream to the pipe (which is connected to the commands input) |
|
993 inputShufflerProcess := [ |
|
994 [ |
|
995 [anInStream atEnd] whileFalse:[ |
|
996 self shuffleFrom:anInStream to:shuffledInStream lineWise:lineWise. |
|
997 shuffledInStream flush |
|
998 ] |
|
999 ] ensure:[ |
|
1000 shuffledInStream close |
|
1001 ] |
|
1002 ] forkNamed:'cmd input shuffler'. |
|
1003 ]. |
|
1004 ((externalOutStream := anOutStream) notNil |
|
1005 and:[externalOutStream isExternalStream not]) ifTrue:[ |
|
1006 pOut := ExternalStream makePipe. |
|
1007 shuffledOutStream := (pOut at:1). |
|
1008 outStreamToClose := externalOutStream := pOut at:2. |
|
1009 lineWise ifTrue:[shuffledOutStream buffered:false]. |
|
1010 outputShufflerProcess := |
|
1011 [ |
|
1012 self shuffleAllFrom:shuffledOutStream to:anOutStream lineWise:lineWise lockWith:terminateLock. |
|
1013 ] forkNamed:'cmd output shuffler'. |
|
1014 ]. |
|
1015 (externalErrStream := anErrStream) notNil ifTrue:[ |
|
1016 anErrStream == anOutStream ifTrue:[ |
|
1017 externalErrStream := externalOutStream |
|
1018 ] ifFalse:[ |
|
1019 anErrStream isExternalStream ifFalse:[ |
|
1020 pErr := ExternalStream makePipe. |
|
1021 shuffledErrStream := (pErr at:1). |
|
1022 errStreamToClose := externalErrStream := pErr at:2. |
|
1023 |
|
1024 lineWise ifTrue:[shuffledErrStream buffered:false]. |
|
1025 errorShufflerProcess := |
|
1026 [ |
|
1027 self shuffleAllFrom:shuffledErrStream to:anErrStream lineWise:lineWise lockWith:terminateLock. |
|
1028 ] forkNamed:'cmd err-output shuffler'. |
|
1029 ] |
|
1030 ] |
|
1031 ]. |
|
1032 ((externalAuxStream := anAuxStream) notNil |
|
1033 and:[externalAuxStream isExternalStream not]) ifTrue:[ |
|
1034 pAux := ExternalStream makePipe. |
|
1035 auxStreamToClose := externalAuxStream := pAux at:1. |
|
1036 shuffledAuxStream := pAux at:2. |
|
1037 |
|
1038 "/ start a reader process, shuffling data from the given |
|
1039 "/ auxStream to the pipe (which is connected to the commands aux) |
|
1040 auxShufflerProcess := [ |
|
1041 [ |
|
1042 [anAuxStream atEnd] whileFalse:[ |
|
1043 self shuffleFrom:anAuxStream to:shuffledAuxStream lineWise:false. |
|
1044 shuffledAuxStream flush |
|
1045 ] |
|
1046 ] ensure:[ |
|
1047 shuffledAuxStream close |
|
1048 ] |
|
1049 ] forkNamed:'cmd aux shuffler'. |
|
1050 ]. |
|
1051 |
|
1052 sema := Semaphore new name:'OS command wait'. |
|
1053 pid := Processor |
|
1054 monitor:[ |
|
1055 self |
|
1056 startProcess:aCommandString |
|
1057 inputFrom:externalInStream |
|
1058 outputTo:externalOutStream |
|
1059 errorTo:externalErrStream |
|
1060 auxFrom:externalAuxStream |
|
1061 inDirectory:dirOrNil |
|
1062 ] |
|
1063 action:[:status | |
|
1064 status stillAlive ifFalse:[ |
|
1065 exitStatus := status. |
|
1066 sema signal. |
|
1067 self closePid:pid |
|
1068 ] |
|
1069 ]. |
|
1070 |
|
1071 inStreamToClose notNil ifTrue:[ |
|
1072 inStreamToClose close |
|
1073 ]. |
|
1074 errStreamToClose notNil ifTrue:[ |
|
1075 errStreamToClose close |
|
1076 ]. |
|
1077 outStreamToClose notNil ifTrue:[ |
|
1078 outStreamToClose close |
|
1079 ]. |
|
1080 auxStreamToClose notNil ifTrue:[ |
|
1081 auxStreamToClose close |
|
1082 ]. |
|
1083 |
|
1084 stopShufflers := [ |
|
1085 inputShufflerProcess notNil ifTrue:[ |
|
1086 terminateLock critical:[inputShufflerProcess terminate]. |
|
1087 inputShufflerProcess waitUntilTerminated |
|
1088 ]. |
|
1089 auxShufflerProcess notNil ifTrue:[ |
|
1090 terminateLock critical:[auxShufflerProcess terminate]. |
|
1091 auxShufflerProcess waitUntilTerminated |
|
1092 ]. |
|
1093 outputShufflerProcess notNil ifTrue:[ |
|
1094 terminateLock critical:[outputShufflerProcess terminate]. |
|
1095 outputShufflerProcess waitUntilTerminated. |
|
1096 self shuffleRestFrom:shuffledOutStream to:anOutStream lineWise:lineWise. |
|
1097 shuffledOutStream close. |
|
1098 ]. |
|
1099 errorShufflerProcess notNil ifTrue:[ |
|
1100 terminateLock critical:[errorShufflerProcess terminate]. |
|
1101 errorShufflerProcess waitUntilTerminated. |
|
1102 self shuffleRestFrom:shuffledErrStream to:anErrStream lineWise:lineWise. |
|
1103 shuffledErrStream close. |
|
1104 ]. |
|
1105 ]. |
|
1106 |
|
1107 pid notNil ifTrue:[ |
|
1108 [ |
|
1109 sema wait. |
|
1110 ] ifCurtailed:[ |
|
1111 "/ terminate the os-command (and all of its forked commands) |
|
1112 self terminateProcessGroup:pid. |
|
1113 self terminateProcess:pid. |
|
1114 self closePid:pid. |
|
1115 stopShufflers value. |
|
1116 ] |
|
1117 ] ifFalse:[ |
|
1118 exitStatus := self osProcessStatusClass processCreationFailure |
|
1119 ]. |
|
1120 stopShufflers value. |
|
1121 exitStatus success ifFalse:[ |
|
1122 ^ aBlock value:exitStatus |
|
1123 ]. |
|
1124 ^ true |
|
1125 |
|
1126 " |
|
1127 |outStream errStream| |
|
1128 |
|
1129 outStream := '' writeStream. |
|
1130 |
|
1131 OperatingSystem executeCommand:'ls -l' |
|
1132 inputFrom:'abc' readStream |
|
1133 outputTo:outStream |
|
1134 errorTo:nil |
|
1135 inDirectory:nil |
|
1136 lineWise:true |
|
1137 onError:[:exitStatus | ^ false]. |
|
1138 outStream contents |
|
1139 " |
|
1140 |
|
1141 " |
|
1142 |outStream errStream| |
|
1143 |
|
1144 outStream := '' writeStream. |
|
1145 |
|
1146 OperatingSystem executeCommand:'gpg -s --batch --no-tty --passphrase-fd 0 /tmp/passwd' |
|
1147 inputFrom:'bla' readStream |
|
1148 outputTo:outStream |
|
1149 errorTo:nil |
|
1150 inDirectory:nil |
|
1151 lineWise:true |
|
1152 onError:[:exitStatus | false]. |
|
1153 outStream contents |
|
1154 " |
962 ! |
1155 ! |
963 |
1156 |
964 executeCommand:aCommandString inputFrom:anInStream outputTo:anOutStream errorTo:anErrStream inDirectory:dirOrNil lineWise:lineWise onError:aBlock |
1157 executeCommand:aCommandString inputFrom:anInStream outputTo:anOutStream errorTo:anErrStream inDirectory:dirOrNil lineWise:lineWise onError:aBlock |
965 "execute the unix command specified by the argument, aCommandString. |
1158 "execute the unix command specified by the argument, aCommandString. |
966 The commandString is passed to a shell for execution - see the description of |
1159 The commandString is passed to a shell for execution - see the description of |