HTVMSUtils.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:21k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /* MODULE HTVMSUtil.c
  2. ** VMS Utility Routines
  3. **
  4. ** AUTHORS:
  5. ** MD Mark Donszelmann    duns@vxdeop.cern.ch
  6. ** FM Foteos Macrides     macrides@sci.wfeb.edu
  7. **
  8. ** HISTORY:
  9. ** 14 Nov 93  MD Written
  10. ** 31 Mar 94  FM Added HTVMS_disableAllPrv
  11. ** 06 Jul 94  FM Added HTVMS_getUIC and HTVMS_isOwner
  12. **
  13. ** BUGS:
  14. **
  15. **
  16. */
  17. #include <ssdef.h>
  18. #include <jpidef.h>
  19. #include <uaidef.h>
  20. #include <prvdef.h>
  21. #include <acldef.h>
  22. #include <armdef.h>
  23. #include <chpdef.h>
  24. #include <lnmdef.h>
  25. #include <libdtdef.h>
  26. #include <descrip.h>
  27. #include <unixlib.h>
  28. #include <stdio.h>
  29. #include <stat.h>
  30. #include <time.h>
  31. #include "HTUtils.h"
  32. #include "HTVMSUtils.h"
  33. #include "HTAccess.h"
  34. #define INFINITY 512            /* file name length @@ FIXME */
  35. typedef struct {
  36.    unsigned BufferLength : 16;
  37.    unsigned ItemCode : 16;
  38.    unsigned BufferAddress : 32;
  39.    unsigned ReturnLengthAddress : 32;
  40. } ItemStruct;
  41. /* PUBLIC HTVMS_authSysPrv()
  42. ** CHECKS IF THIS PROCESS IS AUTHORIZED TO ENABLE SYSPRV
  43. ** ON ENTRY:
  44. ** No arguments.
  45. **
  46. ** ON EXIT:
  47. ** returns YES if SYSPRV is authorized
  48. */
  49. PUBLIC BOOL HTVMS_authSysPrv NOARGS
  50. {
  51. unsigned long Result;
  52. ItemStruct ItemList[2];
  53. unsigned long Length;
  54. unsigned long Buffer[2];
  55.   /* fill Item */
  56.   ItemList[0].BufferLength = sizeof(Buffer);
  57.   ItemList[0].BufferAddress = Buffer;
  58.   ItemList[0].ReturnLengthAddress = &Length;
  59.   ItemList[0].ItemCode = JPI$_AUTHPRIV;
  60.   /* terminate list */
  61.   ItemList[1].ItemCode = 0;
  62.   ItemList[1].BufferLength = 0;
  63.   /* call system */
  64.   Result = SYS$GETJPIW(0, 0, 0, ItemList, 0, 0, 0);
  65.   if (Result != SS$_NORMAL)
  66.      return(NO);  
  67.   if (Buffer[0] & PRV$M_SYSPRV)
  68.      return(YES);
  69.   return(NO);  
  70. }
  71. /* PUBLIC HTVMS_enableSysPrv()
  72. ** ENABLES SYSPRV
  73. ** ON ENTRY:
  74. ** No arguments.
  75. **
  76. ** ON EXIT:
  77. **
  78. */
  79. PUBLIC void HTVMS_enableSysPrv NOARGS
  80. {
  81. unsigned long Result;
  82. unsigned long Prv[2], PreviousPrv[2];
  83.    Prv[0] = PRV$M_SYSPRV;
  84.    Prv[1] = 0;
  85.    Result = SYS$SETPRV(1,&Prv,0,&PreviousPrv);
  86.       if (Result == SS$_NORMAL) {
  87.          if (!(PreviousPrv[0] & PRV$M_SYSPRV)) {
  88.             CTRACE(TDEST, "VMS......... Enabled SYSPRVn");
  89. }
  90.    }
  91. }
  92. /* PUBLIC HTVMS_disableSysPrv()
  93. ** DISABLES SYSPRV
  94. ** ON ENTRY:
  95. ** No arguments.
  96. **
  97. ** ON EXIT:
  98. **
  99. */
  100. PUBLIC void HTVMS_disableSysPrv NOARGS
  101. {
  102. unsigned long Result;
  103. unsigned long Prv[2], PreviousPrv[2];
  104.    Prv[0] = PRV$M_SYSPRV;
  105.    Prv[1] = 0;
  106.    Result = SYS$SETPRV(0,&Prv,0,&PreviousPrv);
  107.       if (Result == SS$_NORMAL) {
  108.          if (PreviousPrv[0] & PRV$M_SYSPRV) {
  109.             CTRACE(TDEST, "VMS......... Disabled SYSPRVn");
  110.          }
  111.    }
  112. }
  113. /* PUBLIC HTVMS_disableAllPrv()
  114. **
  115. ** Disable all privileges except TMPMBX and NETMBX
  116. **
  117. ** ON ENTRY:
  118. ** No arguments.
  119. **
  120. ** ON EXIT:
  121. **
  122. */
  123. PUBLIC void HTVMS_disableAllPrv NOARGS
  124. {
  125. #ifndef MULTINET
  126. #define bzero(s,n) memset(s,'',n)
  127. #endif
  128.     union prvdef prvadr;
  129.     bzero((char *) &prvadr, sizeof(prvadr));
  130.     prvadr.prv$v_cmkrnl = 1;      
  131.     prvadr.prv$v_cmexec = 1;      
  132.     prvadr.prv$v_sysnam = 1;      
  133.     prvadr.prv$v_grpnam = 1;      
  134.     prvadr.prv$v_allspool = 1;    
  135.     prvadr.prv$v_detach = 1;      
  136.     prvadr.prv$v_diagnose = 1;    
  137.     prvadr.prv$v_log_io = 1;      
  138.     prvadr.prv$v_group = 1;       
  139.     prvadr.prv$v_noacnt = 1;      
  140.     prvadr.prv$v_prmceb = 1;      
  141.     prvadr.prv$v_prmmbx = 1;      
  142.     prvadr.prv$v_pswapm = 1;      
  143.     prvadr.prv$v_setpri = 1;      
  144.     prvadr.prv$v_setprv = 1;      
  145.     prvadr.prv$v_world = 1;       
  146.     prvadr.prv$v_mount = 1;       
  147.     prvadr.prv$v_oper = 1;        
  148.     prvadr.prv$v_exquota = 1;     
  149.     prvadr.prv$v_volpro = 1;      
  150.     prvadr.prv$v_phy_io = 1;      
  151.     prvadr.prv$v_bugchk = 1;      
  152.     prvadr.prv$v_prmgbl = 1;      
  153.     prvadr.prv$v_sysgbl = 1;      
  154.     prvadr.prv$v_pfnmap = 1;      
  155.     prvadr.prv$v_shmem = 1;       
  156.     prvadr.prv$v_sysprv = 1;      
  157.     prvadr.prv$v_bypass = 1;      
  158.     prvadr.prv$v_syslck = 1;      
  159.     prvadr.prv$v_share = 1;       
  160.     prvadr.prv$v_upgrade = 1;     
  161.     prvadr.prv$v_downgrade = 1;   
  162.     prvadr.prv$v_grpprv = 1;      
  163.     prvadr.prv$v_readall = 1;     
  164.     prvadr.prv$v_security = 1;    
  165. }
  166. /* PUBLIC HTVMS_checkAccess()
  167. ** CHECKS ACCESS TO FILE FOR CERTAIN USER
  168. ** ON ENTRY:
  169. ** FileName The file to be accessed
  170. ** UserName Name of the user to check access for.
  171. ** User nobody, represented by "" is given NO for an answer
  172. ** Method Method to be checked for
  173. ** 'method' 'access reuired'
  174. ** METHOD_GET read
  175. ** METHOD_HEAD read
  176. **
  177. ** ON EXIT:
  178. ** returns YES if access is allowed
  179. **
  180. ** Not only filename is checked but also filename.dir...
  181. **
  182. */
  183. PUBLIC BOOL HTVMS_checkAccess ARGS3(
  184. CONST char *, FileName,
  185. CONST char *, UserName,
  186. HTMethod, Method)
  187. {
  188. unsigned long Result;
  189. ItemStruct ItemList[2];
  190. unsigned long Flags;
  191. unsigned long FlagsLength;
  192. unsigned long Access;
  193. unsigned long AccessLength;
  194. unsigned long ObjType;
  195. char *VmsName;
  196. char Fname[256];
  197. struct dsc$descriptor_s FileNameDesc;
  198. struct dsc$descriptor_s UserNameDesc;
  199. char *colon;
  200.    /* user nobody should access as from account under which server is running */
  201.    if (0 == strcmp(UserName,""))
  202.    {
  203.       CTRACE(TDEST, "VMSAccess... No access allowed user nobody. Error in rulefile specifying 'nobody' as uid for protect rulen");
  204.       return(NO);
  205.    }
  206.    /* make local copy */
  207.    strcpy(Fname,FileName);
  208.    /* strip off last slash anyway */
  209.    if (Fname[strlen(Fname)-1] == '/')
  210.       Fname[strlen(Fname)-1] = '';
  211.    /* check Filename and convert */
  212.    colon = strchr(Fname,':');
  213.    if (colon)
  214.       VmsName = HTVMS_name("",colon+1);
  215.    else
  216.       VmsName = HTVMS_name("",Fname);
  217.    /* check for GET */
  218.    if ((Method == METHOD_GET) ||
  219.        (Method == METHOD_HEAD)) 
  220.    {
  221.      Access = ARM$M_READ;
  222.      Flags = CHP$M_READ;
  223.      /* fill Access */
  224.      ItemList[0].BufferLength = sizeof(Access);
  225.      ItemList[0].BufferAddress = &Access;
  226.      ItemList[0].ReturnLengthAddress = &AccessLength;
  227.      ItemList[0].ItemCode = CHP$_ACCESS;
  228.      /* fill Flags */
  229.      ItemList[1].BufferLength = sizeof(Flags);
  230.      ItemList[1].BufferAddress = &Flags;
  231.      ItemList[1].ReturnLengthAddress = &FlagsLength;
  232.      ItemList[1].ItemCode = CHP$_FLAGS;
  233.      /* terminate list */
  234.      ItemList[2].ItemCode = 0;
  235.      ItemList[2].BufferLength = 0;
  236.      /* fill input */
  237.      ObjType = ACL$C_FILE;
  238.      UserNameDesc.dsc$w_length = strlen(UserName);
  239.      UserNameDesc.dsc$b_dtype = DSC$K_DTYPE_T;
  240.      UserNameDesc.dsc$b_class = DSC$K_CLASS_S;
  241.      UserNameDesc.dsc$a_pointer = UserName;
  242.      FileNameDesc.dsc$w_length = strlen(VmsName);
  243.      FileNameDesc.dsc$b_dtype = DSC$K_DTYPE_T;
  244.      FileNameDesc.dsc$b_class = DSC$K_CLASS_S;
  245.      FileNameDesc.dsc$a_pointer = VmsName;
  246.      /* call system for filename */
  247.      Result = SYS$CHECK_ACCESS(&ObjType,&FileNameDesc,&UserNameDesc,ItemList);
  248.      if (Result == SS$_NORMAL)
  249.         return(YES);
  250.      /* try with extension .dir... */
  251.      strcat(VmsName,".dir");
  252.      FileNameDesc.dsc$w_length = strlen(VmsName);
  253.      Result = SYS$CHECK_ACCESS(&ObjType,&FileNameDesc,&UserNameDesc,ItemList);
  254.      if (Result == SS$_NORMAL)
  255.         return(YES);
  256.      /* failed for filename and .dir */
  257.      CTRACE(TDEST, "VMSAccess... No access allowed for user '%s', file '%s' under method '%s'n",UserName,Fname,HTMethod_name(Method));
  258.      return(NO);
  259.    }
  260.    CTRACE(TDEST, "VMSAccess... No access allowed for method '%s'n",HTMethod_name(Method));
  261.    return(NO);
  262. }
  263. /* PUBLIC HTVMS_wwwName()
  264. ** CONVERTS VMS Name into WWW Name 
  265. ** ON ENTRY:
  266. ** vmsname VMS file specification (NO NODE)
  267. **
  268. ** ON EXIT:
  269. ** returns  www file specification
  270. **
  271. ** EXAMPLES:
  272. ** vmsname wwwname
  273. ** DISK$USER  disk$user
  274. ** DISK$USER:  /disk$user/
  275. ** DISK$USER:[DUNS]  /disk$user/duns
  276. ** DISK$USER:[DUNS.ECHO]  /disk$user/duns/echo
  277. ** [DUNS]  duns
  278. ** [DUNS.ECHO]  duns/echo
  279. ** [DUNS.ECHO.-.TRANS]  duns/echo/../trans
  280. ** [DUNS.ECHO.--.TRANS]  duns/echo/../../trans
  281. ** [.DUNS]  duns
  282. ** [.DUNS.ECHO]  duns/echo
  283. ** [.DUNS.ECHO]TEST.COM  duns/echo/test.com 
  284. ** [.DUNS.ECHO]TEST-BLAH.COM duns/echo/test-blah.com
  285. ** [.DUNS-ECHO]TEST.COM  duns-echo/test.com
  286. ** [.X-----]TEST.COM x-----/test.com
  287. ** TEST.COM  test.com
  288. ** DISK$USER:[DUNS].RHOSTS /disk$user/duns/.rhosts 
  289. **
  290. **
  291. */
  292. PUBLIC char * HTVMS_wwwName ARGS1(
  293. char *, vmsname)
  294. {
  295. static char wwwname[256];
  296. char *src, *dst;
  297. int dir, up;
  298.    dst = wwwname;
  299.    src = vmsname;
  300.    dir = 0;
  301.    up = 0;
  302.    if (strchr(src,':')) *(dst++) = '/';
  303.    for ( ; *src != '' ; src++)
  304.    {
  305.       switch(*src)
  306.       {
  307.          case ':':  *(dst++) = '/'; break;
  308.          case '-': /* dashes might exist in filename and directory names... */
  309.            if (up)
  310.                    { /* directory and up */
  311.       if (*(src-1) == '-') *(dst++) = '/';
  312.                       *(dst++) = '.'; 
  313.                       *(dst++) = '.'; 
  314.                    }
  315.                    else
  316.                    { /* filename or directory name with a dash */
  317.                       *(dst++) = '-';
  318.                    }
  319.                    break;
  320.          case '.': if (dir)
  321.                    {
  322.                       if (*(src-1) != '[') *(dst++) = '/';
  323.                       up = 1;
  324.                    }
  325.                    else
  326.                    {
  327.          if (*(src-1) == ']') *(dst++) = '/';
  328.                       *(dst++) = '.';
  329.                    }
  330.                    break;
  331.          case '[': dir = 1; up = 1; break;
  332.          case ']': dir = 0; up = 0; break;
  333.          default:  up = 0;
  334.    if (*(src-1) == ']') *(dst++) = '/';
  335.                    *(dst++) = *src; 
  336.                    break;
  337.       }
  338.    }
  339.    *(dst++) = '';
  340.    return(wwwname);
  341. }
  342. /* PUBLIC HTVMS_name()
  343. ** CONVERTS WWW name into a VMS name
  344. ** ON ENTRY:
  345. ** nn Node Name (optional)
  346. ** fn WWW file name
  347. **
  348. ** ON EXIT:
  349. ** returns  vms file specification
  350. **
  351. ** Bug: Returns pointer to static -- non-reentrant
  352. */
  353. PUBLIC char * HTVMS_name ARGS2(
  354. CONST char *, nn, 
  355. CONST char *, fn)
  356. {
  357. /* We try converting the filename into Files-11 syntax. That is, we assume
  358. ** first that the file is, like us, on a VMS node. We try remote
  359. ** (or local) DECnet access. Files-11, VMS, VAX and DECnet
  360. ** are trademarks of Digital Equipment Corporation. 
  361. ** The node is assumed to be local if the hostname WITHOUT DOMAIN
  362. ** matches the local one. @@@
  363. */
  364.     static char vmsname[INFINITY]; /* returned */
  365.     char * filename = (char*)malloc(strlen(fn)+1);
  366.     char * nodename = (char*)malloc(strlen(nn)+2+1); /* Copies to hack */
  367.     char *second; /* 2nd slash */
  368.     char *last; /* last slash */
  369.     
  370.     char * hostname = HTGetHostName();
  371.     if (!filename || !nodename) outofmem(__FILE__, "HTVMSname");
  372.     strcpy(filename, fn);
  373.     strcpy(nodename, ""); /* On same node? Yes if node names match */
  374.     {
  375.         char *p, *q;
  376.         for (p=hostname, q=nn; *p && *p!='.' && *q && *q!='.'; p++, q++){
  377.     if (TOUPPER(*p)!=TOUPPER(*q)) {
  378.         strcpy(nodename, nn);
  379. q = strchr(nodename, '.'); /* Mismatch */
  380. if (q) *q=0; /* Chop domain */
  381. strcat(nodename, "::"); /* Try decnet anyway */
  382. break;
  383.     }
  384. }
  385.     }
  386.     second = strchr(filename+1, '/'); /* 2nd slash */
  387.     last = strrchr(filename, '/'); /* last slash */
  388.         
  389.     if (!second) { /* Only one slash */
  390. sprintf(vmsname, "%s%s", nodename, filename + 1);
  391.     } else if(second==last) { /* Exactly two slashes */
  392. *second = 0; /* Split filename from disk */
  393. sprintf(vmsname, "%s%s:%s", nodename, filename+1, second+1);
  394. *second = '/'; /* restore */
  395.     } else {  /* More than two slashes */
  396. char * p;
  397. *second = 0; /* Split disk from directories */
  398. *last = 0; /* Split dir from filename */
  399. sprintf(vmsname, "%s%s:[%s]%s",
  400. nodename, filename+1, second+1, last+1);
  401. *second = *last = '/'; /* restore filename */
  402. for (p=strchr(vmsname, '['); *p!=']'; p++)
  403.     if (*p=='/') *p='.'; /* Convert dir sep.  to dots */
  404.     }
  405.     free(nodename);
  406.     free(filename);
  407.     return vmsname;
  408. }
  409. /* PUBLIC HTVMS_putenv()
  410. ** Create logical name
  411. ** ON ENTRY:
  412. ** string name value pair separated by equal sign. 
  413. ** "name=value"
  414. **
  415. **
  416. ** ON EXIT:
  417. ** 0  ok
  418. ** 1 failed
  419. **
  420. */
  421. PUBLIC int HTVMS_putenv ARGS1(
  422. CONST char *, string)
  423. {
  424.     $DESCRIPTOR(job_table,"LNM$JOB");
  425.     char * name = (char*)malloc(strlen(string)+1);
  426.     char * value = (char*)malloc(strlen(string)+1); /* Copies to hack */
  427.     char * equal;
  428.     long result = 1;
  429.     /* separate pair */
  430.     strcpy(name,string);
  431.     equal = strchr(name,'=');
  432.     if (equal)
  433.     {
  434.     ItemStruct ItemList[2];
  435.     struct dsc$descriptor_s log_name;
  436.        /* get value */
  437.        *equal = '';
  438.        strcpy(value,equal+1);
  439.        /* fill logical name */       
  440.        log_name.dsc$w_length = strlen(name);
  441.        log_name.dsc$b_dtype = DSC$K_DTYPE_T;
  442.        log_name.dsc$b_class = DSC$K_CLASS_S;
  443.        log_name.dsc$a_pointer = name;
  444.        /* fill Item */
  445.        ItemList[0].BufferLength = strlen(value);
  446.        ItemList[0].BufferAddress = value;
  447.        ItemList[0].ReturnLengthAddress = 0;
  448.        ItemList[0].ItemCode = LNM$_STRING;
  449.        /* terminate list */
  450.        ItemList[1].ItemCode = 0;
  451.        ItemList[1].BufferLength = 0;
  452.        /* put into job logical name table */
  453.        result = SYS$CRELNM(0, &job_table, &log_name, 0, ItemList);
  454.        if ((result == SS$_NORMAL) || (result == SS$_SUPERSEDE))
  455.           result = 0;
  456.        else
  457.           result = 1;
  458.     }    
  459.     free(name);
  460.     free(value);
  461.     return(result);
  462. }
  463. /* PUBLIC HTVMS_start_timer()
  464. ** Starts a timer
  465. ** ON ENTRY:
  466. ** n A number to recognise the timer. 0 may be used to 
  467. ** say that recognision is not needed
  468. ** fun ptr to a function to be called asynchronously
  469. ** sec number of seconds to wait before firing.
  470. **
  471. **
  472. ** ON EXIT:
  473. **
  474. */
  475. PUBLIC void HTVMS_start_timer ARGS3(
  476. CONST int, n,
  477. CONST char *, fun,
  478. CONST int, sec)
  479. {
  480. long Result;
  481. long DeltaTime[2];
  482. long Operation = LIB$K_DELTA_SECONDS;
  483.    Result = LIB$CVT_TO_INTERNAL_TIME(&Operation, &sec, DeltaTime);
  484.    
  485.    Result = SYS$SETIMR(0, DeltaTime, fun, n, 0);
  486. }
  487. /* PUBLIC HTVMS_cancel_timer()
  488. ** Cancel a specific or all timers
  489. ** ON ENTRY:
  490. ** n timer number (0 to cancel all timers)
  491. **
  492. **
  493. ** ON EXIT:
  494. **
  495. */
  496. PUBLIC void HTVMS_cancel_timer ARGS1(
  497. CONST int, n)
  498. {
  499. long Result;
  500.    Result = SYS$CANTIM(n, 0);
  501. }
  502. /* PUBLIC HTVMS_getpwnam()
  503. ** getpwnam routine
  504. ** ON ENTRY:
  505. ** username Username specification
  506. **
  507. **
  508. ** ON EXIT:
  509. ** NULL error
  510. **
  511. */
  512. PUBLIC struct passwd *HTVMS_getpwnam ARGS1(
  513. CONST char *, username)
  514. {
  515. long Result;
  516. struct dsc$descriptor_s UserNameDesc;
  517. ItemStruct ItemList[3];
  518. unsigned long DeviceLength;
  519. char Device[33];
  520. unsigned long DirLength;
  521. char Dir[64];
  522. char VMSName[100];
  523. static struct passwd pw;
  524. static char pw_dir[100];
  525.    /* make sure pointers are correct */
  526.    pw.pw_dir = pw_dir;
  527.    /* construct UserName */
  528.    UserNameDesc.dsc$w_length = strlen(username);
  529.    UserNameDesc.dsc$b_dtype = DSC$K_DTYPE_T;
  530.    UserNameDesc.dsc$b_class = DSC$K_CLASS_S;
  531.    UserNameDesc.dsc$a_pointer = username;
  532.    /* Default Device */
  533.    ItemList[0].BufferLength = 33;
  534.    ItemList[0].BufferAddress = Device;
  535.    ItemList[0].ReturnLengthAddress = &DeviceLength;
  536.    ItemList[0].ItemCode = UAI$_DEFDEV;
  537.    /* Default Directory */
  538.    ItemList[1].BufferLength = 64;
  539.    ItemList[1].BufferAddress = Dir;
  540.    ItemList[1].ReturnLengthAddress = &DirLength;
  541.    ItemList[1].ItemCode = UAI$_DEFDIR;
  542.    /* terminate list */
  543.    ItemList[2].ItemCode = 0;
  544.    ItemList[2].BufferLength = 0;
  545.    /* get info */
  546.    Result = SYS$GETUAI(0,0,&UserNameDesc,ItemList,0,0,0);
  547.    if (Result != SS$_NORMAL)
  548.       return(NULL);
  549.    /* create vms name */
  550.    strncpy(VMSName,&(Device[1]),Device[0]);
  551.    VMSName[Device[0]] = '';
  552.    strncat(VMSName,&(Dir[1]),Dir[0]);
  553.    VMSName[Device[0]+Dir[0]] = '';
  554.    
  555.    /* convert it into www name */
  556.    strcpy(pw_dir,HTVMS_wwwName(VMSName));
  557.    return(&pw);
  558. }
  559. PUBLIC int HTStat ARGS2(
  560. char *, filename, 
  561. stat_t *, info)
  562. {
  563.    /* 
  564.       the following stuff does not work in VMS with a normal stat...
  565.       -->   /disk$user/duns/www if www is a directory
  566. is statted like:  /disk$user/duns/www.dir 
  567. after a normal stat has failed
  568.       -->   /disk$user/duns if duns is a toplevel directory
  569. is statted like: /disk$user/000000/duns.dir
  570.       -->   /disk$user since disk$user is a device
  571. is statted like: /disk$user/000000/000000.dir
  572.       -->   /
  573. searches all devices, no solution yet...
  574.       -->   /vxcern!/disk$cr/wwwteam/login.com
  575. is not statted but granted with fake information...
  576.    */
  577. int Result;
  578. int Len;
  579. char *Ptr, *Ptr2;
  580. char Name[256];
  581.    /* try normal stat... */
  582.    Result = stat(filename,info);
  583.    if (Result == 0)
  584.       return(Result);
  585.    /* make local copy */
  586.    strcpy(Name,filename);
  587.    /* if filename contains a node specification (! or ::), we will try to access
  588.       the file via DECNET, but we do not stat it..., just return success 
  589.       with some fake information... */
  590.    if (HTVMS_checkDecnet(Name))
  591.    {
  592.       /* set up fake info, only the one we use... */
  593.       info->st_dev = NULL;
  594.       info->st_ino[0] = 0;
  595.       info->st_ino[1] = 0;
  596.       info->st_ino[2] = 0;
  597.       info->st_mode = S_IFREG | S_IREAD; /* assume it is a regular Readable file */
  598.       info->st_nlink = NULL;
  599.       info->st_uid = 0;
  600.       info->st_gid = 0;
  601.       info->st_rdev = 0;
  602.       info->st_size = 0;
  603.       info->st_atime = time(NULL);
  604.       info->st_mtime = time(NULL);
  605.       info->st_ctime = time(NULL);
  606.       return(0);
  607.    }
  608.    /* failed,so do device search in case root is requested */
  609.    if (!strcmp(Name,"/"))
  610.    {  /* root requested */
  611.       return(-1);
  612.    }
  613.    
  614.    /* failed so this might be a directory, add '.dir' */
  615.    Len = strlen(Name);
  616.    if (Name[Len-1] == '/')
  617.       Name[Len-1] = '';
  618.    
  619.    /* fail in case of device */
  620.    Ptr = strchr(Name+1,'/');
  621.    if ((Ptr == NULL) && (Name[0] == '/'))
  622.    {  /* device only... */
  623.       strcat(Name,"/000000/000000");
  624.    }
  625.    
  626.    if (Ptr != NULL)
  627.    {  /* correct filename in case of toplevel dir */
  628.       Ptr2 = strchr(Ptr+1,'/');
  629.       if ((Ptr2 == NULL) && (Name[0] == '/'))
  630.       {
  631.          char End[256];
  632.          strcpy(End,Ptr);
  633.          *(Ptr+1) = '';
  634.          strcat(Name,"000000");
  635.          strcat(Name,End);
  636.       }
  637.    }
  638.    /* try in case a file on toplevel directory or .DIR was alreadyt specified */
  639.    Result = stat(Name,info);
  640.    if (Result == 0)
  641.       return(Result);
  642.    /* add .DIR and try again */
  643.    strcat(Name,".dir");
  644.    Result = stat(Name,info);
  645.    return(Result);
  646. }
  647. PUBLIC int HTVMS_checkDecnet ARGS1(
  648. char *, filename) 
  649. {
  650.     /* for VMS we take of the first slash in case a nodename is specified 
  651.        to make sure we access over decnet */
  652.     /* nodenames can only be specified if the first part in the filename
  653.        contains either '!', just before the second slash, or '::' */
  654. int slash = 1;
  655.     if (filename[0] == '/')
  656.        for (slash = 1; (filename[slash] != '') && (filename[slash] != '/'); slash++)
  657.           ;
  658.     /* second slash found */
  659.     if (filename[slash] == '/')
  660.     {  /* unix syntax */
  661.        if ( ((slash >= 1) && (filename[slash-1] == '!')) || 
  662.             ((slash >= 3) && (!strcmp(&filename[slash-3],"%21"))) )
  663.        {
  664.            char *p;
  665.            for (p = filename; *(p+1) != ''; p++)
  666.               *p = *(p+1);
  667.            *p = *(p+1); 
  668.            return(1);
  669.        }
  670.     }
  671.     else
  672.     {  /* vms syntax */
  673.        if (strstr(filename,"::") ||
  674.            strstr(filename,"%3A%3A") )
  675.        {
  676.            char *p;
  677.            for (p = filename; *(p+1) != ''; p++)
  678.               *p = *(p+1);
  679.            *p = *(p+1); 
  680.            return(1);
  681.        }
  682.     }
  683.     return(0);
  684. }
  685. /* PUBLIC HTVMS_getUIC()
  686. ** getUIC routine
  687. ** ON ENTRY:
  688. ** username Username specification
  689. **
  690. **
  691. ** ON EXIT:
  692. ** 0 error
  693. ** UIC VMS User Identification Code for username
  694. **
  695. */
  696. PUBLIC unsigned int HTVMS_getUIC ARGS1(
  697. CONST char *, username)
  698. {
  699. long Result;
  700. struct dsc$descriptor_s UserNameDesc;
  701. ItemStruct ItemList[2];
  702. unsigned long UIC;
  703. unsigned long UICLength;
  704.    /* construct UserName */
  705.    UserNameDesc.dsc$w_length = strlen(username);
  706.    UserNameDesc.dsc$b_dtype = DSC$K_DTYPE_T;
  707.    UserNameDesc.dsc$b_class = DSC$K_CLASS_S;
  708.    UserNameDesc.dsc$a_pointer = username;
  709.    /* UIC */
  710.    ItemList[0].BufferLength = sizeof(UIC);
  711.    ItemList[0].BufferAddress = &UIC;
  712.    ItemList[0].ReturnLengthAddress = &UICLength;
  713.    ItemList[0].ItemCode = UAI$_UIC;
  714.    /* terminate list */
  715.    ItemList[1].ItemCode = 0;
  716.    ItemList[1].BufferLength = 0;
  717.    /* get info */
  718.    Result = SYS$GETUAI(0,0,&UserNameDesc,ItemList,0,0,0);
  719.    if (Result != SS$_NORMAL)
  720.       return(0);
  721.    else
  722.       return((unsigned int) UIC);
  723. }
  724. /* PUBLIC HTVMS_isOwner()
  725. ** CHECKS OWNERSHIP OF FILE FOR CERTAIN USER
  726. ** ON ENTRY:
  727. ** FileName The file or directory to be checked
  728. ** UserName Name of the user to check ownership for.
  729. ** User nobody, represented by "" is given NO for an answer
  730. **
  731. ** ON EXIT:
  732. ** returns YES if FileName is owned by UserName
  733. **
  734. */
  735. PUBLIC BOOL HTVMS_isOwner ARGS2(
  736. CONST char *, FileName,
  737. CONST char *, UserName)
  738. {
  739. struct stat buf;
  740. int Result;
  741.    /* user nobody should access as from account under which server is running */
  742.    if (0 == strcmp(UserName,""))
  743.    {
  744.       CTRACE(TDEST, "VMSisOwner.. No access allowed user nobody.n");
  745.       return(NO);
  746.    }
  747.    /* load buf */
  748.    Result = HTStat(FileName, &buf);
  749.    if (Result) {
  750.       CTRACE(TDEST, "VMSisOwner.. HTStat() failed for '%s'n", FileName);
  751.       return NO;  /* no file or directory, so UserName can't own it */
  752.    }
  753.    /* compare with UIC for UserName */
  754.    if (buf.st_uid != HTVMS_getUIC(UserName)) {
  755.       CTRACE(TDEST, "VMSisOwner.. '%s' does not own '%s'n",
  756.             UserName, FileName);
  757.       return NO;
  758.    }
  759.    return YES;
  760. }