process.pas 5.0 KB

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