shellsysverbs.c

Go to the documentation of this file.
00001 
00002 /*  $Id: shellsysverbs.c 1260 2006-04-13 06:13:10Z sethdill $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #ifdef MACVERSION 
00032 #include <land.h>
00033 #define wsprintf sprintf
00034 #endif
00035 
00036 #include "ops.h"
00037 #include "memory.h"
00038 #include "error.h"
00039 #include "file.h"
00040 #include "resources.h"
00041 #include "scrap.h"
00042 #include "strings.h"
00043 #include "launch.h"
00044 #include "notify.h"
00045 #include "shell.h"
00046 #include "shellmenu.h"
00047 #include "lang.h"
00048 #include "langexternal.h"
00049 #include "langinternal.h"
00050 #include "langipc.h"
00051 #include "kernelverbs.h"
00052 #include "kernelverbdefs.h"
00053 #include "tablestructure.h"
00054 #if flruntime
00055     #include "outpost.h"
00056 #else
00057     #include "shellprivate.h"
00058 #endif
00059 #include "process.h"
00060 #include "processinternal.h"
00061 #include "sysshellcall.h"
00062 
00063 #include "langsystem7.h"  //6.1b7 AR: we need coercetolist
00064 #include "tableverbs.h"  //6.1b7 AR: we need gettablevalue
00065 #include "tableinternal.h" //6.1b7 AR: we need tablepacktable and tableunpacktable
00066 #include "serialnumber.h" //7.1b34 dmb: new isvalidserialnumber verb
00067 #include "byteorder.h"  /* 2006-04-08 aradke: endianness conversion macros */
00068 
00069 #define systemevents (osMask | activMask)
00070 
00071 boolean frontierversion (tyvaluerecord *v); /* 2002-10-13 AR: also used in langhtml.c */
00072     
00073 boolean sysos (tyvaluerecord *v); /* 2002-10-13 AR: also used in langhtml.c */
00074 
00075 
00076 static tyfilespec programfspec;
00077 
00078 static bigstring bsfrontierversion;
00079 
00080 
00081 typedef enum tysystoken { /*verbs that are processed by sys*/
00082     
00083     systemversionfunc,
00084     
00085     systemtaskfunc,
00086     
00087     browsenetworkfunc,
00088     
00089     apprunningfunc,
00090     
00091     frontappfunc,
00092     
00093     bringapptofrontfunc,
00094     
00095     countappsfunc,
00096     
00097     getnthappfunc,
00098     
00099     getapppathfunc,
00100     
00101     memavailfunc,
00102     
00103     machinefunc,
00104 
00105     osfunc,
00106 
00107     getenvironmentvariablefunc,
00108 
00109     setenvironmentvariablefunc,
00110     
00111     unixshellcommandfunc,
00112 
00113     winshellcommandfunc,
00114 
00115     ctsysverbs
00116     } tysystoken;
00117 
00118 
00119 typedef enum tylaunchtoken { /*verbs that are processed by launch*/
00120     
00121     applemenufunc,
00122     
00123     launchappfunc,
00124     
00125     launchappwithdocfunc,
00126     
00127     executeresourcefunc,
00128     
00129     anythingfunc,
00130     
00131     ctlaunchverbs
00132     } tylaunchtoken;
00133 
00134 
00135 typedef enum tyfrontiertoken { /*verbs that are processed by frontier*/
00136     
00137     programpathfunc,
00138     
00139     filepathfunc,
00140     
00141     #if !flruntime
00142     
00143     agentsenablefunc,
00144     
00145     #endif
00146     
00147     requesttofrontfunc,
00148     
00149     isruntimefunc,
00150     
00151     countthreadsfunc,
00152     
00153     isnativefunc,
00154     
00155     reclaimmemoryfunc,
00156     
00157     frontierversionfunc,
00158 
00159     hashstatsfunc,
00160 
00161     gethashloopcountfunc,
00162 
00163     hideapplicationfunc,
00164 
00165     isvalidserialnumberfunc,
00166 
00167     showapplicationfunc,
00168 
00169     ctfrontierverbs
00170     } tyfrontiertoken;
00171 
00172 
00173 typedef enum tyclipboardtoken { /*verbs that are processed by clipboard*/
00174     
00175     getscrapfunc,
00176     
00177     putscrapfunc,
00178     
00179     ctclipboardverbs
00180     } tyclipboardtoken;
00181 
00182 
00183 #if threadverbs
00184 
00185 typedef enum tythreadtoken {
00186     
00187     existsfunc,
00188     
00189     evaluatefunc,
00190 
00191     callscriptfunc,
00192     
00193     getcurrentfunc,
00194     
00195     getcountfunc,
00196     
00197     getnththreadfunc,
00198     
00199     sleepfunc,
00200     
00201     sleepforfunc,
00202 
00203     sleepticksfunc,
00204     
00205     issleepingfunc,
00206     
00207     wakefunc,
00208     
00209     killfunc,
00210     
00211     gettimeslicefunc,
00212     
00213     settimeslicefunc,
00214     
00215     getdefaulttimeslicefunc,
00216     
00217     setdefaulttimeslicefunc,
00218     /*
00219     begincriticalfunc,
00220     
00221     endcriticalfunc,
00222     */
00223     statsfunc,
00224     
00225     ctthreadverbs
00226     
00227     } tythreadtoken;
00228 
00229 #endif
00230 
00231 
00232 static boolean getscrapverb (hdltreenode hparam1, tyvaluerecord *v) {
00233     
00234     /*
00235     5.0a10 dmb: must open/close clipboard. byte swap binary type
00236     */
00237 
00238     OSType type;
00239     Handle hscrap;
00240     hdlhashtable htable;
00241     bigstring bs;
00242     boolean fl = false;
00243         
00244     setbooleanvalue (false, v); /*default return*/
00245     
00246     if (!getostypevalue (hparam1, 1, &type))
00247         return (false);
00248     
00249     flnextparamislast = true;
00250     
00251     if (!getvarparam (hparam1, 2, &htable, bs)) /*returned handle holder*/
00252         return (false);
00253     
00254     shellwritescrap (anyscraptype); /*export our private scrap, in necessary*/
00255     
00256     if (!newemptyhandle (&hscrap))
00257         return (false);
00258     
00259     if (openclipboard ()) {
00260         
00261         fl = getscrap (type, hscrap);
00262         
00263         closeclipboard ();
00264         }
00265     
00266     if (!fl) {
00267         
00268         disposehandle (hscrap);
00269         
00270         return (true); /*not a runtime error; return value is false*/
00271         }
00272     
00273     memtodisklong (type);
00274     
00275     if (!insertinhandle (hscrap, 0L, &type, sizeof (type))) {
00276         
00277         disposehandle (hscrap);
00278         
00279         return (false);
00280         }
00281     
00282     if (!langsetbinaryval (htable, bs, hscrap)) /*probably a memory error*/
00283         return (false);
00284     
00285     (*v).data.flvalue = true;
00286     
00287     return (true);
00288     } /*getscrapverb*/
00289 
00290 
00291 static boolean putscrapverb (hdltreenode hparam1, tyvaluerecord *v) {
00292     
00293     /*
00294     5.0a10 dmb: must open/close clipboard
00295     */
00296 
00297     OSType type;
00298     Handle hbinary;
00299     OSType bintype;
00300     
00301     if (!getostypevalue (hparam1, 1, &type))
00302         return (false);
00303     
00304     flnextparamislast = true;
00305     
00306     if (!getbinaryvalue (hparam1, 2, false, &hbinary))
00307         return (false);
00308     
00309     pullfromhandle (hbinary, 0L, sizeof (bintype), &bintype);
00310     
00311     if (openclipboard ()) {
00312         
00313         releasethreadglobals ();
00314         
00315         resetscrap ();
00316 
00317         grabthreadglobals ();
00318         
00319         (*v).data.flvalue = putscrap (type, hbinary);
00320 
00321         closeclipboard ();
00322         }
00323     
00324     return (true);
00325     } /*putscrapverb*/
00326 
00327 
00328 static boolean shellsysverbwaitroutine (void) {
00329     
00330     /*
00331     12/24/92 dmb: added special case for when yield is disabled
00332     
00333     2.1b9 dmb: systemevents are now just osMask. waiting for all updates 
00334     is dangerous, 'cause they may not be servicable
00335     
00336     3.0b15 dmb: systemevents need to include activate event too. otherwise, 
00337     shelleventavail (EventAvail) can return false when a juggle is indeed 
00338     pending.
00339     */
00340     
00341     boolean fl;
00342     
00343     if (flscriptrunning)
00344         fl = langpartialeventloop ((short) systemevents);
00345     else
00346         fl = shellpartialeventloop ((short) systemevents);
00347     
00348     return (fl);
00349     } /*shellsysverbwaitroutine*/
00350 
00351 
00352 boolean frontierversion (tyvaluerecord *v) { //6.1d1 AR: needed in langhtml.c
00353     
00354     if (stringlength (bsfrontierversion) == 0)
00355         filegetprogramversion (bsfrontierversion);
00356     
00357     return (setstringvalue (bsfrontierversion, v));
00358     } /*frontierversion*/
00359 
00360 
00361 boolean sysos (tyvaluerecord *v) { //6.1d1 AR: needed in langhtml.c
00362 
00363     #ifdef MACVERSION
00364         //#if TARGET_API_MAC_CARBON == 1
00365         //return (setstringvalue(osCarbon, v));
00366         //#else
00367         return (setstringvalue (osMacOS, v));
00368     #endif
00369     
00370     //#endif
00371     
00372     #ifdef WIN95VERSION
00373         OSVERSIONINFO osinfo;
00374 
00375         osinfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
00376 
00377         GetVersionEx (&osinfo);
00378 
00379         if (osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
00380             return (setstringvalue (osWinNT, v));
00381 
00382         return (setstringvalue (osWin95, v));
00383     #endif
00384     } /*sysos*/
00385 
00386 
00387 static boolean sysfunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
00388     
00389     /*
00390     2/12/92 dmb: do partialeventloop on systemtask & bringapptofrontfunc
00391     
00392     5/20/92 dmb: do processyield directly on systemtaskfunc
00393     
00394     8/11/92 dmb: make apprunningfunc accept a string or an ostype
00395     
00396     1/18/93 dmb: in systemtaskfunc, don't call processyield directly; use langbackgroundtask
00397 
00398     5.0b12 dmb: in systemtaskfunc, set flresting to false to make sure we don't slow
00399     down too much
00400     
00401     5.0b16 dmb: undo that change. it affect performance adversely if many threads do it.
00402     */
00403     
00404     register tyvaluerecord *v = vreturned;
00405     
00406     setbooleanvalue (false, v); /*assume the worst*/
00407     
00408     switch (token) { /*these verbs don't need any special globals pushed*/
00409         
00410         case systemversionfunc: {
00411             bigstring bs;
00412             
00413             getsystemversionstring (bs, nil);
00414             
00415             if (!langcheckparamcount (hparam1, 0))
00416                 return (false);
00417                         
00418             return (setstringvalue (bs, v));
00419             }
00420         
00421         case systemtaskfunc:
00422             if (!langcheckparamcount (hparam1, 0)) /*shouldn't have any parameters*/
00423                 return (false);
00424             
00425             shellsysverbwaitroutine ();
00426             
00427             /*
00428             if (!processyield ())
00429                 return (false);
00430             */
00431             
00432             if (!langbackgroundtask (true))
00433                 return (false);
00434             
00435             (*v).data.flvalue = true;
00436             
00437             return (true);
00438         
00439         case browsenetworkfunc:
00440             #ifdef MACVERSION
00441                 return (langipcbrowsenetwork (hparam1, v));
00442             #endif
00443             #ifdef WIN95VERSION
00444             #pragma message ("WIN95: browsenetworkfunc - not yet implemented!")
00445                 break;
00446             #endif
00447 
00448         case apprunningfunc: {
00449             OSType appid;
00450             bigstring bsapp;
00451             tyvaluerecord val;
00452             
00453             flnextparamislast = true;
00454             
00455             /*
00456             if (!getostypevalue (hparam1, 1, &appid))
00457                 return (false);
00458             
00459             (*v).data.flvalue = findrunningapplication (&appid, nil);
00460             */
00461             
00462             if (!getparamvalue (hparam1, 1, &val))
00463                 return (false);
00464             
00465             if (val.valuetype == ostypevaluetype) {
00466                 
00467                 setemptystring (bsapp);
00468                 
00469                 appid = val.data.ostypevalue;
00470                 }
00471             else {
00472                 if (!coercetostring (&val))
00473                     return (false);
00474                 
00475                 pullstringvalue (&val, bsapp);
00476                 
00477                 if (!stringtoostype (bsapp, &appid))
00478                     appid = 0;
00479                 }
00480             
00481             (*v).data.flvalue = findrunningapplication (&appid, bsapp, nil);
00482             
00483             return (true);
00484             }
00485         
00486         case frontappfunc: {
00487             bigstring bs;
00488             
00489             if (!langcheckparamcount (hparam1, 0))
00490                 return (false);
00491             
00492             if (!getfrontapplication (bs, false))
00493                 return (false);
00494             
00495             return (setstringvalue (bs, v));
00496             }
00497         
00498         case bringapptofrontfunc: {
00499             bigstring bs;
00500             
00501             flnextparamislast = true;
00502             
00503             if (!getstringvalue (hparam1, 1, bs))
00504                 return (false);
00505             
00506             (*v).data.flvalue = activateapplication (bs);
00507             
00508             return (true);
00509             }
00510         
00511         case countappsfunc:
00512             if (!langcheckparamcount (hparam1, 0))
00513                 return (false);
00514             
00515             return (setlongvalue (countapplications (), v));
00516         
00517         case getnthappfunc: {
00518             short n;
00519             bigstring bs;
00520             
00521             if (!getintvalue (hparam1, 1, &n))
00522                 return (false);
00523             
00524             if (!getnthapplication (n, bs))
00525                 setemptystring (bs);
00526             
00527             return (setstringvalue (bs, v));
00528             }
00529         
00530         case getapppathfunc: {
00531             bigstring bs;
00532             tyfilespec fs;
00533             
00534             flnextparamislast = true;
00535             
00536             if (!getstringvalue (hparam1, 1, bs))
00537                 return (false);
00538             
00539             if (!getapplicationfilespec (bs, &fs))  /* 2006-02-17 aradke: initializes fs even if it fails */
00540                 setemptystring (bs);
00541             
00542             return (setfilespecvalue (&fs, v));
00543             }
00544         
00545         case memavailfunc:
00546             {
00547             unsigned long memavail;
00548 
00549             #ifdef WIN95VERSION
00550                 MEMORYSTATUS meminfo;
00551 
00552                 meminfo.dwLength = sizeof (MEMORYSTATUS);
00553 
00554                 GlobalMemoryStatus (&meminfo);
00555 
00556                 memavail = meminfo.dwAvailVirtual;
00557             #endif
00558 
00559             #ifdef MACVERSION
00560                 memavail = TempFreeMem();
00561             #endif
00562             
00563             if (!langcheckparamcount (hparam1, 0)) /*shouldn't have any parameters*/
00564                 return (false);
00565             
00566             return (setlongvalue (memavail, v));
00567             }
00568         
00569         case machinefunc:
00570             
00571             #ifdef MACVERSION
00572                 //Code change by Timothy Paustian Friday, June 16, 2000 3:13:09 PM
00573                 //Changed to Opaque call for Carbon
00574                 //Carbon only runs on PPC
00575                 #if TARGET_API_MAC_CARBON
00576                 return (setstringvalue (machinePPC, v));
00577                 #else
00578                 #if GENERATINGPOWERPC
00579                 return (setstringvalue (machinePPC, v));
00580                 #endif
00581                 #if GENERATING68K
00582                 return (setstringvalue (machine68K, v));
00583                 #endif
00584                 #endif
00585 
00586                 
00587             #endif
00588             
00589             #ifdef WIN95VERSION
00590                 return (setstringvalue (machinex86, v));
00591             #endif
00592 
00593             break;
00594 
00595         case osfunc:
00596             return (sysos (v));
00597             break;
00598 
00599         #ifdef WIN95VERSION
00600             case getenvironmentvariablefunc: {
00601                 bigstring bsenvname;
00602                 bigstring buf;
00603                 DWORD res;
00604                 
00605                 flnextparamislast = true;
00606                 
00607                 if (!getstringvalue (hparam1, 1, bsenvname))
00608                     return (false);
00609 
00610                 nullterminate(bsenvname);
00611 
00612                 res = GetEnvironmentVariable (stringbaseaddress(bsenvname), stringbaseaddress(buf), sizeof(buf)-2);
00613 
00614                 if (res > sizeof(buf) - 2) {
00615                     return (setbooleanvalue (false, v));        //safety valve
00616                     }
00617 
00618                 setstringlength (buf, res);
00619 
00620                 return (setstringvalue (buf, v));
00621                 }
00622                 break;
00623 
00624             case setenvironmentvariablefunc: {
00625                 bigstring bsenvname;
00626                 bigstring bsenvval;
00627                 bigstring bserror, bserror2;
00628                 boolean res;
00629                 
00630                 if (!getstringvalue (hparam1, 1, bsenvname))
00631                     return (false);
00632 
00633                 flnextparamislast = true;
00634                 
00635                 if (!getstringvalue (hparam1, 2, bsenvval))
00636                     return (false);
00637 
00638                 nullterminate(bsenvname);
00639                 nullterminate(bsenvval);
00640 
00641                 res = SetEnvironmentVariable (stringbaseaddress(bsenvname), stringbaseaddress(bsenvval));
00642 
00643                 if (res) {
00644                     return (setbooleanvalue (true, v)); 
00645                     }
00646 
00647                 getsystemerrorstring (GetLastError(), bserror);
00648 
00649                 nullterminate(bserror);
00650 
00651                 wsprintf (bserror2, "Can't set environment variable \"%s\" to \"%s\" because %s", stringbaseaddress (bsenvname), stringbaseaddress (bsenvval), stringbaseaddress (bserror));
00652 
00653                 setstringlength (bserror2, strlen(stringbaseaddress(bserror2)));
00654 
00655                 shellerrormessage (bserror2);
00656 
00657                 return (setbooleanvalue (false, v));    
00658                 }
00659                 break;
00660         #endif
00661         
00662         #if TARGET_API_MAC_CARBON == 1
00663         
00664             case unixshellcommandfunc: { /*7.0b51 PBS: call shell on OS X*/
00665             
00666                 Handle hcommand, hreturn;
00667                 
00668                 flnextparamislast = true;
00669                 
00670                 if (!getexempttextvalue (hparam1, 1, &hcommand))
00671                     return (false);
00672                 
00673                 newemptyhandle (&hreturn);
00674                                         
00675                 if (!unixshellcall (hcommand, hreturn)) {
00676                 
00677                     disposehandle (hreturn);
00678                     
00679                     disposehandle (hcommand);
00680                     
00681                     return (false);
00682                     } /*if*/
00683                 
00684                 disposehandle (hcommand);
00685                     
00686                 return (setheapvalue (hreturn, stringvaluetype, v));
00687                 }
00688         
00689         #endif 
00690         
00691         #ifdef WIN95VERSION
00692 
00693             case winshellcommandfunc: {
00694                 Handle hcommand;
00695                 Handle houttext = nil;
00696                 Handle herrtext = nil;
00697                 long exitcode = 0;
00698                 tyaddress adrexitcode, adrstderr;
00699                 short ctconsumed = 1;
00700                 short ctpositional = 1;
00701                 boolean flneedexitcode, flneedstderr;
00702                 tyvaluerecord val;
00703                 
00704                 if (!getexempttextvalue (hparam1, 1, &hcommand))
00705                     return (false);
00706                 
00707                 if (!getoptionaladdressparam (hparam1, &ctconsumed, &ctpositional, "\x0b" "adrExitCode", &adrexitcode.ht, adrexitcode.bs))
00708                     return (false);
00709                 
00710                 flnextparamislast = true;
00711                 
00712                 if (!getoptionaladdressparam (hparam1, &ctconsumed, &ctpositional, "\x0b" "adrStdErr", &adrstderr.ht, adrstderr.bs))
00713                     return (false);
00714                 
00715                 flneedexitcode = (adrexitcode.ht != nil) || !isemptystring (adrexitcode.bs);
00716                 
00717                 flneedstderr = (adrstderr.ht != nil) || !isemptystring (adrstderr.bs);
00718 
00719                 newemptyhandle (&houttext);
00720 
00721                 if (flneedstderr)
00722                     newemptyhandle (&herrtext);
00723                                         
00724                 if (!winshellcall (hcommand, houttext, herrtext,
00725                                         (flneedexitcode ? &exitcode : nil))) {
00726                 
00727                     disposehandle (houttext);
00728                     
00729                     disposehandle (herrtext);
00730                     
00731                     disposehandle (hcommand);
00732                     
00733                     return (false);
00734                     } /*if*/
00735                 
00736                 disposehandle (hcommand);
00737                 
00738                 if (flneedexitcode) {
00739 
00740                     setlongvalue (exitcode, &val);
00741                     
00742                     if (!langsetsymboltableval (adrexitcode.ht, adrexitcode.bs, val))
00743                         return (false);
00744                     }
00745                     
00746                 if (flneedstderr) {
00747 
00748                     setheapvalue (herrtext, stringvaluetype, &val);
00749                     
00750                     if (!langsetsymboltableval (adrstderr.ht, adrstderr.bs, val))
00751                         return (false);
00752                     
00753                     exemptfromtmpstack (&val);
00754                     }
00755                     
00756                 return (setheapvalue (houttext, stringvaluetype, v));
00757                 }
00758 
00759         #endif //WIN95VERSION
00760         
00761         default:
00762             break;
00763         }
00764 
00765     getstringlist (langerrorlist, unimplementedverberror, bserror);
00766 
00767     return (false);
00768     } /*sysfunctionvalue*/
00769 
00770 
00771 static boolean launchfunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
00772     
00773     /*
00774     3/10/92 dmb: added launch.appWithDocument.  check default paths
00775     
00776     5/6/93 dmb: make sure that we return false is an oserror has occurred
00777     */
00778     
00779     register tyvaluerecord *v = vreturned;
00780     
00781     setbooleanvalue (false, v); /*assume the worst*/
00782     
00783     oserror (noErr); /*clear now so we can check it at end*/
00784     
00785     switch (token) { /*these verbs don't need any special globals pushed*/
00786         
00787         #ifdef MACVERSION
00788         case applemenufunc: {
00789             bigstring bs;
00790             
00791             flnextparamislast = true;
00792             
00793             if (!getstringvalue (hparam1, 1, bs))
00794                 return (false);
00795             
00796             (*v).data.flvalue = shellapplemenu (bs);
00797             
00798             break;
00799             }
00800         #endif
00801         
00802         case launchappfunc: {
00803             tyfilespec fsapp;
00804             
00805             flnextparamislast = true;
00806             
00807             if (!getfilespecvalue (hparam1, 1, &fsapp))
00808                 return (false);
00809             
00810             (*v).data.flvalue = launchapplication (&fsapp, nil, false);
00811             
00812             break;
00813             }
00814         
00815         case launchappwithdocfunc: {
00816             tyfilespec fsapp, fsdoc;
00817             
00818             if (!getfilespecvalue (hparam1, 1, &fsapp))
00819                 return (false);
00820             
00821             flnextparamislast = true;
00822             
00823             if (!getfilespecvalue (hparam1, 2, &fsdoc))
00824                 return (false);
00825             
00826             (*v).data.flvalue = launchapplication (&fsapp, &fsdoc, false);
00827             
00828             break;
00829             }
00830         
00831         case executeresourcefunc: {
00832             ResType type;
00833             short id;
00834             
00835             if (!getostypevalue (hparam1, 1, &type))
00836                 return (false);
00837             
00838             flnextparamislast = true;
00839             
00840             if (!getintvalue (hparam1, 2, &id))
00841                 return (false);
00842             
00843             (*v).data.flvalue = executeresource (type, id, nil);
00844             
00845             break;
00846             }
00847         
00848         case anythingfunc:
00849             #ifdef MACVERSION
00850                 return (filelaunchanythingverb (hparam1, v));
00851             #endif
00852             #ifdef WIN95VERSION
00853             #pragma message ("WIN95: anythingfunc - not yet implemented! (uses filelaunchanthingverb)")
00854                 getstringlist (langerrorlist, unimplementedverberror, bserror);
00855 
00856                 return (false);
00857             #endif
00858         
00859         default:
00860             getstringlist (langerrorlist, unimplementedverberror, bserror);
00861 
00862             return (false);
00863         }
00864     
00865     return (getoserror () == noErr);
00866     } /*launchfunctionvalue*/
00867 
00868 
00869 extern long fullpathloopcount;
00870 
00871 extern boolean hashstatsverb (tyvaluerecord *v);
00872 
00873 static boolean frontierfunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
00874 #pragma unused (bserror)
00875 
00876     /*
00877     6/5/92 dmb: added isruntime func
00878     
00879     6/1/93 dmb: when vreturned is nil, return whether or not verb token must 
00880     be run in the Frontier process
00881     */
00882     
00883     register tyvaluerecord *v = vreturned;
00884     
00885     if (v == nil) { /*need Frontier process?*/
00886         
00887         switch (token) {
00888             
00889             case requesttofrontfunc:
00890                 return (true);
00891             
00892             default:
00893                 return (false);
00894             }
00895         }
00896     
00897     setbooleanvalue (false, v); /*assume the worst*/
00898     
00899     switch (token) { /*these verbs don't need any special globals pushed*/
00900         
00901         case programpathfunc: {
00902             
00903             if (!langcheckparamcount (hparam1, 0))
00904                 return (false);
00905             
00906             return (setfilespecvalue (&programfspec, v));
00907             }
00908         
00909         case filepathfunc: {
00910             tyfilespec fs;
00911             
00912             if (!langcheckparamcount (hparam1, 0))
00913                 return (false);
00914             
00915             #if flruntime
00916             
00917             fs = currentfile.fspec;
00918             
00919             #else
00920             
00921             shellpushfrontrootglobals ();
00922             
00923             windowgetfspec (shellwindow, &fs);
00924             
00925             shellpopglobals ();
00926             
00927             #endif
00928             
00929             return (setfilespecvalue (&fs, v));
00930             }
00931         
00932         #if !flruntime
00933         
00934         case agentsenablefunc: {
00935             boolean fl;
00936             
00937             flnextparamislast = true;
00938             
00939             if (!getbooleanvalue (hparam1, 1, &fl))
00940                 return (false);
00941             
00942             (*v).data.flvalue = setagentsenable (fl);
00943             
00944             return (true);
00945             }
00946         
00947         #endif
00948         
00949         case requesttofrontfunc: {
00950             bigstring bsmessage;
00951             
00952             flnextparamislast = true;
00953             
00954             if (!getstringvalue (hparam1, 1, bsmessage))
00955                 return (false);
00956 
00957             #ifdef MACVERSION       
00958                 (*v).data.flvalue = shellisactive () || notifyuser (bsmessage);
00959             #endif
00960 
00961             #ifdef WIN95VERSION
00962             #pragma message ("WIN95: case requesttofrontfunc,  windows case currently forced.")
00963                 (*v).data.flvalue = shellisactive() || SetForegroundWindow (hwndActive);
00964             #endif
00965 
00966             return (true);
00967             }
00968         
00969         case isruntimefunc: {
00970             if (!langcheckparamcount (hparam1, 0))
00971                 return (false);
00972             
00973             #if flruntime
00974             
00975             (*v).data.flvalue = true;
00976             
00977             #endif
00978             
00979             return (true);
00980             }
00981         
00982         case countthreadsfunc: {
00983             if (!langcheckparamcount (hparam1, 0))
00984                 return (false);
00985             
00986             return (setlongvalue (processthreadcount (), v));
00987             }
00988         
00989         case isnativefunc:
00990             #if __powerc || __GNUC__
00991                 (*v).data.flvalue = true;
00992             #else
00993             
00994                 (*v).data.flvalue = false;
00995             #endif
00996             
00997             return (true);
00998         
00999         case reclaimmemoryfunc: {
01000             long ctbytes = longinfinity;
01001 
01002             if (!langcheckparamcount (hparam1, 0))
01003                 return (false);
01004             
01005             hashflushcache (&ctbytes);
01006 
01007             return (setlongvalue (longinfinity - ctbytes, v));
01008             }
01009         
01010         case frontierversionfunc:
01011             return (frontierversion (v));
01012         
01013         case hashstatsfunc:{
01014             if (!langcheckparamcount (hparam1, 0))
01015                 return (false);
01016 
01017             return (hashstatsverb (v));
01018             }
01019 
01020         case gethashloopcountfunc:{
01021             long myx;
01022 
01023             if (!langcheckparamcount (hparam1, 0))
01024                 return (false);
01025                 
01026             myx = fullpathloopcount;
01027 
01028             fullpathloopcount = 0;
01029 
01030             return (setlongvalue (myx, v));
01031             }
01032 
01033         case hideapplicationfunc: { /*7.1b9 PBS: minimize to system tray*/
01034             
01035             #ifdef WIN95VERSION
01036                 
01037                 releasethreadglobals ();
01038 
01039                 ShowWindow (shellframewindow, SW_HIDE);
01040 
01041                 grabthreadglobals ();
01042             
01043             #endif
01044 
01045             return (setbooleanvalue (true, v));
01046             }
01047 
01048         case isvalidserialnumberfunc: { /*7.1b34 dmb: expose the functionality as a verb*/
01049             bigstring bssn;
01050             
01051             flnextparamislast = true;
01052             
01053             if (!getstringvalue (hparam1, 1, bssn))
01054                 return (false);
01055 
01056             (*v).data.flvalue = isvalidserialnumber (bssn);
01057 
01058             return (true);
01059             }
01060         
01061         case showapplicationfunc: { /*2004-11-28 aradke: re-emerge from system tray*/
01062 
01063             #ifdef WIN95VERSION
01064                 
01065                 releasethreadglobals ();
01066 
01067                 ShowWindow (shellframewindow, SW_SHOW);
01068 
01069                 grabthreadglobals ();
01070             
01071             #endif
01072 
01073             return (setbooleanvalue (true, v));
01074             }
01075 
01076         default:
01077             return (false);
01078         }
01079     } /*frontierfunctionvalue*/
01080 
01081 
01082 static boolean clipboardfunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
01083     
01084     register tyvaluerecord *v = vreturned;
01085     #ifdef MACVERSION
01086         typrocessid processid;
01087     #endif
01088     
01089     setbooleanvalue (false, v); /*assume the worst*/
01090     
01091     #ifdef MACVERSION
01092         processid = getcurrentprocessid ();
01093         
01094         if (!isfrontapplication (processid)) {
01095             
01096             getstringlist (langerrorlist, cantbackgroundclipboard, bserror);
01097             
01098             return (false);
01099             }
01100     #endif
01101     
01102     switch (token) { /*these verbs don't need any special globals pushed*/
01103         
01104         case getscrapfunc:
01105             return (getscrapverb (hparam1, v));
01106         
01107         case putscrapfunc:
01108             return (putscrapverb (hparam1, v));
01109         
01110         default:
01111             return (false);
01112         }
01113     } /*clipboardfunctionvalue*/
01114 
01115 
01116 static boolean getthreadvalue (hdltreenode hfirst, short pnum, hdlprocessthread *hthread) {
01117     
01118     long id;
01119     
01120     if (!getlongvalue (hfirst, pnum, &id))
01121         return (false);
01122     
01123     *hthread = getprocessthread (id);
01124     
01125     if (*hthread == nil) {
01126         
01127         langlongparamerror (badthreadiderror, id);
01128         
01129         return (false);
01130         }
01131     
01132     return (true);
01133     } /*getthreadvalue*/
01134 
01135 
01136 static boolean threadverbprocessstarted (void) {
01137     
01138     /*
01139     we don't want Frontier's menus to dim when thread.evaluate's newly-added 
01140     process start.
01141     */
01142     
01143     processnotbusy ();
01144     
01145     return (true);
01146     } /*threadverbprocessstarted*/
01147 
01148 
01149 static boolean threaddisposecontext (void) {
01150     /*
01151     6.1b7 AR: For thread.callScript, dispose the context table.
01152     */
01153 
01154     register hdlprocessrecord hp = currentprocess;
01155 
01156     if (hp != nil && (**hp).hcontext != nil)
01157         disposehashtable ((**hp).hcontext, true);
01158 
01159     return (true);
01160     }
01161 
01162 
01163 static boolean threadcallscriptverb (bigstring bsscriptname, tyvaluerecord vparams, hdlhashtable hcontext, tyvaluerecord *v) {
01164 
01165     /*
01166     8.0.4 dmb: handle running code values
01167     
01168     9.1b3 AR: copy bsscriptname to processrecord so the thread can be more easily
01169     identified in the system.compiler.threads table
01170     */
01171     
01172     hdlprocessrecord hp;
01173     hdlprocessthread hthread;
01174 
01175     bigstring bsverb;
01176     boolean fl = false;
01177     boolean flchained = false;
01178     tyvaluerecord val;
01179     hdltreenode hfunctioncall;
01180     hdltreenode hparamlist;
01181     hdltreenode hcode;
01182     hdlhashtable htable;
01183     tyvaluerecord vhandler;
01184     hdlhashnode handlernode;
01185     
01186     /*build code tree, see langrunscript*/
01187 
01188     pushhashtable (roottable);
01189     
01190     fl = langexpandtodotparams (bsscriptname, &htable, bsverb);
01191 
01192     if (fl && htable == nil)
01193         langsearchpathlookup (bsverb, &htable);
01194 
01195     pophashtable();
01196     
01197     if (!fl)
01198         goto exit;
01199     
01200     if (!hashtablelookupnode (htable, bsverb, &handlernode)) {
01201         
01202         langparamerror (unknownfunctionerror, bsverb);
01203         
01204         goto exit;
01205         }
01206     
01207     vhandler = (**handlernode).val;
01208     
01209     /*build a code tree and call the handler, with our error hook in place*/
01210     
01211     hcode = nil;
01212     
01213     if (vhandler.valuetype == codevaluetype) {
01214 
01215         hcode = vhandler.data.codevalue;
01216     }
01217     else if ((**htable).valueroutine == nil) { /*not a kernel table*/
01218         
01219         if (!langexternalvaltocode (vhandler, &hcode)) {
01220 
01221             langparamerror (notfunctionerror, bsverb);
01222 
01223             goto exit;
01224             }
01225         
01226         if (hcode == nil) { /*needs compilation*/
01227             
01228             if (!langcompilescript (handlernode, &hcode))
01229                 goto exit;
01230             }
01231         }
01232     
01233     if (!setaddressvalue (htable, bsverb, &val))
01234         goto exit;
01235     
01236     if (!pushfunctionreference (val, &hfunctioncall))
01237         goto exit;
01238     
01239     if (hcontext != nil) {
01240         
01241         flchained = (**hcontext).flchained;
01242         
01243         if (flchained)
01244             pushhashtable (hcontext);
01245         else
01246             chainhashtable (hcontext); /*establishes outer local context*/
01247         }
01248 
01249     fl = langbuildparamlist (&vparams, &hparamlist);
01250     
01251     if (hcontext != nil) {
01252         
01253         if (flchained)
01254             pophashtable ();
01255         else
01256             unchainhashtable ();
01257         }
01258     
01259     if (!fl) {
01260         
01261         langdisposetree (hfunctioncall);
01262         
01263         goto exit;
01264         }
01265     
01266     if (!pushfunctioncall (hfunctioncall, hparamlist, &hcode)) /*consumes input parameters*/
01267         goto exit;
01268 
01269     if (!pushbinaryoperation (moduleop, hcode, nil, &hcode)) /*needs this level???*/
01270         goto exit;
01271 
01272     /*launch separate process, see processruntext*/
01273     
01274     newlyaddedprocess = nil; //process manager global
01275 
01276     if (!addnewprocess (hcode, true, nil, (long) 0)) {
01277         
01278         langdisposetree (hcode);
01279         
01280         goto exit;
01281         }
01282     
01283     /*return thread id*/
01284 
01285     hp = newlyaddedprocess; //process.c global; will be nil if a process wasn't just added
01286             
01287     if ((hp == nil) || !scheduleprocess (hp, &hthread))
01288         return (setlongvalue (0, v));
01289             
01290     (**hp).processstartedroutine = &threadverbprocessstarted; //don't dim the menu bar
01291 
01292     copystring (bsscriptname, (**hp).bsname);   /* 9.1b3 AR */
01293 
01294     if (hcontext != nil) {
01295 
01296         Handle hpacked;
01297         boolean fldummy;
01298 
01299         /*make a copy of the context table*/
01300 
01301         if (!tablepacktable (hcontext, true, &hpacked, &fldummy))
01302             goto exit;
01303 
01304         if (!tableunpacktable (hpacked, true, &hcontext))
01305             goto exit;      
01306 
01307         /*set the child thread's context to the copy of the context table*/
01308 
01309         (**hp).hcontext = hcontext;
01310 
01311         /*make sure the copy of the context table will be disposed*/
01312 
01313         (**hp).processkilledroutine = &threaddisposecontext;
01314         }
01315 
01316     return (setlongvalue (getthreadid (hthread), v));
01317 
01318 exit:
01319 
01320     return (false);
01321     }/*threadcallscriptverb*/
01322 
01323 
01324 static boolean threadstatsverb (hdltreenode hparam1, tyvaluerecord *v) {
01325     
01326     /*
01327     6.2b6 AR: New verb for debugging thread-related problems
01328     */
01329 
01330     hdlhashtable htable, hstatstable;
01331     bigstring bs;
01332 
01333     flnextparamislast = true;
01334 
01335     if (!getvarparam (hparam1, 1, &htable, bs))
01336         return (false);
01337 
01338     if (!langsuretablevalue (htable, bs, &hstatstable))
01339         return (false);
01340         
01341     if (!processgetstats (hstatstable))
01342         return (false);
01343         
01344     return (setbooleanvalue (true, v));
01345     }/*threadstatsverb*/
01346 
01347 
01348 static boolean threadfunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
01349     
01350     /*
01351     4.1b3 dmb: new verbs
01352     
01353     4.1b5 dmb: added thread.sleep
01354     
01355     4.1b6 dmb: make thread.sleepFor take seconds, not ticks
01356     
01357     5.0d13 dmb: added v == nil check
01358     */
01359     
01360     register tyvaluerecord *v = vreturned;
01361     typrocessid processid;
01362     unsigned long ticks;
01363     
01364     if (v == nil) { /*need Frontier process?*/
01365         
01366         switch (token) {
01367             
01368             case evaluatefunc:
01369             case callscriptfunc:
01370             case sleepfunc:
01371             case sleepforfunc:
01372             case sleepticksfunc:
01373             case issleepingfunc:
01374             case wakefunc:
01375             case killfunc:
01376             /*
01377             case begincriticalfunc:
01378             case endcriticalfunc:
01379             */
01380             case statsfunc:
01381                 return (true);
01382             
01383             case existsfunc:
01384             case getcurrentfunc:
01385             case getcountfunc:
01386             case getnththreadfunc:
01387             case gettimeslicefunc:
01388             case getdefaulttimeslicefunc:
01389             case settimeslicefunc:
01390             case setdefaulttimeslicefunc:
01391             default:
01392                 return (false);
01393             }
01394         }
01395     
01396     setbooleanvalue (false, v); // assume the worst
01397     
01398     processid = getcurrentprocessid ();
01399     
01400     if (!iscurrentapplication (processid)) {
01401         
01402         getstringlist (langerrorlist, cantbackgroundclipboard, bserror);    // ***
01403         
01404         return (false);
01405         }
01406     
01407     switch (token) {
01408         
01409         case existsfunc: {
01410             long id;
01411             
01412             flnextparamislast = true;
01413             
01414             if (!getlongvalue (hparam1, 1, &id))
01415                 return (false);
01416             
01417             return (setbooleanvalue (getprocessthread (id) != nil, v));
01418             }
01419         
01420         case evaluatefunc: {
01421             Handle htext;
01422             hdlprocessrecord hp;
01423             hdlprocessthread hthread;
01424             
01425             flnextparamislast = true;
01426             
01427             if (!getexempttextvalue (hparam1, 1, &htext))
01428                 return (false);
01429             
01430             newlyaddedprocess = nil; //process manager global
01431             
01432             if (!processruntext (htext))
01433                 return (false);
01434             
01435             hp = newlyaddedprocess; //process.c global; will be nil if a process wasn't just added
01436             
01437             if ((hp == nil) || !scheduleprocess (hp, &hthread))
01438                 return (setlongvalue (0, v));
01439             
01440             (**hp).processstartedroutine = &threadverbprocessstarted;
01441 
01442             return (setlongvalue (getthreadid (hthread), v));
01443             }
01444         
01445         case callscriptfunc: {
01446 
01447             bigstring bsscriptname;
01448             tyvaluerecord vparams;
01449             hdlhashtable hcontext = nil;
01450             boolean fl;
01451     
01452             if (!getstringvalue (hparam1, 1, bsscriptname))
01453                 return (false);
01454     
01455             if (!getparamvalue (hparam1, 2, &vparams))
01456                 return (false);
01457     
01458             if (vparams.valuetype != recordvaluetype)
01459                 if (!coercetolist (&vparams, listvaluetype))
01460                     return (false);
01461     
01462             if (langgetparamcount (hparam1) > 2) {
01463         
01464                 flnextparamislast = true;
01465 
01466                 if (!gettablevalue (hparam1, 3, &hcontext))
01467                     return (false);
01468                 }
01469                 
01470             (**(getcurrentthreadglobals ())).debugthreadingcookie = token;
01471 
01472             fl = threadcallscriptverb (bsscriptname, vparams, hcontext, v);
01473             
01474             (**(getcurrentthreadglobals ())).debugthreadingcookie = 0;
01475 
01476             return (fl);
01477             }
01478 
01479         case getcurrentfunc:
01480             if (!langcheckparamcount (hparam1, 0))
01481                 return (false);
01482             
01483             return (setlongvalue (getthreadid (getcurrentthread ()), v));
01484         
01485         case getcountfunc:
01486             if (!langcheckparamcount (hparam1, 0))
01487                 return (false);
01488             
01489             return (setlongvalue (processthreadcount (), v));
01490         
01491         case getnththreadfunc: {
01492             short n;
01493             
01494             flnextparamislast = true;
01495             
01496             if (!getintvalue (hparam1, 1, &n))
01497                 return (false);
01498             
01499             return (setlongvalue (getthreadid (nthprocessthread (n)), v));
01500             }
01501         
01502         case sleepfunc: {
01503             hdlprocessthread hthread;
01504             
01505             flnextparamislast = true;
01506             
01507             if (!getthreadvalue (hparam1, 1, &hthread))
01508                 return (false);
01509             
01510             return (setbooleanvalue (processsleep (hthread, -1), v));
01511             }
01512         
01513         case sleepforfunc: {
01514             long n;
01515             boolean fl;
01516             
01517             flnextparamislast = true;
01518             
01519             if (!getlongvalue (hparam1, 1, &n))
01520                 return (false);
01521             
01522             (**(getcurrentthreadglobals ())).debugthreadingcookie = token;
01523 
01524             fl = processsleep (getcurrentthread (), n * 60);
01525             
01526             (**(getcurrentthreadglobals ())).debugthreadingcookie = 0;
01527 
01528             return (setbooleanvalue (fl, v));
01529             }
01530         
01531         case sleepticksfunc: {
01532             long n;
01533             boolean fl;
01534             
01535             flnextparamislast = true;
01536             
01537             if (!getlongvalue (hparam1, 1, &n))
01538                 return (false);
01539             
01540             (**(getcurrentthreadglobals ())).debugthreadingcookie = token;
01541 
01542             fl = processsleep (getcurrentthread (), n);
01543             
01544             (**(getcurrentthreadglobals ())).debugthreadingcookie = 0;
01545 
01546             return (setbooleanvalue (fl, v));
01547             }
01548 
01549         case issleepingfunc: {
01550             hdlprocessthread hthread;
01551             
01552             flnextparamislast = true;
01553             
01554             if (!getthreadvalue (hparam1, 1, &hthread))
01555                 return (false);
01556             
01557             return (setbooleanvalue (processissleeping (hthread), v));
01558             }
01559         
01560         case wakefunc: {
01561             hdlprocessthread hthread;
01562             
01563             flnextparamislast = true;
01564             
01565             if (!getthreadvalue (hparam1, 1, &hthread))
01566                 return (false);
01567             
01568             return (setbooleanvalue (wakeprocessthread (hthread), v));
01569             }
01570         
01571         case killfunc: {
01572             hdlprocessthread hthread;
01573             
01574             flnextparamislast = true;
01575             
01576             if (!getthreadvalue (hparam1, 1, &hthread))
01577                 return (false);
01578             
01579             return (setbooleanvalue (killprocessthread (hthread), v));
01580             }
01581         
01582         case gettimeslicefunc:
01583             if (!langcheckparamcount (hparam1, 0))
01584                 return (false);
01585             
01586             getprocesstimeslice (&ticks);
01587 
01588             return (setlongvalue (ticks, v));
01589         
01590         case settimeslicefunc:
01591             flnextparamislast = true;
01592 
01593             if (!getlongvalue (hparam1, 1, (long *) (&ticks)))
01594                 return (false);
01595             
01596             return (setbooleanvalue (setprocesstimeslice (ticks), v));
01597     
01598         case getdefaulttimeslicefunc:
01599             if (!langcheckparamcount (hparam1, 0))
01600                 return (false);
01601             
01602             getdefaulttimeslice (&ticks);
01603 
01604             return (setlongvalue (ticks, v));
01605         
01606         case setdefaulttimeslicefunc:
01607             flnextparamislast = true;
01608 
01609             if (!getlongvalue (hparam1, 1, (long *) (&ticks)))
01610                 return (false);
01611             
01612             return (setbooleanvalue (setdefaulttimeslice (ticks), v));
01613         /*
01614         case begincriticalfunc:
01615             if (!langcheckparamcount (hparam1, 0))
01616                 return (false);
01617             
01618             ++fldisableyield;
01619             
01620             return (setbooleanvalue (true, v));
01621         
01622         case endcriticalfunc:
01623             if (!langcheckparamcount (hparam1, 0))
01624                 return (false);
01625             
01626             if (fldisableyield > 0) {
01627             
01628                 --fldisableyield;
01629                 
01630                 (*v).data.flvalue = true;
01631                 }
01632             
01633             return (true);
01634         */
01635         case statsfunc:
01636             return (threadstatsverb (hparam1, v));
01637 
01638         default:
01639             return (false);
01640         }
01641     } /*threadfunctionvalue*/
01642 
01643 
01644 boolean sysinitverbs (void) {
01645     
01646     getapplicationfilespec (nil, &programfspec);
01647     
01648     launchcallbacks.waitcallback = &shellsysverbwaitroutine;
01649     
01650     if (!loadfunctionprocessor (idsysverbs, &sysfunctionvalue))
01651         return (false);
01652     
01653     if (!loadfunctionprocessor (idlaunchverbs, &launchfunctionvalue))
01654         return (false);
01655     
01656     if (!loadfunctionprocessor (idclipboardverbs, &clipboardfunctionvalue))
01657         return (false);
01658     
01659     if (!loadfunctionprocessor (idfrontierverbs, &frontierfunctionvalue))
01660         return (false);
01661     
01662     if (!loadfunctionprocessor (idthreadverbs, &threadfunctionvalue))
01663         return (false);
01664     
01665     return (true);
01666     } /*sysinitverbs*/
01667 
01668 
01669 
01670 

Generated on Wed May 31 18:20:01 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6