home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / contrib / samba / samba-1.8 / samba-1 / samba-1.8.05 / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  121.1 KB  |  4,985 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.8.
  4.    Copyright (C) Andrew Tridgell 1992,1993,1994
  5.    
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.    
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #include "includes.h"
  22.  
  23. pstring scope = "";
  24.  
  25. int DEBUGLEVEL = 1;
  26.  
  27. BOOL passive = False;
  28.  
  29. int Protocol = PROTOCOL_COREPLUS;
  30.  
  31.  
  32. /* a default finfo structure to ensure all fields are sensible */
  33. file_info def_finfo = {-1,0,0,0,0,0,0,""};
  34.  
  35. /* these are some file handles where debug info will be stored */
  36. FILE *dbf = NULL;
  37. FILE *login=NULL;
  38. FILE *logout=NULL;
  39.  
  40. /* the client file descriptor */
  41. int Client = 0;
  42.  
  43. /* info on the client */
  44. struct from_host Client_info=
  45. {"UNKNOWN","0.0.0.0",NULL};
  46.  
  47. /* the last IP received from */
  48. struct in_addr lastip;
  49.  
  50. /* the last port received from */
  51. int lastport=0;
  52.  
  53. /* my IP, the broadcast IP and the Netmask */
  54. struct in_addr myip;
  55. struct in_addr bcast_ip;
  56. struct in_addr Netmask;
  57.  
  58. int trans_num = 0;
  59.  
  60. /* this is set to true on a big_endian machine (like a sun sparcstation)
  61. this means that all shorts and ints must be byte swapped before being
  62. put in the buffer */
  63. BOOL NeedSwap=False;
  64.  
  65. /*
  66.    case handling on filenames 
  67. */
  68. int case_sensitivity = CASE_LOWER;
  69.  
  70.  
  71. /* this structure is used to hold information about the machine that 
  72.    the program is running on */
  73. machine_struct machine_info;
  74.  
  75. BOOL casesignames = False; /* Placed here to allow client to link without 
  76.                   including loadparms.o. Set by reply_lanman2;
  77.                */
  78.  
  79. pstring debugf = DEBUGFILE;
  80.  
  81. /*******************************************************************
  82. write an debug message on the debugfile. The first arg is the debuglevel.
  83. ********************************************************************/
  84. #ifdef __STDC__
  85. int Debug1(char *format_str, ...)
  86. {
  87. #else
  88. int Debug1(va_alist)
  89. va_dcl
  90. {
  91.   char *format_str;
  92. #endif
  93.   va_list ap;
  94.   
  95.   if (!dbf) 
  96.     {
  97.           dbf = fopen(debugf,"w");
  98.     if (dbf)
  99.       setbuf(dbf,NULL);
  100.     else
  101.       return(0);
  102.     }
  103.  
  104.   
  105. #ifdef __STDC__
  106.   va_start(ap, format_str);
  107. #else
  108.   va_start(ap);
  109.   format_str = va_arg(ap,char *);
  110. #endif
  111.  
  112.   vfprintf(dbf,format_str,ap);
  113.  
  114.   fflush(dbf);
  115.  
  116.   va_end(ap);
  117.   return(0);
  118. }
  119.  
  120.  
  121. #ifdef STRING_DEBUG
  122. #define LONG_LEN (sizeof(pstring)/3)
  123. int mystrlen(char *s)
  124. {
  125.   int n=0;
  126.   while (*s++)
  127.     n++;
  128.   if (n > LONG_LEN)
  129.     DEBUG(0,("ERROR: long string\n"));
  130.   return n;
  131. }
  132.  
  133. char *mystrchr(char *s,char c)
  134. {
  135. if (strlen(s) > LONG_LEN)
  136.   DEBUG(0,("ERROR: long string\n"));
  137. while (*s)
  138.   {
  139.     if (*s == c) break;
  140.     s++;
  141.   }
  142. if (*s == c)
  143.   return s;
  144. else
  145.   return NULL;
  146. }
  147.  
  148.  
  149. char *mystrrchr(char *s,char c)
  150. {
  151. char *s2;
  152. if (strlen(s) > LONG_LEN)
  153.   DEBUG(0,("ERROR: long string\n"));
  154.  
  155. s2 = s + strlen(s);
  156.  
  157. while (s != s2)
  158.   {
  159.     if (*s2 == c) break;
  160.     s2--;
  161.   }
  162. if (*s2 == c)
  163.   return s2;
  164. else
  165.   return NULL;
  166. }
  167.  
  168. char *mystrcpy(char *d,char *s)
  169. {
  170.   if (strlen(s) > LONG_LEN)
  171.     DEBUG(0,("ERROR: long string\n"));
  172.   while ((*d++  = *s++));
  173. }
  174.  
  175. char *mystrncpy(char *d,char *s,int n)
  176. {
  177.   if (strlen(s) > LONG_LEN)
  178.     DEBUG(0,("ERROR: long string\n"));
  179.   while ((*d++  = *s++) && n--);
  180. }
  181.  
  182. char *mystrcat(char *d,char *s)
  183. {
  184.   if (strlen(s) > LONG_LEN || strlen(d)>LONG_LEN)
  185.     DEBUG(0,("ERROR: long string\n"));
  186.   d+=strlen(d);
  187.   while ((*d++  = *s++));
  188. }
  189.  
  190. void mymemcpy(char *d,char *s,int n)
  191. {
  192. if (n > LONG_LEN)
  193.   DEBUG(0,("ERROR: long copy\n"));
  194. while (n--)
  195.   *d++ = *s++;
  196. }
  197.  
  198. void mymemset(char *d,char c,int n)
  199. {
  200. if (n > LONG_LEN)
  201.   DEBUG(0,("ERROR: long set\n"));
  202. while (n--)
  203.   *d++ = c;
  204. }
  205. #endif
  206.  
  207.  
  208. int extra_time_offset = 0;
  209.  
  210. /****************************************************************************
  211. return the difference between local and GMT time
  212. ****************************************************************************/
  213. int TimeDiff(void)
  214. {
  215.   static BOOL initialised = False;
  216.   static int timediff = 0;
  217.  
  218.   if (!initialised)
  219.     {
  220.       /* There are four ways of getting the time difference between GMT and
  221.      local time. Use the following defines to decide which your system
  222.      can handle */
  223. #ifdef HAVE_GETTIMEOFDAY
  224.       struct timeval tv;
  225.       struct timezone tz;
  226.  
  227.       gettimeofday(&tv, &tz);
  228.       timediff = 60 * tz.tz_minuteswest;
  229. #else
  230.       time_t t=time(NULL);
  231.  
  232. #ifdef HAVE_TIMELOCAL
  233.       timediff = timelocal(gmtime(&t)) - t;
  234. #else
  235. #ifdef HAVE_TIMEZONE
  236.       localtime(&t);
  237.       timediff = timezone;
  238. #else
  239.       timediff = - (localtime(&t)->tm_gmtoff);
  240. #endif
  241. #endif
  242. #endif
  243.       DEBUG(3,("timediff=%d\n",timediff));
  244.       initialised = True;
  245.     }
  246.  
  247. return(timediff + (extra_time_offset*60));
  248. }
  249.  
  250.  
  251. /****************************************************************************
  252. try to optimise the timelocal call, it can be quite expenive on some machines
  253. ****************************************************************************/
  254. time_t TimeLocal(struct tm *tm,int timemul)
  255. {
  256. #ifdef sun386
  257.   return(timelocal(tm) + timemul * TimeDiff());
  258. #else
  259.   return(mktime(tm) + timemul * TimeDiff());
  260. #endif
  261. }
  262.  
  263. /****************************************************************************
  264. try to optimise the localtime call, it can be quite expenive on some machines
  265. timemul is normally LOCAL_TO_GMT, GMT_TO_LOCAL or 0
  266. ****************************************************************************/
  267. struct tm *LocalTime(time_t *t,int timemul)
  268. {
  269.   time_t t2 = *t;
  270.  
  271.   t2 += timemul * TimeDiff();
  272.  
  273.   return(gmtime(&t2));
  274. }
  275.  
  276.  
  277. /*******************************************************************
  278. safely copies memory, ensuring no overlap problems.
  279. ********************************************************************/
  280. void safe_memcpy(void *dest,void *src,int size)
  281. {
  282.   /* do the copy in chunks of size difference. This relies on the 
  283.      capability of pointer comparison. */
  284.  
  285.   int difference = ABS((char *)dest - (char *)src);
  286.  
  287.   if (difference == 0 || size <= 0)
  288.     return;
  289.  
  290.   if (difference >= size) /* no overlap problem */
  291.     {
  292.       memcpy(dest,src,size);
  293.       return;
  294.     }
  295.  
  296.   if (dest > src) /* copy the last chunks first */
  297.     {
  298.       char *this_dest=dest;
  299.       char *this_src=src;
  300.       this_dest += size - difference;
  301.       this_src += size - difference;
  302.       while (size>0)
  303.     {
  304.       memcpy(this_dest,this_src,difference);
  305.       this_dest -= difference;
  306.       this_src -= difference;
  307.       size -= difference;
  308.     }
  309.     }
  310.   else
  311.     { /* copy from the front */
  312.       char *this_dest=dest;
  313.       char *this_src=src;
  314.       while (size>0)
  315.     {
  316.       memcpy(this_dest,this_src,difference);
  317.       this_dest += difference;
  318.       this_src += difference;
  319.       size -= difference;
  320.     }
  321.     }
  322. }
  323.  
  324. /****************************************************************************
  325. prompte a dptr (to make it recently used)
  326. ****************************************************************************/
  327. void array_promote(char *array,int elsize,int element)
  328. {
  329.   char *p;
  330.   if (element == 0)
  331.     return;
  332.  
  333.   p = (char *)malloc(elsize);
  334.  
  335.   if (!p)
  336.     {
  337.       DEBUG(5,("Ahh! Can't malloc\n"));
  338.       return;
  339.     }
  340.   memcpy(p,array + element * elsize, elsize);
  341.   safe_memcpy(array + elsize,array,elsize*element);
  342.   memcpy(array,p,elsize);
  343.   free(p);
  344. }
  345.     
  346. /****************************************************************************
  347.   close the socket communication
  348. ****************************************************************************/
  349. void close_sockets(void )
  350. {
  351.   extern int Client;
  352.   close(Client);
  353.   Client = 0;
  354. }
  355.  
  356. /****************************************************************************
  357.   return the date and time as a string
  358. ****************************************************************************/
  359. char *timestring(void )
  360. {
  361.   static char TimeBuf[100];
  362.   time_t t;
  363.   t = time(NULL);
  364. #ifdef NO_STRFTIME
  365.   strcpy(TimeBuf, asctime(LocalTime(&t,GMT_TO_LOCAL)));
  366. #else
  367. #ifdef CLIX
  368.   strftime(TimeBuf,100,"%m/%d/%y %I:%M:%S %p",LocalTime(&t,GMT_TO_LOCAL));
  369. #else
  370. #ifdef AMPM
  371.   strftime(TimeBuf,100,"%D %r",LocalTime(&t,GMT_TO_LOCAL));
  372. #else
  373.   strftime(TimeBuf,100,"%D %T",LocalTime(&t,GMT_TO_LOCAL));
  374. #endif
  375. #endif /* CLIX */
  376. #endif
  377.   return(TimeBuf);
  378. }
  379.  
  380. /****************************************************************************
  381. determine whether we are in the specified group
  382. ****************************************************************************/
  383. BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups)
  384. {
  385.   int i;
  386.  
  387.   if (group == current_gid) return(True);
  388.  
  389.   for (i=0;i<ngroups;i++)
  390.     if (group == groups[i])
  391.       return(True);
  392.  
  393.   return(False);
  394. }
  395.  
  396. /****************************************************************************
  397. line strncpy but always null terminates. Make sure there is room!
  398. ****************************************************************************/
  399. char *StrnCpy(char *dest,char *src,int n)
  400. {
  401.   char *d = dest;
  402.   while (n-- && (*d++ = *src++)) ;
  403.   *d = 0;
  404.   return(dest);
  405. }
  406.  
  407.  
  408. /****************************************************************************
  409. interpret the weird netbios "name"
  410. ****************************************************************************/
  411. void name_interpret(char *in,char *out)
  412. {
  413.  
  414. int len = (*in++) / 2;
  415. while (len--)
  416.   {
  417.     *out = ((in[0]-'A')<<4) + (in[1]-'A');
  418.     in += 2;
  419.     out++;
  420.   }
  421. *out = 0;
  422. /* Handle any scope names */
  423. while(*in) 
  424.   {
  425.   *out++ = '.'; /* Scope names are separated by periods */
  426.   len = *(unsigned char *)in++;
  427.   StrnCpy(out, in, len);
  428.   out += len;
  429.   *out=0;
  430.   in += len;
  431.   }
  432. }
  433.  
  434. /****************************************************************************
  435. mangle a name into netbios format
  436. ****************************************************************************/
  437. int name_mangle(char *In,char *Out)
  438. {
  439.   char *in = (char *)In;
  440.   char *out = (char *)Out;
  441.   char *p, *label;
  442.   int len = 2*strlen((char *)in);
  443.   int pad = 0;
  444.  
  445.   if (len/2 < 16)
  446.     pad = 16 - (len/2);
  447.  
  448.   *out++ = 2*(strlen((char *)in) + pad);
  449.   while (*in)
  450.     {
  451.       out[0] = (in[0]>>4) + 'A';
  452.       out[1] = (in[0] & 0xF) + 'A';
  453.       in++;
  454.       out+=2;
  455.     }
  456.   
  457.   while (pad--)
  458.     {
  459.       out[0] = 'C';
  460.       out[1] = 'A';
  461.       out+=2;
  462.     }
  463.   
  464.   label = scope;
  465.   while (*label)
  466.     {
  467.       p = strchr(label, '.');
  468.       if (p == 0)
  469.     p = label + strlen(label);
  470.       *out++ = p - label;
  471.       memcpy(out, label, p - label);
  472.       out += p - label;
  473.       label += p - label + (*p == '.');
  474.     }
  475.   *out = 0;
  476.   return(name_len(Out));
  477. }
  478.  
  479. /*******************************************************************
  480.   byte swap an object - the byte order of the object is reversed
  481. ********************************************************************/
  482. void *object_byte_swap(void *obj,int size)
  483. {
  484.   int i;
  485.   char c;
  486.   char *p1 = (char *)obj;
  487.   char *p2 = p1 + size - 1;
  488.   
  489.   size /= 2;
  490.   
  491.   for (i=0;i<size;i++)
  492.     {
  493.       c = *p1;
  494.       *p1 = *p2;
  495.       *p2 = c;
  496.       p1++;
  497.       p2--;
  498.     }
  499.   return(obj);
  500. }
  501.  
  502. /****************************************************************************
  503.   byte swap a uint16
  504. ****************************************************************************/
  505. uint16 uint16_byte_swap(uint16 x)
  506. {
  507.   uint16 res;
  508.   res = x;
  509.   SWP(&res,sizeof(res));
  510.   return(res);
  511. }
  512.  
  513. /****************************************************************************
  514.   byte swap a uint32
  515. ****************************************************************************/
  516. uint32 uint32_byte_swap(uint32 x)
  517. {
  518.   uint32 res;
  519.   res = x;
  520.   SWP(&res,sizeof(res));
  521.   return(res);
  522. }
  523.  
  524. /*******************************************************************
  525.   turn the last component of a name into a case independent form.
  526.   (Used for lanman2 case independent filename support).
  527. ********************************************************************/
  528. void find_case_independent_name(char *name)
  529. {
  530.   void *dirptr;
  531.   struct DIRECT *dptr;
  532.   pstring dir_to_search = "";
  533.   char *search_name;
  534.   char *p;
  535.  
  536.   /* Ensure name doesn't end in '/' */
  537.   while(*(p = &name[strlen(name)-1]) == '/')
  538.     *p = '\0';
  539.  
  540.   if((p = strrchr(name,'/'))==NULL)
  541.      {
  542.        strcpy(dir_to_search,".");
  543.        search_name = name;
  544.      }
  545.   else
  546.      {
  547.        StrnCpy(dir_to_search,name,p-name);
  548.        search_name = p+1;
  549.      }
  550.  
  551.   DEBUG(3,("make_case_independent name - searching for %s in %s\n",name,dir_to_search));
  552.  
  553.   dirptr = (void *)opendir(dir_to_search);
  554.   
  555.   if (!dirptr)
  556.     return;
  557.  
  558.   dptr = readdir(dirptr);
  559.   while (dptr)
  560.     {
  561.       if (strequal(dptr->d_name,search_name))
  562.     {
  563.       DEBUG(3,("find_case_independent_name - replacing %s with %s\n",search_name,dptr->d_name));
  564.       memcpy(search_name,dptr->d_name,strlen(dptr->d_name));
  565.       closedir(dirptr);
  566.       return;
  567.     }
  568.       dptr = readdir(dirptr);
  569.     }
  570.   
  571.   /* didn't find it */
  572.   closedir(dirptr);
  573.   return;
  574. }
  575.  
  576. /*******************************************************************
  577.   check if a file exists
  578. ********************************************************************/
  579. BOOL file_exist(char *fname)
  580. {
  581.   struct stat st;
  582.   
  583.   if((Protocol >= PROTOCOL_LANMAN2) && casesignames)
  584.     { /* We could use unix_convert_lanman2 here but find_case...
  585.      is a big optimization if this has already been done 
  586.      (ie. we only need to seach for the last component) */
  587.       find_case_independent_name(fname);
  588.     }
  589.  
  590.   if (stat(fname,&st) != 0) 
  591.     return(False);
  592.  
  593. #if (defined(NEXT2) || defined(NEXT3_0))
  594.   if ((S_IFREG & st.st_mode)>0)
  595.     return(True);
  596.   else
  597.     return(False);
  598. #else
  599.   return(S_ISREG(st.st_mode));
  600. #endif
  601. }
  602.  
  603. /*******************************************************************
  604.   check if a directory exists
  605. ********************************************************************/
  606. BOOL directory_exist(char *dname)
  607. {
  608.   struct stat st;
  609.  
  610.   if((Protocol >= PROTOCOL_LANMAN2) && casesignames)
  611.     { /* We could use unix_convert_lanman2 here but find_case...
  612.      is a big optimization if this has already been done 
  613.      (ie. we only need to seach for the last component) */
  614.       find_case_independent_name(dname);
  615.     }
  616.  
  617.   if (stat(dname,&st) != 0) 
  618.     return(False);
  619.  
  620. #if (defined(NEXT2) || defined(NEXT3_0))
  621.   if ((S_IFDIR & st.st_mode)>0)
  622.     return(True);
  623.   else
  624.     return(False);
  625. #else
  626.   return(S_ISDIR(st.st_mode));
  627. #endif
  628. }
  629.  
  630. /*******************************************************************
  631. returns the size in bytes of the named file
  632. ********************************************************************/
  633. uint32 file_size(char *file_name)
  634. {
  635.   struct stat buf;
  636.   buf.st_size = 0;
  637.   stat(file_name,&buf);
  638.   return(buf.st_size);
  639. }
  640.  
  641. /*******************************************************************
  642.   create a 16 bit dos packed date
  643. ********************************************************************/
  644. uint16 make_dos_date1(time_t unixdate)
  645. {
  646.   uint16 ret;
  647.   unsigned char *p;
  648.   struct tm *t;
  649.  
  650.   t = LocalTime(&unixdate,GMT_TO_LOCAL);
  651.   p = (unsigned char *)&ret;
  652.   p[0] = t->tm_mday | (((t->tm_mon+1) & 0x7) << 5);
  653.   p[1] = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
  654.   return(ret);
  655. }
  656.  
  657. /*******************************************************************
  658.   create a 16 bit dos packed time
  659. ********************************************************************/
  660. uint16 make_dos_time1(time_t unixdate)
  661. {
  662.   uint16 ret;
  663.   unsigned char *p = (unsigned char *)&ret;
  664.   struct tm *t = LocalTime(&unixdate,GMT_TO_LOCAL);
  665.  
  666.   p[0] = (t->tm_sec/2) | ((t->tm_min & 0x7) << 5);
  667.   p[1] = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3));
  668.  
  669.   return(ret);
  670. }
  671.  
  672. /*******************************************************************
  673.   create a 32 bit dos packed date/time from some parameters
  674. ********************************************************************/
  675. uint32 make_dos_date(time_t unixdate)
  676. {
  677.   uint32 ret;
  678.   uint16 *v = (uint16 *)&ret;
  679.  
  680.   *v++ = make_dos_time1(unixdate);
  681.   *v = make_dos_date1(unixdate);
  682.  
  683.   return(ret);
  684. }
  685.  
  686. /*******************************************************************
  687.   create a 32 bit dos packed date/time from some parameters
  688. ********************************************************************/
  689. uint32 make_dos_date2(time_t unixdate)
  690. {
  691.   uint32 ret;
  692.   uint16 *v = (uint16 *)&ret;
  693.  
  694.   *v++ = make_dos_date1(unixdate);
  695.   *v = make_dos_time1(unixdate);
  696.  
  697.   return(ret);
  698. }
  699.  
  700. /*******************************************************************
  701. put a dos date into a buffer (time/date format)
  702. ********************************************************************/
  703. void put_dos_date(char *buf,int offset,time_t unixdate)
  704. {
  705.   uint32 x = make_dos_date(unixdate);
  706.   memcpy(buf+offset,(char *)&x,sizeof(x));
  707. }
  708.  
  709. /*******************************************************************
  710. put a dos date into a buffer (date/time format)
  711. ********************************************************************/
  712. void put_dos_date2(char *buf,int offset,time_t unixdate)
  713. {
  714.   uint32 x = make_dos_date2(unixdate);
  715.   memcpy(buf+offset,(char *)&x,sizeof(x));
  716. }
  717.  
  718.  
  719. /*******************************************************************
  720.   interpret a 32 bit dos packed date/time to some parameters
  721. ********************************************************************/
  722. void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
  723. {
  724.   unsigned char *p = (unsigned char *)&date;
  725.  
  726.   *second = 2*(p[0] & 0x1F);
  727.   *minute = (p[0]>>5) + ((p[1]&0x7)<<3);
  728.   *hour = (p[1]>>3);
  729.   *day = p[2]&0x1F;
  730.   *month = (p[2]>>5) + ((p[3]&0x1)<<3) - 1;
  731.   *year = (p[3]>>1) + 80;
  732. }
  733.  
  734. /*******************************************************************
  735.   create a unix date from a dos date
  736. ********************************************************************/
  737. time_t make_unix_date(void *date_ptr)
  738. {
  739.   uint32 dos_date;
  740.   struct tm t;
  741.  
  742.   memcpy(&dos_date,date_ptr,4);
  743.  
  744.   if (dos_date == 0) return(0);
  745.   
  746.   interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
  747.              &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
  748.   t.tm_wday = 1;
  749.   t.tm_yday = 1;
  750.   t.tm_isdst = 0;
  751. /*  DEBUG(4,("year=%d month=%d day=%d hr=%d min=%d sec=%d\n",t.tm_year,t.tm_mon,
  752.      t.tm_mday,t.tm_hour,t.tm_sec)); */
  753.   return (TimeLocal(&t,GMT_TO_LOCAL));
  754. }
  755.  
  756. /*******************************************************************
  757.   create a unix date from a dos date
  758. ********************************************************************/
  759. time_t make_unix_date2(void *date_ptr)
  760. {
  761.   uint32 dos_date;
  762.   struct tm t;
  763.   unsigned char *p = (unsigned char *)&dos_date;
  764.   unsigned char c;
  765.  
  766.   memcpy(&dos_date,date_ptr,4);
  767.  
  768.   if (dos_date == 0) return(0); 
  769.  
  770.   c = p[0];
  771.   p[0] = p[2];
  772.   p[2] = c;
  773.   c = p[1];
  774.   p[1] = p[3];
  775.   p[3] = c;
  776.  
  777.   
  778.   interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
  779.              &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
  780.   t.tm_wday = 1;
  781.   t.tm_yday = 1;
  782.   t.tm_isdst = 0;
  783.   DEBUG(4,("year=%d month=%d day=%d hr=%d min=%d sec=%d\n",t.tm_year,t.tm_mon,
  784.      t.tm_mday,t.tm_hour,t.tm_sec));
  785.   return (TimeLocal(&t,GMT_TO_LOCAL));
  786. }
  787.  
  788.  
  789. /*******************************************************************
  790. return a string representing an attribute for a file
  791. ********************************************************************/
  792. char *attrib_string(int mode)
  793. {
  794.   static char attrstr[10];
  795.  
  796.   attrstr[0] = 0;
  797.  
  798.   if (mode & aVOLID) strcat(attrstr,"V");
  799.   if (mode & aDIR) strcat(attrstr,"D");
  800.   if (mode & aARCH) strcat(attrstr,"A");
  801.   if (mode & aHIDDEN) strcat(attrstr,"H");
  802.   if (mode & aSYSTEM) strcat(attrstr,"S");
  803.   if (mode & aRONLY) strcat(attrstr,"R");      
  804.  
  805.   return(attrstr);
  806. }
  807.  
  808.  
  809. /*******************************************************************
  810.   true if the machine is big endian
  811. ********************************************************************/
  812. BOOL big_endian(void )
  813. {
  814.   int x = 2;
  815.   char *s;
  816.   s = (char *)&x;
  817.   return(s[0] == 0);
  818. }
  819.  
  820. /*******************************************************************
  821.   compare 2 strings 
  822. ********************************************************************/
  823. BOOL strequal(char *s1,char *s2)
  824. {
  825.   if (!s1 || !s2) return(False);
  826.   
  827.   return(strcasecmp(s1,s2)==0);
  828. }
  829.  
  830.  
  831. /*******************************************************************
  832.   convert a string to lower case
  833. ********************************************************************/
  834. void strlower(char *s)
  835. {
  836.   while (*s)
  837.     {
  838. #ifdef KANJI
  839.     if (is_shift_jis (*s)) {
  840.         s += 2;
  841.     } else if (is_kana (*s)) {
  842.         s++;
  843.     } else {
  844.         if (isupper(*s))
  845.         *s = tolower(*s);
  846.         s++;
  847.     }
  848. #else
  849.       if (isupper(*s))
  850.       *s = tolower(*s);
  851.       s++;
  852. #endif /* KANJI */
  853.     }
  854. }
  855.  
  856. /*******************************************************************
  857.   convert a string to upper case
  858. ********************************************************************/
  859. void strupper(char *s)
  860. {
  861.   while (*s)
  862.     {
  863. #ifdef KANJI
  864.     if (is_shift_jis (*s)) {
  865.         s += 2;
  866.     } else if (is_kana (*s)) {
  867.         s++;
  868.     } else {
  869.         if (islower(*s))
  870.         *s = toupper(*s);
  871.         s++;
  872.     }
  873. #else
  874.       if (islower(*s))
  875.     *s = toupper(*s);
  876.       s++;
  877. #endif
  878.     }
  879. }
  880.  
  881. /*******************************************************************
  882.   convert a string to "normal" form
  883. ********************************************************************/
  884. void strnorm(char *s)
  885. {
  886.   if (case_sensitivity == CASE_UPPER)
  887.     strupper(s);
  888.   else
  889.     strlower(s);
  890. }
  891.  
  892.  
  893. /****************************************************************************
  894.   string replace
  895. ****************************************************************************/
  896. void string_replace(char *s,char old,char new)
  897. {
  898.   while (*s)
  899.     {
  900. #ifdef KANJI
  901.     if (is_shift_jis (*s)) {
  902.         s += 2;
  903.     } else if (is_kana (*s)) {
  904.         s++;
  905.     } else {
  906.         if (old == *s)
  907.         *s = new;
  908.         s++;
  909.     }
  910. #else
  911.       if (old == *s)
  912.     *s = new;
  913.       s++;
  914. #endif /* KANJI */
  915.     }
  916. }
  917.  
  918. /****************************************************************************
  919.   make a file into unix format
  920. ****************************************************************************/
  921. void unix_format(char *fname)
  922. {
  923.   pstring namecopy="";
  924.   string_replace(fname,'\\','/');
  925.  
  926.   if (*fname == '/')
  927.     {
  928.       strcpy(namecopy,fname);
  929.       strcpy(fname,".");
  930.       strcat(fname,namecopy);
  931.     }  
  932. }
  933.  
  934. /****************************************************************************
  935.   make a file into dos format
  936. ****************************************************************************/
  937. void dos_format(char *fname)
  938. {
  939.   string_replace(fname,'/','\\');
  940. }
  941.  
  942.  
  943. /****************************************************************************
  944.   set a value at buf[pos] to integer val
  945. ****************************************************************************/
  946. void sival(char *buf,int pos,uint32 val)
  947. {
  948.   SWP(&val,sizeof(val));
  949.   memcpy(buf + pos,(char *)&val,sizeof(val));
  950. }
  951.  
  952. /****************************************************************************
  953.   set a value at buf[pos] to int16 val
  954. ****************************************************************************/
  955. void ssval(char *buf,int pos,uint16 val)
  956. {
  957.   SWP(&val,sizeof(val));
  958.   memcpy(buf + pos,(char *)&val,sizeof(int16));
  959. }
  960.  
  961. /****************************************************************************
  962.   get a 32 bit integer value
  963. ****************************************************************************/
  964. uint32 ival(char *buf,int pos)
  965. {
  966.   uint32 val;
  967.   memcpy((char *)&val,buf + pos,sizeof(int));
  968.   SWP(&val,sizeof(val));
  969.   return(val);
  970. }
  971.  
  972.  
  973. /****************************************************************************
  974.   get a int16 value
  975. ****************************************************************************/
  976. uint16 sval(char *buf,int pos)
  977. {
  978.   uint16 val;
  979.   memcpy((char *)&val,buf + pos,sizeof(uint16));
  980.   SWP(&val,sizeof(val));
  981.   return(val);
  982. }
  983.  
  984.  
  985. /****************************************************************************
  986.   set a value at buf[pos] to signed integer val
  987. ****************************************************************************/
  988. void sival_s(char *buf,int pos,int32 val)
  989. {
  990.   SWP(&val,sizeof(val));
  991.   memcpy(buf + pos,(char *)&val,sizeof(val));
  992. }
  993.  
  994. /****************************************************************************
  995.   set a value at buf[pos] to signed int16 val
  996. ****************************************************************************/
  997. void ssval_s(char *buf,int pos,int16 val)
  998. {
  999.   SWP(&val,sizeof(val));
  1000.   memcpy(buf + pos,(char *)&val,sizeof(int16));
  1001. }
  1002.  
  1003. /****************************************************************************
  1004.   get a 32 bit integer value
  1005. ****************************************************************************/
  1006. int32 ival_s(char *buf,int pos)
  1007. {
  1008.   int32 val;
  1009.   memcpy((char *)&val,buf + pos,sizeof(int32));
  1010.   SWP(&val,sizeof(val));
  1011.   return(val);
  1012. }
  1013.  
  1014.  
  1015. /****************************************************************************
  1016.   get a int16 value
  1017. ****************************************************************************/
  1018. int16 sval_s(char *buf,int pos)
  1019. {
  1020.   int16 val;
  1021.   memcpy((char *)&val,buf + pos,sizeof(int16));
  1022.   SWP(&val,sizeof(val));
  1023.   return(val);
  1024. }
  1025.  
  1026.  
  1027. /*******************************************************************
  1028.   show a smb message structure
  1029. ********************************************************************/
  1030. void show_msg(char *buf)
  1031. {
  1032.   int i;
  1033.   DEBUG(3,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
  1034.       smb_len(buf),
  1035.       (int)CVAL(buf,smb_com),
  1036.       (int)CVAL(buf,smb_rcls),
  1037.       (int)CVAL(buf,smb_reh),
  1038.       (int)SVAL(buf,smb_err),
  1039.       (int)CVAL(buf,smb_flg),
  1040.       (int)CVAL(buf,smb_flg2)));
  1041.   DEBUG(3,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
  1042.       (int)SVAL(buf,smb_tid),
  1043.       (int)SVAL(buf,smb_pid),
  1044.       (int)SVAL(buf,smb_uid),
  1045.       (int)SVAL(buf,smb_mid),
  1046.       (int)CVAL(buf,smb_wct)));
  1047.   for (i=0;i<(int)CVAL(buf,smb_wct);i++)
  1048.     DEBUG(3,("smb_vwv[%d]=%d (0x%X)\n",i,
  1049.       SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
  1050.   DEBUG(3,("smb_bcc=%d\n",(int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)))));
  1051. }
  1052.  
  1053. /*******************************************************************
  1054.   return the length of an smb packet
  1055. ********************************************************************/
  1056. int smb_len(char *buf)
  1057. {
  1058.   int msg_flags = CVAL(buf,1);
  1059.   uint16 len = SVAL(buf,2);
  1060.   BSWP(&len,2);
  1061.  
  1062.   if (msg_flags & 1)
  1063.     len += 1<<16;
  1064.  
  1065.   return len;
  1066. }
  1067.  
  1068. /*******************************************************************
  1069.   set the length of an smb packet
  1070. ********************************************************************/
  1071. void smb_setlen(char *buf,int len)
  1072. {
  1073.   SSVAL(buf,2,len);
  1074.   BSWP(buf+2,2);
  1075.  
  1076. /*
  1077.   CVAL(buf,3) = len & 0xFF;
  1078.   CVAL(buf,2) = (len >> 8) & 0xFF;
  1079. */
  1080.   CVAL(buf,4) = 0xFF;
  1081.   CVAL(buf,5) = 'S';
  1082.   CVAL(buf,6) = 'M';
  1083.   CVAL(buf,7) = 'B';
  1084.  
  1085.  
  1086.   if (len >= (1 << 16))
  1087.     CVAL(buf,1) |= 1;
  1088. }
  1089.  
  1090. /*******************************************************************
  1091.   setup the word count and byte count for a smb message
  1092. ********************************************************************/
  1093. int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
  1094. {
  1095.   if (zero)
  1096.     memset(buf + smb_size,0,num_words*2 + num_bytes);
  1097.   CVAL(buf,smb_wct) = num_words;
  1098.   SSVAL(buf,smb_vwv + num_words*sizeof(WORD),num_bytes);  
  1099.   smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
  1100.   return (smb_size + num_words*2 + num_bytes);
  1101. }
  1102.  
  1103. /*******************************************************************
  1104. return the number of smb words
  1105. ********************************************************************/
  1106. int smb_numwords(char *buf)
  1107. {
  1108.   return (CVAL(buf,smb_wct));
  1109. }
  1110.  
  1111. /*******************************************************************
  1112. return the size of the smb_buf region of a message
  1113. ********************************************************************/
  1114. int smb_buflen(char *buf)
  1115. {
  1116.   return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
  1117. }
  1118.  
  1119. /*******************************************************************
  1120. trim the specified elements off the front and back of a string
  1121. ********************************************************************/
  1122. void trim_string(char *s,char *front,char *back)
  1123. {
  1124.   while (front && *front && strncmp(s,front,strlen(front)) == 0)
  1125.     {
  1126.       char *p = s;
  1127.       while (1)
  1128.     {
  1129.       if (!(*p = p[strlen(front)]))
  1130.         break;
  1131.       p++;
  1132.     }
  1133.     }
  1134.   
  1135.   while (back && *back && (strncmp(s+strlen(s)-strlen(back),back,strlen(back))==0))
  1136.     s[strlen(s)-strlen(back)] = 0;
  1137. }
  1138.  
  1139.  
  1140. /*******************************************************************
  1141. reduce a file name, removing .. elements.
  1142. ********************************************************************/
  1143. void dos_clean_name(char *s)
  1144. {
  1145.   char *p=NULL;
  1146.  
  1147.   DEBUG(3,("dos_clean_name [%s]\n",s));
  1148.  
  1149.   /* remove any double slashes */
  1150.   string_sub(s, "\\\\", "\\");
  1151.  
  1152.   while ((p = strstr(s,"\\..")) != NULL)
  1153.     {
  1154.       pstring s1;
  1155.  
  1156.       *p = 0;
  1157.       strcpy(s1,p+3);
  1158.  
  1159.       if ((p=strrchr(s,'\\')) != NULL)
  1160.     *p = 0;
  1161.       else
  1162.     *s = 0;
  1163.       strcat(s,s1);
  1164.     }  
  1165.  
  1166.   string_sub(s, "\\.\\", "\\");
  1167. }
  1168.  
  1169. /*******************************************************************
  1170. reduce a file name, removing .. elements. 
  1171. ********************************************************************/
  1172. void unix_clean_name(char *s)
  1173. {
  1174.   char *p=NULL;
  1175.  
  1176.   DEBUG(3,("unix_clean_name [%s]\n",s));
  1177.  
  1178.   /* remove any double slashes */
  1179.   string_sub(s, "//","/");
  1180.  
  1181.   while ((p = strstr(s,"/..")) != NULL)
  1182.     {
  1183.       pstring s1;
  1184.  
  1185.       *p = 0;
  1186.       strcpy(s1,p+3);
  1187.  
  1188.       if ((p=strrchr(s,'/')) != NULL)
  1189.     *p = 0;
  1190.       else
  1191.     *s = 0;
  1192.       strcat(s,s1);
  1193.     }  
  1194. }
  1195.  
  1196.  
  1197. /*******************************************************************
  1198.   return a pointer to the smb_buf data area
  1199. ********************************************************************/
  1200. int smb_buf_ofs(char *buf)
  1201. {
  1202.   return (smb_size + CVAL(buf,smb_wct)*2);
  1203. }
  1204.  
  1205. /*******************************************************************
  1206.   return a pointer to the smb_buf data area
  1207. ********************************************************************/
  1208. char *smb_buf(char *buf)
  1209. {
  1210.   return (buf + smb_buf_ofs(buf));
  1211. }
  1212.  
  1213.  
  1214. /*******************************************************************
  1215. skip past some strings in a buffer
  1216. ********************************************************************/
  1217. char *skip_string(char *buf,int n)
  1218. {
  1219.   while (n--)
  1220.     buf += strlen(buf) + 1;
  1221.   return(buf);
  1222. }
  1223.  
  1224.  
  1225. /*******************************************************************
  1226. a wrapper for the normal chdir() function
  1227. ********************************************************************/
  1228. int ChDir(char *path)
  1229. {
  1230.   DEBUG(3,("chdir to %s\n",path));
  1231.   return(chdir(path));
  1232. }
  1233.  
  1234.  
  1235. /* Linked list structures for a caching GetWd function. */
  1236. #define MAX_GETWDCACHE (100)
  1237. #define MAGIC (0xABCD)
  1238. #define GETWD_PARANOID 1
  1239.  
  1240. struct ino_list
  1241. {
  1242.   int magic;
  1243.   struct ino_list *next;
  1244.   struct ino_list *back;
  1245.   ino_t inode;
  1246.   dev_t dev;
  1247.   int first;
  1248.   int count;
  1249.   int weight;
  1250.   char *text;
  1251. };
  1252.  
  1253. static int total_count = 0;
  1254.  
  1255. static struct ino_list ino_head =
  1256. { MAGIC, NULL, NULL, (ino_t)0, (dev_t)0, 0, 0, 1 << 8, NULL };
  1257.  
  1258. /*******************************************************************
  1259.   return the absolute current directory path. A dumb version.
  1260. ********************************************************************/
  1261. char *Dumb_GetWd(char *s)
  1262. {
  1263. #ifdef USE_GETCWD
  1264.     return ((char *)getcwd(s,sizeof(pstring)));
  1265. #else
  1266.     return ((char *)getwd(s));
  1267. #endif
  1268. }
  1269.  
  1270. BOOL use_getwd_cache = False;
  1271.  
  1272. /*******************************************************************
  1273.   return the absolute current directory path
  1274. ********************************************************************/
  1275. char *GetWd(char *s)
  1276. {
  1277.   pstring wd="";
  1278.   struct stat st, st2;
  1279.   int i;
  1280.   struct ino_list *ino_p, *ino_tmp;
  1281.  
  1282.   if (!use_getwd_cache)
  1283.     return(Dumb_GetWd(s));
  1284.  
  1285. #define DISABLE_CACHE {DEBUG(0,("PLEASE REPORT THIS ERROR!\n"));use_getwd_cache=False;return(Dumb_GetWd(s));}
  1286.  
  1287.   /*  Get the inode of the current directory, if this doesn't work we're
  1288.       in trouble :-) */
  1289.  
  1290.   if (stat(".",&st) == -1) 
  1291.     {
  1292.       DEBUG(0,("Very strange, couldn't stat \".\"\n"));
  1293.       return(NULL);
  1294.     }
  1295.  
  1296.   /*  First a bit of housekeeping, we want to avoid 'total_count' overflowing
  1297.       and going negative. This would cause havoc with the weighting calculations
  1298.       used to keep the most commonly used directories near the top of the list.
  1299.       As it is only used in a relative manner, if it gets too large divide it,
  1300.       and the values it's used with, by two. */
  1301.  
  1302.   if (total_count >= 10000)
  1303.     {
  1304.       total_count /= 2;
  1305.       for (ino_p = ino_head.next; ino_p; ino_p = ino_p->next)
  1306.     {
  1307.           ino_p->first /= 2;
  1308.           ino_p->count /= 2;
  1309.     }
  1310.     }
  1311.   
  1312.   /*  Check whether I have this inode already. This is done with a simple
  1313.       linear search, hash tables anybody?
  1314.       The code works by getting the inode (and device number) of the 
  1315.       current directory and looking it up in it's list. First time through
  1316.       it will not find a match so fall back on getcwd/getwd but add the
  1317.       information to the list. Subsequent times through that match will
  1318.       be found and the directory name returned - although only after the
  1319.       sanity check of getting the inode and device of that directory and
  1320.       seeing if they agree with the stat of the current directory.
  1321.    
  1322.       Q: will this work with NFS/RFS/something-else-FS mounted filesystems?
  1323.       
  1324.       It's a linear search but the code tries to keep it sensible by moving
  1325.       the most commonly used entries at the head of the list. */
  1326.  
  1327.   i = 0;
  1328.   for (ino_p = ino_head.next; ino_p; ino_p = ino_p->next)
  1329.     {
  1330.       
  1331. #if GETWD_PARANOID
  1332.       if (ino_p->magic != MAGIC)
  1333.     {
  1334.       DEBUG(0,("Hmm, funny magic number\n"));
  1335.       DISABLE_CACHE;
  1336.     }
  1337.       if (ino_p->back)
  1338.     {
  1339.           if (ino_p->back->next != ino_p)
  1340.         {
  1341.           DEBUG(0,("Hmm, back/next links inconsistant\n"));
  1342.           DISABLE_CACHE;
  1343.         }
  1344.           if (ino_p->back->back && ino_p->back->back->next->next != ino_p)
  1345.         {
  1346.           DEBUG(0,("Hmm, back/back/next/next links inconsistant\n"));
  1347.           DISABLE_CACHE;
  1348.         }
  1349.     }
  1350. #endif
  1351.  
  1352.       /*  Calculate a weight for the entry and gradually sift less used ones
  1353.       down the list by swapping. Note that the swapping disconnects the
  1354.       backpointers so don't expect to run back up the list. We keep a
  1355.       fair amount of granularity in the 'weight' value to avoid excessive
  1356.       swapping of elements.. it is, after all, only a guide.. */
  1357.       
  1358.       ino_p->weight = (ino_p->count << 8) / (total_count - ino_p->first);
  1359.       
  1360. #if GETWD_PARANOID
  1361.       if (ino_p->weight > (1 << 8))
  1362.     {
  1363.       DEBUG(0,("Weight too high for %s, %d\n",ino_p->text, ino_p->weight));
  1364.       DISABLE_CACHE;
  1365.     }
  1366. #endif
  1367.  
  1368.       if (ino_p->back && ino_p->weight > ino_p->back->weight)
  1369.     {
  1370.           DEBUG(4,("swap %s (%d) and %s (%d)\n",
  1371.            ino_p->text,ino_p->weight,ino_p->back->text,
  1372.            ino_p->back->weight));
  1373.           ino_tmp = ino_p->back;
  1374.       
  1375. #if GETWD_PARANOID
  1376.           if (ino_tmp->back == NULL)
  1377.         {
  1378.           DEBUG(0,("Oh dear, Backpointer NULL\n"));
  1379.           DISABLE_CACHE;
  1380.         }
  1381.           else if (ino_tmp->back->magic != MAGIC)
  1382.         {
  1383.           DEBUG(0,("Hmm, funny magic number looking back\n"));
  1384.           DISABLE_CACHE;
  1385.         }
  1386. #endif
  1387.  
  1388.           ino_tmp->back->next = ino_p;
  1389.           ino_tmp->next = ino_p->next;
  1390.           ino_p->next = ino_tmp;
  1391.           ino_p->back = NULL;
  1392.     }
  1393.  
  1394.       /*  If we have found an entry with a matching inode and dev number
  1395.       then find the inode number for the directory in the cached string.
  1396.       If this agrees with that returned by the stat for the current
  1397.       directory then all is o.k. (but make sure it is a directory all
  1398.       the same...) */
  1399.       
  1400.       if (st.st_ino == ino_p->inode &&
  1401.       st.st_dev == ino_p->dev)
  1402.     {
  1403.           if (stat(ino_p->text,&st2) == 0)
  1404.         {
  1405.           if (st.st_ino == st2.st_ino &&
  1406.           st.st_dev == st2.st_dev &&
  1407.           (st2.st_mode & S_IFMT) == S_IFDIR)
  1408.                 {
  1409.           total_count++;
  1410.           ino_p->count++;
  1411.           DEBUG(3,("Found cached GetWd %s [%d, %d]\n",
  1412.                ino_p->text, i, ino_p->weight));
  1413.           strcpy (s, ino_p->text);
  1414.           return (s);
  1415.                 }
  1416.  
  1417.           /*  If the inode is different then something's changed, scrub 
  1418.           the entry and start from scratch. */
  1419.  
  1420.           else
  1421.                 {
  1422.           DEBUG(3,("cached string %s bad\n",ino_p->text));
  1423.           ino_tmp = ino_p->back;
  1424.           ino_tmp->next = ino_p->next;
  1425.           free (ino_p->text);
  1426.           free (ino_p);
  1427.           ino_p = ino_tmp;
  1428.                 }
  1429.         }
  1430.     }
  1431.       
  1432.       /*  Set up a temporary backpointer, this will not be maintained when
  1433.       elements are swapped so should not be relied on long term. It helps
  1434.       however for immediate views back up the list. */
  1435.  
  1436.       i++;
  1437.       if (ino_p->next)
  1438.     ino_p->next->back = ino_p;
  1439.       else
  1440.     break;
  1441.       
  1442.       /*  Skip out of the loop if at the end of the list leaving ino_p 
  1443.       referring to the last element. */
  1444.       
  1445.     }
  1446.  
  1447.   /*  We don't have the information to hand so rely on traditional methods.
  1448.       The very slow getcwd, which spawns a process on some systems, or the
  1449.       not quite so bad getwd. */
  1450.  
  1451. #ifdef USE_GETCWD
  1452.   if (getcwd(wd,sizeof(wd)) == NULL)
  1453.     {
  1454.       DEBUG(0,("Getcwd failed, errno %d\n",errno));
  1455.       return (NULL);
  1456.     }
  1457. #else
  1458.   if (!getwd(wd))
  1459.     {
  1460.       DEBUG(0,("Getwd failed, errno %d\n",errno));
  1461.       return (NULL);
  1462.     }
  1463. #endif
  1464.  
  1465.   DEBUG(3,("GetWd %s, inode %d, dev %x\n",wd,(int)st.st_ino,(int)st.st_dev));
  1466.  
  1467.   /*  We'll prepend the new entry, prepending it means that it is at the head
  1468.       of the list for the next request - working on the principle that these
  1469.       lookups seldom come alone. */
  1470.   
  1471.   if (i > MAX_GETWDCACHE && ino_p)
  1472.     {
  1473.       free (ino_p->text);
  1474.       ino_p->back->next = NULL;
  1475.     }
  1476.   else if ((ino_p = (struct ino_list *)malloc (sizeof (struct ino_list))) == NULL)
  1477.     {
  1478.       DEBUG(0,("Oh dear, malloc failed extending list of directories\n"));
  1479.       strcpy (s, wd);
  1480.       return (s);
  1481.     }
  1482.   ino_p->magic = MAGIC;
  1483.   ino_p->next = ino_head.next;
  1484.   ino_p->back = &ino_head;
  1485.   ino_head.next = ino_p;
  1486.   
  1487.   /*  copy the inode number and directory name into the entry. */
  1488.   
  1489.   ino_p->inode = st.st_ino;
  1490.   ino_p->dev = st.st_dev;
  1491.   ino_p->first = total_count++;
  1492.   ino_p->count = 1;
  1493.   ino_p->weight = 0;
  1494.   if ((ino_p->text = (char *)malloc (strlen(wd)+1)) == NULL)
  1495.     {
  1496.       DEBUG(0,("Oh dear, malloc failed extending list of directories\n"));
  1497.       ino_head.next = ino_p->next;
  1498.       free (ino_p);
  1499.       strcpy (s, wd);
  1500.       return (s);
  1501.     }
  1502.   strcpy (ino_p->text,wd);
  1503.   
  1504.   strcpy (s, wd);
  1505.   return (s);
  1506. }
  1507.  
  1508.  
  1509. /*******************************************************************
  1510. reduce a file name, removing .. elements and checking that 
  1511. it is below dir in the heirachy. This uses GwtWd() and so must be run
  1512. on the system that has the referenced file system.
  1513.  
  1514. widelinks are allowed if widelinks is true
  1515. ********************************************************************/
  1516. BOOL reduce_name(char *s,char *dir,BOOL widelinks)
  1517. {
  1518. #ifndef REDUCE_PATHS
  1519.   return True;
  1520. #else
  1521.   pstring dir2="";
  1522.   pstring wd="";
  1523.   pstring basename="";
  1524.   pstring newname="";
  1525.   char *p=NULL;
  1526.   BOOL relative = (*s != '/');
  1527.  
  1528.   if (widelinks)
  1529.     {
  1530.       unix_clean_name(s);
  1531.       /* can't have a leading .. */
  1532.       if (strncmp(s,"..",2) == 0)
  1533.     {
  1534.       DEBUG(3,("Illegal file name? (%s)\n",s));
  1535.       return(False);
  1536.     }
  1537.       return(True);
  1538.     }
  1539.   
  1540.   DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
  1541.  
  1542.   /* remove any double slashes */
  1543.   string_sub(s,"//","/");
  1544.  
  1545.   if (!GetWd(wd))
  1546.     {
  1547.       DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
  1548.       return(False);
  1549.     }
  1550.  
  1551.   if (ChDir(dir) != 0)
  1552.     {
  1553.       DEBUG(0,("couldn't chdir to %s\n",dir));
  1554.       return(False);
  1555.     }
  1556.  
  1557.   if (!GetWd(dir2))
  1558.     {
  1559.       DEBUG(0,("couldn't getwd for %s\n",dir));
  1560.       ChDir(wd);
  1561.       return(False);
  1562.     }
  1563.  
  1564.   strcpy(basename,s);
  1565.   p = strrchr(basename,'/');
  1566.  
  1567.     if (p && (p != basename))
  1568.       {
  1569.     *p = 0;
  1570.     if (strcmp(p+1,".")==0)
  1571.       p[1]=0;
  1572.     if (strcmp(p+1,"..")==0)
  1573.       *p = '/';
  1574.       }
  1575.  
  1576.   if (ChDir(basename) != 0)
  1577.     {
  1578.       ChDir(wd);
  1579.       DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,basename));
  1580.       return(False);
  1581.     }
  1582.  
  1583.   if (!GetWd(newname))
  1584.     {
  1585.       ChDir(wd);
  1586.       DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
  1587.       return(False);
  1588.     }
  1589.  
  1590.   if (p && (p != basename))
  1591.     {
  1592.       strcat(newname,"/");
  1593.       strcat(newname,p+1);
  1594.     }
  1595.  
  1596.   {
  1597.     int l = strlen(dir2);    
  1598.     if (dir2[l-1] == '/')
  1599.       l--;
  1600.  
  1601.     if (strncmp(newname,dir2,l) != 0)
  1602.       {
  1603.     ChDir(wd);
  1604.     DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l));
  1605.     return(False);
  1606.       }
  1607.  
  1608.     if (relative)
  1609.       {
  1610.     if (newname[l] == '/')
  1611.       strcpy(s,newname + l + 1);
  1612.     else
  1613.       strcpy(s,newname+l);
  1614.       }
  1615.     else
  1616.       strcpy(s,newname);
  1617.   }
  1618.  
  1619.   ChDir(wd);
  1620.  
  1621.   if (strlen(s) == 0)
  1622.     strcpy(s,"./");
  1623.  
  1624.   DEBUG(3,("reduced to %s\n",s));
  1625.   return(True);
  1626. #endif
  1627. }
  1628.  
  1629. /****************************************************************************
  1630. expand some *s 
  1631. ****************************************************************************/
  1632. void expand_one(char *Mask,int len)
  1633. {
  1634.   char *p1;
  1635.   while ((p1 = strchr(Mask,'*')) != NULL)
  1636.     {
  1637.       int lfill = (len+1) - strlen(Mask);
  1638.       int l1= (p1 - Mask);
  1639.       pstring tmp="";
  1640.       strcpy(tmp,Mask);  
  1641.       memset(tmp+l1,'?',lfill);
  1642.       strcpy(tmp + l1 + lfill,Mask + l1 + 1);    
  1643.       strcpy(Mask,tmp);      
  1644.     }
  1645. }
  1646.  
  1647. /****************************************************************************
  1648. expand a wildcard expression, replacing *s with ?s
  1649. ****************************************************************************/
  1650. void expand_mask(char *Mask,BOOL doext)
  1651. {
  1652.   pstring mbeg="",mext="";
  1653.   pstring dirpart="";
  1654.   pstring filepart="";
  1655.   BOOL hasdot = False;
  1656.   char *p1;
  1657.   BOOL absolute = (*Mask == '\\');
  1658.  
  1659.   /* parse the directory and filename */
  1660.   if (strchr(Mask,'\\'))
  1661.     dirname_dos(Mask,dirpart);
  1662.  
  1663.   filename_dos(Mask,filepart);
  1664.  
  1665.   strcpy(mbeg,filepart);
  1666.   if ((p1 = strchr(mbeg,'.')) != NULL)
  1667.     {
  1668.       hasdot = True;
  1669.       *p1 = 0;
  1670.       p1++;
  1671.       strcpy(mext,p1);
  1672.     }
  1673.   else
  1674.     {
  1675.       strcpy(mext,"");
  1676.       if (strlen(mbeg) > 8)
  1677.     {
  1678.       strcpy(mext,mbeg + 8);
  1679.       mbeg[8] = 0;
  1680.     }
  1681.     }
  1682.  
  1683.   if (*mbeg == 0)
  1684.     strcpy(mbeg,"????????");
  1685.   if ((*mext == 0) && doext && !hasdot)
  1686.     strcpy(mext,"???");
  1687.  
  1688.   /* expand *'s */
  1689.   expand_one(mbeg,8);
  1690.   if (*mext)
  1691.     expand_one(mext,3);
  1692.  
  1693.   strcpy(Mask,dirpart);
  1694.   if (*dirpart || absolute) strcat(Mask,"\\");
  1695.   strcat(Mask,mbeg);
  1696.   strcat(Mask,".");
  1697.   strcat(Mask,mext);
  1698.  
  1699.   DEBUG(6,("Mask expanded to [%s]\n",Mask));
  1700. }  
  1701.  
  1702.  
  1703. /****************************************************************************
  1704. does a string have any uppercase chars in it?
  1705. ****************************************************************************/
  1706. BOOL strhasupper(char *s)
  1707. {
  1708.   while (*s) 
  1709.     {
  1710. #ifdef KANJI
  1711.     if (is_shift_jis (*s)) {
  1712.         s += 2;
  1713.     } else if (is_kana (*s)) {
  1714.         s++;
  1715.     } else {
  1716.         if (isupper(*s)) return(True);
  1717.         s++;
  1718.     }
  1719. #else 
  1720.       if (isupper(*s)) return(True);
  1721.       s++;
  1722. #endif /* KANJI */
  1723.     }
  1724.   return(False);
  1725. }
  1726.  
  1727. /****************************************************************************
  1728. does a string have any lowercase chars in it?
  1729. ****************************************************************************/
  1730. BOOL strhaslower(char *s)
  1731. {
  1732.   while (*s) 
  1733.     {
  1734. #ifdef KANJI
  1735.     if (is_shift_jis (*s)) {
  1736.         s += 2;
  1737.     } else if (is_kana (*s)) {
  1738.         s++;
  1739.     } else {
  1740.         if (islower(*s)) return(True);
  1741.         s++;
  1742.     }
  1743. #else 
  1744.       if (islower(*s)) return(True);
  1745.       s++;
  1746. #endif /* KANJI */
  1747.     }
  1748.   return(False);
  1749. }
  1750.  
  1751. /****************************************************************************
  1752. find the number of chars in a string
  1753. ****************************************************************************/
  1754. int count_chars(char *s,char c)
  1755. {
  1756.   int count=0;
  1757.   while (*s) 
  1758.     {
  1759.       if (*s == c)
  1760.     count++;
  1761.       s++;
  1762.     }
  1763.   return(count);
  1764. }
  1765.  
  1766.  
  1767. /****************************************************************************
  1768. Search for a name in a directory in a case independent way.
  1769. Returns 0 if found and places new name in matchname, 1 and name
  1770. placed in matchname otherwise.
  1771. ****************************************************************************/
  1772. int search_lanman2(char *dir_to_search, char *name, char *matchname, int flags)
  1773. {
  1774.   void *dirptr;
  1775.   struct DIRECT *dptr;
  1776.  
  1777.   DEBUG(3,("search_lanman2 - searching for %s in %s\n",name,dir_to_search));
  1778.  
  1779.   dirptr = (void *)opendir(dir_to_search);
  1780.  
  1781.   if (!dirptr)
  1782.     return 1;
  1783.  
  1784.   dptr = readdir(dirptr);
  1785.   while (dptr)
  1786.     {
  1787.       if (strequal(dptr->d_name,name))
  1788.     {
  1789.       pstring fullpath = "";
  1790.       struct stat st;
  1791.  
  1792.       /* Check name matches with required flags */
  1793.       strcpy(fullpath,dir_to_search);
  1794.       if(fullpath[strlen(fullpath)-1] != '/')
  1795.         strcat(fullpath,"/");
  1796.       strcat(fullpath,dptr->d_name);
  1797.       stat(fullpath, &st);
  1798.       if(st.st_mode & flags)
  1799.         {
  1800.           strcpy(matchname, dptr->d_name);
  1801.           DEBUG(3,("search_lanman2 - replacing %s with %s\n",name,matchname));
  1802.           closedir(dirptr);
  1803.           return 0;
  1804.         }
  1805.     }
  1806.       dptr = readdir(dirptr);
  1807.     }
  1808.   
  1809.   /* didn't find it */
  1810.   strcpy(matchname, name);
  1811.   closedir(dirptr);
  1812.   return 1;
  1813. }
  1814.  
  1815. /****************************************************************************
  1816. convert a lanman2 name to a unix name - possibly checking case
  1817. ****************************************************************************/
  1818. void unix_convert_lanman2(char *s,char *home,BOOL case_is_sig)
  1819. {
  1820.   char *p, *tnp;
  1821.   pstring tmpname = "";
  1822.   pstring name = "";
  1823.   pstring dir_to_search = "";
  1824.   pstring matching_name = "";
  1825.  
  1826.   unix_format(s);
  1827.  
  1828.   if(case_is_sig)
  1829.     return; /* We can use unix case dependent names */
  1830.  
  1831.   DEBUG(5,("Converting name %s to lanman2 name (home=%s)\n",s,home));
  1832.  
  1833.   strcpy(tmpname,s);
  1834.   unix_clean_name(tmpname);
  1835.  
  1836.   /* We must go through the directories given
  1837.      in the name, looking for a case insensitive match. */
  1838.   
  1839.   tnp = tmpname;
  1840.   /* Optimization to stop searching for ./././ at the
  1841.      start of tmpname */
  1842.   while(strncmp(tnp,"./",2)==0)
  1843.     tnp += 2;
  1844.   while((p  = strchr(tnp,'/')))
  1845.     {
  1846.       StrnCpy(name, tnp, p - tnp);
  1847.  
  1848.       if(tnp == tmpname)
  1849.     strcpy(dir_to_search,".");
  1850.       else
  1851.     StrnCpy(dir_to_search, tmpname, tnp - tmpname);
  1852.  
  1853.       /* Open the directory theoretically containing the
  1854.      directory 'name' and search for a case independent
  1855.      version of it */
  1856.       if(search_lanman2(dir_to_search, name, matching_name, S_IFDIR))
  1857.     {
  1858.       /* If we didn't find it then we may as well quit */
  1859.       strcpy(s,tmpname);
  1860.       
  1861.       DEBUG(5,("search_lanman2 fail : Converted to lanman2 name %s\n",s));
  1862.  
  1863.       return;
  1864.     }
  1865.  
  1866.       /* Replace the incorrect case version of the
  1867.      name with the correct on in the directory */
  1868.       memcpy(tnp, matching_name, strlen(matching_name));
  1869.  
  1870.       tnp = p + 1;
  1871.     }
  1872.  
  1873.   /* Here tnp is pointing at the last component of the name or at '\0' */
  1874.   if(*tnp)
  1875.     {
  1876.       StrnCpy(dir_to_search, tmpname, tnp - tmpname);
  1877.  
  1878.       if(0==search_lanman2(dir_to_search, tnp, matching_name, S_IFDIR|S_IFREG))
  1879.     memcpy(tnp,matching_name,strlen(matching_name));
  1880.     }
  1881.   strcpy(s,tmpname);
  1882.  
  1883.   DEBUG(5,("Converted to lanman2 name %s\n",s));
  1884.  
  1885. }
  1886.  
  1887. /****************************************************************************
  1888.   see if a name matches a mask. The mask takes the form of several characters,
  1889.   with ? being a wild card.
  1890. ****************************************************************************/
  1891. BOOL mask_match(char *Name,char *Mask,BOOL dodots,BOOL case_sensitive, BOOL doext)
  1892. {
  1893.   char *p1,*p2;
  1894.   pstring nbeg=""; /* beginning of name */
  1895.   pstring next=""; /* extension of name */
  1896.   pstring mext=""; /* extension of mask */
  1897.   pstring mbeg=""; /* beg of mask */  
  1898.   pstring name,mask;
  1899.   BOOL hasdot=False;
  1900.  
  1901.   DEBUG(3,("mmatch [%s] [%s] %d\n",Name,Mask,dodots));
  1902.  
  1903.   if (strcmp(Name,Mask) == 0)
  1904.     return(True);
  1905.  
  1906.   strcpy(name,Name);
  1907.   strcpy(mask,Mask);
  1908.  
  1909.   if (!case_sensitive)
  1910.     {
  1911.       strlower(name);
  1912.       strlower(mask);
  1913.     }
  1914.  
  1915.   strcpy(mbeg,mask);
  1916.   if ((p1 = strchr(mbeg,'.')) != NULL)
  1917.     {
  1918.       hasdot = True;
  1919.       *p1 = 0;
  1920.       p1++;
  1921.       strcpy(mext,p1);
  1922.     }
  1923.   else
  1924.     {
  1925.       strcpy(mext,"");
  1926.       if (strlen(mbeg) > 8)
  1927.     {
  1928.       strcpy(mext,mbeg + 8);
  1929.       mbeg[8] = 0;
  1930.     }
  1931.     }
  1932.  
  1933.   if (*mbeg == 0)
  1934.     strcpy(mbeg,"????????");
  1935.   if (*mext == 0 && doext && !hasdot)
  1936.     strcpy(mext,"???");
  1937.  
  1938.   /* expand *'s */
  1939.   expand_one(mbeg,8);
  1940.   if (*mext)
  1941.     expand_one(mext,3);
  1942.   
  1943.   /* a couple of special cases */
  1944.   if (strequal(name,".") || strequal(name,".."))
  1945.     return(dodots && strequal(mbeg,"????????") && strequal(mext,"???"));
  1946.  
  1947.   if (strequal(mbeg,"????????") && strequal(mext,"???"))
  1948.     return(True);
  1949.  
  1950.   strcpy(nbeg,name);
  1951.   if ((p1 = strchr(nbeg,'.')) != NULL)
  1952.     {
  1953.       *p1 = 0;
  1954.       p1++;
  1955.       strcpy(next,p1);
  1956.       if (strchr(next,'.')) /* can't have two .s in a name */
  1957.     return(False);
  1958.     }
  1959.   else
  1960.     strcpy(next,"");
  1961.  
  1962.   /* strip trailing spaces */
  1963.   string_replace(nbeg,' ',0);  
  1964.   string_replace(mbeg,' ',0);  
  1965.   string_replace(next,' ',0);  
  1966.   string_replace(mext,' ',0);  
  1967.   
  1968.   if (strlen(nbeg) == 0) return(False);
  1969.   if (strlen(mbeg) == 0) return(False);
  1970.   if (strlen(nbeg) > 8) return(False);
  1971.   if (strlen(next) > 3) return(False);
  1972.   if (strlen(mbeg) > 8) return(False);
  1973.   if (strlen(mext) > 3) return(False);
  1974.   if (strlen(nbeg) > strlen(mbeg)) return(False);
  1975.   if (strlen(next) > strlen(mext)) return(False);
  1976.   
  1977.   /* only accept lowercase names */
  1978.   p1 = name;
  1979. #ifdef KANJI
  1980.   while (*p1) {
  1981.       if (is_shift_jis (*p1)) {
  1982.       p1 += 2;
  1983.       } else if (is_kana (*p1)) {
  1984.       p1++;
  1985.       } else {
  1986.       if (isupper(*p1++)) return(False);
  1987.       }
  1988.   }
  1989. #else 
  1990.   while (*p1) 
  1991.     if (isupper(*p1++)) return(False);
  1992. #endif /* KANJI */
  1993.  
  1994.   DEBUG(3,("Matching [%8.8s.%3.3s] to [%8.8s.%3.3s]\n",nbeg,next,mbeg,mext));
  1995.   
  1996.   p1 = nbeg;
  1997.   p2 = mbeg;
  1998.   while (*p2)
  1999.     {
  2000.       if ((*p2 != '?') && (*p1 != *p2)) 
  2001.     return(False);
  2002.       p2++;
  2003.       if (*p1) p1++;
  2004.     }
  2005.   
  2006.   p1 = next;
  2007.   p2 = mext;
  2008.   while (*p2)
  2009.     {
  2010.       if ((*p2 != '?') && (*p1 != *p2)) 
  2011.     return(False);
  2012.       p2++;
  2013.       if (*p1) p1++;
  2014.     }
  2015.  
  2016.   DEBUG(3,("Matched correctly\n"));
  2017.  
  2018.   return(True);
  2019. }
  2020.  
  2021.  
  2022. /****************************************************************************
  2023.   make a dir struct
  2024. ****************************************************************************/
  2025. void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date)
  2026. {  
  2027.   char *p;
  2028.   pstring mask2="";
  2029.  
  2030.   strcpy(mask2,mask);
  2031.  
  2032.   if ((mode & aDIR) != 0)
  2033.     size = 0;
  2034.  
  2035.   memset(buf+1,' ',11);
  2036.   if ((p = strchr(mask2,'.')) != NULL)
  2037.     {
  2038.       *p = 0;
  2039.       memcpy(buf+1,mask2,MIN(strlen(mask2),8));
  2040.       memcpy(buf+9,p+1,MIN(strlen(p+1),3));
  2041.       *p = '.';
  2042.     }
  2043.   else
  2044.     memcpy(buf+1,mask2,MIN(strlen(mask2),11));
  2045.  
  2046.   memset(buf+21,0,DIR_STRUCT_SIZE-21);
  2047.   CVAL(buf,21) = mode;
  2048.   put_dos_date(buf,22,date);
  2049.   SSVAL(buf,26,size & 0xFFFF);
  2050.   SSVAL(buf,28,size >> 16);
  2051.   StrnCpy(buf+30,fname,12);
  2052.   strupper(buf+30);
  2053. }
  2054.  
  2055.  
  2056. /****************************************************************************
  2057. log a packet to logout
  2058. ****************************************************************************/
  2059. void log_out(char *buffer,int len)
  2060. {
  2061.   if (logout)
  2062.     {
  2063.       fprintf(logout,"\n%s Transaction %d (%d)\n",timestring(),trans_num++,len);
  2064.       fwrite(buffer,len,1,logout);
  2065.       fflush(logout);
  2066.     }      
  2067.   DEBUG(7,("logged %d bytes out\n",len));
  2068. }
  2069.  
  2070. /****************************************************************************
  2071. log a packet to login
  2072. ****************************************************************************/
  2073. void log_in(char *buffer,int len)
  2074. {
  2075.   if (login)
  2076.     {
  2077.       fprintf(login,"\n%s Transaction %d (%d)\n",timestring(),trans_num++,len);
  2078.       fwrite(buffer,len,1,login);
  2079.       fflush(login);
  2080.     }      
  2081.   DEBUG(7,("logged %d bytes in\n",len));
  2082. }
  2083.  
  2084. /****************************************************************************
  2085. write to a socket
  2086. ****************************************************************************/
  2087. int write_socket(int fd,char *buf,int len)
  2088. {
  2089.   int ret=0;
  2090.  
  2091.   if (passive)
  2092.     return(len);
  2093.   DEBUG(6,("write_socket(%d,%d)\n",fd,len));
  2094.   ret = write(fd,buf,len);
  2095.       
  2096.   DEBUG(4,("write_socket(%d,%d) gave %d\n",fd,len,ret));
  2097.   return(ret);
  2098. }
  2099.  
  2100. /****************************************************************************
  2101. read from a socket
  2102. ****************************************************************************/
  2103. int read_udp_socket(int fd,char *buf,int len)
  2104. {
  2105.   /* #define NORECVFROM */
  2106. #ifdef NORECVFROM
  2107.   return(read(fd,buf,len));
  2108. #else
  2109.   int ret;
  2110.   struct sockaddr sock;
  2111.   int socklen;
  2112.   
  2113.   socklen = sizeof(sock);
  2114.   memset((char *)&sock, 0, socklen);
  2115.   memset((char *)&lastip, 0, sizeof(lastip));
  2116.   ret = recvfrom(fd,buf,len,0,&sock,&socklen);
  2117.   if (ret <= 0)
  2118.     {
  2119.       DEBUG(2,("read socket failed. ERRNO=%d\n",errno));
  2120.       return(0);
  2121.     }
  2122.  
  2123.   lastip = *(struct in_addr *) &sock.sa_data[2];
  2124.   lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
  2125.   if (DEBUGLEVEL > 0)
  2126.     DEBUG(3,("read %d bytes\n",ret));
  2127.  
  2128.   return(ret);
  2129. #endif
  2130. }
  2131.  
  2132. /****************************************************************************
  2133. Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
  2134. else
  2135. if SYSV use O_NDELAY
  2136. if BSD use FNDELAY
  2137. ****************************************************************************/
  2138. int set_blocking(int fd, BOOL set)
  2139. {
  2140. int val;
  2141. #ifdef O_NONBLOCK
  2142. #define FLAG_TO_SET O_NONBLOCK
  2143. #else
  2144. #ifdef SYSV
  2145. #define FLAG_TO_SET O_NDELAY
  2146. #else /* BSD */
  2147. #define FLAG_TO_SET FNDELAY
  2148. #endif
  2149. #endif
  2150.  
  2151.   if((val = fcntl(fd, F_GETFL, 0))==-1)
  2152.     return -1;
  2153.   if(set) /* Turn blocking on - ie. clear nonblock flag */
  2154.     val &= ~FLAG_TO_SET;
  2155.   else
  2156.     val |= FLAG_TO_SET;
  2157.   return fcntl( fd, F_SETFL, val);
  2158. #undef FLAG_TO_SET
  2159. }
  2160.  
  2161.  
  2162. /****************************************************************************
  2163. Calculate the difference in timeout values. Return 1 if val1 > val2,
  2164. 0 if val1 == val2, -1 if val1 < val2. Stores result in retval. retval
  2165. may be == val1 or val2
  2166. ****************************************************************************/
  2167. int tval_sub( struct timeval *retval, struct timeval *val1, struct timeval *val2)
  2168. {
  2169.     long usecdiff = val1->tv_usec - val2->tv_usec;
  2170.     long secdiff = val1->tv_sec - val2->tv_sec;
  2171.     if(usecdiff < 0) {
  2172.         usecdiff = 1000000 + usecdiff;
  2173.         secdiff--;
  2174.     }
  2175.     retval->tv_sec = secdiff;
  2176.     retval->tv_usec = usecdiff;
  2177.     if(secdiff < 0)
  2178.         return -1;
  2179.     if(secdiff > 0)
  2180.         return 1;
  2181.     return (usecdiff < 0 ) ? -1 : ((usecdiff > 0 ) ? 1 : 0);
  2182. }
  2183.  
  2184. /****************************************************************************
  2185. read data from a device with a timout in msec.
  2186. mincount = if timeout, minimum to read before returning
  2187. maxcount = number to be read.
  2188. ****************************************************************************/
  2189. int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL exact)
  2190. {
  2191.   fd_set fds;
  2192.   int selrtn;
  2193.   int readret;
  2194.   int nread = 0;
  2195.   struct timeval timeout, tval1, tval2, tvaldiff;
  2196.   struct timezone tz;
  2197.  
  2198.   /* just checking .... */
  2199.   if (maxcnt <= 0) return(0);
  2200.  
  2201.   if(time_out == -2)
  2202.     time_out = DEFAULT_PIPE_TIMEOUT;
  2203.  
  2204.   /* Blocking read */
  2205.   if(time_out < 0) {
  2206.     return read(fd, buf, maxcnt);
  2207.   }
  2208.   
  2209.   /* Non blocking read */
  2210.   if(time_out == 0) {
  2211.     set_blocking(fd, False);
  2212.     nread = read(fd, buf, maxcnt);
  2213.     if(nread == -1 && errno == EWOULDBLOCK)
  2214.       nread = 0;
  2215.     set_blocking(fd,True);
  2216.     return nread;
  2217.   }
  2218.  
  2219.   /* Most difficult - timeout read */
  2220.   /* If this is ever called on a disk file and 
  2221.      mincnt is greater then the filesize then
  2222.      system performance will suffer severely as 
  2223.      select always return true on disk files */
  2224.  
  2225.   /* Set initial timeout */
  2226.   timeout.tv_sec = time_out / 1000;
  2227.   timeout.tv_usec = 1000 * (time_out % 1000);
  2228.  
  2229.   /* As most UNIXes don't modify the value of timeout
  2230.      when they return from select we need to get the timeofday (in usec)
  2231.      now, and also after the select returns so we know
  2232.      how much time has elapsed */
  2233.  
  2234.   if (exact)
  2235.     gettimeofday( &tval1, &tz);
  2236.   nread = 0; /* Number of bytes we have read */
  2237.  
  2238.   for(;;) 
  2239.     {
  2240.       
  2241.       FD_ZERO(&fds);
  2242.       FD_SET(fd,&fds);
  2243.       
  2244.       do {    
  2245.     selrtn = select(255,SELECT_CAST &fds,NULL,NULL,&timeout);
  2246.       } 
  2247.       while( selrtn < 0  &&  errno == EINTR );
  2248.       
  2249.       /* Check if error */
  2250.       if(selrtn == -1)
  2251.     return -1;
  2252.       
  2253.       /* Did we timeout ? */
  2254.       if (selrtn == 0 )
  2255.     break; /* Yes */
  2256.       
  2257.       readret = read( fd, buf+nread, maxcnt-nread);
  2258.       if(readret == -1)
  2259.     return -1;
  2260.  
  2261.       if (readret == 0)
  2262.     break;
  2263.       
  2264.       nread += readret;
  2265.       
  2266.       /* If we have read more than mincnt then return */
  2267.       if( nread >= mincnt )
  2268.     break;
  2269.  
  2270.       /* We need to do another select - but first reduce the
  2271.      time_out by the amount of time already elapsed - if
  2272.      this is less than zero then return */
  2273.       if (exact)
  2274.     {
  2275.       gettimeofday( &tval2, &tz);
  2276.       (void)tval_sub( &tvaldiff, &tval2, &tval1);
  2277.       
  2278.       if( tval_sub( &timeout, &timeout, &tvaldiff) <= 0) 
  2279.         {
  2280.           /* We timed out */
  2281.           break;
  2282.         }
  2283.     }
  2284.       
  2285.       /* Save the time of day as we need to do the select 
  2286.      again (saves a system call)*/
  2287.       tval1 = tval2;
  2288.     }
  2289.  
  2290.   /* Return the number we got */
  2291.   return(nread);
  2292. }
  2293.  
  2294. /****************************************************************************
  2295. read data from the client. Maxtime is in 10ths of a sec
  2296. ****************************************************************************/
  2297. int read_max_udp(int fd,char *buffer,int bufsize,int maxtime)
  2298. {
  2299.   fd_set fds;
  2300.   int selrtn;
  2301.   int nread;
  2302.   struct timeval timeout;
  2303.  
  2304.   FD_ZERO(&fds);
  2305.   FD_SET(fd,&fds);
  2306.  
  2307.   timeout.tv_sec = maxtime / 10;
  2308.   timeout.tv_usec = (maxtime % 10) * 100000;
  2309.  
  2310.   do {    
  2311.     if (maxtime > 0)
  2312.       selrtn = select(255,SELECT_CAST &fds,NULL,NULL,&timeout);
  2313.     else
  2314.       selrtn = select(255,SELECT_CAST &fds,NULL,NULL,NULL);
  2315.   } 
  2316.   while( selrtn < 0  &&  errno == EINTR );
  2317.  
  2318.  
  2319.   if (!FD_ISSET(fd,&fds))
  2320.     return 0;
  2321.  
  2322.   nread = read_udp_socket(fd, buffer, bufsize);
  2323.  
  2324.   /* return the number got */
  2325.   return(nread);
  2326. }
  2327.  
  2328. /****************************************************************************
  2329. write data to a device with a timout in msec.
  2330. ****************************************************************************/
  2331. int write_with_timeout(int fd, char *buf, int length, long time_out)
  2332. {
  2333.   fd_set fds;
  2334.   int selrtn;
  2335.   int nwritten = 0;
  2336.   int writeret;
  2337.   struct timeval timeout, tval1, tval2, tvaldiff;
  2338.   struct timezone tz;
  2339.  
  2340.   if(time_out == -2)
  2341.     time_out = DEFAULT_PIPE_TIMEOUT;
  2342.  
  2343.   /* Blocking write */
  2344.   if(time_out == -1) {
  2345.     return write(fd, buf, length);
  2346.   }
  2347.   
  2348.   /* Non blocking write */
  2349.   if(time_out == 0) {
  2350.     set_blocking(fd, False);
  2351.     nwritten = write(fd, buf, length);
  2352.     if( nwritten == -1 && errno == EWOULDBLOCK)
  2353.       nwritten = 0;
  2354.     set_blocking(fd,True);
  2355.     return nwritten;
  2356.   }
  2357.  
  2358.   /* Most difficult - timeout write */
  2359.  
  2360.   /* Set initial timeout */
  2361.   timeout.tv_sec = time_out / 1000;
  2362.   timeout.tv_usec = 1000*(time_out % 1000);
  2363.  
  2364.   /* As most UNIXes don't modify the value of timeout
  2365.      when they return from select we need to get the timeofday (in usec)
  2366.      now, and also after the select returns so we know
  2367.      how much time has elapsed */
  2368.  
  2369.   gettimeofday( &tval1, &tz);
  2370.   nwritten = 0; /* Number of bytes we have written */
  2371.  
  2372.   for(;;) {
  2373.  
  2374.     FD_ZERO(&fds);
  2375.     FD_SET(fd,&fds);
  2376.  
  2377.     /* Wait with timeout until we can write */
  2378.     do {    
  2379.       selrtn = select(255,NULL,SELECT_CAST &fds,NULL,&timeout);
  2380.     } 
  2381.     while( selrtn < 0  &&  errno == EINTR );
  2382.  
  2383.     /* Check if error */
  2384.     if(selrtn == -1)
  2385.       return -1;
  2386.  
  2387.     /* Did we timeout ? */
  2388.     if (selrtn == 0 )
  2389.       break; /* Yes */
  2390.  
  2391.     /* Set the fd nonblocking and write as much as we can */
  2392.     set_blocking(fd, False);
  2393.     writeret = write( fd, buf+nwritten, length-nwritten );
  2394.     set_blocking(fd,True);
  2395.     if(writeret == -1)
  2396.       return -1;
  2397.     nwritten += writeret;
  2398.  
  2399.     /* If we have written more than length then return */
  2400.     if( nwritten >= length )
  2401.       break;
  2402.  
  2403.     /* We need to do another select - but first reduce the
  2404.      time_out by the amount of time already elapsed - if
  2405.      this is less than zero then return */
  2406.     gettimeofday( &tval2, &tz);
  2407.     (void)tval_sub( &tvaldiff, &tval2, &tval1);
  2408.  
  2409.     if( tval_sub( &timeout, &timeout, &tvaldiff) <= 0) {
  2410.       /* We timed out */
  2411.       break;
  2412.     }
  2413.     
  2414.     /* Save the time of day as we need to do the 
  2415.        select again (saves a system call)*/
  2416.     tval1 = tval2;
  2417.   }
  2418.   /* Return the number we got */
  2419.   return(nwritten);
  2420. }
  2421.  
  2422.  
  2423. /****************************************************************************
  2424. send a keepalive packet (rfc1002)
  2425. ****************************************************************************/
  2426. BOOL send_keepalive(void)
  2427. {
  2428.   unsigned char buf[4];
  2429.   int nwritten = 0;
  2430.  
  2431.   buf[0] = 0x85;
  2432.   buf[1] = buf[2] = buf[3] = 0;
  2433.  
  2434.   while (nwritten < 4)
  2435.     {
  2436.       int ret = write_socket(Client,(char *)&buf[nwritten],4 - nwritten);
  2437.       if (ret <= 0)
  2438.     return(False);
  2439.       nwritten += ret;
  2440.     }
  2441.   return(True);
  2442. }
  2443.  
  2444. int keepalive = 0;
  2445.  
  2446.  
  2447. /****************************************************************************
  2448.   read data from the client, reading exactly N bytes. 
  2449. ****************************************************************************/
  2450. BOOL read_data(int fd,char *buffer,int N)
  2451. {
  2452.   int maxtime = keepalive;
  2453.   int  nready;
  2454.   int nread = 0;  
  2455.  
  2456.   if (maxtime > 0)
  2457.     {
  2458.       fd_set fds;
  2459.       int selrtn;
  2460.       struct timeval timeout;
  2461.       
  2462.       FD_ZERO(&fds);
  2463.       FD_SET(fd,&fds);
  2464.             
  2465.       timeout.tv_sec = maxtime;
  2466.       timeout.tv_usec = 0;
  2467.       
  2468.       while ((selrtn = select(255,SELECT_CAST &fds,NULL,NULL,&timeout)) == 0)
  2469.     {
  2470.       DEBUG(6,("Sending keepalive\n"));
  2471.       if (!send_keepalive())
  2472.         {
  2473.           DEBUG(0,("keepalive failed!\n"));
  2474.           return(False);
  2475.         }
  2476.       timeout.tv_sec = maxtime;
  2477.       timeout.tv_usec = 0;
  2478.       FD_ZERO(&fds);
  2479.       FD_SET(fd,&fds);            
  2480.     }
  2481.     }
  2482.  
  2483.   while (nread < N)
  2484.     {
  2485.       nready = read(fd,buffer + nread,N - nread);
  2486.       if (nready <= 0)
  2487.     return False;
  2488.       nread += nready;
  2489.     }
  2490.   return True;
  2491. }
  2492.  
  2493.  
  2494. /* variables used by the read prediction module */
  2495. int rp_fd = -1;
  2496. int rp_offset = 0;
  2497. int rp_length = 0;
  2498. int rp_alloced = 0;
  2499. int rp_predict_fd = -1;
  2500. int rp_predict_offset = 0;
  2501. int rp_predict_length = 0;
  2502. int rp_timeout = 5;
  2503. time_t rp_time = 0;
  2504. char *rp_buffer = NULL;
  2505.  
  2506.  
  2507. /****************************************************************************
  2508. handle read prediction on a file
  2509. ****************************************************************************/
  2510. int read_predict(int fd,int offset,char *buf,int num)
  2511. {
  2512.   int ret = 0;
  2513.   int possible = rp_length - (offset - rp_offset);
  2514.  
  2515.   possible = MIN(possible,num);
  2516.  
  2517.   /* give data if possible */
  2518.   if (fd == rp_fd && 
  2519.       offset >= rp_offset && 
  2520.       possible>0 &&
  2521.       time(NULL)-rp_time < rp_timeout)
  2522.     {
  2523.       ret = possible;
  2524.       memcpy(buf,rp_buffer + (offset-rp_offset),possible);
  2525.       DEBUG(5,("read-prediction gave %d bytes\n",ret));
  2526.     }
  2527.  
  2528.   /* prepare the next prediction */
  2529.   rp_predict_fd = fd;
  2530.   rp_predict_offset = offset + num;
  2531.   rp_predict_length = num;
  2532.  
  2533.   return(ret);
  2534. }
  2535.  
  2536. /****************************************************************************
  2537. pre-read some data
  2538. ****************************************************************************/
  2539. void do_read_prediction()
  2540. {
  2541.   if (rp_predict_fd == -1) 
  2542.     return;
  2543.  
  2544.   rp_fd = rp_predict_fd;
  2545.   rp_offset = rp_predict_offset;
  2546.   rp_length = 0;
  2547.  
  2548.   rp_predict_fd = -1;
  2549.  
  2550.   if (rp_predict_length > rp_alloced)
  2551.     {
  2552.       rp_buffer = Realloc(rp_buffer,rp_predict_length);
  2553.       rp_alloced = rp_predict_length;
  2554.       if (!rp_buffer)
  2555.     {
  2556.       DEBUG(0,("can't allocate read-prediction buffer\n"));
  2557.       rp_alloced = 0;
  2558.       return;
  2559.     }
  2560.     }
  2561.  
  2562.   if (lseek(rp_fd,0,SEEK_CUR) != rp_offset && lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset)
  2563.     return;
  2564.  
  2565.   rp_length = read(rp_fd,rp_buffer,rp_predict_length);
  2566.   rp_time = time(NULL);
  2567.   if (rp_length < 0)
  2568.     rp_length = 0;
  2569. }
  2570.  
  2571. /****************************************************************************
  2572. invalidate read-prediction on a fd
  2573. ****************************************************************************/
  2574. void invalidate_read_prediction(int fd)
  2575. {
  2576.  if (rp_fd == fd) 
  2577.    rp_fd = -1;
  2578.  if (rp_predict_fd == fd)
  2579.    rp_predict_fd = -1;
  2580. }
  2581.  
  2582.  
  2583. /****************************************************************************
  2584. read 4 bytes of a smb packet and return the smb length of the packet
  2585. possibly store the result in the buffer
  2586. ****************************************************************************/
  2587. int read_smb_length(int fd,char *inbuf,int timeout)
  2588. {
  2589.   char *buffer;
  2590.   char buf[4];
  2591.   int len=0, msg_type;
  2592.   BOOL ok=False;
  2593.  
  2594.   if (inbuf)
  2595.     buffer = inbuf;
  2596.   else
  2597.     buffer = buf;
  2598.  
  2599.   while (!ok)
  2600.     {
  2601.       if (timeout > 0)
  2602.     ok = (read_with_timeout(fd,buffer,4,4,timeout,False) == 4);
  2603.       else
  2604.     ok = read_data(fd,buffer,4);
  2605.  
  2606.       if (!ok)
  2607.     {
  2608.       if (timeout>0)
  2609.         {
  2610.           DEBUG(6,("client timeout (timeout was %d)\n", timeout));
  2611.           return(-1);
  2612.         }
  2613.       else
  2614.         {
  2615.           DEBUG(6,("couldn't read from client\n"));
  2616.           exit(1);
  2617.         }
  2618.     }
  2619.  
  2620.       len = smb_len(buffer);
  2621.       msg_type = CVAL(buffer,0);
  2622.  
  2623.       if (msg_type == 0x85) 
  2624.     {
  2625.       DEBUG(5,( "Got keepalive packet\n"));
  2626.       ok = False;
  2627.     }
  2628.     }
  2629.  
  2630.   return(len);
  2631. }
  2632.  
  2633.  
  2634.  
  2635. /****************************************************************************
  2636.   read an smb from a fd and return it's length
  2637. The timeout is in micro seconds
  2638. ****************************************************************************/
  2639. BOOL receive_smb(char *buffer,int timeout)
  2640. {
  2641.   int len;
  2642.   int fd = Client;
  2643.   BOOL ok;
  2644.  
  2645.   memset(buffer,0,smb_size + 100);
  2646.  
  2647.   len = read_smb_length(fd,buffer,timeout);
  2648.   if (len == -1)
  2649.     return(False);
  2650.  
  2651.   if (len > BUFFER_SIZE)
  2652.     {
  2653.       DEBUG(0,("Invalid packet length! (%d bytes)\n",len));
  2654.       if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
  2655.     exit(0);
  2656.     }
  2657.  
  2658.   ok = read_data(fd,buffer+4,len);
  2659.  
  2660.   if (!ok)
  2661.     {
  2662.       DEBUG(0,("couldn't read %d bytes from client\n",len));
  2663.       close_sockets();
  2664.       exit(1);
  2665.     }
  2666.  
  2667.   log_in(buffer,len+4);
  2668.   return(True);
  2669. }
  2670.  
  2671.  
  2672. /****************************************************************************
  2673.   send an smb to a fd 
  2674. ****************************************************************************/
  2675. BOOL send_smb(char *buffer)
  2676. {
  2677.   int fd = Client;
  2678.   int len;
  2679.   int ret,nwritten=0;
  2680.   len = smb_len(buffer) + 4;
  2681.  
  2682.   log_out(buffer,len);
  2683.  
  2684.   while (nwritten < len)
  2685.     {
  2686.       ret = write_socket(fd,buffer+nwritten,len - nwritten);
  2687.       if (ret <= 0)
  2688.     {
  2689.       DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
  2690.           close_sockets();
  2691.       exit(1);
  2692.     }
  2693.       nwritten += ret;
  2694.     }
  2695.  
  2696.  
  2697.   return True;
  2698. }
  2699.  
  2700.  
  2701. /****************************************************************************
  2702. word out the length of a nmb message
  2703. ****************************************************************************/
  2704. int nmb_len(char *buf)
  2705. {
  2706. int i;
  2707. int ret = 12;
  2708. char *p = buf;
  2709. int qdcount = SVAL(buf,4);
  2710. int ancount = SVAL(buf,6);
  2711. int nscount = SVAL(buf,8);
  2712. int arcount = SVAL(buf,10);
  2713.  
  2714. /* check for insane qdcount values? */
  2715. if (qdcount > 100 || qdcount < 0)
  2716.   {
  2717.     DEBUG(6,("Invalid qdcount? qdcount=%d\n",qdcount));
  2718.     return(0);
  2719.   }
  2720.  
  2721. for (i=0;i<qdcount;i++)
  2722.   {
  2723.     p = buf + ret;
  2724.     ret += name_len(p) + 4;
  2725.   }
  2726.  
  2727. for (i=0;i<(ancount + nscount + arcount);i++)
  2728.   {
  2729.     int rdlength;
  2730.     p = buf + ret;
  2731.     ret += name_len(p) + 8;
  2732.     p = buf + ret;
  2733.     rdlength = SVAL(p,0);
  2734.     ret += rdlength + 2;
  2735.   }
  2736.  
  2737. return(ret);
  2738. }
  2739.  
  2740.  
  2741. int nmb_recv_len = 0;
  2742.  
  2743. /****************************************************************************
  2744. receive a name message
  2745. ****************************************************************************/
  2746. BOOL receive_nmb(char *buffer,int timeout)
  2747. {
  2748.   int ret = read_max_udp(Client,buffer,BUFFER_SIZE,timeout);
  2749.  
  2750.   nmb_recv_len = ret;
  2751.  
  2752.   if (ret < 0)
  2753.     {
  2754.       DEBUG(0,("No bytes from client\n"));
  2755.       close_sockets();
  2756.       exit(0);
  2757.     }
  2758.   
  2759.   if (ret <= 1)
  2760.     return False;
  2761.  
  2762.   log_in(buffer,ret);
  2763.  
  2764.   DEBUG(3,("received packet from (%s) nmb_len=%d len=%d\n",
  2765.     inet_ntoa(lastip),nmb_len(buffer),ret));
  2766.  
  2767.   return(True);
  2768. }
  2769.  
  2770.  
  2771. /****************************************************************************
  2772. send a name message
  2773. ****************************************************************************/
  2774. BOOL send_nmb(char *buf, int len, struct in_addr *ip)
  2775. {
  2776.   BOOL ret;
  2777.   struct sockaddr_in sock_out;
  2778.   int one=1;
  2779.  
  2780. #if 1
  2781.   /* allow broadcasts on it */
  2782.   setsockopt(Client,SOL_SOCKET,SO_BROADCAST,(char *)&one,sizeof(one));
  2783. #endif
  2784.           
  2785.   /* set the address and port */
  2786.   memset((char *)&sock_out, 0, sizeof(sock_out));
  2787.   memcpy((char *)&sock_out.sin_addr,(char *)ip, 4);
  2788.   sock_out.sin_port = htons( 137 );
  2789.   sock_out.sin_family = AF_INET;
  2790.   
  2791.   /* log the packet */
  2792.   log_out(buf,len);
  2793.  
  2794.   if (DEBUGLEVEL > 0)
  2795.     DEBUG(3,("sending a packet of len %d to (%s) on port 137 of type DGRAM\n",
  2796.       len,inet_ntoa(*ip)));
  2797.     
  2798.   /* send it */
  2799.   ret = (sendto(Client,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
  2800.  
  2801.   if (!ret)
  2802.     DEBUG(0,("Send packet failed. ERRNO=%d\n",errno));
  2803.  
  2804.   return(ret);
  2805. }
  2806.  
  2807.  
  2808. /****************************************************************************
  2809. find a pointer to a netbios name
  2810. ****************************************************************************/
  2811. char *name_ptr(char *buf,int ofs)
  2812. {
  2813.   unsigned char c = *(unsigned char *)(buf+ofs);
  2814.  
  2815.   if ((c & 0xC0) == 0xC0)
  2816.     {
  2817.       uint16 l;
  2818.       char *p = (char *)&l;
  2819.       memcpy((char *)&l,buf+ofs,2);
  2820.       p[0] &= ~0xC0;
  2821.       l = SVAL(p,0);
  2822.       DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
  2823.       return(buf + l);
  2824.     }
  2825.   else
  2826.     return(buf+ofs);
  2827. }  
  2828.  
  2829. /****************************************************************************
  2830. extract a netbios name from a buf
  2831. ****************************************************************************/
  2832. void name_extract(char *buf,int ofs,char *name)
  2833. {
  2834.   strcpy(name,"");
  2835.   name_interpret(name_ptr(buf,ofs),name);
  2836. }  
  2837.   
  2838.  
  2839.  
  2840. /****************************************************************************
  2841. show a nmb message
  2842. ****************************************************************************/
  2843. void show_nmb(char *inbuf)
  2844. {
  2845.   int i,l;
  2846.   int name_trn_id = SVAL(inbuf,0);
  2847.   int opcode = (CVAL(inbuf,2) >> 3) & 0xF;
  2848.   int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
  2849.   int rcode = CVAL(inbuf,3) & 0xF;
  2850.   int qdcount = SVAL(inbuf,4);
  2851.   int ancount = SVAL(inbuf,6);
  2852.   int nscount = SVAL(inbuf,8);
  2853.   int arcount = SVAL(inbuf,10);
  2854.   char name[100];
  2855.  
  2856.   DEBUG(3,("\nPACKET INTERPRETATION\n"));
  2857.  
  2858. #if 0
  2859.   if (dbf)
  2860.     fwrite(inbuf,1,nmb_len(inbuf),dbf);
  2861.   DEBUG(0,("\n"));
  2862. #endif
  2863.  
  2864.   if (opcode == 5 && ((nm_flags & ~1) == 0x10) && rcode == 0)
  2865.     DEBUG(3,("NAME REGISTRATION REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  2866.  
  2867.   if (opcode == 5 && ((nm_flags & ~1) == 0x00) && rcode == 0)
  2868.     DEBUG(3,("NAME OVERWRITE REQUEST AND DEMAND (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  2869.   
  2870.   if (opcode == 9 && ((nm_flags & ~1) == 0x00) && rcode == 0)
  2871.     DEBUG(3,("NAME REFRESH REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  2872.   
  2873.   if (opcode == 5 && nm_flags == 0x58 && rcode == 0)
  2874.     DEBUG(3,("POSITIVE NAME REGISTRATION RESPONSE\n"));
  2875.   
  2876.   if (opcode == 5 && nm_flags == 0x58 && rcode != 0 && rcode != 7)
  2877.     DEBUG(3,("NEGATIVE NAME REGISTRATION RESPONSE\n"));
  2878.   
  2879.   if (opcode == 5 && nm_flags == 0x50 && rcode == 0)
  2880.     DEBUG(3,("END-NODE CHALLENGE REGISTRATION RESPONSE\n"));
  2881.   
  2882.   if (opcode == 5 && nm_flags == 0x58 && rcode != 0 && rcode == 7)
  2883.     DEBUG(3,("NAME CONFLICT DEMAND\n"));
  2884.   
  2885.   if (opcode == 6 && (nm_flags&~1) == 0x00 && rcode == 0)
  2886.     DEBUG(3,("NAME RELEASE REQUEST & DEMAND (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  2887.   
  2888.   if (opcode == 6 && (nm_flags&~1) == 0x40 && rcode == 0)
  2889.     DEBUG(3,("POSITIVE NAME RELEASE RESPONSE\n"));
  2890.   
  2891.   if (opcode == 6 && (nm_flags&~1) == 0x40 && rcode != 0)
  2892.     DEBUG(3,("NEGATIVE NAME RELEASE RESPONSE\n"));
  2893.   
  2894.   if (opcode == 0 && (nm_flags&~1) == 0x10 && rcode == 0)
  2895.     DEBUG(3,("NAME QUERY REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  2896.   
  2897.   if (opcode == 0 && (nm_flags&~0x28) == 0x50 && rcode == 0)
  2898.     DEBUG(3,("POSITIVE NAME QUERY RESPONSE\n"));
  2899.   
  2900.   if (opcode == 0 && (nm_flags&~0x08) == 0x50 && rcode != 0)
  2901.     DEBUG(3,("NEGATIVE NAME QUERY RESPONSE\n"));
  2902.   
  2903.   if (opcode == 0 && nm_flags == 0x10 && rcode == 0)
  2904.     DEBUG(3,("REDIRECT NAME QUERY RESPONSE\n"));
  2905.  
  2906.   if (opcode == 7 && nm_flags == 0x80 && rcode == 0)
  2907.     DEBUG(3,("WAIT FOR ACKNOWLEDGEMENT RESPONSE\n"));
  2908.   
  2909.   if (opcode == 0 && (nm_flags&~1) == 0x00 && rcode == 0)
  2910.     DEBUG(3,("NODE STATUS REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  2911.  
  2912.   if (opcode == 0 && nm_flags == 0x40 && rcode == 0)
  2913.     DEBUG(3,("NODE STATUS RESPONSE\n"));
  2914.   
  2915.   
  2916.   DEBUG(3,("name_trn_id=0x%x\nopcode=0x%x\nnm_flags=0x%x\nrcode=0x%x\n",
  2917.     name_trn_id,opcode,nm_flags,rcode));
  2918.   DEBUG(3,("qdcount=%d\nancount=%d\nnscount=%d\narcount=%d\n",
  2919.     qdcount,ancount,nscount,arcount));
  2920.  
  2921.   l = 12;
  2922.   for (i=0;i<qdcount;i++)
  2923.     {
  2924.       int type,class;
  2925.       DEBUG(3,("QUESTION %d\n",i));
  2926.       name_extract(inbuf,l,name);
  2927.       l += name_len(inbuf+l);
  2928.       type = SVAL(inbuf+l,0);
  2929.       class = SVAL(inbuf+l,2);
  2930.       l += 4;
  2931.       DEBUG(3,("\t%s\n\ttype=0x%x\n\tclass=0x%x\n",name,type,class));
  2932.     }
  2933.  
  2934.   for (i=0;i<(ancount + nscount + arcount);i++)
  2935.     {
  2936.       int type,class,ttl,rdlength;
  2937.       DEBUG(3,("RESOURCE %d\n",i));
  2938.       name_extract(inbuf,l,name);
  2939.       l += name_len(inbuf + l);
  2940.       type = SVAL(inbuf+l,0);
  2941.       class = SVAL(inbuf+l,2);
  2942.       ttl = IVAL(inbuf+l,4);
  2943.       rdlength = SVAL(inbuf+l,8);
  2944.       l += 10 + rdlength;
  2945.       DEBUG(3,("\t%s\n\ttype=0x%x\n\tclass=0x%x\n",name,type,class));
  2946.       DEBUG(3,("\tttl=%d\n\trdlength=%d\n",ttl,rdlength));
  2947.     }
  2948.  
  2949.   DEBUG(3,("\n"));
  2950.   
  2951. }
  2952.  
  2953. /****************************************************************************
  2954. return the total storage length of a mangled name
  2955. ****************************************************************************/
  2956. int name_len(char *s)
  2957. {
  2958.   unsigned char c = *(unsigned char *)s;
  2959.   if ((c & 0xC0) == 0xC0)
  2960.     return(2);
  2961.   return(strlen(s) + 1);
  2962. }
  2963.  
  2964. /****************************************************************************
  2965. send a single packet to a port on another machine
  2966. ****************************************************************************/
  2967. BOOL send_packet(char *buf,int len,struct in_addr *ip,int port,int type)
  2968. {
  2969.   BOOL ret;
  2970.   int out_fd;
  2971.   struct sockaddr_in sock_out;
  2972.   int one=1;
  2973.  
  2974.   if (passive)
  2975.     return(True);
  2976.  
  2977.   /* create a socket to write to */
  2978.   out_fd = socket(AF_INET, type, 0);
  2979.   if (out_fd == -1) 
  2980.     {
  2981.       DEBUG(0,("socket failed"));
  2982.       return False;
  2983.     }
  2984. #if 1
  2985.   /* allow broadcasts on it */
  2986.   setsockopt(out_fd,SOL_SOCKET,SO_BROADCAST,(char *)&one,sizeof(one));
  2987. #endif
  2988.           
  2989.   /* set the address and port */
  2990.   memset((char *)&sock_out, 0, sizeof(sock_out));
  2991.   memcpy((char *)&sock_out.sin_addr,(char *)ip, 4);
  2992.   sock_out.sin_port = htons( port );
  2993.   sock_out.sin_family = AF_INET;
  2994.   
  2995.   /* log the packet */
  2996.   log_out(buf,len);
  2997.  
  2998.   if (DEBUGLEVEL > 0)
  2999.     DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n",
  3000.       len,inet_ntoa(*ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM"));
  3001.     
  3002.   /* send it */
  3003.   ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
  3004.  
  3005.   if (!ret)
  3006.     DEBUG(0,("Send packet failed. ERRNO=%d\n",errno));
  3007.  
  3008.   close(out_fd);
  3009.   return(ret);
  3010. }
  3011.  
  3012.  
  3013. /****************************************************************************
  3014. check if a string is part of a list
  3015. ****************************************************************************/
  3016. BOOL in_list(char *s,char *list,BOOL case_sensitive)
  3017. {
  3018.   char *listcopy;
  3019.   char *t;
  3020.  
  3021.   if (!list) return(False);
  3022.  
  3023.   listcopy = strdup(list);
  3024.   if (!listcopy)
  3025.     return(False);
  3026.  
  3027.   for (t=strtok(listcopy,LIST_SEP); t; t = strtok(NULL,LIST_SEP))
  3028.     {
  3029.       if (case_sensitive)
  3030.     {
  3031.       if (strcmp(t,s) == 0)
  3032.         {
  3033.           free(listcopy);
  3034.           return(True);
  3035.         }
  3036.     }
  3037.       else
  3038.     {
  3039.       if (strcasecmp(t,s) == 0)
  3040.         {
  3041.           free(listcopy);
  3042.           return(True);
  3043.         }
  3044.     }
  3045.     }
  3046.   free(listcopy);
  3047.   return(False);
  3048. }
  3049.  
  3050. /* this is used to prevent lots of mallocs of size 1 */
  3051. char *null_string = NULL;
  3052.  
  3053. /****************************************************************************
  3054. set a string value, allocing the space for the string
  3055. ****************************************************************************/
  3056. BOOL string_init(char **dest,char *src)
  3057. {
  3058.   int l;
  3059.   if (!src)     
  3060.     src = "";
  3061.  
  3062.   l = strlen(src);
  3063.  
  3064.   if (l == 0)
  3065.     {
  3066.       if (!null_string)
  3067.     {
  3068.       null_string = (char *)malloc(1);
  3069.       *null_string = 0;
  3070.     }
  3071.       *dest = null_string;
  3072.     }
  3073.   else
  3074.     {
  3075.       *dest = (char *)malloc(l+1);
  3076.       strcpy(*dest,src);
  3077.     }
  3078.   return(True);
  3079. }
  3080.  
  3081. /****************************************************************************
  3082. free a string value
  3083. ****************************************************************************/
  3084. void string_free(char **s)
  3085. {
  3086.   if (!s || !(*s)) return;
  3087.   if (*s == null_string)
  3088.     *s = NULL;
  3089.   if (*s) free(*s);
  3090.   *s = NULL;
  3091. }
  3092.  
  3093. /****************************************************************************
  3094. set a string value, allocing the space for the string, and deallocating any 
  3095. existing space
  3096. ****************************************************************************/
  3097. BOOL string_set(char **dest,char *src)
  3098. {
  3099.   string_free(dest);
  3100.  
  3101.   return(string_init(dest,src));
  3102. }
  3103.  
  3104. /****************************************************************************
  3105. substitute a string for a pattern in another string. Make sure there is 
  3106. enough room!
  3107.  
  3108. This routine looks for pattern in s and replaces it with 
  3109. insert. It may do multiple replacements.
  3110.  
  3111. return True if a substitution was done.
  3112. ****************************************************************************/
  3113. BOOL string_sub(char *s,char *pattern,char *insert)
  3114. {
  3115.   BOOL ret = False;
  3116.   char *p;
  3117.   int ls = strlen(s);
  3118.   int lp = strlen(pattern);
  3119.   int li = strlen(insert);
  3120.  
  3121.   if (!*pattern) return(False);
  3122.  
  3123.   while (lp <= ls && (p = strstr(s,pattern)))
  3124.     {
  3125.       ret = True;
  3126.       safe_memcpy(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
  3127.       memcpy(p,insert,li);
  3128.       s = p + li;
  3129.       ls = strlen(s);
  3130.     }
  3131.   return(ret);
  3132. }
  3133.  
  3134. /****************************************************************************
  3135. get a users home directory. tries as-is then lower case
  3136. ****************************************************************************/
  3137. char *get_home_dir(char *user)
  3138. {
  3139.   static struct passwd *pass;
  3140.  
  3141.   pass = Get_Pwnam(user);
  3142.  
  3143.   if (!pass) return(NULL);
  3144.   return(pass->pw_dir);      
  3145. }
  3146.  
  3147.  
  3148. /****************************************************************************
  3149. become a daemon, discarding the controlling terminal
  3150. ****************************************************************************/
  3151. void become_daemon(void)
  3152. {
  3153. #ifndef NO_FORK_DEBUG
  3154.   if (fork())
  3155.     exit(0);
  3156.  
  3157.   /* detach from the terminal */
  3158. #ifdef LINUX
  3159.   setpgrp();
  3160. #endif
  3161.  
  3162. #ifdef USE_SETSID
  3163.   setsid();
  3164. #else
  3165.   {
  3166.     int i = open("/dev/tty", O_RDWR);
  3167.     if (i >= 0) 
  3168.       {
  3169.     ioctl(i, (int) TIOCNOTTY, (char *)0);      
  3170.     close(i);
  3171.       }
  3172.   }
  3173. #endif
  3174. #endif
  3175. }
  3176.  
  3177. /****************************************************************************
  3178. calculate the default netmask for an address
  3179. ****************************************************************************/
  3180. static void default_netmask(struct in_addr *inm, struct in_addr *iad)
  3181. {
  3182.   unsigned long ad = ntohl(iad->s_addr);
  3183.   unsigned long nm;
  3184.   /*
  3185.   ** Guess a netmask based on the class of the IP address given.
  3186.   */
  3187.   if ( (ad & 0x80000000) == 0 ) {
  3188.     /* class A address */
  3189.     nm = 0xFF000000;
  3190.   } else if ( (ad & 0xC0000000) == 0x80000000 ) {
  3191.     /* class B address */
  3192.     nm = 0xFFFF0000;
  3193.   } else if ( (ad & 0xE0000000) == 0xC0000000 ) {
  3194.     /* class C address */
  3195.     nm = 0xFFFFFF00;
  3196.   }  else {
  3197.     /* class D or E; netmask doesn't make much sense */
  3198.     nm =  0;
  3199.   }
  3200.   inm->s_addr = htonl(nm);
  3201. }
  3202.  
  3203. /****************************************************************************
  3204.   get the broadcast address for our address 
  3205. (troyer@saifr00.ateng.az.honeywell.com)
  3206. ****************************************************************************/
  3207. void get_broadcast (struct in_addr *if_ipaddr,
  3208.                     struct in_addr *if_bcast,
  3209.                     struct in_addr *if_nmask)
  3210. {
  3211.   int sock = -1;               /* AF_INET raw socket desc */
  3212.   char buff[1024];
  3213.   struct ifreq *ifr;
  3214.   int i;
  3215.  
  3216. #ifdef USE_IFREQ
  3217.   struct ifreq ifreq;
  3218.   struct strioctl strioctl;
  3219.   struct ifconf *ifc;
  3220. #else
  3221.   struct ifconf ifc;
  3222. #endif
  3223.  
  3224.   /* get a default netmask and broadcast */
  3225.   default_netmask(if_nmask, if_ipaddr);
  3226.   {
  3227.     unsigned long ip = ntohl(if_ipaddr->s_addr);
  3228.     unsigned long nm = ntohl(if_nmask->s_addr);
  3229.     ip &= nm;                           /* mask down to our network number */
  3230.     ip |= ( 0x00FFFFFF & ~nm );         /* insert 1s in host field         */
  3231.     if_bcast->s_addr = htonl(ip);
  3232.   }
  3233.   
  3234.   
  3235.   /* Create a socket to the INET kernel. */
  3236. #if USE_SOCKRAW
  3237.   if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
  3238. #else
  3239.   if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
  3240. #endif
  3241.       {
  3242.         DEBUG(0,( "Unable to open socket to get broadcast address\n"));
  3243.         return;
  3244.       }
  3245.   
  3246.   /* Get a list of the configures interfaces */
  3247. #ifdef USE_IFREQ
  3248.   ifc = (struct ifconf *)buff;
  3249.   ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
  3250.   strioctl.ic_cmd = SIOCGIFCONF;
  3251.   strioctl.ic_dp  = (char *)ifc;
  3252.   strioctl.ic_len = sizeof(buff);
  3253.   if (ioctl(sock, I_STR, &strioctl) < 0)
  3254.     {
  3255.       DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
  3256.       return;
  3257.     }
  3258.   ifr = (struct ifreq *)ifc->ifc_req;
  3259.   
  3260.   /* Loop through interfaces, looking for given IP address */
  3261.   for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
  3262. #else
  3263.     ifc.ifc_len = sizeof(buff);
  3264.   ifc.ifc_buf = buff;
  3265.   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
  3266.     {
  3267.       DEBUG(0,( "SIOCGIFCONF: %s\n", strerror(errno)));
  3268.       return;
  3269.     }
  3270.   ifr = ifc.ifc_req;
  3271.   
  3272.   /* Loop through interfaces, looking for given IP address */
  3273.   for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
  3274. #endif
  3275.     {
  3276.       DEBUG(3,("Interface: %s  IP addr: %s\n", ifr->ifr_name,
  3277.             inet_ntoa((*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr)));
  3278.       if (if_ipaddr->s_addr ==
  3279.       (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr)
  3280.     break;
  3281.     }
  3282.   
  3283.   if (i < 0)
  3284.     {
  3285.       DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
  3286.       return;
  3287.     }
  3288.   
  3289.   /* Get the broadcast address from the kernel */
  3290. #ifdef USE_IFREQ
  3291.   ifreq = *ifr;
  3292.   
  3293.   strioctl.ic_cmd = SIOCGIFBRDADDR;
  3294.   strioctl.ic_dp  = (char *)&ifreq;
  3295.   strioctl.ic_len = sizeof(struct ifreq);
  3296.   if (ioctl(sock, I_STR, &strioctl) < 0)
  3297.     DEBUG(0,( "Failed I_STR/SIOCGIFBRDADDR: %s\n", strerror(errno)));
  3298.   else
  3299.     *if_bcast = ((struct sockaddr_in *)&ifreq.ifr_broadaddr)->sin_addr;
  3300. #else
  3301.   if (ioctl(sock, SIOCGIFBRDADDR, ifr) < 0)
  3302.     DEBUG(0,("SIOCGIFBRDADDR failed\n"));
  3303.   else
  3304.     *if_bcast = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
  3305. #endif
  3306.   
  3307.   /* Get the netmask address from the kernel */
  3308. #ifdef USE_IFREQ
  3309.   ifreq = *ifr;
  3310.   
  3311.   strioctl.ic_cmd = SIOCGIFNETMASK;
  3312.   strioctl.ic_dp  = (char *)&ifreq;
  3313.   strioctl.ic_len = sizeof(struct ifreq);
  3314.   if (ioctl(sock, I_STR, &strioctl) < 0)
  3315.     DEBUG(0,( "Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
  3316.   else
  3317.     *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
  3318. #else
  3319.   if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
  3320.     DEBUG(0,("SIOCGIFNETMASK failed\n"));
  3321.   else
  3322.     *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
  3323. #endif
  3324.   
  3325.   /* Close up shop */
  3326.   (void) close(sock);
  3327.   
  3328.   DEBUG(2,("Broadcast address for %s = %s\n", ifr->ifr_name,
  3329.         inet_ntoa(*if_bcast)));
  3330.   DEBUG(2,("Netmask for %s = %s\n", ifr->ifr_name,
  3331.         inet_ntoa(*if_nmask)));
  3332.   
  3333.   return;
  3334. }  /* get_broadcast */
  3335.  
  3336.  
  3337. /****************************************************************************
  3338.   true if two netbios names are equal
  3339. ****************************************************************************/
  3340. BOOL name_equal(char *s1,char *s2)
  3341. {
  3342.   char *p1, *p2;
  3343.   while (*s1 && *s2 && (*s1!=' ') && (*s2!=' ')) {
  3344.     p1 = s1;
  3345.     p2 = s2; /* toupper has side effects as a macro */
  3346.     if (toupper(*p1) != toupper(*p2))
  3347.       return(False);
  3348.     s1++;
  3349.     s2++;
  3350.   }
  3351.   if ((*s1 == 0 || *s1 == ' ') && (*s2 == 0 || *s2 == ' '))    
  3352.     return(True);  
  3353.   else
  3354.     return(False);
  3355. }
  3356.  
  3357.  
  3358. /****************************************************************************
  3359. do a netbios name query to find someones IP
  3360. ****************************************************************************/
  3361. BOOL name_query(char *inbuf,char *outbuf,char *name,
  3362.         struct in_addr to_ip,struct in_addr *ip,int maxtime,
  3363.         void (*fn)())
  3364. {
  3365.   static uint16 name_trn_id = 0x6242;
  3366.   char *p;
  3367.   BOOL saved_swap = NeedSwap;
  3368.   BOOL found = False;
  3369.   time_t start_time = time(NULL);
  3370.   time_t this_time = start_time;
  3371.  
  3372.   NeedSwap = !big_endian();
  3373.  
  3374.   DEBUG(2,("Querying name %s\n",name));
  3375.  
  3376.   name_trn_id += getpid() % 100;
  3377.   name_trn_id = (name_trn_id % 0x7FFF);
  3378.  
  3379.   SSVAL(outbuf,0,name_trn_id);
  3380.   CVAL(outbuf,2) = 0x1;
  3381.   CVAL(outbuf,3) = (1<<4) | 0x0;
  3382.   SSVAL(outbuf,4,1);
  3383.   SSVAL(outbuf,6,0);
  3384.   SSVAL(outbuf,8,0);
  3385.   SSVAL(outbuf,10,0);  
  3386.   p = outbuf+12;
  3387.   name_mangle(name,p);
  3388.   p += name_len(p);
  3389.   SSVAL(p,0,0x20);
  3390.   SSVAL(p,2,0x1);
  3391.   p += 4;
  3392.  
  3393.   DEBUG(2,("Sending name query for %s\n",name));
  3394.  
  3395.   show_nmb(outbuf);
  3396.   if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip))
  3397.     {
  3398.       NeedSwap = saved_swap;
  3399.       return False;
  3400.     }
  3401.  
  3402.   while (!found && this_time - start_time <= maxtime)
  3403.     {
  3404.       this_time = time(NULL);
  3405.  
  3406.       if (receive_nmb(inbuf,1))
  3407.     {     
  3408.       int rec_name_trn_id = SVAL(inbuf,0);
  3409.       int opcode = (CVAL(inbuf,2) >> 3) & 0xF;
  3410.       int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
  3411.       int rcode = CVAL(inbuf,3) & 0xF;
  3412.       show_nmb(inbuf);
  3413.  
  3414.       /* is it a positive response to our request? */
  3415.       if ((rec_name_trn_id == name_trn_id) && 
  3416.           opcode == 0 && (nm_flags&~0x28) == 0x50 && rcode == 0)
  3417.         {
  3418.           found = True;
  3419.           DEBUG(2,("Got a positive name query response from %s\n",
  3420.                inet_ntoa(lastip)));
  3421.           memcpy((char *)ip,inbuf + 12 + name_len(inbuf+12) + 12,4);
  3422.         }
  3423.       else
  3424.         {
  3425.           if (fn)
  3426.         fn(inbuf,outbuf+nmb_len(outbuf));
  3427.         }
  3428.     }
  3429.     }
  3430.   NeedSwap = saved_swap;
  3431.   return(found);
  3432. }
  3433.  
  3434. /****************************************************************************
  3435. do a netbios name status to a host
  3436. ****************************************************************************/
  3437. BOOL name_status(char *inbuf,char *outbuf,char *name)
  3438. {
  3439.   int maxtime = 5;
  3440.   static uint16 name_trn_id = 0x4262;
  3441.   char *p;
  3442.   BOOL saved_swap = NeedSwap;
  3443.   BOOL found = False;
  3444.   time_t start_time = time(NULL);
  3445.   time_t this_time = start_time;
  3446.  
  3447.   NeedSwap = !big_endian();
  3448.  
  3449.   DEBUG(1,("Querying status of name %s\n",name));
  3450.  
  3451.   name_trn_id += getpid() % 100;
  3452.   name_trn_id = (name_trn_id % 10000);
  3453.  
  3454.   SSVAL(outbuf,0,name_trn_id);
  3455.   CVAL(outbuf,2) = 0;
  3456.   CVAL(outbuf,3) = (1<<4) | 0x0;
  3457.   SSVAL(outbuf,4,1);
  3458.   SSVAL(outbuf,6,0);
  3459.   SSVAL(outbuf,8,0);
  3460.   SSVAL(outbuf,10,0);  
  3461.   p = outbuf+12;
  3462.   name_mangle(name,p);
  3463.   p += name_len(p);
  3464.   SSVAL(p,0,0x21);
  3465.   SSVAL(p,2,0x1);
  3466.   p += 4;
  3467.  
  3468.   DEBUG(2,("Sending name status query for %s\n",name));
  3469.  
  3470.   show_nmb(outbuf);
  3471.   if (!send_nmb(outbuf,nmb_len(outbuf), &bcast_ip))
  3472.     {
  3473.       NeedSwap = saved_swap;
  3474.       return False;
  3475.     }
  3476.  
  3477.   while (!found && this_time - start_time <= maxtime)
  3478.     {
  3479.       this_time = time(NULL);
  3480.  
  3481.       if (receive_nmb(inbuf,1))
  3482.     {
  3483.       int rec_name_trn_id = SVAL(inbuf,0);
  3484.       int opcode = (CVAL(inbuf,2) >> 3) & 0xF;
  3485.       int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
  3486.       int rcode = CVAL(inbuf,3) & 0xF;
  3487.       show_nmb(inbuf);
  3488.  
  3489.       /* is it a positive response to our request? */
  3490.       if ((rec_name_trn_id == name_trn_id) && 
  3491.           (opcode == 0 && nm_flags == 0x40 && rcode == 0))
  3492.         {
  3493.           char *p = inbuf + 12 + name_len(inbuf+12) + 10;
  3494.           int num_names = CVAL(p,0);
  3495.           found = True;
  3496.           DEBUG(0,("Got a positive node status response from %s\n",
  3497.                inet_ntoa(lastip)));
  3498.  
  3499.           DEBUG(0,("received %d names\n",num_names));
  3500.           p += 1;
  3501.           while (num_names--)
  3502.         {
  3503.           char qname[100];
  3504.           char flags[20]="";
  3505.           strcpy(qname,p);
  3506.           p += 16;
  3507.           if (p[0] & 0x80) strcat(flags,"<GROUP> ");
  3508.           if (p[0] & 0x60 == 0) strcat(flags,"B ");
  3509.           if (p[0] & 0x60 == 1) strcat(flags,"P ");
  3510.           if (p[0] & 0x60 == 2) strcat(flags,"M ");
  3511.           if (p[0] & 0x60 == 3) strcat(flags,"_ ");
  3512.           if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
  3513.           if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
  3514.           if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
  3515.           if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
  3516.           
  3517.           DEBUG(0,("\t%s\t%s\n",qname,flags));
  3518.           p+=2;
  3519.         }
  3520.         }
  3521.     }
  3522.     }
  3523.  
  3524.   if (!found)
  3525.     DEBUG(0,("No response (this is not unusual)\n"));
  3526.   NeedSwap = saved_swap;
  3527.   return(found);
  3528. }
  3529.  
  3530.  
  3531. /****************************************************************************
  3532. put up a yes/no prompt
  3533. ****************************************************************************/
  3534. BOOL yesno(char *p)
  3535. {
  3536.   pstring ans;
  3537.   printf("%s",p);
  3538.  
  3539.   if (!fgets(ans,sizeof(ans)-1,stdin))
  3540.     return(False);
  3541.  
  3542.   if (*ans == 'y' || *ans == 'Y')
  3543.     return(True);
  3544.  
  3545.   return(False);
  3546. }
  3547.  
  3548. /****************************************************************************
  3549. read a line from a file with possible \ continuation chars. 
  3550. Blanks at the start or end of a line are stripped.
  3551. The string will be allocated if s2 is NULL
  3552. ****************************************************************************/
  3553. char *fgets_slash(char *s2,int maxlen,FILE *f)
  3554. {
  3555.   char *s=s2;
  3556.   int len = 0;
  3557.   int c;
  3558.   BOOL start_of_line = True;
  3559.  
  3560.   if (feof(f))
  3561.     return(NULL);
  3562.  
  3563.   if (!s2)
  3564.     {
  3565.       maxlen = MIN(maxlen,8);
  3566.       s = (char *)Realloc(s,maxlen);
  3567.     }
  3568.  
  3569.   if (!s || maxlen < 2) return(NULL);
  3570.  
  3571.   *s = 0;
  3572.  
  3573.   while (len < maxlen-1)
  3574.     {
  3575.       c = getc(f);
  3576.       switch (c)
  3577.     {
  3578.     case '\r':
  3579.       break;
  3580.     case '\n':
  3581.       while (len > 0 && s[len-1] == ' ')
  3582.         {
  3583.           s[--len] = 0;
  3584.         }
  3585.       if (len > 0 && s[len-1] == '\\')
  3586.         {
  3587.           s[--len] = 0;
  3588.           start_of_line = True;
  3589.           break;
  3590.         }
  3591.       return(s);
  3592.     case EOF:
  3593.       if (len <= 0 && !s2) 
  3594.         free(s);
  3595.       return(len>0?s:NULL);
  3596.     case ' ':
  3597.       if (start_of_line)
  3598.         break;
  3599.     default:
  3600.       start_of_line = False;
  3601.       s[len++] = c;
  3602.       s[len] = 0;
  3603.     }
  3604.       if (!s2 && len > maxlen-3)
  3605.     {
  3606.       maxlen *= 2;
  3607.       s = (char *)Realloc(s,maxlen);
  3608.       if (!s) return(NULL);
  3609.     }
  3610.     }
  3611.   return(s);
  3612. }
  3613.  
  3614.  
  3615.  
  3616. /****************************************************************************
  3617. set the length of a file from a filedescriptor.
  3618. Returns 0 on success, -1 on failure.
  3619. ****************************************************************************/
  3620. int set_filelen(int fd, long len)
  3621. {
  3622. /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
  3623.    extend a file with ftruncate. Provide alternate implementation
  3624.    for this */
  3625.  
  3626. #if FTRUNCATE_CAN_EXTEND
  3627.   return ftruncate(fd, len);
  3628. #else
  3629.   struct stat st;
  3630.   char c = 0;
  3631.   long currpos = lseek(fd, 0L, SEEK_CUR);
  3632.  
  3633.   if(currpos < 0)
  3634.     return -1;
  3635.   /* Do an fstat to see if the file is longer than
  3636.      the requested size (call ftruncate),
  3637.      or shorter, in which case seek to len - 1 and write 1
  3638.      byte of zero */
  3639.   if(fstat(fd, &st)<0)
  3640.     return -1;
  3641.  
  3642.   if(st.st_size == len)
  3643.     return 0;
  3644.   if(st.st_size > len)
  3645.     return ftruncate(fd, len);
  3646.  
  3647.   if(lseek(fd, len-1, SEEK_SET) != len -1)
  3648.     return -1;
  3649.   if(write(fd, &c, 1)!=1)
  3650.     return -1;
  3651.   /* Seek to where we were */
  3652.   lseek(fd, currpos, SEEK_SET);
  3653.   return 0;
  3654. #endif
  3655. }
  3656.  
  3657.  
  3658. /****************************************************************************
  3659. return the byte checksum of some data
  3660. ****************************************************************************/
  3661. int byte_checksum(char *buf,int len)
  3662. {
  3663.   unsigned char *p = (unsigned char *)buf;
  3664.   int ret = 0;
  3665.   while (len--)
  3666.     ret += *p++;
  3667.   return(ret);
  3668. }
  3669.  
  3670. /* some useful string operations. */
  3671.  
  3672. /**************************************************************************
  3673. Replace n characters in str1 with str2, starting at offset start in str1.
  3674. If strlen(str2) is greater than n, it is up to the caller to ensure that 
  3675. there is enough space in str1.
  3676. **************************************************************************/
  3677. void replacestr(char *str1, char *str2, int start, int n)
  3678. {
  3679.    int  len;
  3680.    char *tstr;
  3681.  
  3682.    len = strlen(str2);
  3683.    tstr = str1;
  3684.  
  3685.    if (len < n)                /* ie., closing up the string */
  3686.       closestr(str1, start, n - len);
  3687.    else
  3688.       if (len > n)             /* ie., opening up the string */
  3689.          openstr(str1, start, len - n);
  3690.  
  3691.    str1 += start;
  3692.    while (*str2)
  3693.       *str1++ = *str2++;
  3694. }
  3695.  
  3696. /***********************************************************************
  3697. Open a gap in s, n chars wide at offset start.
  3698. ***********************************************************************/
  3699. void openstr(char *s, int start, int n)
  3700. {
  3701.    char *src;
  3702.    char *dest;
  3703.    char *tptr;
  3704.    int  len;
  3705.  
  3706.    if (n > 0)
  3707.       if ((tptr = s) != NULL)
  3708.       {
  3709.          len = strlen(s);
  3710.          if (start >= 0 && start < len)
  3711.          {
  3712.             s += start;
  3713.             src = s + len;
  3714.             dest = src + n;
  3715.             while (src != s)
  3716.                *dest-- = *src--;
  3717.             *dest = *src;
  3718.          }
  3719.       }
  3720. }
  3721.  
  3722. /***********************************************************************
  3723. Close up s by n chars, at offset start.
  3724. ***********************************************************************/
  3725. void closestr(char *s, int start, int n)
  3726. {
  3727.    char *src;
  3728.    char *dest;
  3729.    int  len;
  3730.  
  3731.    if (n > 0)
  3732.       if ((src = dest = s) != NULL)
  3733.       {
  3734.          len = strlen(s);
  3735.          if (start >= 0 && start < len - n)
  3736.          {
  3737.             src += start + n;
  3738.             dest += start;
  3739.   
  3740.             while (*src)
  3741.                *dest++ = *src++;
  3742.             *dest = '\0';
  3743.          }
  3744.       }
  3745. }
  3746.  
  3747.  
  3748. /****************************************************************************
  3749. apply a function to upper/lower case combinations
  3750. of a string and return true if one of them returns true.
  3751. try up to N uppercase letters.
  3752. offset is the first char to try and change (start with 0)
  3753. it assumes the string starts lowercased
  3754. ****************************************************************************/
  3755. BOOL string_combinations(char *s,int offset,BOOL (*fn)(),int N)
  3756. {
  3757.   int len = strlen(s);
  3758.   int i;
  3759.   if (N <= 0 || offset >= len)
  3760.     return(fn(s));
  3761.   for (i=offset;i<len;i++)
  3762.     {      
  3763.       char c = s[i];
  3764.       if (string_combinations(s,i+1,fn,N-1))
  3765.     return(True);
  3766.       if (islower(c))
  3767.     s[i] = toupper(c);
  3768.       if (string_combinations(s,i+1,fn,N-1))
  3769.     return(True);
  3770.       s[i] = c;
  3771.     }
  3772.   return(False);
  3773. }
  3774.  
  3775.  
  3776. /****************************************************************************
  3777. apply a function to all upper/lower case combinations
  3778. of a string and return true if one of them returns true.
  3779. Don't try more than 2^N combinations
  3780. ****************************************************************************/
  3781. BOOL string_combinations_all(char *s,BOOL (*fn)(),int N)
  3782. {
  3783.   int limit;
  3784.   int j,i;
  3785.  
  3786.   N = MIN(N,strlen(s));
  3787.   limit = (1<<N);
  3788.  
  3789.   for (i=0;i<limit;i++)
  3790.     {
  3791.       for (j=0;j<N;j++)
  3792.     {
  3793.       if (i & (1<<j))
  3794.         {
  3795.           if (islower(s[j]))
  3796.         s[j] = toupper(s[j]);
  3797.         }
  3798.       else
  3799.         {
  3800.           if (isupper(s[j]))
  3801.         s[j] = tolower(s[j]);
  3802.         }
  3803.     }
  3804.       if (fn(s))
  3805.     return(True);
  3806.     }
  3807.   return(False);
  3808. }
  3809.       
  3810.  
  3811. #ifdef HPUX
  3812. /****************************************************************************
  3813. this is a version of setbuffer() for those machines that only have setvbuf
  3814. ****************************************************************************/
  3815. void setbuffer(FILE *f,char *buf,int bufsize)
  3816. {
  3817.   setvbuf(f,buf,_IOFBF,bufsize);
  3818. }
  3819. #endif
  3820.  
  3821.  
  3822. /****************************************************************************
  3823. parse out a directory name from a path name. Assumes dos style filenames.
  3824. ****************************************************************************/
  3825. char *dirname_dos(char *path,char *buf)
  3826. {
  3827.   char *p = strrchr(path,'\\');
  3828.  
  3829.   if (!p)
  3830.     strcpy(buf,path);
  3831.   else
  3832.     {
  3833.       *p = 0;
  3834.       strcpy(buf,path);
  3835.       *p = '\\';
  3836.     }
  3837.  
  3838.   return(buf);
  3839. }
  3840.  
  3841.  
  3842. /****************************************************************************
  3843. parse out a filename from a path name. Assumes dos style filenames.
  3844. ****************************************************************************/
  3845. char *filename_dos(char *path,char *buf)
  3846. {
  3847.   char *p = strrchr(path,'\\');
  3848.  
  3849.   if (!p)
  3850.     strcpy(buf,path);
  3851.   else
  3852.     strcpy(buf,p+1);
  3853.  
  3854.   return(buf);
  3855. }
  3856.  
  3857.  
  3858. struct
  3859. {
  3860.   int thresh;
  3861.   int count;
  3862.   int tsize;
  3863.   int time;
  3864. }
  3865. time_stats[] = {
  3866.   {0,0,0,0},
  3867.   {1,0,0,0},
  3868.   {5,0,0,0},
  3869.   {10,0,0,0},
  3870.   {50,0,0,0},
  3871.   {200,0,0,0},
  3872.   {500,0,0,0},
  3873.   {-1,0,0,0}};
  3874.  
  3875.  
  3876. /****************************************************************************
  3877. stats recording
  3878. ****************************************************************************/
  3879. void stats_record(int size,int t)
  3880. {
  3881.   int bin=1;
  3882.  
  3883.   while (time_stats[bin].thresh != -1)
  3884.     {
  3885.       if (size/1024 < time_stats[bin].thresh)
  3886.     break;
  3887.       bin++;
  3888.     }
  3889.  
  3890.   bin--;
  3891.  
  3892.   time_stats[bin].time += t;
  3893.   time_stats[bin].tsize += size;
  3894.   time_stats[bin].count++;
  3895. }
  3896.  
  3897. /****************************************************************************
  3898. stats reporting
  3899. ****************************************************************************/
  3900. void stats_report(void)
  3901. {
  3902.   int bin=0;
  3903.   while (time_stats[bin].thresh != -1)
  3904.     {
  3905.       if (time_stats[bin].count > 0) 
  3906.     DEBUG(0,("More than %3dk (%d)   %6d times    %g secs. %g k/sec\n",
  3907.           time_stats[bin].thresh,
  3908.           time_stats[bin].tsize/(1024*time_stats[bin].count),
  3909.           time_stats[bin].count,time_stats[bin].time/1.0e6,
  3910.           (time_stats[bin].tsize/1024.0)/(time_stats[bin].time/1.0e6)));
  3911.       bin++;
  3912.     }    
  3913. }
  3914.  
  3915. /****************************************************************************
  3916. expand a pointer to be a particular size
  3917. ****************************************************************************/
  3918. void *Realloc(void *p,int size)
  3919. {
  3920.   void *ret=NULL;
  3921.   if (!p)
  3922.     ret = (void *)malloc(size);
  3923.   else
  3924.     ret = (void *)realloc(p,size);
  3925.  
  3926.   if (!ret)
  3927.     DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
  3928.  
  3929.   return(ret);
  3930. }
  3931.  
  3932.  
  3933. /****************************************************************************
  3934. check if it's a null mtime
  3935. ****************************************************************************/
  3936. BOOL null_mtime(time_t mtime)
  3937. {
  3938.   if (mtime == 0 || mtime == 0xFFFFFFFF)
  3939.     return(True);
  3940.   return(False);
  3941. }
  3942.  
  3943.  
  3944. /****************************************************************************
  3945. set the time on a file
  3946. ****************************************************************************/
  3947. BOOL set_filetime(char *fname,time_t mtime)
  3948. {
  3949.   struct utimbuf times;
  3950.  
  3951.   if (null_mtime(mtime)) return(True);
  3952.  
  3953.   times.modtime = times.actime = mtime;
  3954.  
  3955.   return(utime(fname,×) == 0);
  3956. }
  3957.  
  3958.  
  3959. #ifdef NOSTRDUP
  3960. /****************************************************************************
  3961. duplicate a string
  3962. ****************************************************************************/
  3963. char *strdup(char *s)
  3964. {
  3965.   char *ret = NULL;
  3966.   if (!s) return(NULL);
  3967.   ret = (char *)malloc(strlen(s)+1);
  3968.   if (!ret) return(NULL);
  3969.   strcpy(ret,s);
  3970.   return(ret);
  3971. }
  3972. #endif
  3973.  
  3974.  
  3975. /****************************************************************************
  3976.   Signal handler for SIGPIPE (write on a disconnected socket) 
  3977. ****************************************************************************/
  3978. void Abort(void )
  3979. {
  3980.   DEBUG(0,("Abort called. Probably got SIGPIPE\n"));
  3981.   exit(1);
  3982. }
  3983.  
  3984.  
  3985. #ifdef REPLACE_STRLEN
  3986. /****************************************************************************
  3987. a replacement strlen() that returns int for solaris
  3988. ****************************************************************************/
  3989. int Strlen(char *s)
  3990. {
  3991.   int ret=0;
  3992.   if (!s) return(0);
  3993.   while (*s++) ret++;
  3994.   return(ret);
  3995. }
  3996. #endif
  3997.  
  3998.  
  3999. /****************************************************************************
  4000. return a time at the start of the current month
  4001. ****************************************************************************/
  4002. time_t start_of_month(void)
  4003. {
  4004.   time_t t = time(NULL);
  4005.   struct tm *t2;
  4006.   
  4007.   t2 = gmtime(&t);
  4008.   
  4009.   t2->tm_mday = 1;
  4010.   t2->tm_hour = 0;
  4011.   t2->tm_min = 0;
  4012.   t2->tm_sec = 0;
  4013.   
  4014. #ifdef sun386
  4015.   return(timelocal(t2));
  4016. #else
  4017.   return(mktime(t2));
  4018. #endif
  4019. }
  4020.  
  4021.  
  4022. /*******************************************************************
  4023.   check for a sane unix date
  4024. ********************************************************************/
  4025. BOOL sane_unix_date(time_t unixdate)
  4026. {
  4027.   struct tm t,today;
  4028.   time_t t_today = time(NULL);
  4029.   
  4030.   t = *(LocalTime(&unixdate,LOCAL_TO_GMT));
  4031.   today = *(LocalTime(&t_today,LOCAL_TO_GMT));
  4032.   
  4033.   if (t.tm_year < 80)
  4034.     return(False);
  4035.   
  4036.   if (t.tm_year >  today.tm_year)
  4037.     return(False);
  4038.   
  4039.   if (t.tm_year == today.tm_year &&
  4040.       t.tm_mon > today.tm_mon)
  4041.     return(False);
  4042.   
  4043.   
  4044.   if (t.tm_year == today.tm_year &&
  4045.       t.tm_mon == today.tm_mon &&
  4046.       t.tm_mday > (today.tm_mday+1))
  4047.     return(False);
  4048.   
  4049.   return(True);
  4050. }
  4051.  
  4052.  
  4053.  
  4054. #ifdef NO_FTRUNCATE
  4055.  /*******************************************************************
  4056. ftruncate for operating systems that don't have it
  4057. ********************************************************************/
  4058. int ftruncate(int f,long l)
  4059. {
  4060.       struct  flock   fl;
  4061.  
  4062.       fl.l_whence = 0;
  4063.       fl.l_len = 0;
  4064.       fl.l_start = l;
  4065.       fl.l_type = F_WRLCK;
  4066.       return fcntl(f, F_FREESP, &fl);
  4067. }
  4068. #endif
  4069.  
  4070.  
  4071. /****************************************************************************
  4072. register a netbios name on the net.
  4073. ****************************************************************************/
  4074. BOOL register_name(name_struct *name,struct in_addr *destip,void (*fn)())
  4075. {
  4076.   int count;
  4077.   char *p;
  4078.   char *inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  4079.   char *outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  4080.   BOOL saved_swap = NeedSwap;
  4081.   static uint16 name_trn_id = 0;
  4082.  
  4083.   if (name_trn_id == 0) name_trn_id = getpid() + (time(NULL) % 1000);
  4084.  
  4085.   NeedSwap = !big_endian();
  4086.  
  4087.   if ((inbuf == NULL) || (outbuf == NULL)) 
  4088.     {
  4089.       NeedSwap = saved_swap;
  4090.       return False;
  4091.     }
  4092.  
  4093.   name_trn_id++;
  4094.  
  4095.   DEBUG(1,("Registering name %s (%s) nb_flags=0x%x\n",
  4096.     name->name, inet_ntoa(name->ip) ,name->nb_flags));
  4097.  
  4098.   SSVAL(outbuf,0,name_trn_id);
  4099.   CVAL(outbuf,2) = (0x5<<3) | 0x1;
  4100.   CVAL(outbuf,3) = (1<<4) | 0x0;
  4101.   SSVAL(outbuf,4,1);
  4102.   SSVAL(outbuf,6,0);
  4103.   SSVAL(outbuf,8,0);
  4104.   SSVAL(outbuf,10,1);  
  4105.   p = outbuf+12;
  4106.   name_mangle(name->name,p);
  4107.   p += name_len(p);
  4108.   SSVAL(p,0,0x20);
  4109.   SSVAL(p,2,0x1);
  4110.   p += 4;
  4111.   CVAL(p,0) = 0xC0;
  4112.   CVAL(p,1) = 12;
  4113.   p += 2;
  4114.   SSVAL(p,0,0x20);
  4115.   SSVAL(p,2,0x1);
  4116.   SIVAL(p,4,0); /* my own ttl */
  4117.   SSVAL(p,8,6);
  4118.   CVAL(p,10) = name->nb_flags;
  4119.   CVAL(p,11) = 0;
  4120.   p += 12;
  4121.   memcpy(p,(char *)&(name->ip),4);
  4122.   p += 4;
  4123.  
  4124.   count = 3;
  4125.   while (count--)
  4126.     {
  4127.       DEBUG(3,("Sending reg request for %s at (%s)\n",
  4128.         name->name,inet_ntoa(name->ip)));
  4129.  
  4130.  
  4131.       show_nmb(outbuf);
  4132.       if (!send_nmb(outbuf,nmb_len(outbuf),destip))
  4133.     {
  4134.       free(inbuf);free(outbuf);
  4135.       NeedSwap = saved_swap;
  4136.       return False;
  4137.     }
  4138.  
  4139.       if (receive_nmb(inbuf,3))
  4140.     {
  4141.           int rec_name_trn_id = SVAL(inbuf,0);
  4142.       int opcode = CVAL(inbuf,2) >> 3;
  4143.       int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
  4144.       int rcode = CVAL(inbuf,3) & 0xF;
  4145.  
  4146.       /* is it a negative response to our request? */
  4147.       if ((rec_name_trn_id == name_trn_id) && 
  4148.               (opcode == 21 && nm_flags == 0x58 && rcode != 0 && rcode != 7))
  4149.         {
  4150.           char qname[100];
  4151.           name_extract(inbuf,12,qname);
  4152.           if (name_equal(qname,name->name))
  4153.         {
  4154.           DEBUG(0,("Someone (%s) gave us a negative name regregistration response!\n",
  4155.             inet_ntoa(lastip)));
  4156.           free(inbuf);free(outbuf);
  4157.           NeedSwap = saved_swap;
  4158.           return False;
  4159.         }
  4160.           else
  4161.         {
  4162.           DEBUG(0,("%s gave negative name regregistration for %s??\n",
  4163.             inet_ntoa(lastip),qname));
  4164.         }          
  4165.         }      
  4166.       
  4167.       /* it's something else - process it anyway, unless we are running
  4168.        as a daemon. This is necessary as we may have been started by a 
  4169.        name query of our name arriving on port 137 (often happens) */
  4170.       if (fn)
  4171.         {
  4172.           show_nmb(inbuf);
  4173.           fn(inbuf,outbuf + nmb_len(outbuf));
  4174.         }
  4175.     }
  4176.     }
  4177.  
  4178.   /* increment the packet id */
  4179.   name_trn_id++;
  4180.  
  4181.   /* don't demand on groups */
  4182.   if ((name->nb_flags & 0x80) != 0)
  4183.     {
  4184.       free(inbuf);free(outbuf);
  4185.       NeedSwap = saved_swap;
  4186.       return(True);
  4187.     }
  4188.  
  4189.   /* no negative replies, send a demand */
  4190.   p = outbuf;
  4191.   SSVAL(outbuf,0,name_trn_id);
  4192.   CVAL(outbuf,2) = (0x5<<3);
  4193.   CVAL(outbuf,3) = (1<<4) | 0x0;
  4194.   SSVAL(outbuf,4,1);
  4195.   SSVAL(outbuf,6,0);
  4196.   SSVAL(outbuf,8,0);
  4197.   SSVAL(outbuf,10,1);  
  4198.   p = outbuf+12;
  4199.   name_mangle(name->name,p);
  4200.   p += name_len(p);
  4201.   SSVAL(p,0,0x20);
  4202.   SSVAL(p,2,0x1);
  4203.   p += 4;
  4204.   CVAL(p,0) = 0xC0;
  4205.   CVAL(p,1) = 12;
  4206.   p += 2;
  4207.   SSVAL(p,0,0x20);
  4208.   SSVAL(p,2,0x1);
  4209.   SIVAL(p,4,0); /* my own ttl */
  4210.   SSVAL(p,8,6);
  4211.   CVAL(p,10) = name->nb_flags;
  4212.   CVAL(p,11) = 0;
  4213.   p += 12;
  4214.   memcpy(p,(char *)&(name->ip),4);
  4215.   p += 4;
  4216.   
  4217.   DEBUG(3,("Sending reg demand for %s at (%s)\n",
  4218.     name->name,inet_ntoa(name->ip)));
  4219.  
  4220.   show_nmb(outbuf);
  4221.  
  4222.   {
  4223.     BOOL ret = send_nmb(outbuf,nmb_len(outbuf),destip);
  4224.  
  4225.     free(inbuf);free(outbuf);
  4226.   
  4227.     NeedSwap = saved_swap;
  4228.     return(ret);
  4229.   }
  4230. }
  4231.  
  4232.  
  4233. /****************************************************************************
  4234. get my own name and IP
  4235. ****************************************************************************/
  4236. BOOL get_myname(char *myname,struct in_addr *ip)
  4237. {
  4238.   struct hostent *hp;
  4239.   pstring myhostname="";
  4240.  
  4241.   /* get my host name */
  4242.   if (gethostname(myhostname, sizeof(myhostname)) == -1) 
  4243.     {
  4244.       DEBUG(0,("gethostname failed\n"));
  4245.       return False;
  4246.     } 
  4247.  
  4248.   /* get host info */
  4249.   if ((hp = Get_Hostbyname(myhostname)) == 0) 
  4250.     {
  4251.       DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",myhostname));
  4252.       return False;
  4253.     }
  4254.  
  4255.   if (myname)
  4256.     {
  4257.       /* split off any parts after an initial . */
  4258.       char *p = strchr(myhostname,'.');
  4259.       if (p) *p = 0;
  4260.  
  4261.       strcpy(myname,myhostname);
  4262.     }
  4263.  
  4264.   if (ip)
  4265.     memcpy((char *)ip,(char *)hp->h_addr,4);
  4266.  
  4267.   return(True);
  4268. }
  4269.  
  4270.  
  4271. /****************************************************************************
  4272. true if two IP addresses are equal
  4273. ****************************************************************************/
  4274. BOOL ip_equal(struct in_addr *ip1,struct in_addr *ip2)
  4275. {
  4276.   char *p1=(char *)ip1;
  4277.   char *p2=(char *)ip2;
  4278.   int l = sizeof(*ip1);
  4279.   while (l--)
  4280.     if (*p1++ != *p2++)
  4281.       return(False);
  4282.   return(True);
  4283. }
  4284.  
  4285.  
  4286. /****************************************************************************
  4287. get info about the machine and OS
  4288. ****************************************************************************/
  4289. void get_machine_info(void)
  4290. {
  4291. #if !HAVE_SYSCONF
  4292.  
  4293.   /* assume it doesn't have saved uids and gids */
  4294.   machine_info.have_saved_ids = False;
  4295.  
  4296. #else
  4297.  
  4298.   machine_info.have_saved_ids = (sysconf(_POSIX_SAVED_IDS) == 1);
  4299.  
  4300. #endif
  4301.  
  4302.   DEBUG(3,("Sysconfig:\n"));
  4303.   DEBUG(3,("\tsaved_ids = %d\n",machine_info.have_saved_ids));
  4304.   DEBUG(3,("\n"));
  4305. }
  4306.  
  4307.  
  4308. /****************************************************************************
  4309. construct a netbios datagram. The length of the construct is returned
  4310. ****************************************************************************/
  4311. int construct_datagram(char *buffer, int data_len, int msg_type, int flags, 
  4312.                struct in_addr *source_ip, int source_port, 
  4313.                char *source_name, char *dest_name)
  4314. {
  4315.   static int dgm_id = -1;
  4316.   int dgm_length = data_len;
  4317.   char *p;
  4318.   BOOL saved_swap = NeedSwap;
  4319.   NeedSwap = !big_endian();
  4320.  
  4321.   /* initialise the datagram id */
  4322.   if (dgm_id < 0)
  4323.     dgm_id = (getpid() * 10) % 16000;
  4324.  
  4325.   CVAL(buffer,0) = msg_type;
  4326.   CVAL(buffer,1) = flags | 0x2; /* first fragment */
  4327.   SSVAL(buffer,2,dgm_id++);
  4328.   memcpy(buffer + 4,(char *)source_ip,4);
  4329.   SSVAL(buffer,8,source_port);
  4330.   SSVAL(buffer,12,0);
  4331.   p = buffer + 14;
  4332.   name_mangle(source_name,p);
  4333.   dgm_length += name_len(p);
  4334.   p += name_len(p);
  4335.   name_mangle(dest_name,p);
  4336.   dgm_length += name_len(p);
  4337.   p += name_len(p);
  4338.   SSVAL(buffer,10,dgm_length);
  4339.   
  4340.   NeedSwap = saved_swap;
  4341.  
  4342.   return((int)(p - buffer));
  4343. }
  4344.  
  4345.  
  4346. /****************************************************************************
  4347. open a socket of the specified type, port and address for incoming data
  4348. ****************************************************************************/
  4349. int open_socket_in(int type, int port)
  4350. {
  4351.   struct hostent *hp;
  4352.   struct sockaddr_in sock;
  4353.   pstring host_name;
  4354.   int res;
  4355.  
  4356.   /* get my host name */
  4357.   if (gethostname(host_name, sizeof(host_name)) == -1) 
  4358.     { DEBUG(0,("gethostname failed\n")); return -1; } 
  4359.  
  4360.   /* get host info */
  4361.   if ((hp = Get_Hostbyname(host_name)) == 0) 
  4362.     {
  4363.       DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name));
  4364.       return -1;
  4365.     }
  4366.   
  4367.   memset((char *)&sock, 0, sizeof(sock));
  4368.   memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
  4369.   sock.sin_port = htons( port );
  4370.   sock.sin_family = hp->h_addrtype;
  4371.   sock.sin_addr.s_addr = INADDR_ANY;
  4372.   res = socket(hp->h_addrtype, type, 0);
  4373.   if (res == -1) 
  4374.     { DEBUG(0,("socket failed\n")); return -1; }
  4375.  
  4376. #ifdef SO_REUSEADDR
  4377.   {
  4378.     int one = 1;
  4379.     if (setsockopt(res, SOL_SOCKET, SO_REUSEADDR,(char *)&one, sizeof(one)) == -1)
  4380.       { DEBUG(3,("setsockopt(REUSEADDR) failed - ignored\n")); }
  4381.   }
  4382. #endif
  4383.   
  4384.   /* now we've got a socket - we need to bind it */
  4385.   if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) 
  4386.     { 
  4387.       if (port < 1000)
  4388.     DEBUG(0,("bind failed on port %d\n",port)); 
  4389.       close(res); 
  4390.  
  4391.       if (port >= 1000 && port < 9000)
  4392.     return(open_socket_in(type,port+1));
  4393.  
  4394.       return(-1); 
  4395.     }
  4396.   DEBUG(1,("bind succeeded on port %d\n",port));
  4397.  
  4398.   return res;
  4399. }
  4400.  
  4401.  
  4402. /****************************************************************************
  4403. create an outgoing socket
  4404. ****************************************************************************/
  4405. int open_socket_out(struct in_addr *addr, int port )
  4406. {
  4407.   struct sockaddr_in sock_out;
  4408.   int res;
  4409.  
  4410.   /* create a socket to write to */
  4411.   res = socket(PF_INET, SOCK_STREAM, 0);
  4412.   if (res == -1) 
  4413.     { DEBUG(0,("socket error\n")); return -1; }
  4414.   
  4415.   memset((char *)&sock_out, 0, sizeof(sock_out));
  4416.   memcpy((char *)&sock_out.sin_addr,(char *)addr,4);
  4417.   
  4418.   sock_out.sin_port = htons( port );
  4419.   sock_out.sin_family = PF_INET;
  4420.  
  4421.   DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
  4422.   
  4423.   /* and connect it to the destination */
  4424.   if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))<0)
  4425.     { DEBUG(0,("connect error: %s\n",strerror(errno))); close(res); return -1; }
  4426.  
  4427.   return res;
  4428. }
  4429.  
  4430.  
  4431. /****************************************************************************
  4432. interpret a protocol description string, with a default
  4433. ****************************************************************************/
  4434. int interpret_protocol(char *str,int def)
  4435. {
  4436.   if (strequal(str,"NT1"))
  4437.     return(PROTOCOL_NT1);
  4438.   if (strequal(str,"LANMAN2"))
  4439.     return(PROTOCOL_LANMAN2);
  4440.   if (strequal(str,"LANMAN1"))
  4441.     return(PROTOCOL_LANMAN1);
  4442.   if (strequal(str,"CORE"))
  4443.     return(PROTOCOL_CORE);
  4444.   if (strequal(str,"COREPLUS"))
  4445.     return(PROTOCOL_COREPLUS);
  4446.   if (strequal(str,"CORE+"))
  4447.     return(PROTOCOL_COREPLUS);
  4448.   
  4449.   DEBUG(0,("Unrecognised protocol level %s\n",str));
  4450.   
  4451.   return(def);
  4452. }
  4453.  
  4454. /****************************************************************************
  4455. interpret a security level
  4456. ****************************************************************************/
  4457. int interpret_security(char *str,int def)
  4458. {
  4459.   if (strequal(str,"USER"))
  4460.     return(SEC_USER);
  4461.   if (strequal(str,"SHARE"))
  4462.     return(SEC_SHARE);
  4463.   
  4464.   DEBUG(0,("Unrecognised security level %s\n",str));
  4465.   
  4466.   return(def);
  4467. }
  4468.  
  4469.  
  4470. /****************************************************************************
  4471. interpret an internet address or name into an IP address in 4 byte form
  4472. ****************************************************************************/
  4473. unsigned long interpret_addr(char *str)
  4474. {
  4475.   struct hostent *hp;
  4476.   unsigned long res;
  4477.  
  4478.   /* if it's in the form of an IP address then get the lib to interpret it */
  4479.   if (isdigit(str[0]))
  4480.     return(inet_addr(str));
  4481.  
  4482.   /* otherwise assume it's a network name of some sort and use Get_Hostbyname */
  4483.   if ((hp = Get_Hostbyname(str)) == 0) 
  4484.     {
  4485.       DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",str));
  4486.       return 0;
  4487.     }
  4488.  
  4489.   memcpy((char *)&res,(char *)hp->h_addr,sizeof(res));
  4490.   return(res);
  4491. }
  4492.  
  4493. /****************************************************************************
  4494. interpret an 8 byte "filetime" structure to a time_t
  4495. It's originally in "100ns units since jan 1st 1601"
  4496. ****************************************************************************/
  4497. time_t interpret_filetime(char *p)
  4498. {
  4499.   double d;
  4500.  
  4501.   /* use double precision arithmetic */
  4502.  
  4503.   /* this gives us seconds since jan 1st 1601 (approx) */
  4504.   d = (IVAL(p,4)*256.0 + CVAL(p,3)) * (1.0e-7 * (1<<24));
  4505.  
  4506.   /* now adjust by 369 years to make the secs since 1970 */
  4507.   d -= 369.0*365.25*24*60*60;
  4508.  
  4509.   /* and a fudge factor as we got it wrong by a few days */
  4510.   d += (3*24*60*60 - 60*60 + 2);
  4511.  
  4512.   return((time_t)d);
  4513. }
  4514.  
  4515. /****************************************************************************
  4516. interpret a short filename structure
  4517. The length of the structure is returned
  4518. ****************************************************************************/
  4519. int interpret_short_filename(char *p,file_info *finfo)
  4520. {
  4521.   finfo->mode = CVAL(p,21);
  4522.  
  4523.   finfo->mtime = finfo->atime = finfo->ctime = make_unix_date(p+22);
  4524.   finfo->size = SVAL(p,26) + (SVAL(p,28)<<16);
  4525.   strcpy(finfo->name,p+30);
  4526.   
  4527.   return(DIR_STRUCT_SIZE);
  4528. }
  4529.  
  4530. /****************************************************************************
  4531. interpret a long filename structure - this is mostly guesses at the moment
  4532. The length of the structure is returned
  4533. The structure of a long filename depends on the info level. 260 is used
  4534. by NT and 2 is used by OS/2
  4535. ****************************************************************************/
  4536. int interpret_long_filename(int level,char *p,file_info *finfo)
  4537. {
  4538.   if (finfo)
  4539.     *finfo = def_finfo;
  4540.  
  4541.   switch (level)
  4542.     {
  4543.     case 260: /* NT uses this, but also accepts 2 */
  4544.       if (finfo)
  4545.     {
  4546.       strcpy(finfo->name,p+94);
  4547.       finfo->size = IVAL(p,40);
  4548.       finfo->mode = CVAL(p,56);
  4549.       finfo->mtime = interpret_filetime(p+24); 
  4550.     }
  4551.       return(SVAL(p,0));
  4552.  
  4553.     case 2: /* this is what OS/2 uses */
  4554.       if (finfo)
  4555.     {
  4556.       strcpy(finfo->name,p+31);
  4557.       finfo->size = IVAL(p,16);
  4558.       finfo->mode = CVAL(p,24);
  4559.       finfo->atime = make_unix_date2(p+8);
  4560.       finfo->mtime = make_unix_date2(p+12);
  4561.     }
  4562.       return(32 + CVAL(p,30));
  4563.  
  4564.     case 1: /* OS/2 understands this */
  4565.       if (finfo)
  4566.     {
  4567.       strcpy(finfo->name,p+27);
  4568.       finfo->size = IVAL(p,16);
  4569.       finfo->mode = CVAL(p,24);
  4570.       finfo->ctime = make_unix_date2(p+4);
  4571.       finfo->atime = make_unix_date2(p+8);
  4572.       finfo->mtime = make_unix_date2(p+12);
  4573.     }
  4574.       return(28 + CVAL(p,26));
  4575.     }
  4576.  
  4577.   DEBUG(1,("Unknown long filename format %d\n",level));
  4578.   return(SVAL(p,0));
  4579. }
  4580.  
  4581.  
  4582. /****************************************************************************
  4583. run a command via system() using smbrun
  4584. ****************************************************************************/
  4585. int smbrun(char *cmd)
  4586. {
  4587.   int ret;
  4588.   pstring syscmd;
  4589.  
  4590.   if (getuid() == geteuid() && getgid() == getegid())
  4591.     return(system(cmd));
  4592.  
  4593. #ifndef SMBRUN
  4594.   DEBUG(0,("WARNING - can't find smbrun! is your Makefile OK?\n"));
  4595.   return(-1);
  4596. #endif
  4597.  
  4598.   sprintf(syscmd,"%s \"%s\"",SMBRUN,cmd);
  4599.  
  4600.   DEBUG(5,("smbrun - running %s ",syscmd));
  4601.   ret = system(syscmd);
  4602.   DEBUG(5,("gave %d\n",ret));
  4603.   return(ret);
  4604. }
  4605.  
  4606. /****************************************************************************
  4607. internals of Get_Pwnam wrapper
  4608. ****************************************************************************/
  4609. struct passwd *_Get_Pwnam(char *s)
  4610. {
  4611.   struct passwd *ret;
  4612.  
  4613.   ret = getpwnam(s);
  4614.   if (ret)
  4615.     {
  4616. #ifdef GETPWANAM
  4617.       struct passwd_adjunct *pwret;
  4618.       pwret = getpwanam(s);
  4619.       if (pwret)
  4620.     {
  4621.       free(ret->pw_passwd);
  4622.       ret->pw_passwd = pwret->pwa_passwd;
  4623.     }
  4624. #endif
  4625.     }
  4626.  
  4627.   return(ret);
  4628. }
  4629.  
  4630.  
  4631. /****************************************************************************
  4632. a wrapper for getpwnam() that tries with all lower and all upper case 
  4633. if the initial name fails. Also tried with first letter capitalised
  4634. Note that this changes user!
  4635. ****************************************************************************/
  4636. struct passwd *Get_Pwnam(char *user)
  4637. {
  4638.   fstring user2;
  4639.  
  4640.   struct passwd *ret;  
  4641.  
  4642.   if (!user || !(*user))
  4643.     return(NULL);
  4644.  
  4645.   ret = _Get_Pwnam(user);
  4646.   if (ret) return(ret);
  4647.  
  4648.   strcpy(user2,user);
  4649.  
  4650.   strlower(user);
  4651.   ret = _Get_Pwnam(user);
  4652.   if (ret)  return(ret);
  4653.  
  4654.   strupper(user);
  4655.   ret = _Get_Pwnam(user);
  4656.   if (ret) return(ret);
  4657.  
  4658.   /* try with first letter capitalised */
  4659.   if (strlen(user) > 1)
  4660.     strlower(user+1);  
  4661.   ret = _Get_Pwnam(user);
  4662.   if (ret) return(ret);
  4663.  
  4664.   /* restore the original name */
  4665.   strcpy(user,user2);
  4666.  
  4667.   return(NULL);
  4668. }
  4669.  
  4670. /****************************************************************************
  4671. a wrapper for gethostbyname() that tries with all lower and all upper case 
  4672. if the initial name fails
  4673. ****************************************************************************/
  4674. struct hostent *Get_Hostbyname(char *name)
  4675. {
  4676.   char *name2 = strdup(name);
  4677.   struct hostent *ret;
  4678.  
  4679.   if (!name2)
  4680.     {
  4681.       DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
  4682.       exit(0);
  4683.     }
  4684.  
  4685.   ret = gethostbyname(name2);
  4686.   if (ret != NULL)
  4687.     {
  4688.       free(name2);
  4689.       return(ret);
  4690.     }
  4691.  
  4692.   /* try with all lowercase */
  4693.   strlower(name2);
  4694.   ret = gethostbyname(name2);
  4695.   if (ret != NULL)
  4696.     {
  4697.       free(name2);
  4698.       return(ret);
  4699.     }
  4700.  
  4701.   /* try with all uppercase */
  4702.   strupper(name2);
  4703.   ret = gethostbyname(name2);
  4704.   if (ret != NULL)
  4705.     {
  4706.       free(name2);
  4707.       return(ret);
  4708.     }
  4709.   
  4710.   /* nothing works :-( */
  4711.   free(name2);
  4712.   return(NULL);
  4713. }
  4714.  
  4715.  
  4716. /****************************************************************************
  4717. simple routines to do connection counting
  4718. ****************************************************************************/
  4719. BOOL fcntl_lock(int fd,int op,int offset,int count,int type)
  4720. {
  4721. #if HAVE_FCNTL_LOCK
  4722.   struct flock lock;
  4723.   int ret;
  4724.   unsigned long mask = ((unsigned)1<<31);
  4725.  
  4726.   /* interpret negative counts as large numbers */
  4727.   if (count < 0)
  4728.     count &= ~mask;
  4729.  
  4730.   /* no negative offsets */
  4731.   offset &= ~mask;
  4732.  
  4733.   /* count + offset must be in range */
  4734.   while ((offset < 0 || (offset + count < 0)) && mask)
  4735.     {
  4736.       offset &= ~mask;
  4737.       mask = mask >> 1;
  4738.     }
  4739.  
  4740.   DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,offset,count,type));
  4741.  
  4742.   lock.l_type = type;
  4743.   lock.l_whence = SEEK_SET;
  4744.   lock.l_start = offset;
  4745.   lock.l_len = count;
  4746.   lock.l_pid = 0;
  4747.  
  4748.   errno = 0;
  4749.  
  4750.   ret = fcntl(fd,op,&lock);
  4751.  
  4752.   if (errno != 0)
  4753.     DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
  4754.  
  4755.   /* a lock query */
  4756.   if (op == F_GETLK)
  4757.     {
  4758.       if ((ret != -1) &&
  4759.       (lock.l_type != F_UNLCK) && 
  4760.       (lock.l_pid != 0) && 
  4761.       (lock.l_pid != getpid()))
  4762.     {
  4763.       DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
  4764.       return(True);
  4765.     }
  4766.  
  4767.       /* it must be not locked or locked by me */
  4768.       return(False);
  4769.     }
  4770.  
  4771.   /* a lock set or unset */
  4772.   if (ret == -1)
  4773.     {
  4774.       DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
  4775.            offset,count,op,type,strerror(errno)));
  4776.  
  4777.       /* perhaps it doesn't support this sort of locking?? */
  4778.       if (errno == EINVAL)
  4779.     {
  4780.       DEBUG(3,("locking not supported? returning True\n"));
  4781.       return(True);
  4782.     }
  4783.  
  4784.       return(False);
  4785.     }
  4786.  
  4787.   /* everything went OK */
  4788.   DEBUG(5,("Lock call successful\n"));
  4789.  
  4790.   return(True);
  4791. #else
  4792.   return(False);
  4793. #endif
  4794. }
  4795.  
  4796. /****************************************************************************
  4797. try to get a write lock
  4798. ****************************************************************************/
  4799. BOOL try_lock(int fd,int offset,int count)
  4800. {
  4801.   int tries = 3;
  4802.   while (tries--)
  4803.     {
  4804.       if (fcntl_lock(fd,F_SETLK,offset,count,F_WRLCK))
  4805.     return(True);
  4806.  
  4807.       sleep(1);
  4808.     }
  4809.   return(False);
  4810. }
  4811.  
  4812.  
  4813. /****************************************************************************
  4814. check if a process exists. Does this work on all unixes?
  4815. ****************************************************************************/
  4816. BOOL process_exists(int pid)
  4817. {
  4818.   return(pid == getpid() || kill(pid,0) == 0);
  4819. }
  4820.  
  4821. /****************************************************************************
  4822. locking fread
  4823. ****************************************************************************/
  4824. int lockfread(void *p,int pos,int size,int n,FILE *f)
  4825. {
  4826.   int ret;
  4827.  
  4828.   if (fseek(f,pos,SEEK_SET) != 0)
  4829.     {
  4830.       DEBUG(3,("lockfread couldn't seek to %d\n",pos));
  4831.       return(0);
  4832.     }
  4833.  
  4834.   if (!try_lock(fileno(f),pos,size*n))
  4835.     {
  4836.       DEBUG(3,("lockfread couldn't lock\n"));
  4837.       return(0);
  4838.     }
  4839.  
  4840.   ret = fread(p,size,n,f);
  4841.  
  4842.   fcntl_lock(fileno(f),F_SETLK,pos,size*n,F_UNLCK);
  4843.   return(ret);
  4844. }
  4845.  
  4846.  
  4847.  
  4848. #if (defined(SecureWare) && defined(SCO))
  4849. /* This is needed due to needing the nap() function but we don't want
  4850.    to include the Xenix libraries since that will break other things...
  4851.    BTW: system call # 0x0c28 is the same as calling nap() */
  4852. long nap(long milliseconds) {
  4853.   return syscall(0x0c28, milliseconds);
  4854. }
  4855. #endif
  4856.  
  4857. #ifdef NO_INITGROUPS
  4858. #include <sys/types.h>
  4859. #include <limits.h>
  4860. #include <grp.h>
  4861.  
  4862. #ifndef NULL
  4863. #define NULL (void *)0
  4864. #endif
  4865.  
  4866. /****************************************************************************
  4867.  some systems don't have an initgroups call 
  4868. ****************************************************************************/
  4869. void initgroups(name,id)
  4870. char *name;
  4871. GID_TYPE id;
  4872. {
  4873.   GID_TYPE  grouplst[NGROUPS_MAX];
  4874.   int    i;
  4875.   struct group *g;
  4876.   char   *gr;
  4877.  
  4878.   grouplst[0] = id;
  4879.   i = 1;
  4880.   while (i < NGROUPS_MAX && 
  4881.      ((g = (struct group *)getgrent()) != (struct group *)NULL)) 
  4882.     {
  4883.       if (g->gr_gid == id)
  4884.     continue;
  4885.       gr = g->gr_mem[0];
  4886.       while (gr && (*gr != (char)NULL)) {
  4887.     if (strcmp(name,gr) == 0) {
  4888.       grouplst[i] = g->gr_gid;
  4889.       i++;
  4890.       gr = (char *)NULL;
  4891.       break;
  4892.     }
  4893.     gr++;
  4894.       }
  4895.     }
  4896.   endgrent();
  4897.   setgroups(i,grouplst);
  4898. }
  4899. #endif
  4900.  
  4901.  
  4902. #if WRAP_MALLOC
  4903.  
  4904. /* undo the wrapping temporarily */
  4905. #undef malloc
  4906. #undef realloc
  4907. #undef free
  4908.  
  4909. /****************************************************************************
  4910. wrapper for malloc() to catch memory errors
  4911. ****************************************************************************/
  4912. void *malloc_wrapped(int size,char *file,int line)
  4913. {
  4914. #ifdef xx_old_malloc
  4915.   void *res = xx_old_malloc(size);
  4916. #else
  4917.   void *res = malloc(size);
  4918. #endif
  4919.   DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
  4920.     file,line,
  4921.     size,(unsigned int)res));
  4922.   return(res);
  4923. }
  4924.  
  4925. /****************************************************************************
  4926. wrapper for realloc() to catch memory errors
  4927. ****************************************************************************/
  4928. void *realloc_wrapped(void *ptr,int size,char *file,int line)
  4929. {
  4930. #ifdef xx_old_realloc
  4931.   void *res = xx_old_realloc(ptr,size);
  4932. #else
  4933.   void *res = realloc(ptr,size);
  4934. #endif
  4935.   DEBUG(3,("Realloc\n"));
  4936.   DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
  4937.     file,line,
  4938.     (unsigned int)ptr));
  4939.   DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
  4940.     file,line,
  4941.     size,(unsigned int)res));
  4942.   return(res);
  4943. }
  4944.  
  4945. /****************************************************************************
  4946. wrapper for free() to catch memory errors
  4947. ****************************************************************************/
  4948. void free_wrapped(void *ptr,char *file,int line)
  4949. {
  4950. #ifdef xx_old_free
  4951.   xx_old_free(ptr);
  4952. #else
  4953.   free(ptr);
  4954. #endif
  4955.   DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
  4956.     file,line,(unsigned int)ptr));
  4957.   return;
  4958. }
  4959.  
  4960. /* and re-do the define for spots lower in this file */
  4961. #define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
  4962. #define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
  4963. #define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
  4964.  
  4965. #endif
  4966.  
  4967. #ifdef REPLACE_STRSTR
  4968. /****************************************************************************
  4969. Mips version of strstr doesn't seem to work correctly.
  4970. There is a #define in includes.h to redirect calls to this function.
  4971. ****************************************************************************/
  4972. char *Strstr(char *s, char *p)
  4973. {
  4974.     int len = strlen(p);
  4975.  
  4976.     while ( *s != '\0' ) {
  4977.         if ( strncmp(s, p, len) == 0 )
  4978.         return s;
  4979.         s++;
  4980.     }
  4981.  
  4982.     return NULL;
  4983. }
  4984. #endif /* REPLACE_STRSTR */
  4985.