home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume34 / fsp / part01 / server_file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-18  |  17.0 KB  |  633 lines

  1.     /*********************************************************************\
  2.     *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
  3.     *                                                                     *
  4.     *  You may copy or modify this file in any manner you wish, provided  *
  5.     *  that this notice is always included, and that you hold the author  *
  6.     *  harmless for any loss or damage resulting from the installation or *
  7.     *  use of this software.                                              *
  8.     \*********************************************************************/
  9.  
  10. #include "server_def.h"
  11.  
  12. /*****************************************************************************
  13. * This is a modified server_file that hash file names.                 *
  14. *****************************************************************************/
  15.  
  16. #define NBSIZE (2*sizeof(UBUF))
  17.  
  18. extern *malloc();
  19.  
  20. #define fexist(A) (!access(A,0))
  21. #define touch(A) close(open(A,O_CREAT,0777))
  22. #define LF_PFX '&'
  23. #define LP_PFX '\\'
  24.  
  25. /*****************************************************************************
  26. * Routine to check a path string given by the client.
  27. * Will replace null string by ".".
  28. * In case of error, returns the error string.
  29. *****************************************************************************/
  30.  
  31. /*****************************************************************************
  32. *  The PPATH structure is filled in by the function check_path when given a
  33. *  path string.  The elements are filled in as such:
  34. *    fullp      pointer to a string containing the full path name
  35. *    f_ptr      pointer to begining of the last component of the path
  36. *       f_len      length of the last component of the path
  37. *    d_ptr      pointer to begining of the directory part of path
  38. *       d_len      length of the directory part of the path
  39. *
  40. *  fullp is a null-terminated full path string.
  41. *  f_ptr is always a null-terminated sub-string of fullp.
  42. *  p_ptr is generally not null-terminated.
  43. *****************************************************************************/
  44.  
  45. char *check_path(fullp,len,pp)
  46.     char *fullp;
  47.     int   len;
  48.     PPATH *pp;
  49. {
  50.     char *s;
  51.     int state;
  52.  
  53.     if(len < 1) return("Path must have non-zero length");
  54.     if(fullp[len-1]) return("Path not null terminated");
  55.  
  56.     pp->d_ptr = "."; pp->d_len = 1;    /* initial dir part ---> root */
  57.  
  58.     if(len == 1 && fullp[0] == 0)    /* null path --> root */
  59.     {
  60.     pp->fullp = pp->f_ptr = ".";
  61.     pp->f_len = 1;
  62.     return(NULLP);
  63.     }
  64.  
  65.     for(s = pp->fullp = pp->f_ptr = fullp, state = 0; *s; s++)
  66.     {
  67.     if(*s <= ' ' || *s >= '~') return("Path contains illegal chars");
  68.  
  69.     switch(*s)
  70.     {
  71.         case LF_PFX:
  72.         case LP_PFX:
  73.         case    '.': if(!state) return("Path can't begin with '.'");
  74.              break;
  75.  
  76.         case    '/': if(!state) return("Path can't contain '//'");
  77.              pp->d_ptr = fullp;
  78.              pp->d_len = s - fullp;
  79.              pp->f_ptr = s+1;
  80.              state = 0;
  81.              break;
  82.  
  83.         default    : state = 1;
  84.              break;
  85.     }
  86.     }
  87.  
  88.     pp->f_len = s - pp->f_ptr;
  89.     return(NULLP);
  90. }
  91.  
  92. /*****************************************************************************
  93. * Put the directory part of the path pp into dbuf.
  94. * return pointer to the null character.
  95. *****************************************************************************/
  96.  
  97. char *copy_dir(dbuf,pp)
  98.     char *dbuf;
  99.     PPATH *pp;
  100. {
  101.     char *p1,*p2;
  102.     int cnt;
  103.  
  104.     for(p1 = dbuf, p2 = pp->d_ptr, cnt = pp->d_len; cnt--; *p1++ = *p2++);
  105.     *p1 = 0; return(p1);
  106. }
  107.  
  108. /*****************************************************************************
  109. * Reads directory and write directory listing file.
  110. *****************************************************************************/
  111.  
  112. static build_dir_file(fp)
  113.     FILE *fp;
  114. {
  115.     int nlen, skip, rem;
  116.     DIR *dir_f;
  117. #ifdef DIRENT
  118.     struct dirent *dp;
  119. #else
  120.     struct direct *dp;
  121. #endif
  122.     struct stat    sb;
  123.     register char  *s;
  124.     RDIRENT rdb;
  125.     static char marker[] = "******************";
  126.     char longname[UBUF_SPACE];
  127.     FILE *lfp;
  128.  
  129.     if(!(dir_f = opendir(".")))    /* assume I have cd to path already */
  130.     { fprintf(stderr,"Can't open dir during initialization\n"); exit(1); }
  131.  
  132.     for(rem = UBUF_SPACE; dp = readdir(dir_f); )
  133.     {
  134.     if (dp->d_ino == 0) continue;
  135.     s = dp->d_name;
  136.  
  137.     if(s[0] == LF_PFX)
  138.     {
  139.         s[0] = LP_PFX;
  140.         if(!(lfp = fopen(s,"r"))) { unlink(s); *s = LF_PFX; unlink(s); }
  141.         fgets(longname,UBUF_SPACE,lfp);  fclose(lfp);
  142.         s[0] = LF_PFX; s = longname; longname[UBUF_SPACE-1] = 0;
  143.     }
  144.  
  145.     if(s[0] == LP_PFX) continue;
  146.                         /* hide dot files */
  147.     if((s[0] == '.') && ((s[1] !=  0 ) &&
  148.                  (s[1] != '.' || s[2] != 0))) continue;
  149.  
  150.     if(stat(dp->d_name,&sb)) continue;
  151.  
  152.     nlen = strlen(s)+1;
  153.  
  154.     if(rem < RDHSIZE + nlen)
  155.     {
  156.         rdb.type = RDTYPE_SKIP;
  157.         if(rem <= RDHSIZE) { fwrite(marker,1,rem    ,fp); }
  158.               else { fwrite(marker,1,RDHSIZE,fp);
  159.                  fwrite(s, 1,rem-RDHSIZE,fp); }
  160.         rem = UBUF_SPACE;
  161.     }
  162.  
  163.     rdb.type = ((S_IFDIR & sb.st_mode)) ? RDTYPE_DIR : RDTYPE_FILE;
  164.     rdb.size = htonl(sb.st_size);
  165.     rdb.time = htonl(sb.st_mtime);
  166.  
  167.     fwrite((char *) &rdb,1,RDHSIZE,fp);
  168.     fwrite(s,1,nlen,fp);
  169.     rem -= (nlen + RDHSIZE);
  170.  
  171.     if((skip = (nlen + RDHSIZE) & 0x3))
  172.         { fwrite((char *) &rdb,1,4-skip,fp); rem -= (4-skip); }
  173.  
  174.     if(!rem) rem = UBUF_SPACE;
  175.     }
  176.  
  177.     rdb.type = RDTYPE_END;
  178.     fwrite((char *) &rdb,1,RDHSIZE,fp);
  179.  
  180.     fflush(fp);
  181.     closedir(dir_f);
  182. }
  183.  
  184. /***************************************************************************/
  185.  
  186. char *server_get_dir(pp,fp)
  187.     PPATH *pp;            /* returned file may not point at BOF */
  188.     FILE **fp;
  189. {
  190.     char *server_get_dir_2();
  191.     struct stat sd, sf;
  192.     char   list_p[NBSIZE];
  193.     int    fsp_content_exists;
  194.  
  195.     if(stat(pp->fullp,&sd)) return("Can't find directory");
  196.     if(!(S_IFDIR & sd.st_mode)) return("Not a directory");
  197.  
  198.     sprintf(list_p,"%s/.FSP_CONTENT",pp->fullp);
  199.  
  200.     if(fsp_content_exists = !stat(list_p,&sf))
  201.     {
  202.     if(sf.st_mtime >= sd.st_mtime)
  203.     {
  204.         *fp = fopen(list_p,"r");
  205.         if(!*fp) return("Can't read directory listing");
  206.         return((char *)0);
  207.     }
  208.     }
  209.  
  210.     if(!fsp_content_exists &&
  211.     always_use_cache_dir) return(server_get_dir_2(pp,fp,&sd));
  212.  
  213.     if(!(*fp = fopen(list_p,"w+")))
  214.     {
  215.     if(!fsp_content_exists &&
  216.        !always_use_cache_dir) return(server_get_dir_2(pp,fp,&sd));
  217.     return("directory unreadable");
  218.     }
  219.     if(chdir(pp->fullp)) return("Can't cd to directory");
  220.     build_dir_file(*fp);
  221.     if(chdir(home_dir) == -1) { perror("chdir2"); exit(1); }
  222.     return(NULLP);
  223. }
  224.  
  225. char *server_get_dir_2(pp,fp,sd)
  226.     PPATH *pp;
  227.     FILE **fp;
  228.     struct stat *sd;
  229. {
  230.     struct stat sf;
  231.     char   name_p[NBSIZE], list_p[NBSIZE], tmp[UBUF_SPACE];
  232.     unsigned int hash, i, mask, new_namefile;
  233.     unsigned char *p;
  234.     FILE *np;
  235.  
  236.     mask = dir_cache_limit << 8;
  237.  
  238.     for(hash = 0, p = (unsigned char *) pp->fullp; *p; p++)
  239.     {
  240.     hash = (hash << 1) ^ *p;
  241.     if(hash & mask) hash ^= (mask+1);
  242.     }
  243.  
  244.     for(i = 8; i--; )
  245.     {
  246.     hash <<= 1;
  247.     if(hash & mask) hash ^= (mask+1);
  248.     }
  249.  
  250.     hash = (hash >> 8) & (mask-1);
  251.  
  252.     sprintf(name_p,"%s/.N%x",dir_cache_dir,hash);
  253.     sprintf(list_p,"%s/.L%x",dir_cache_dir,hash);
  254.  
  255.     if(!(np = fopen(name_p,"r"))) new_namefile = 1; else
  256.     {
  257.     fgets(tmp,UBUF_SPACE,np); fclose(np);
  258.  
  259.     if(strcmp(tmp,pp->fullp)) new_namefile = 1; else
  260.     {
  261.         if(!stat(list_p,&sf) && (sf.st_mtime >= sd->st_mtime))
  262.         {
  263.         *fp = fopen(list_p,"r");
  264.         if(!*fp) return("Can't read directory listing");
  265.         return((char *)0);
  266.         }
  267.         new_namefile = 0;
  268.     }
  269.     }
  270.  
  271.     if(new_namefile)
  272.     {
  273.     if(!(np = fopen(name_p,"w")))
  274.         return("Can't write directory listing name file");
  275.     fputs(pp->fullp,np); fclose(np);
  276.     }
  277.  
  278.     if(!(*fp = fopen(list_p,"w+"))) return("directory unreadable");
  279.     if(chdir(pp->fullp)) return("Can't cd to directory");
  280.     build_dir_file(*fp);
  281.     if(chdir(home_dir) == -1) { perror("chdir2"); exit(1); }
  282.     return(NULLP);
  283. }
  284.  
  285. /**********************************************************************/
  286.  
  287. char *server_del_file(pp,inet_num)        /* assume path is validated */
  288.     PPATH *pp;
  289.     unsigned long inet_num;
  290. {
  291.     int is_long;
  292.     struct stat sb;
  293.     char   ok_del_p[NBSIZE], owner_p[NBSIZE];
  294.  
  295.     if(is_long = (pp->f_len > max_nlen)) fold_path(pp);
  296.  
  297.     if(stat(pp->fullp,&sb)) return("unlink: file not accessible");
  298.     if(!(S_IFREG & sb.st_mode)) return("unlink: not an ordinary file");
  299.  
  300.     sprintf(copy_dir( owner_p,pp),"/.OWN.%08X"  ,inet_num);
  301.      strcpy(copy_dir(ok_del_p,pp),"/.FSP_OK_DEL"         );
  302.  
  303.     if(!fexist(owner_p) && !fexist(ok_del_p))
  304.             return("no permission for removing this file");
  305.  
  306.     if(unlink(pp->fullp) == -1) return("unlink: cannot unlink");
  307.  
  308.     if(is_long) { *pp->f_ptr = LP_PFX; unlink(pp->fullp); }
  309.  
  310.     return(NULLP);
  311. }
  312.  
  313. /**********************************************************************/
  314.  
  315. char *server_del_dir(pp,inet_num)
  316.     PPATH *pp;
  317.     unsigned long inet_num;
  318. {
  319.     struct stat sb;
  320.     char   list_p[NBSIZE], ok_del_p[NBSIZE], ok_add_p[NBSIZE], owner_p[NBSIZE];
  321.     int    has_ok_del_p, has_ok_add_p;
  322.  
  323.     if(stat(pp->fullp,&sb)) return("rmdir: directory not accessible");
  324.     if(!(S_IFDIR & sb.st_mode)) return("rmdir: not an ordinary directory");
  325.  
  326.     sprintf( owner_p,"%s/.OWN.%08X"   ,pp->fullp,inet_num);
  327.     sprintf(  list_p,"%s/.FSP_CONTENT",pp->fullp         );
  328.     sprintf(ok_del_p,"%s/.FSP_OK_DEL" ,pp->fullp         );
  329.     sprintf(ok_add_p,"%s/.FSP_OK_ADD" ,pp->fullp         );
  330.  
  331.     if(!fexist(owner_p)) return("no permission for removing this directory");
  332.  
  333.     unlink(owner_p); unlink( list_p);
  334.     has_ok_del_p = !unlink(ok_del_p);
  335.     has_ok_add_p = !unlink(ok_add_p);
  336.  
  337.     if(rmdir(pp->fullp) != 0)
  338.     {
  339.     if(has_ok_del_p) touch(ok_del_p);
  340.     if(has_ok_add_p) touch(ok_add_p);
  341.     if(     owner_p) touch( owner_p);
  342.     return("rmdir: cannot unlink");
  343.     }
  344.  
  345.     return(NULLP);
  346. }
  347.  
  348. /**********************************************************************/
  349.  
  350. char *server_make_dir(pp,inet_num)
  351.     PPATH *pp;
  352.     unsigned long inet_num;
  353. {
  354.     char ok_add_p[NBSIZE], owner_p[NBSIZE];
  355.  
  356.     sprintf(copy_dir( owner_p,pp),"/.OWN.%08X"  ,inet_num);
  357.      strcpy(copy_dir(ok_add_p,pp),"/.FSP_OK_ADD"         );
  358.  
  359.     if(!fexist(owner_p) && !fexist(ok_add_p))
  360.             return("no permission for directory creation");
  361.  
  362.     sprintf(owner_p,"%s/.OWN.%08X",pp->fullp,inet_num);
  363.  
  364.     if(mkdir(pp->fullp,0777) != 0) return("Can't create directory");
  365.  
  366.     touch(owner_p);
  367.     return(NULLP);
  368. }
  369.  
  370. /**********************************************************************/
  371.  
  372. char *server_get_file(pp,fp)
  373.     PPATH *pp;
  374.     FILE **fp;
  375. {
  376.     struct stat sb;
  377.  
  378.     if(pp->f_len > max_nlen) fold_path(pp);
  379.  
  380.     if(stat(pp->fullp,&sb)) return("Can't find file");
  381.     if(!(S_IFREG & sb.st_mode)) return("Not a file");
  382.     if(!(*fp = fopen(pp->fullp,"r"))) return("Can't open file");
  383.     return(NULLP);
  384. }
  385.  
  386. /**********************************************************************/
  387.  
  388. char *server_get_pro(pp,result,inet_num) /* result and pp->fullp may overlap */
  389.     PPATH *pp;
  390.     char *result;
  391.     unsigned long inet_num;
  392. {
  393.     struct stat sb;
  394.     char   buf[NBSIZE];
  395.     char  *owner_s, *del_s, *add_s;
  396.  
  397.     if(stat(pp->fullp,&sb)) return("getpro: directory not accessible");
  398.     if(!(S_IFDIR & sb.st_mode)) return("getpro: not an ordinary directory");
  399.  
  400.     sprintf(buf,"%s/.OWN.%08X",pp->fullp,inet_num);
  401.     owner_s = ( fexist(buf)) ? "your" : "some other";
  402.     sprintf(buf,"%s/.FSP_OK_DEL" ,pp->fullp);
  403.     del_s   = (!fexist(buf)) ? "NO" : "YES";
  404.     sprintf(buf,"%s/.FSP_OK_ADD" ,pp->fullp);
  405.     add_s   = (!fexist(buf)) ? "NO" : "YES";
  406.  
  407.     sprintf(result,"(owner: %s machine)(delete: %s)(create: %s)",
  408.                         owner_s, del_s, add_s);
  409.     return(NULLP);
  410. }
  411.  
  412. /**********************************************************************/
  413.  
  414. char *server_set_pro(pp,key,inet_num)
  415.     PPATH *pp;
  416.     char *key;
  417.     unsigned long inet_num;
  418. {
  419.     struct stat sb;
  420.     char   buf[NBSIZE];
  421.  
  422.     if(stat(pp->fullp,&sb)) return("getpro: directory not accessible");
  423.     if(!(S_IFDIR & sb.st_mode)) return("getpro: not an ordinary directory");
  424.  
  425.     sprintf(buf,"%s/.OWN.%08X",pp->fullp,inet_num);
  426.     if(!fexist(buf)) return("no permission for changing the protection-mode");
  427.  
  428.     switch(key[1])
  429.     {
  430.     case 'c': sprintf(buf,"%s/.FSP_OK_ADD",pp->fullp); break;
  431.     case 'd': sprintf(buf,"%s/.FSP_OK_DEL",pp->fullp); break;
  432.     default : return("bad flag");
  433.     }
  434.  
  435.     switch(key[0])
  436.     {
  437.     case '+':  touch(buf); break;
  438.     case '-': unlink(buf); break;
  439.     default : return("bad flag");
  440.     }
  441.  
  442.     return(NULLP);
  443. }
  444.  
  445. /**********************************************************************
  446. *  These two are used for file uploading.
  447. **********************************************************************/
  448.  
  449. char *server_up_load(data,len,pos,inet_num,port_num)
  450.     char *data;
  451.     int    len;
  452.     unsigned long pos, inet_num;
  453.     unsigned short port_num;
  454. {
  455.     FILE *fp;
  456.     char  tname[NBSIZE];
  457.  
  458.     sprintf(tname,"%s/.T%08X%04X",dir_cache_dir,inet_num,port_num);
  459.  
  460.     if(pos) {             fp = fopen(tname,"a"); }
  461.        else { unlink(tname); fp = fopen(tname,"w"); }
  462.  
  463.     if(!fp) return("Cannot open temporary file");
  464.  
  465.     fwrite(data, 1, len, fp);
  466.     fclose(fp);
  467.  
  468.     return(NULLP);
  469. }
  470.  
  471. char *server_install(pp,inet_num,port_num)
  472.     PPATH *pp;
  473.     unsigned long inet_num;
  474.     unsigned short port_num;
  475. {
  476.     FILE *ft, *fp;
  477.     char      tname[NBSIZE],  owner_p[NBSIZE], save_p[NBSIZE], buf[512];
  478.     char   ok_del_p[NBSIZE], ok_add_p[NBSIZE];
  479.     int bytes, is_long;
  480.  
  481.     if(is_long = (pp->f_len > max_nlen))
  482.             { strcpy(save_p,pp->f_ptr); fold_path(pp); }
  483.  
  484.     sprintf(copy_dir(owner_p,pp),"/.OWN.%08X",inet_num);
  485.     sprintf(tname,"%s/.T%08X%04X",dir_cache_dir,inet_num,port_num);
  486.  
  487.     if(!fexist(owner_p))
  488.     {
  489.     strcpy(copy_dir(ok_add_p,pp),"/.FSP_OK_ADD");
  490.     strcpy(copy_dir(ok_del_p,pp),"/.FSP_OK_DEL");
  491.  
  492.     if(!fexist(ok_add_p))
  493.     {
  494.         unlink(tname);
  495.         return("no permission for creating that file");
  496.     }
  497.  
  498.     if(!fexist(ok_del_p) && fexist(pp->fullp))
  499.     {
  500.         unlink(tname);
  501.         return("no permission for replacing that file");
  502.     }
  503.     }
  504.  
  505.     unlink(pp->fullp);
  506.     if(link(tname,pp->fullp) == 0) { unlink(tname); goto done; }
  507.  
  508.     if(!(ft = fopen(tname,"r"))) { unlink(tname);
  509.                    return("Can't open temporary file"); }
  510.  
  511.     if(!(fp = fopen(pp->fullp ,"w"))) { unlink(tname); fclose(ft);
  512.                    return("Can't open file for output"); }
  513.  
  514.     while(bytes = fread(buf,1,sizeof(buf),ft)) fwrite(buf,1,bytes,fp);
  515.  
  516.     fclose(ft); fclose(fp); unlink(tname);
  517.  
  518.   done:
  519.  
  520.     if(is_long)
  521.     {
  522.     *pp->f_ptr = LP_PFX;
  523.     if(!(fp = fopen(pp->fullp,"w")))
  524.     {
  525.         *pp->f_ptr = LF_PFX; unlink(tname);
  526.         return("Can't create long named file for output");
  527.     }
  528.     fputs(save_p,fp); fclose(fp);
  529.     }
  530.  
  531.     return(NULLP);
  532. }
  533.  
  534. /**********************************************************************/
  535.  
  536. char *server_secure_file(pp,inet_num,port_num)    /* assume path is validated */
  537.     PPATH *pp;
  538.     unsigned long  inet_num;
  539.     unsigned short port_num;
  540. {
  541.     int is_long;
  542.     struct stat sb;
  543.     char   ok_del_p[NBSIZE], owner_p[NBSIZE], temp_p[NBSIZE];
  544.  
  545.     if(is_long = (pp->f_len > max_nlen)) fold_path(pp);
  546.  
  547.     if(stat(pp->fullp,&sb)) return("grab: file not accessible");
  548.     if(!(S_IFREG & sb.st_mode)) return("grab: not an ordinary file");
  549.  
  550.     sprintf(copy_dir( owner_p,pp),"/.OWN.%08X"  ,inet_num         );
  551.      strcpy(copy_dir(ok_del_p,pp),"/.FSP_OK_DEL"                  );
  552.     sprintf(copy_dir(  temp_p,pp),"/.G%08X%04X" ,inet_num,port_num);
  553.  
  554.     if(!fexist(owner_p) && !fexist(ok_del_p))
  555.             return("grab: no permission for grabbing this file");
  556.  
  557.     unlink(temp_p);
  558.     if(link(pp->fullp,temp_p) == -1) return("grab: cannot make link");
  559.     if(unlink(pp->fullp) == -1) { unlink(temp_p);
  560.                   return("grab: cannot unlink"); }
  561.  
  562.     if(is_long) { *pp->f_ptr = LP_PFX; unlink(pp->fullp); }
  563.  
  564.     return(NULLP);
  565. }
  566.  
  567. char *server_grab_file(pp,fp,inet_num,port_num)
  568.     PPATH *pp;
  569.     FILE **fp;
  570.     unsigned long  inet_num;
  571.     unsigned short port_num;
  572. {
  573.     struct stat sb;
  574.     char temp_p[NBSIZE];
  575.  
  576.     sprintf(copy_dir(temp_p,pp),"/.G%08X%04X",inet_num,port_num);
  577.  
  578.     if(stat(temp_p,&sb)) return("grab: can't find file");
  579.     if(!(S_IFREG & sb.st_mode)) return("grab: Not a file");
  580.     if(!(*fp = fopen(temp_p,"r"))) return("grab: can't open file");
  581.     return(NULLP);
  582. }
  583.  
  584. char *server_grab_done(pp,inet_num,port_num)
  585.     PPATH *pp;
  586.     unsigned long  inet_num;
  587.     unsigned short port_num;
  588. {
  589.     struct stat sb;
  590.     char temp_p[NBSIZE];
  591.  
  592.     sprintf(copy_dir(temp_p,pp),"/.G%08X%04X",inet_num,port_num);
  593.  
  594.     if(stat(temp_p,&sb)) return("grab: can't find temporary file");
  595.     if(unlink(temp_p) == -1) return("grab: can't delete temporary file");
  596.     return(NULLP);
  597. }
  598.  
  599. /**********************************************************************/
  600.  
  601. fold_path(pp)
  602.     PPATH *pp;
  603. {
  604.     unsigned char *p;
  605.     unsigned long v1, v2;
  606.  
  607.     p = (unsigned char *) pp->f_ptr;
  608.  
  609.     for(v1 = 0; v2 = *p++; )
  610.     {
  611.     if(v1 & 0x80000000) { v1 = (v1 << 1) ^ v2 ^ 1; }
  612.                else { v1 = (v1 << 1) ^ v2    ; }
  613.     }
  614.  
  615.     sprintf(pp->f_ptr,"%c%08X",LF_PFX,v1);
  616.     pp->f_len = 9;
  617. }
  618.  
  619. /**********************************************************************/
  620.  
  621. init_home_dir()
  622. {
  623.     if(*home_dir != '/') { fprintf(stderr,"[%s] does not start with a /\n");
  624.                exit(1); }
  625.  
  626.     if(chdir(home_dir) == -1) { perror("chdir"); exit(1); }
  627.  
  628.     if(dbug) { fprintf(stderr,"home on %s\n",home_dir); fflush(stderr); }
  629. }
  630.  
  631. /***************************************************************************/
  632.