home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / rom / dos / createnewproc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-27  |  8.8 KB  |  320 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: createnewproc.c,v 1.11 1997/01/27 00:36:15 ldp Exp $
  4.     $Log: createnewproc.c,v $
  5.     Revision 1.11  1997/01/27 00:36:15  ldp
  6.     Polish
  7.  
  8.     Revision 1.10  1996/12/09 13:53:23  aros
  9.     Added empty templates for all missing functions
  10.  
  11.     Moved #include's into first column
  12.  
  13.     Revision 1.9  1996/10/24 15:50:25  aros
  14.     Use the official AROS macros over the __AROS versions.
  15.  
  16.     Revision 1.8  1996/10/23 14:22:23  aros
  17.     Use the systems' stacksize
  18.  
  19.     Revision 1.7  1996/10/10 13:19:33  digulla
  20.     Several IPTR/BPTR-Casts (Fleischer)
  21.  
  22.     Revision 1.6  1996/09/21 14:15:05  digulla
  23.     Number TagList
  24.     New tag: NP_UserData
  25.     Don't free non-allocated resources.
  26.  
  27.     Revision 1.5  1996/09/13 17:50:05  digulla
  28.     Use IPTR
  29.  
  30.     Revision 1.4  1996/09/11 12:56:39  digulla
  31.     Bugfix and a lot of new checks by M. Fleischer
  32.  
  33.     Desc:
  34.     Lang: english
  35. */
  36. #include <exec/memory.h>
  37. #include <proto/exec.h>
  38. #include <dos/dosextens.h>
  39. #include <dos/filesystem.h>
  40. #include <dos/dostags.h>
  41. #include <proto/dos.h>
  42. #include <utility/tagitem.h>
  43. #include <proto/utility.h>
  44. #include "dos_intern.h"
  45.  
  46. #define NEWLIST(l)                          \
  47. ((l)->lh_Head=(struct Node *)&(l)->lh_Tail, \
  48.  (l)->lh_Tail=NULL,                         \
  49.  (l)->lh_TailPred=(struct Node *)(l))
  50.  
  51. static void KillCurrentProcess(void);
  52. struct Process *AddProcess(struct Process *process, STRPTR argPtr,
  53. ULONG argSize, APTR initialPC, APTR finalPC, struct DosLibrary *DOSBase);
  54.  
  55. /*****************************************************************************
  56.  
  57.     NAME */
  58. #include <proto/dos.h>
  59.  
  60.     AROS_LH1(struct Process *, CreateNewProc,
  61.  
  62. /*  SYNOPSIS */
  63.     AROS_LHA(struct TagItem *, tags, D1),
  64.  
  65. /*  LOCATION */
  66.     struct DosLibrary *, DOSBase, 83, Dos)
  67.  
  68. /*  FUNCTION
  69.     Create a new process using the tagitem array.
  70.  
  71.     INPUTS
  72.     tags - information on the new process.
  73.  
  74.     RESULT
  75.     Pointer to the new process or NULL on error.
  76.  
  77.     NOTES
  78.  
  79.     EXAMPLE
  80.  
  81.     BUGS
  82.  
  83.     SEE ALSO
  84.  
  85.     INTERNALS
  86.  
  87.     HISTORY
  88.     29-10-95    digulla automatically created from
  89.                 dos_lib.fd and clib/dos_protos.h
  90.  
  91. *****************************************************************************/
  92. {
  93.     AROS_LIBFUNC_INIT
  94.     AROS_LIBBASE_EXT_DECL(struct DosLibrary *,DOSBase)
  95.  
  96.     /* Allocated resources */
  97.     struct Process *process=NULL;
  98.     BPTR input=0, output=0, curdir=0;
  99.     STRPTR stack=NULL, name=NULL, argptr=NULL;
  100.     ULONG namesize, argsize=0;
  101.     struct MemList *memlist=NULL;
  102.     struct CommandLineInterface *cli=NULL;
  103.  
  104.     struct Process *me=(struct Process *)FindTask(NULL);
  105.     STRPTR s;
  106.     BPTR *oldpath, *newpath, *nextpath;
  107.  
  108.     struct TagItem defaults[]=
  109.     {
  110.     /* 0 */    { NP_Seglist,       0 },
  111.     /* 1 */    { NP_Entry,       (IPTR)NULL },
  112.     /* 2 */    { NP_Input,       ~0ul },
  113.     /* 3 */    { NP_CloseInput,    1 },
  114.     /* 4 */    { NP_Output,       ~0ul },
  115.     /* 5 */    { NP_CloseOutput,   1 },
  116.     /* 6 */    { NP_Error,       0 },
  117.     /* 7 */    { NP_CloseError,    1 },
  118.     /* 8 */    { NP_CurrentDir,    ~0ul },
  119.     /* 9 */    { NP_StackSize,       AROS_STACKSIZE },
  120.     /*11 */    { NP_Name,       (IPTR)"New Process" },
  121.     /*12 */    { NP_Priority,       me->pr_Task.tc_Node.ln_Pri },
  122.     /*13 */    { NP_Arguments,       (IPTR)NULL },
  123.     /*14 */    { NP_Cli,       0 },
  124.     /*15 */    { NP_UserData,       (IPTR)NULL },
  125.     { TAG_END, 0 }
  126.     };
  127.     /* C has no exceptions. This is a simple replacement. */
  128. #define ERROR_IF(a)  if(a) goto error  /* Throw a generic error. */
  129. #define ENOMEM_IF(a) if(a) goto enomem /* Throw out of memory. */
  130.  
  131.     ApplyTagChanges(defaults,tags);
  132.  
  133.     process=(struct Process *)AllocMem(sizeof(struct Process),MEMF_PUBLIC|MEMF_CLEAR);
  134.     ENOMEM_IF(process==NULL);
  135.     stack=AllocMem(defaults[9].ti_Data,MEMF_PUBLIC);
  136.     ENOMEM_IF(stack==NULL);
  137.     s=(STRPTR)defaults[10].ti_Data;
  138.     while(*s++)
  139.     ;
  140.     namesize=s-(STRPTR)defaults[10].ti_Data;
  141.     name=AllocMem(namesize,MEMF_PUBLIC);
  142.     ENOMEM_IF(name==NULL);
  143.     s=(STRPTR)defaults[12].ti_Data;
  144.     if(s!=NULL)
  145.     {
  146.     while(*s++)
  147.         ;
  148.     argsize=s-(STRPTR)defaults[12].ti_Data;
  149.     argptr=(STRPTR)AllocVec(argsize,MEMF_PUBLIC);
  150.     ENOMEM_IF(argptr==NULL);
  151.     }
  152.     memlist=AllocMem(sizeof(struct MemList)+2*sizeof(struct MemEntry),MEMF_ANY);
  153.     ENOMEM_IF(memlist==NULL);
  154.     if(defaults[13].ti_Data)
  155.     {
  156.     cli=(struct CommandLineInterface *)AllocDosObject(DOS_CLI,NULL);
  157.     ENOMEM_IF(cli==NULL);
  158.     oldpath=NULL;
  159.     if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  160.     {
  161.         struct CommandLineInterface *oldcli=Cli();
  162.         if(oldcli!=NULL)
  163.         oldpath=BADDR(oldcli->cli_CommandDir);
  164.     }
  165.     newpath=&cli->cli_CommandDir;
  166.     while(oldpath!=NULL)
  167.     {
  168.         nextpath=AllocVec(2*sizeof(BPTR),MEMF_CLEAR);
  169.         ENOMEM_IF(nextpath==NULL);
  170.         newpath[0]=MKBADDR(nextpath);
  171.         nextpath[1]=DupLock(oldpath[1]);
  172.         ERROR_IF(!nextpath[1]);
  173.         newpath=nextpath;
  174.         oldpath=BADDR(oldpath[0]);
  175.     }
  176.     }
  177.     if(defaults[2].ti_Data==~0ul)
  178.     {
  179.     input=Open("NIL:",MODE_OLDFILE);
  180.     ERROR_IF(!input);
  181.     defaults[2].ti_Data=(IPTR)input;
  182.     }
  183.     if(defaults[4].ti_Data==~0ul)
  184.     {
  185.     output=Open("NIL:",MODE_NEWFILE);
  186.     ERROR_IF(!output);
  187.     defaults[4].ti_Data=(IPTR)output;
  188.     }
  189.     if(defaults[8].ti_Data==~0ul)
  190.     {
  191.     if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  192.     {
  193.         curdir=Lock("",SHARED_LOCK);
  194.         ERROR_IF(!curdir);
  195.         defaults[8].ti_Data=(IPTR)curdir;
  196.     }else
  197.         defaults[8].ti_Data=0;
  198.     }
  199.  
  200.     CopyMem((APTR)defaults[10].ti_Data,name,namesize);
  201.     CopyMem((APTR)defaults[12].ti_Data,argptr,argsize);
  202.     process->pr_Task.tc_Node.ln_Type=NT_PROCESS;
  203.     process->pr_Task.tc_Node.ln_Name=name;
  204.     process->pr_Task.tc_Node.ln_Pri=defaults[11].ti_Data;
  205.     process->pr_Task.tc_SPLower=stack;
  206.     process->pr_Task.tc_SPUpper=stack+defaults[9].ti_Data;
  207.  
  208.  
  209. /*  process->pr_ReturnAddr; */
  210.     NEWLIST(&process->pr_Task.tc_MemEntry);
  211.     memlist->ml_NumEntries=3;
  212.     memlist->ml_ME[0].me_Addr=process;
  213.     memlist->ml_ME[0].me_Length=sizeof(struct Process);
  214.     memlist->ml_ME[1].me_Addr=stack;
  215.     memlist->ml_ME[1].me_Length=defaults[9].ti_Data;
  216.     memlist->ml_ME[2].me_Addr=name;
  217.     memlist->ml_ME[2].me_Length=namesize;
  218.     AddHead(&process->pr_Task.tc_MemEntry,&memlist->ml_Node);
  219.     process->pr_MsgPort.mp_Node.ln_Type=NT_MSGPORT;
  220.     process->pr_MsgPort.mp_Flags=PA_SIGNAL;
  221.     process->pr_MsgPort.mp_SigBit=SIGB_DOS;
  222.     process->pr_MsgPort.mp_SigTask=process;
  223.     NEWLIST(&process->pr_MsgPort.mp_MsgList);
  224.     process->pr_SegList=(BPTR)defaults[0].ti_Data;
  225.     process->pr_StackSize=defaults[9].ti_Data;
  226.     process->pr_GlobVec=NULL;
  227.     Forbid();
  228.     process->pr_TaskNum=DOSBase->dl_ProcCnt++;
  229.     Permit();
  230.     process->pr_StackBase=MKBADDR(process->pr_Task.tc_SPUpper);
  231.     process->pr_Result2=0;
  232.     process->pr_CurrentDir=(BPTR)defaults[8].ti_Data;
  233.     process->pr_CIS=(BPTR)defaults[2].ti_Data;
  234.     process->pr_COS=(BPTR)defaults[4].ti_Data;
  235.     process->pr_CES=(BPTR)defaults[6].ti_Data;
  236.  
  237.     process->pr_Task.tc_UserData = (APTR)defaults[15].ti_Data;
  238.  
  239. /*  process->pr_ConsoleTask=; */
  240. /*  process->pr_FileSystemTask=; */
  241.     process->pr_CLI=MKBADDR(cli);
  242. /*  process->pr_PktWait=; */
  243. /*  process->pr_WindowPtr=; */
  244. /*  process->pr_HomeDir=; */
  245.     process->pr_Flags=(defaults[3].ti_Data?PRF_CLOSEINPUT:0)|
  246.               (defaults[5].ti_Data?PRF_CLOSEOUTPUT:0)|
  247.               (defaults[7].ti_Data?PRF_CLOSEERROR:0)|
  248.               (defaults[13].ti_Data?PRF_FREECLI:0)|
  249.               PRF_FREEARGS|PRF_FREESEGLIST|PRF_FREECURRDIR;
  250. /*  process->pr_ExitCode=; */
  251. /*  process->pr_ExitData=; */
  252.     process->pr_Arguments=argptr;
  253.     NEWLIST((struct List *)&process->pr_LocalVars);
  254.     process->pr_ShellPrivate=0;
  255.  
  256.     if(AddProcess(process,argptr,argsize,defaults[0].ti_Data?
  257.           (BPTR *)BADDR(defaults[0].ti_Data)+1:
  258.           (BPTR *)defaults[1].ti_Data,KillCurrentProcess,
  259.           DOSBase)!=NULL)
  260.     return process;
  261.  
  262.     /* Fall through */
  263. enomem:
  264.     if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  265.     me->pr_Result2=ERROR_NO_FREE_STORE;
  266. error:
  267.     if (cli)
  268.     FreeDosObject(DOS_CLI,cli);
  269.  
  270.     if (curdir)
  271.     UnLock(curdir);
  272.  
  273.     if (output)
  274.     Close(output);
  275.  
  276.     if (input)
  277.     Close(input);
  278.  
  279.     if (argptr)
  280.     FreeVec(argptr);
  281.  
  282.     if(memlist!=NULL)
  283.     FreeMem(memlist,sizeof(struct MemList)+2*sizeof(struct MemEntry));
  284.  
  285.     if(name!=NULL)
  286.     FreeMem(name,namesize);
  287.  
  288.     if(stack!=NULL)
  289.     FreeMem(stack,defaults[9].ti_Data);
  290.  
  291.     if(process!=NULL)
  292.     FreeMem(process,sizeof(struct Process));
  293.  
  294.     return NULL;
  295.     AROS_LIBFUNC_EXIT
  296. } /* CreateNewProc */
  297.  
  298. static void KillCurrentProcess(void)
  299. {
  300.     /* I need the global here because there is no local way to get it */
  301.     extern struct DosLibrary *DOSBase;
  302.     struct Process *me=(struct Process *)FindTask(NULL);
  303.  
  304.     if(me->pr_Flags&PRF_CLOSEINPUT)
  305.     Close(me->pr_CIS);
  306.     if(me->pr_Flags&PRF_CLOSEOUTPUT)
  307.     Close(me->pr_COS);
  308.     if(me->pr_Flags&PRF_CLOSEERROR)
  309.     Close(me->pr_CES);
  310.     if(me->pr_Flags&PRF_FREEARGS)
  311.     FreeVec(me->pr_Arguments);
  312.     if(me->pr_Flags&PRF_FREESEGLIST)
  313.     UnLoadSeg(me->pr_SegList);
  314.     if(me->pr_Flags&PRF_FREECURRDIR)
  315.     UnLock(me->pr_CurrentDir);
  316.     if(me->pr_Flags&PRF_FREECLI)
  317.     FreeDosObject(DOS_CLI,BADDR(me->pr_CLI));
  318.     RemTask(NULL);
  319. }
  320.