Show
Ignore:
Timestamp:
08/20/08 17:55:19 (4 years ago)
Author:
mwhitworth
Message:

Add support for loading scripts via #! notation.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • Whitix/trunk/fs/vfs/load.c

    r701 r849  
    5252 
    5353static int ExecElf(struct ExecArgs* execArgs); 
     54static int ExecScript(struct ExecArgs* args); 
    5455 
    5556/*********************************************************************** 
     
    7273        int err; 
    7374 
    74         err=DoOpenFile(file,pathName,FILE_READ,0); 
     75        err=DoOpenFile(file, pathName, FILE_READ, 0); 
    7576 
    7677        if (err) 
    7778                return err; 
    78  
     79         
    7980        if (file->vNode->mode & VFS_ATTR_DIR) 
    8081                return -EISDIR; 
     
    146147        IrqSaveFlags(flags); 
    147148 
    148         /* Map in the argument pages */ 
     149        /* Map in the argument pages. */ 
    149150        VirtSetCurrent(args->process->memManager); 
    150151 
     
    275276 
    276277        if (args->argv) 
    277                 ExecCopyStrings(args,args->argv,argCount); 
    278  
    279         ExecCopyStrings(args,&args->process->name,1); 
     278                ExecCopyStrings(args,args->argv, argCount); 
     279 
     280        ExecCopyStrings(args, &args->process->name, 1); 
    280281 
    281282        return ExecSetupArgs(args); 
     
    377378        ExecSetupContext(&execArgs,pathName,fds,argv); 
    378379 
    379         /* Open exectuable */ 
     380        /* Open executable */ 
    380381        err=ExecOpen(pathName,&execArgs.exec); 
    381382        if (err) 
     
    401402        err=ExecSetupFs(process, fds); 
    402403 
    403         /* Keep going through all formats until we run out of formats, then return false */ 
    404         err=ExecElf(&execArgs); 
     404        if (err) 
     405                return err; 
     406 
     407        /* Try executing it as a script first. */ 
     408        err=ExecScript(&execArgs); 
     409         
     410        if (err) 
     411                err=ExecElf(&execArgs); 
    405412 
    406413        if (err) 
     
    420427         */ 
    421428 
    422         execArgs.thread=ThrCreateThread(process,execArgs.entryPoint,true,(DWORD)execArgs.stackP, ((void*)-1)); /* 'process' still points to the same structure */ 
     429        execArgs.thread=ThrCreateThread(process,execArgs.entryPoint, true, (DWORD)execArgs.stackP, ((void*)-1)); /* 'process' still points to the same structure */ 
    423430 
    424431        ThrStartThread(execArgs.thread); 
     
    454461        int len; 
    455462 
    456         /* Seperate argv and the auxillary entries table */ 
    457         STACK_PUSH(args->stackP,0); 
    458  
    459463        addr=args->process->memManager->argsStart; 
    460464 
     
    462466        while (argCount--) 
    463467        { 
    464                 STACK_PUSH(args->stackP,addr); 
     468                STACK_PUSH(args->stackP, addr); 
    465469                len=strlen((char*)addr)+1; 
    466470                addr+=len; 
     
    575579        PUSH_AUX_ENT(args->stackP,AT_FLAGS, 0); 
    576580 
     581        /* Seperate argv and the auxillary entries table */ 
     582        STACK_PUSH(args->stackP,0); 
     583 
    577584        ExecSetupStack(args); 
    578585 
     
    679686} 
    680687 
     688static int ExecRemoveFirstArg(struct ExecArgs* args) 
     689{ 
     690        char* p; 
     691        DWORD currVirtPage; 
     692         
     693        if (!args->argc) 
     694                return 0; 
     695         
     696        currVirtPage=VirtAllocateTemp(args->argPages[args->stackPos >> 12]); 
     697         
     698        p=(char*)(currVirtPage+PAGE_OFFSET(args->stackPos)); 
     699         
     700        p-=2; 
     701         
     702        /* TODO: May have to go back to a previous page. */ 
     703        while (*p != '\0' && p > (char*)currVirtPage) 
     704                p--; 
     705                 
     706        args->stackPos=(DWORD)(p-(char*)currVirtPage); 
     707                 
     708        args->argc--; 
     709         
     710        return 0; 
     711} 
     712 
     713static int ExecScript(struct ExecArgs* args) 
     714{ 
     715        char* buffer; 
     716        char* copy; 
     717        int err; 
     718        char* interpName, *interpArg; 
     719        struct File file; 
     720         
     721        buffer=(char*)malloc(512); 
     722        if (!DoReadFile(&args->exec, (BYTE*)buffer, 512)) 
     723        { 
     724                KePrint("Failed to read file %s\n", args->pathName); 
     725                err=-EIO; 
     726                goto freeBuffer; 
     727        } 
     728 
     729        if (buffer[0] != '#' || buffer[1] != '!') 
     730                return -EINVAL; 
     731                 
     732        /* Parse the #! line */ 
     733        buffer[511]='\0'; 
     734         
     735        copy=strchr(buffer, '\n'); 
     736         
     737        if (!copy) 
     738                copy=&buffer[511]; 
     739                 
     740        *copy='\0'; 
     741         
     742        while (copy > buffer) 
     743        { 
     744                copy--; 
     745                if ((*copy == ' ') || (*copy == '\t')) 
     746                        *copy='\0'; 
     747                else 
     748                        break; 
     749        } 
     750         
     751        for (copy=buffer+2; (*copy == ' ') || (*copy == '\t'); copy++); 
     752         
     753        /* Could not find the interpreter name. */ 
     754        if (!*copy) 
     755                return -EINVAL; 
     756         
     757        /* TODO: Close the open executable? */ 
     758                 
     759        interpName=copy; 
     760        interpArg=NULL; 
     761         
     762        for (; *copy && (*copy != ' ') && (*copy != '\t'); copy++); 
     763         
     764        while ((*copy == ' ') || (*copy == '\t')) 
     765                *copy='\0'; 
     766                 
     767        if (*copy) 
     768                interpArg=copy; 
     769                 
     770        err=ExecOpen(interpName, &file); 
     771         
     772        if (err) 
     773                goto freeBuffer; 
     774         
     775        /* Change the executable to the interpreter. */ 
     776        memcpy(&args->exec, &file, sizeof(struct File)); 
     777        args->process->exec=args->exec.vNode; 
     778         
     779        /* Remove the first argument. */ 
     780        ExecRemoveFirstArg(args); 
     781         
     782        /* <interp> <interp args> <script name>. Done in reverse order. */ 
     783         
     784        ExecCopyStrings(args, &args->process->name, 1); 
     785         
     786        if (interpArg) 
     787                ExecCopyStrings(args, &interpArg, 1); 
     788         
     789        ExecCopyStrings(args, &interpName, 1); 
     790         
     791        err=ExecElf(args); 
     792         
     793freeBuffer:              
     794        free(buffer); 
     795         
     796        return err; 
     797} 
     798 
    681799/* TODO: 
    682800   - Improve resource cleanup 
     
    706824        char* interpreter=NULL; 
    707825 
     826        DoSeekFile(&args->exec, 0, 0); 
     827 
    708828        /* Should calculate total program header size. TODO: Memory map in. See linker code. */ 
    709829        buffer=(BYTE*)malloc(512); 
    710         if (!DoReadFile(&args->exec,buffer,512)) 
     830        if (!DoReadFile(&args->exec, buffer, 512)) 
    711831        { 
    712832                KePrint("Failed to read file %s\n",args->pathName); 
     
    717837        header=(struct ElfHeader*)buffer; 
    718838 
    719         if (ElfCheckHeader(header,ELF_EXEC | ELF_DYN)) 
    720         { 
    721                 KePrint("%s: not a valid ELF executable\n",args->pathName); 
     839        if (ElfCheckHeader(header, ELF_EXEC | ELF_DYN)) 
     840        { 
     841                KePrint("%s: not a valid ELF executable\n", args->pathName); 
    722842                err=-EINVAL; 
    723843                goto freeBuffer; 
     
    821941        if (copiedName) 
    822942        { 
    823                 err=Exec(pathName,fds,argv); 
     943                err=Exec(copiedName, fds, argv); 
    824944                free(copiedName); 
    825945        }