process.pas 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. {
  2. Spawning and messaging another DOS process
  3. Free Pascal for MorphOS example
  4. (dirty, but actually does work... sometimes... :)
  5. Copyright (C) 2004 by Karoly Balogh
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { * Thanks fly to Sigbjorn 'CISC' Skjaeret for hints and * }
  13. { * Michal 'kiero' Wozniak for example code. * }
  14. { * 2004.12.10 * }
  15. {$MODE FPC}
  16. program process;
  17. uses exec, utility, doslib;
  18. type
  19. pMyMsg = ^tMyMsg;
  20. tMyMsg = Record
  21. mm_MsgNode : tMessage;
  22. mm_Command : DWord;
  23. end;
  24. var
  25. ThMsg : tMyMsg;
  26. ThStartupMsg: tMyMsg;
  27. ThChildPort : pMsgPort;
  28. ThPort : pMsgPort;
  29. ThReplyPort : pMsgPort;
  30. ThProc : pProcess;
  31. const
  32. SUBPROCESS_NAME : PChar = 'FPC subprocess';
  33. const
  34. TCMD_HELLO = 1;
  35. TCMD_WORLD = 2;
  36. TCMD_SPACE = 3;
  37. TCMD_EXCL = 4;
  38. TCMD_NEWL = 5;
  39. TCMD_QUIT = $FF;
  40. procedure ShutDown(Err: String);
  41. begin
  42. if assigned(ThReplyPort) then DeleteMsgPort(ThReplyPort);
  43. if assigned(ThPort) then DeleteMsgPort(ThPort);
  44. if Err<>'' then begin
  45. writeln(Err);
  46. halt(1);
  47. end else
  48. halt(0);
  49. end;
  50. { * This is our subtask procedure * }
  51. { * Our subtask do exists until this procedure exits. * }
  52. procedure MyProcess;
  53. var
  54. thisThread: pProcess;
  55. startupMsg: pMyMsg;
  56. mainMsg : pMyMsg;
  57. mainPort : pMsgPort;
  58. finish : Boolean;
  59. begin
  60. { * Getting startupmsg * }
  61. NewGetTaskAttrs(NIL,@startupMsg,sizeof(startupMsg^),
  62. TASKINFOTYPE_STARTUPMSG,[TAG_DONE]);
  63. startupMsg^.mm_Command:=0;
  64. { * Getting taskport * }
  65. NewGetTaskAttrs(NIL,@mainPort,sizeof(mainPort^),
  66. TASKINFOTYPE_TASKMSGPORT,[TAG_DONE]);
  67. finish:=False;
  68. repeat
  69. mainMsg:=pMyMsg(GetMsg(mainPort));
  70. if mainMsg<>NIL then begin
  71. { * Using write in such an example is not really elegant * }
  72. { * since write is not reentrant yet, so if more tasks * }
  73. { * use it in the same time, it will make troubles. * }
  74. { * but it does what we want now. * }
  75. Case mainMsg^.mm_Command Of
  76. TCMD_HELLO: write('Hello');
  77. TCMD_WORLD: write('World');
  78. TCMD_SPACE: write(' ');
  79. TCMD_EXCL : write('!');
  80. TCMD_NEWL : writeln;
  81. TCMD_QUIT : finish:=True;
  82. end;
  83. Inc(startupMsg^.mm_Command);
  84. ReplyMsg(pMessage(mainMsg));
  85. end;
  86. { * Polling for messages... * }
  87. { * It's possible to use WaitPort() of course, but * }
  88. { * you probably want to do some stuff in the background * }
  89. { * so it's more useful to poll then. Replace Delay() * }
  90. { * with your code, or more, add your code after it. * }
  91. Delay(1);
  92. until finish;
  93. { * We MUST NOT reply StartupMsg! * }
  94. { * It will be replied by exec internally. * }
  95. end;
  96. { * This is a helper proc, makes sending * }
  97. { * of command messages more easy. * }
  98. procedure SendMsg(msgID : DWord);
  99. begin
  100. with ThMsg do begin
  101. with mm_MsgNode do begin
  102. mn_Node.ln_Type:=NT_MESSAGE;
  103. mn_Length:=SizeOf(tMyMsg);
  104. mn_ReplyPort:=ThPort;
  105. end;
  106. mm_Command:=msgID;
  107. end;
  108. PutMsg(ThChildPort,pMessage(@ThMsg));
  109. end;
  110. begin
  111. ThReplyPort:=CreateMsgPort;
  112. ThPort:=CreateMsgPort;
  113. if (ThReplyPort=NIL) or (ThPort=NIL) then
  114. ShutDown('Can''t create message ports.');
  115. { * Setting up StartupMsg * }
  116. with ThStartupMsg do begin
  117. with mm_MsgNode do begin
  118. mn_Node.ln_Type:=NT_MESSAGE;
  119. mn_Length:=SizeOf(tMyMsg);
  120. mn_ReplyPort:=ThReplyPort;
  121. end;
  122. end;
  123. ThProc:=CreateNewProcTags([NP_CodeType , CODETYPE_PPC,
  124. NP_Entry , DWord(@MyProcess),
  125. NP_Name , DWord(SUBPROCESS_NAME),
  126. NP_StartupMsg , DWord(@ThStartupMsg),
  127. NP_TaskMsgPort , DWord(@ThChildPort),
  128. { * such stacksize is overkill for our current * }
  129. { * subtask, but more complex things may actually * }
  130. { * require even more... * }
  131. NP_PPCStackSize, 32768,
  132. TAG_DONE]);
  133. if ThProc=NIL then ShutDown('Can''t create subprocess!');
  134. SendMsg(TCMD_HELLO);
  135. WaitPort(ThPort); GetMsg(ThPort);
  136. SendMsg(TCMD_SPACE);
  137. WaitPort(ThPort); GetMsg(ThPort);
  138. SendMsg(TCMD_WORLD);
  139. WaitPort(ThPort); GetMsg(ThPort);
  140. SendMsg(TCMD_EXCL);
  141. WaitPort(ThPort); GetMsg(ThPort);
  142. SendMsg(TCMD_NEWL);
  143. WaitPort(ThPort); GetMsg(ThPort);
  144. SendMsg(TCMD_QUIT);
  145. WaitPort(ThPort); GetMsg(ThPort);
  146. { * Wait our subprocess to exit... * }
  147. WaitPort(ThReplyPort); GetMsg(ThReplyPort);
  148. writeln('Subtask got ',ThStartupMsg.mm_Command,' message(s).');
  149. ShutDown('');
  150. end.